diff --git a/docs/en/28-releases/01-tdengine.md b/docs/en/28-releases/01-tdengine.md
index a9336697f2..f4d9ba8e42 100644
--- a/docs/en/28-releases/01-tdengine.md
+++ b/docs/en/28-releases/01-tdengine.md
@@ -10,6 +10,10 @@ For TDengine 2.x installation packages by version, please visit [here](https://w
import Release from "/components/ReleaseV3";
+## 3.0.5.1
+
+
+
## 3.0.5.0
diff --git a/docs/en/28-releases/02-tools.md b/docs/en/28-releases/02-tools.md
index 28c2ff7a7f..f3099b13b4 100644
--- a/docs/en/28-releases/02-tools.md
+++ b/docs/en/28-releases/02-tools.md
@@ -10,6 +10,10 @@ For other historical version installers, please visit [here](https://www.taosdat
import Release from "/components/ReleaseV3";
+## 2.5.2
+
+
+
## 2.5.1
diff --git a/docs/zh/28-releases/01-tdengine.md b/docs/zh/28-releases/01-tdengine.md
index 3ee19de84f..ae47388566 100644
--- a/docs/zh/28-releases/01-tdengine.md
+++ b/docs/zh/28-releases/01-tdengine.md
@@ -10,6 +10,10 @@ TDengine 2.x 各版本安装包请访问[这里](https://www.taosdata.com/all-do
import Release from "/components/ReleaseV3";
+## 3.0.5.1
+
+
+
## 3.0.5.0
diff --git a/docs/zh/28-releases/02-tools.md b/docs/zh/28-releases/02-tools.md
index fbd12b1440..ba58ed9600 100644
--- a/docs/zh/28-releases/02-tools.md
+++ b/docs/zh/28-releases/02-tools.md
@@ -10,6 +10,10 @@ taosTools 各版本安装包下载链接如下:
import Release from "/components/ReleaseV3";
+## 2.5.2
+
+
+
## 2.5.1
diff --git a/include/common/tcommon.h b/include/common/tcommon.h
index d2352e100c..ea17262abd 100644
--- a/include/common/tcommon.h
+++ b/include/common/tcommon.h
@@ -198,6 +198,7 @@ typedef struct SDataBlockInfo {
SBlockID id;
int16_t hasVarCol;
int16_t dataLoad; // denote if the data is loaded or not
+ uint8_t scanFlag;
// TODO: optimize and remove following
int64_t version; // used for stream, and need serialization
diff --git a/include/libs/nodes/plannodes.h b/include/libs/nodes/plannodes.h
index f44b622cc0..453c5d4914 100644
--- a/include/libs/nodes/plannodes.h
+++ b/include/libs/nodes/plannodes.h
@@ -53,6 +53,8 @@ typedef struct SLogicNode {
EDataOrderLevel requireDataOrder; // requirements for input data
EDataOrderLevel resultDataOrder; // properties of the output data
EGroupAction groupAction;
+ EOrder inputTsOrder;
+ EOrder outputTsOrder;
} SLogicNode;
typedef enum EScanType {
@@ -111,7 +113,6 @@ typedef struct SJoinLogicNode {
SNode* pMergeCondition;
SNode* pOnConditions;
bool isSingleTableJoin;
- EOrder inputTsOrder;
SNode* pColEqualOnConditions;
} SJoinLogicNode;
@@ -229,8 +230,6 @@ typedef struct SWindowLogicNode {
int8_t igExpired;
int8_t igCheckUpdate;
EWindowAlgorithm windowAlgo;
- EOrder inputTsOrder;
- EOrder outputTsOrder;
} SWindowLogicNode;
typedef struct SFillLogicNode {
@@ -241,7 +240,6 @@ typedef struct SFillLogicNode {
SNode* pWStartTs;
SNode* pValues; // SNodeListNode
STimeWindow timeRange;
- EOrder inputTsOrder;
} SFillLogicNode;
typedef struct SSortLogicNode {
@@ -310,6 +308,8 @@ typedef struct SDataBlockDescNode {
typedef struct SPhysiNode {
ENodeType type;
+ EOrder inputTsOrder;
+ EOrder outputTsOrder;
SDataBlockDescNode* pOutputDataBlockDesc;
SNode* pConditions;
SNodeList* pChildren;
@@ -406,7 +406,6 @@ typedef struct SSortMergeJoinPhysiNode {
SNode* pMergeCondition;
SNode* pOnConditions;
SNodeList* pTargets;
- EOrder inputTsOrder;
SNode* pColEqualOnConditions;
} SSortMergeJoinPhysiNode;
@@ -460,8 +459,6 @@ typedef struct SWindowPhysiNode {
int64_t watermark;
int64_t deleteMark;
int8_t igExpired;
- EOrder inputTsOrder;
- EOrder outputTsOrder;
bool mergeDataBlock;
} SWindowPhysiNode;
@@ -488,7 +485,6 @@ typedef struct SFillPhysiNode {
SNode* pWStartTs; // SColumnNode
SNode* pValues; // SNodeListNode
STimeWindow timeRange;
- EOrder inputTsOrder;
} SFillPhysiNode;
typedef SFillPhysiNode SStreamFillPhysiNode;
diff --git a/include/libs/nodes/querynodes.h b/include/libs/nodes/querynodes.h
index f570698395..678c694d9b 100644
--- a/include/libs/nodes/querynodes.h
+++ b/include/libs/nodes/querynodes.h
@@ -69,6 +69,7 @@ typedef struct SColumnNode {
uint64_t tableId;
int8_t tableType;
col_id_t colId;
+ uint16_t projIdx; // the idx in project list, start from 1
EColumnType colType; // column or tag
bool hasIndex;
char dbName[TSDB_DB_NAME_LEN];
diff --git a/include/libs/qcom/query.h b/include/libs/qcom/query.h
index de3eba599d..6a1091e658 100644
--- a/include/libs/qcom/query.h
+++ b/include/libs/qcom/query.h
@@ -281,7 +281,8 @@ extern int32_t (*queryProcessMsgRsp[TDMT_MAX])(void* output, char* msg, int32_t
(_code) == TSDB_CODE_PAR_INVALID_DROP_COL || ((_code) == TSDB_CODE_TDB_INVALID_TABLE_ID))
#define NEED_CLIENT_REFRESH_VG_ERROR(_code) \
((_code) == TSDB_CODE_VND_HASH_MISMATCH || (_code) == TSDB_CODE_VND_INVALID_VGROUP_ID)
-#define NEED_CLIENT_REFRESH_TBLMETA_ERROR(_code) ((_code) == TSDB_CODE_TDB_INVALID_TABLE_SCHEMA_VER)
+#define NEED_CLIENT_REFRESH_TBLMETA_ERROR(_code) \
+ ((_code) == TSDB_CODE_TDB_INVALID_TABLE_SCHEMA_VER || (_code) == TSDB_CODE_MND_INVALID_SCHEMA_VER)
#define NEED_CLIENT_HANDLE_ERROR(_code) \
(NEED_CLIENT_RM_TBLMETA_ERROR(_code) || NEED_CLIENT_REFRESH_VG_ERROR(_code) || \
NEED_CLIENT_REFRESH_TBLMETA_ERROR(_code))
diff --git a/source/client/src/clientMain.c b/source/client/src/clientMain.c
index 7573fd5968..63b16a30c5 100644
--- a/source/client/src/clientMain.c
+++ b/source/client/src/clientMain.c
@@ -1120,6 +1120,7 @@ void doAsyncQuery(SRequestObj *pRequest, bool updateMetaForce) {
if (NEED_CLIENT_HANDLE_ERROR(code)) {
tscDebug("0x%" PRIx64 " client retry to handle the error, code:%d - %s, tryCount:%d, reqId:0x%" PRIx64,
pRequest->self, code, tstrerror(code), pRequest->retry, pRequest->requestId);
+ refreshMeta(pRequest->pTscObj, pRequest);
pRequest->prevCode = code;
doAsyncQuery(pRequest, true);
return;
diff --git a/source/common/src/tdatablock.c b/source/common/src/tdatablock.c
index 79b730721e..0104384bd3 100644
--- a/source/common/src/tdatablock.c
+++ b/source/common/src/tdatablock.c
@@ -791,8 +791,8 @@ size_t blockDataGetRowSize(SSDataBlock* pBlock) {
* @return
*/
size_t blockDataGetSerialMetaSize(uint32_t numOfCols) {
- // | version | total length | total rows | total columns | flag seg| block group id | column schema | each column
- // length |
+ // | version | total length | total rows | total columns | flag seg| block group id | column schema
+ // | each column length |
return sizeof(int32_t) + sizeof(int32_t) + sizeof(int32_t) + sizeof(int32_t) + sizeof(int32_t) + sizeof(uint64_t) +
numOfCols * (sizeof(int8_t) + sizeof(int32_t)) + numOfCols * sizeof(int32_t);
}
diff --git a/source/dnode/mgmt/mgmt_vnode/src/vmWorker.c b/source/dnode/mgmt/mgmt_vnode/src/vmWorker.c
index e41c9e10d7..76e2f93027 100644
--- a/source/dnode/mgmt/mgmt_vnode/src/vmWorker.c
+++ b/source/dnode/mgmt/mgmt_vnode/src/vmWorker.c
@@ -218,6 +218,7 @@ static int32_t vmPutMsgToQueue(SVnodeMgmt *pMgmt, SRpcMsg *pMsg, EQueueType qtyp
if (pMsg->msgType != TDMT_VND_ALTER_CONFIRM && pVnode->disable) {
dDebug("vgId:%d, msg:%p put into vnode-write queue failed since its disable", pVnode->vgId, pMsg);
terrno = TSDB_CODE_VND_STOPPED;
+ code = terrno;
break;
}
dGTrace("vgId:%d, msg:%p put into vnode-write queue", pVnode->vgId, pMsg);
diff --git a/source/dnode/vnode/src/sma/smaTimeRange.c b/source/dnode/vnode/src/sma/smaTimeRange.c
index 3542ea9ffb..84cd44e837 100644
--- a/source/dnode/vnode/src/sma/smaTimeRange.c
+++ b/source/dnode/vnode/src/sma/smaTimeRange.c
@@ -29,7 +29,7 @@ int32_t tdProcessTSmaInsert(SSma *pSma, int64_t indexUid, const char *msg) {
int32_t code = TSDB_CODE_SUCCESS;
if ((code = tdProcessTSmaInsertImpl(pSma, indexUid, msg)) < 0) {
- smaWarn("vgId:%d, insert tsma data failed since %s", SMA_VID(pSma), tstrerror(terrno));
+ smaError("vgId:%d, insert tsma data failed since %s", SMA_VID(pSma), tstrerror(terrno));
}
return code;
@@ -346,6 +346,43 @@ _end:
return TSDB_CODE_SUCCESS;
}
+static int32_t tsmaProcessDelReq(SSma *pSma, int64_t indexUid, SBatchDeleteReq *pDelReq) {
+ int32_t code = 0;
+ int32_t lino = 0;
+
+ if (taosArrayGetSize(pDelReq->deleteReqs) > 0) {
+ int32_t len = 0;
+ tEncodeSize(tEncodeSBatchDeleteReq, pDelReq, len, code);
+ TSDB_CHECK_CODE(code, lino, _exit);
+
+ void *pBuf = rpcMallocCont(len + sizeof(SMsgHead));
+ if (!pBuf) {
+ code = terrno;
+ TSDB_CHECK_CODE(code, lino, _exit);
+ }
+
+ SEncoder encoder;
+ tEncoderInit(&encoder, POINTER_SHIFT(pBuf, sizeof(SMsgHead)), len);
+ tEncodeSBatchDeleteReq(&encoder, pDelReq);
+ tEncoderClear(&encoder);
+
+ ((SMsgHead *)pBuf)->vgId = TD_VID(pSma->pVnode);
+
+ SRpcMsg delMsg = {.msgType = TDMT_VND_BATCH_DEL, .pCont = pBuf, .contLen = len + sizeof(SMsgHead)};
+ code = tmsgPutToQueue(&pSma->pVnode->msgCb, WRITE_QUEUE, &delMsg);
+ TSDB_CHECK_CODE(code, lino, _exit);
+ }
+
+_exit:
+ taosArrayDestroy(pDelReq->deleteReqs);
+ if (code) {
+ smaError("vgId:%d, failed at line %d to process delete req for smaIndex %" PRIi64 " since %s", SMA_VID(pSma), lino,
+ indexUid, tstrerror(code));
+ }
+
+ return code;
+}
+
/**
* @brief Insert/Update Time-range-wise SMA data.
*
@@ -355,7 +392,6 @@ _end:
*/
static int32_t tdProcessTSmaInsertImpl(SSma *pSma, int64_t indexUid, const char *msg) {
const SArray *pDataBlocks = (const SArray *)msg;
- // TODO: destroy SSDataBlocks(msg)
if (!pDataBlocks) {
terrno = TSDB_CODE_TSMA_INVALID_PTR;
smaWarn("vgId:%d, insert tsma data failed since pDataBlocks is NULL", SMA_VID(pSma));
@@ -419,8 +455,10 @@ static int32_t tdProcessTSmaInsertImpl(SSma *pSma, int64_t indexUid, const char
goto _err;
}
- // TODO deleteReq
- taosArrayDestroy(deleteReq.deleteReqs);
+ if ((terrno = tsmaProcessDelReq(pSma, indexUid, &deleteReq)) != 0) {
+ goto _err;
+ }
+
#if 0
if (!strncasecmp("td.tsma.rst.tb", pTsmaStat->pTSma->dstTbName, 14)) {
terrno = TSDB_CODE_APP_ERROR;
diff --git a/source/dnode/vnode/src/tsdb/tsdbCommit2.c b/source/dnode/vnode/src/tsdb/tsdbCommit2.c
index 6d9e670598..7e5db55eba 100644
--- a/source/dnode/vnode/src/tsdb/tsdbCommit2.c
+++ b/source/dnode/vnode/src/tsdb/tsdbCommit2.c
@@ -21,8 +21,8 @@ typedef struct {
TFileSetArray *fsetArr;
TFileOpArray fopArray[1];
- SSkmInfo skmTb[1];
- SSkmInfo skmRow[1];
+ // SSkmInfo skmTb[1];
+ // SSkmInfo skmRow[1];
int32_t minutes;
int8_t precision;
@@ -56,48 +56,29 @@ typedef struct {
SIterMerger *tombIterMerger;
// writer
- SBlockData blockData[2];
- int32_t blockDataIdx;
- SDataFileWriter *dataWriter;
- SSttFileWriter *sttWriter;
+ SFSetWriter *writer;
} SCommitter2;
static int32_t tsdbCommitOpenWriter(SCommitter2 *committer) {
int32_t code = 0;
int32_t lino = 0;
- // stt writer
- SSttFileWriterConfig config[1] = {{
+ SFSetWriterConfig config = {
.tsdb = committer->tsdb,
+ .toSttOnly = true,
+ .compactVersion = committer->compactVersion,
+ .minRow = committer->minRow,
.maxRow = committer->maxRow,
.szPage = committer->szPage,
.cmprAlg = committer->cmprAlg,
- .compactVersion = committer->compactVersion,
- .file =
- {
- .type = TSDB_FTYPE_STT,
- .did = committer->ctx->did,
- .fid = committer->ctx->fid,
- .cid = committer->ctx->cid,
- },
- }};
+ .fid = committer->ctx->fid,
+ .cid = committer->ctx->cid,
+ .did = committer->ctx->did,
+ .level = 0,
+ };
- code = tsdbSttFileWriterOpen(config, &committer->sttWriter);
- TSDB_CHECK_CODE(code, lino, _exit);
-
- // data writer
if (committer->sttTrigger == 1) {
- // data writer
- SDataFileWriterConfig config = {
- .tsdb = committer->tsdb,
- .cmprAlg = committer->cmprAlg,
- .maxRow = committer->maxRow,
- .szPage = committer->szPage,
- .fid = committer->ctx->fid,
- .cid = committer->ctx->cid,
- .did = committer->ctx->did,
- .compactVersion = committer->compactVersion,
- };
+ config.toSttOnly = false;
if (committer->ctx->fset) {
for (int32_t ftype = TSDB_FTYPE_MIN; ftype < TSDB_FTYPE_MAX; ftype++) {
@@ -107,11 +88,11 @@ static int32_t tsdbCommitOpenWriter(SCommitter2 *committer) {
}
}
}
-
- code = tsdbDataFileWriterOpen(&config, &committer->dataWriter);
- TSDB_CHECK_CODE(code, lino, _exit);
}
+ code = tsdbFSetWriterOpen(&config, &committer->writer);
+ TSDB_CHECK_CODE(code, lino, _exit);
+
_exit:
if (code) {
TSDB_ERROR_LOG(TD_VID(committer->tsdb->pVnode), lino, code);
@@ -120,22 +101,10 @@ _exit:
}
static int32_t tsdbCommitCloseWriter(SCommitter2 *committer) {
- int32_t code = 0;
- int32_t lino = 0;
-
- code = tsdbSttFileWriterClose(&committer->sttWriter, 0, committer->fopArray);
- TSDB_CHECK_CODE(code, lino, _exit);
-
- code = tsdbDataFileWriterClose(&committer->dataWriter, 0, committer->fopArray);
- TSDB_CHECK_CODE(code, lino, _exit);
-
-_exit:
- if (code) {
- TSDB_ERROR_LOG(TD_VID(committer->tsdb->pVnode), lino, code);
- }
- return code;
+ return tsdbFSetWriterClose(&committer->writer, 0, committer->fopArray);
}
+#if 0
static int32_t tsdbCommitTSDataToDataTableBegin(SCommitter2 *committer, const TABLEID *tbid) {
int32_t code = 0;
int32_t lino = 0;
@@ -331,17 +300,30 @@ _exit:
}
return code;
}
+#endif
static int32_t tsdbCommitTSData(SCommitter2 *committer) {
- int32_t code = 0;
- int32_t lino = 0;
+ int32_t code = 0;
+ int32_t lino = 0;
+ SMetaInfo info;
- // loop iter
- if (committer->sttTrigger == 1) {
- code = tsdbCommitTSDataToData(committer);
+ for (SRowInfo *row; (row = tsdbIterMergerGetData(committer->dataIterMerger)) != NULL;) {
+ if (row->uid != committer->ctx->tbid->uid) {
+ // Ignore table of obsolescence
+ if (metaGetInfo(committer->tsdb->pVnode->pMeta, row->uid, &info, NULL) != 0) {
+ code = tsdbIterMergerSkipTableData(committer->dataIterMerger, (TABLEID *)row);
+ TSDB_CHECK_CODE(code, lino, _exit);
+ continue;
+ }
+
+ committer->ctx->tbid->suid = row->suid;
+ committer->ctx->tbid->uid = row->uid;
+ }
+
+ code = tsdbFSetWriteRow(committer->writer, row);
TSDB_CHECK_CODE(code, lino, _exit);
- } else {
- code = tsdbCommitTSDataToStt(committer);
+
+ code = tsdbIterMergerNext(committer->dataIterMerger);
TSDB_CHECK_CODE(code, lino, _exit);
}
@@ -356,22 +338,12 @@ static int32_t tsdbCommitTombData(SCommitter2 *committer) {
int32_t code = 0;
int32_t lino = 0;
- if (committer->dataWriter == NULL || tsdbSttFileWriterIsOpened(committer->sttWriter)) {
- for (STombRecord *record; (record = tsdbIterMergerGetTombRecord(committer->tombIterMerger));) {
- code = tsdbSttFileWriteTombRecord(committer->sttWriter, record);
- TSDB_CHECK_CODE(code, lino, _exit);
+ for (STombRecord *record; (record = tsdbIterMergerGetTombRecord(committer->tombIterMerger));) {
+ code = tsdbFSetWriteTombRecord(committer->writer, record);
+ TSDB_CHECK_CODE(code, lino, _exit);
- code = tsdbIterMergerNext(committer->tombIterMerger);
- TSDB_CHECK_CODE(code, lino, _exit);
- }
- } else {
- for (STombRecord *record; (record = tsdbIterMergerGetTombRecord(committer->tombIterMerger));) {
- code = tsdbDataFileWriteTombRecord(committer->dataWriter, record);
- TSDB_CHECK_CODE(code, lino, _exit);
-
- code = tsdbIterMergerNext(committer->tombIterMerger);
- TSDB_CHECK_CODE(code, lino, _exit);
- }
+ code = tsdbIterMergerNext(committer->tombIterMerger);
+ TSDB_CHECK_CODE(code, lino, _exit);
}
_exit:
@@ -532,8 +504,7 @@ static int32_t tsdbCommitFileSetBegin(SCommitter2 *committer) {
ASSERT(TARRAY2_SIZE(committer->dataIterArray) == 0);
ASSERT(committer->dataIterMerger == NULL);
- ASSERT(committer->sttWriter == NULL);
- ASSERT(committer->dataWriter == NULL);
+ ASSERT(committer->writer == NULL);
code = tsdbCommitOpenReader(committer);
TSDB_CHECK_CODE(code, lino, _exit);
@@ -663,8 +634,7 @@ static int32_t tsdbCloseCommitter(SCommitter2 *committer, int32_t eno) {
ASSERT(0);
}
- ASSERT(committer->dataWriter == NULL);
- ASSERT(committer->sttWriter == NULL);
+ ASSERT(committer->writer == NULL);
ASSERT(committer->dataIterMerger == NULL);
ASSERT(committer->tombIterMerger == NULL);
TARRAY2_DESTROY(committer->dataIterArray, NULL);
diff --git a/source/dnode/vnode/src/tsdb/tsdbCommit2.h b/source/dnode/vnode/src/tsdb/tsdbCommit2.h
index 72d7eb48ee..41f72f345b 100644
--- a/source/dnode/vnode/src/tsdb/tsdbCommit2.h
+++ b/source/dnode/vnode/src/tsdb/tsdbCommit2.h
@@ -15,6 +15,7 @@
#include "tsdbDataFileRW.h"
#include "tsdbFS2.h"
+#include "tsdbFSetRW.h"
#include "tsdbIter.h"
#include "tsdbSttFileRW.h"
diff --git a/source/dnode/vnode/src/tsdb/tsdbFSetRW.c b/source/dnode/vnode/src/tsdb/tsdbFSetRW.c
new file mode 100644
index 0000000000..949de99a4b
--- /dev/null
+++ b/source/dnode/vnode/src/tsdb/tsdbFSetRW.c
@@ -0,0 +1,292 @@
+/*
+ * Copyright (c) 2019 TAOS Data, Inc.
+ *
+ * This program is free software: you can use, redistribute, and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3
+ * or later ("AGPL"), as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+#include "tsdbFSetRW.h"
+
+// SFSetWriter ==================================================
+struct SFSetWriter {
+ SFSetWriterConfig config[1];
+
+ SSkmInfo skmTb[1];
+ SSkmInfo skmRow[1];
+ uint8_t *bufArr[10];
+
+ struct {
+ TABLEID tbid[1];
+ } ctx[1];
+
+ // writer
+ SBlockData blockData[2];
+ int32_t blockDataIdx;
+ SDataFileWriter *dataWriter;
+ SSttFileWriter *sttWriter;
+};
+
+static int32_t tsdbFSetWriteTableDataBegin(SFSetWriter *writer, const TABLEID *tbid) {
+ int32_t code = 0;
+ int32_t lino = 0;
+
+ writer->ctx->tbid->suid = tbid->suid;
+ writer->ctx->tbid->uid = tbid->uid;
+
+ code = tsdbUpdateSkmTb(writer->config->tsdb, writer->ctx->tbid, writer->skmTb);
+ TSDB_CHECK_CODE(code, lino, _exit);
+
+ writer->blockDataIdx = 0;
+ for (int32_t i = 0; i < ARRAY_SIZE(writer->blockData); i++) {
+ code = tBlockDataInit(&writer->blockData[i], writer->ctx->tbid, writer->skmTb->pTSchema, NULL, 0);
+ TSDB_CHECK_CODE(code, lino, _exit);
+ }
+
+_exit:
+ if (code) {
+ TSDB_ERROR_LOG(TD_VID(writer->config->tsdb->pVnode), lino, code);
+ }
+ return code;
+}
+
+static int32_t tsdbFSetWriteTableDataEnd(SFSetWriter *writer) {
+ if (writer->ctx->tbid->uid == 0) return 0;
+
+ int32_t code = 0;
+ int32_t lino = 0;
+
+ int32_t cidx = writer->blockDataIdx;
+ int32_t pidx = ((cidx + 1) & 1);
+ int32_t numRow = ((writer->blockData[pidx].nRow + writer->blockData[cidx].nRow) >> 1);
+
+ if (writer->blockData[pidx].nRow > 0 && numRow >= writer->config->minRow) {
+ ASSERT(writer->blockData[pidx].nRow == writer->config->maxRow);
+
+ SRowInfo row = {
+ .suid = writer->ctx->tbid->suid,
+ .uid = writer->ctx->tbid->uid,
+ .row = tsdbRowFromBlockData(writer->blockData + pidx, 0),
+ };
+
+ for (int32_t i = 0; i < numRow; i++) {
+ row.row.iRow = i;
+
+ code = tsdbDataFileWriteRow(writer->dataWriter, &row);
+ TSDB_CHECK_CODE(code, lino, _exit);
+ }
+
+ code = tsdbDataFileFlush(writer->dataWriter);
+ TSDB_CHECK_CODE(code, lino, _exit);
+
+ for (int32_t i = numRow; i < writer->blockData[pidx].nRow; i++) {
+ row.row.iRow = i;
+ code = tsdbDataFileWriteRow(writer->dataWriter, &row);
+ TSDB_CHECK_CODE(code, lino, _exit);
+ }
+
+ row.row = tsdbRowFromBlockData(writer->blockData + cidx, 0);
+ for (int32_t i = 0; i < writer->blockData[cidx].nRow; i++) {
+ row.row.iRow = i;
+ code = tsdbDataFileWriteRow(writer->dataWriter, &row);
+ TSDB_CHECK_CODE(code, lino, _exit);
+ }
+ } else {
+ // pidx
+ if (writer->blockData[pidx].nRow > 0) {
+ code = tsdbDataFileWriteBlockData(writer->dataWriter, &writer->blockData[pidx]);
+ TSDB_CHECK_CODE(code, lino, _exit);
+ }
+
+ // cidx
+ if (writer->blockData[cidx].nRow < writer->config->minRow) {
+ code = tsdbSttFileWriteBlockData(writer->sttWriter, &writer->blockData[cidx]);
+ TSDB_CHECK_CODE(code, lino, _exit);
+ } else {
+ code = tsdbDataFileWriteBlockData(writer->dataWriter, &writer->blockData[cidx]);
+ TSDB_CHECK_CODE(code, lino, _exit);
+ }
+ }
+
+ for (int32_t i = 0; i < ARRAY_SIZE(writer->blockData); i++) {
+ tBlockDataReset(&writer->blockData[i]);
+ }
+
+_exit:
+ if (code) {
+ TSDB_ERROR_LOG(TD_VID(writer->config->tsdb->pVnode), lino, code);
+ }
+ return code;
+}
+
+int32_t tsdbFSetWriterOpen(SFSetWriterConfig *config, SFSetWriter **writer) {
+ int32_t code = 0;
+ int32_t lino = 0;
+
+ writer[0] = taosMemoryCalloc(1, sizeof(*writer[0]));
+ if (writer[0] == NULL) return TSDB_CODE_OUT_OF_MEMORY;
+
+ writer[0]->config[0] = config[0];
+
+ // data writer
+ if (!config->toSttOnly) {
+ SDataFileWriterConfig dataWriterConfig = {
+ .tsdb = config->tsdb,
+ .cmprAlg = config->cmprAlg,
+ .maxRow = config->maxRow,
+ .szPage = config->szPage,
+ .fid = config->fid,
+ .cid = config->cid,
+ .did = config->did,
+ .compactVersion = config->compactVersion,
+ .skmTb = writer[0]->skmTb,
+ .skmRow = writer[0]->skmRow,
+ .bufArr = writer[0]->bufArr,
+ };
+ for (int32_t ftype = 0; ftype < TSDB_FTYPE_MAX; ++ftype) {
+ dataWriterConfig.files[ftype].exist = config->files[ftype].exist;
+ dataWriterConfig.files[ftype].file = config->files[ftype].file;
+ }
+
+ code = tsdbDataFileWriterOpen(&dataWriterConfig, &writer[0]->dataWriter);
+ TSDB_CHECK_CODE(code, lino, _exit);
+ }
+
+ // stt writer
+ SSttFileWriterConfig sttWriterConfig = {
+ .tsdb = config->tsdb,
+ .maxRow = config->maxRow,
+ .szPage = config->szPage,
+ .cmprAlg = config->cmprAlg,
+ .compactVersion = config->compactVersion,
+ .did = config->did,
+ .fid = config->fid,
+ .cid = config->cid,
+ .level = config->level,
+ .skmTb = writer[0]->skmTb,
+ .skmRow = writer[0]->skmRow,
+ .bufArr = writer[0]->bufArr,
+ };
+ code = tsdbSttFileWriterOpen(&sttWriterConfig, &writer[0]->sttWriter);
+ TSDB_CHECK_CODE(code, lino, _exit);
+
+_exit:
+ if (code) {
+ TSDB_ERROR_LOG(TD_VID(config->tsdb->pVnode), lino, code);
+ }
+ return code;
+}
+
+int32_t tsdbFSetWriterClose(SFSetWriter **writer, bool abort, TFileOpArray *fopArr) {
+ if (writer[0] == NULL) return 0;
+
+ int32_t code = 0;
+ int32_t lino = 0;
+
+ STsdb *tsdb = writer[0]->config->tsdb;
+
+ // end
+ if (!writer[0]->config->toSttOnly) {
+ code = tsdbDataFileWriterClose(&writer[0]->dataWriter, abort, fopArr);
+ TSDB_CHECK_CODE(code, lino, _exit);
+ }
+
+ code = tsdbSttFileWriterClose(&writer[0]->sttWriter, abort, fopArr);
+ TSDB_CHECK_CODE(code, lino, _exit);
+
+ // free
+ for (int32_t i = 0; i < ARRAY_SIZE(writer[0]->blockData); i++) {
+ tBlockDataDestroy(&writer[0]->blockData[i]);
+ }
+ for (int32_t i = 0; i < ARRAY_SIZE(writer[0]->bufArr); i++) {
+ tFree(writer[0]->bufArr[i]);
+ }
+ tDestroyTSchema(writer[0]->skmRow->pTSchema);
+ tDestroyTSchema(writer[0]->skmTb->pTSchema);
+ taosMemoryFree(writer[0]);
+ writer[0] = NULL;
+
+_exit:
+ if (code) {
+ TSDB_ERROR_LOG(TD_VID(tsdb->pVnode), lino, code);
+ }
+ return code;
+}
+
+int32_t tsdbFSetWriteRow(SFSetWriter *writer, SRowInfo *row) {
+ int32_t code = 0;
+ int32_t lino = 0;
+
+ if (writer->config->toSttOnly) {
+ code = tsdbSttFileWriteRow(writer->sttWriter, row);
+ TSDB_CHECK_CODE(code, lino, _exit);
+ } else {
+ if (writer->ctx->tbid->uid != row->uid) {
+ code = tsdbFSetWriteTableDataEnd(writer);
+ TSDB_CHECK_CODE(code, lino, _exit);
+
+ code = tsdbFSetWriteTableDataBegin(writer, (TABLEID *)row);
+ TSDB_CHECK_CODE(code, lino, _exit);
+ }
+
+ if (row->row.type == TSDBROW_ROW_FMT) {
+ code = tsdbUpdateSkmRow(writer->config->tsdb, writer->ctx->tbid, TSDBROW_SVERSION(&row->row), writer->skmRow);
+ TSDB_CHECK_CODE(code, lino, _exit);
+ }
+
+ TSDBKEY key = TSDBROW_KEY(&row->row);
+ if (key.version <= writer->config->compactVersion //
+ && writer->blockData[writer->blockDataIdx].nRow > 0 //
+ && key.ts == writer->blockData[writer->blockDataIdx].aTSKEY[writer->blockData[writer->blockDataIdx].nRow - 1]) {
+ code = tBlockDataUpdateRow(&writer->blockData[writer->blockDataIdx], &row->row, writer->skmRow->pTSchema);
+ TSDB_CHECK_CODE(code, lino, _exit);
+ } else {
+ if (writer->blockData[writer->blockDataIdx].nRow >= writer->config->maxRow) {
+ int32_t idx = ((writer->blockDataIdx + 1) & 1);
+ if (writer->blockData[idx].nRow >= writer->config->maxRow) {
+ code = tsdbDataFileWriteBlockData(writer->dataWriter, &writer->blockData[idx]);
+ TSDB_CHECK_CODE(code, lino, _exit);
+
+ tBlockDataClear(&writer->blockData[idx]);
+ }
+ writer->blockDataIdx = idx;
+ }
+
+ code =
+ tBlockDataAppendRow(&writer->blockData[writer->blockDataIdx], &row->row, writer->skmRow->pTSchema, row->uid);
+ TSDB_CHECK_CODE(code, lino, _exit);
+ }
+ }
+
+_exit:
+ if (code) {
+ TSDB_ERROR_LOG(TD_VID(writer->config->tsdb->pVnode), lino, code);
+ }
+ return code;
+}
+
+int32_t tsdbFSetWriteTombRecord(SFSetWriter *writer, const STombRecord *tombRecord) {
+ int32_t code = 0;
+ int32_t lino = 0;
+
+ if (writer->config->toSttOnly || tsdbSttFileWriterIsOpened(writer->sttWriter)) {
+ code = tsdbSttFileWriteTombRecord(writer->sttWriter, tombRecord);
+ TSDB_CHECK_CODE(code, lino, _exit);
+ } else {
+ code = tsdbDataFileWriteTombRecord(writer->dataWriter, tombRecord);
+ TSDB_CHECK_CODE(code, lino, _exit);
+ }
+
+_exit:
+ if (code) {
+ TSDB_ERROR_LOG(TD_VID(writer->config->tsdb->pVnode), lino, code);
+ }
+ return code;
+}
\ No newline at end of file
diff --git a/source/dnode/vnode/src/tsdb/tsdbFSetRW.h b/source/dnode/vnode/src/tsdb/tsdbFSetRW.h
new file mode 100644
index 0000000000..b5710407cf
--- /dev/null
+++ b/source/dnode/vnode/src/tsdb/tsdbFSetRW.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2019 TAOS Data, Inc.
+ *
+ * This program is free software: you can use, redistribute, and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3
+ * or later ("AGPL"), as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+#include "tsdbDataFileRW.h"
+#include "tsdbSttFileRW.h"
+
+#ifndef _TSDB_FSET_RW_H
+#define _TSDB_FSET_RW_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//
+typedef struct SFSetWriter SFSetWriter;
+typedef struct {
+ STsdb *tsdb;
+ bool toSttOnly;
+ int64_t compactVersion;
+ int32_t minRow;
+ int32_t maxRow;
+ int32_t szPage;
+ int8_t cmprAlg;
+ int32_t fid;
+ int64_t cid;
+ SDiskID did;
+ int32_t level;
+ struct {
+ bool exist;
+ STFile file;
+ } files[TSDB_FTYPE_MAX];
+} SFSetWriterConfig;
+
+int32_t tsdbFSetWriterOpen(SFSetWriterConfig *config, SFSetWriter **writer);
+int32_t tsdbFSetWriterClose(SFSetWriter **writer, bool abort, TFileOpArray *fopArr);
+int32_t tsdbFSetWriteRow(SFSetWriter *writer, SRowInfo *row);
+int32_t tsdbFSetWriteTombRecord(SFSetWriter *writer, const STombRecord *tombRecord);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*_TSDB_FSET_RW_H*/
\ No newline at end of file
diff --git a/source/dnode/vnode/src/tsdb/tsdbMerge.c b/source/dnode/vnode/src/tsdb/tsdbMerge.c
index f3a599b7a0..97229714e8 100644
--- a/source/dnode/vnode/src/tsdb/tsdbMerge.c
+++ b/source/dnode/vnode/src/tsdb/tsdbMerge.c
@@ -19,15 +19,13 @@ typedef struct {
STsdb *tsdb;
TFileSetArray *fsetArr;
- int32_t sttTrigger;
- int32_t maxRow;
- int32_t minRow;
- int32_t szPage;
- int8_t cmprAlg;
- int64_t compactVersion;
- int64_t cid;
- SSkmInfo skmTb[1];
- SSkmInfo skmRow[1];
+ int32_t sttTrigger;
+ int32_t maxRow;
+ int32_t minRow;
+ int32_t szPage;
+ int8_t cmprAlg;
+ int64_t compactVersion;
+ int64_t cid;
// context
struct {
@@ -37,10 +35,7 @@ typedef struct {
bool toData;
int32_t level;
SSttLvl *lvl;
- // STFileObj *fobj;
TABLEID tbid[1];
- int32_t blockDataIdx;
- SBlockData blockData[2];
} ctx[1];
TFileOpArray fopArr[1];
@@ -53,8 +48,7 @@ typedef struct {
TTsdbIterArray tombIterArr[1];
SIterMerger *tombIterMerger;
// writer
- SSttFileWriter *sttWriter;
- SDataFileWriter *dataWriter;
+ SFSetWriter *writer;
} SMerger;
static int32_t tsdbMergerOpen(SMerger *merger) {
@@ -86,8 +80,7 @@ static int32_t tsdbMergerClose(SMerger *merger) {
}
taosThreadRwlockUnlock(&merger->tsdb->rwLock);
- ASSERT(merger->dataWriter == NULL);
- ASSERT(merger->sttWriter == NULL);
+ ASSERT(merger->writer == NULL);
ASSERT(merger->dataIterMerger == NULL);
ASSERT(TARRAY2_SIZE(merger->dataIterArr) == 0);
ASSERT(TARRAY2_SIZE(merger->sttReaderArr) == 0);
@@ -96,11 +89,6 @@ static int32_t tsdbMergerClose(SMerger *merger) {
TARRAY2_DESTROY(merger->dataIterArr, NULL);
TARRAY2_DESTROY(merger->sttReaderArr, NULL);
TARRAY2_DESTROY(merger->fopArr, NULL);
- for (int32_t i = 0; i < ARRAY_SIZE(merger->ctx->blockData); i++) {
- tBlockDataDestroy(merger->ctx->blockData + i);
- }
- tDestroyTSchema(merger->skmTb->pTSchema);
- tDestroyTSchema(merger->skmRow->pTSchema);
_exit:
if (code) {
@@ -109,6 +97,7 @@ _exit:
return code;
}
+#if 0
static int32_t tsdbMergeToDataTableEnd(SMerger *merger) {
if (merger->ctx->blockData[0].nRow + merger->ctx->blockData[1].nRow == 0) return 0;
@@ -297,6 +286,7 @@ _exit:
}
return code;
}
+#endif
static int32_t tsdbMergeFileSetBeginOpenReader(SMerger *merger) {
int32_t code = 0;
@@ -413,56 +403,36 @@ static int32_t tsdbMergeFileSetBeginOpenWriter(SMerger *merger) {
code = TSDB_CODE_FS_NO_VALID_DISK;
TSDB_CHECK_CODE(code, lino, _exit);
}
-
- {
- // to new level
- SSttFileWriterConfig config[1] = {{
- .tsdb = merger->tsdb,
- .maxRow = merger->maxRow,
- .szPage = merger->szPage,
- .cmprAlg = merger->cmprAlg,
- .compactVersion = merger->compactVersion,
- .file =
- {
- .type = TSDB_FTYPE_STT,
- .did = did,
- .fid = merger->ctx->fset->fid,
- .cid = merger->cid,
- .size = 0,
- .stt = {{
- .level = merger->ctx->level,
- }},
- },
- }};
- code = tsdbSttFileWriterOpen(config, &merger->sttWriter);
- TSDB_CHECK_CODE(code, lino, _exit);
- }
+ SFSetWriterConfig config = {
+ .tsdb = merger->tsdb,
+ .toSttOnly = true,
+ .compactVersion = merger->compactVersion,
+ .minRow = merger->minRow,
+ .maxRow = merger->maxRow,
+ .szPage = merger->szPage,
+ .cmprAlg = merger->cmprAlg,
+ .fid = merger->ctx->fset->fid,
+ .cid = merger->cid,
+ .did = did,
+ .level = merger->ctx->level,
+ };
if (merger->ctx->toData) {
- SDataFileWriterConfig config[1] = {{
- .tsdb = merger->tsdb,
- .cmprAlg = merger->cmprAlg,
- .maxRow = merger->maxRow,
- .szPage = merger->szPage,
- .fid = merger->ctx->fset->fid,
- .cid = merger->cid,
- .did = did,
- .compactVersion = merger->compactVersion,
- }};
+ config.toSttOnly = false;
- for (int32_t i = 0; i < TSDB_FTYPE_MAX; i++) {
- if (merger->ctx->fset->farr[i]) {
- config->files[i].exist = true;
- config->files[i].file = merger->ctx->fset->farr[i]->f[0];
+ for (int32_t ftype = 0; ftype < TSDB_FTYPE_MAX; ++ftype) {
+ if (merger->ctx->fset->farr[ftype]) {
+ config.files[ftype].exist = true;
+ config.files[ftype].file = merger->ctx->fset->farr[ftype]->f[0];
} else {
- config->files[i].exist = false;
+ config.files[ftype].exist = false;
}
}
-
- code = tsdbDataFileWriterOpen(config, &merger->dataWriter);
- TSDB_CHECK_CODE(code, lino, _exit);
}
+ code = tsdbFSetWriterOpen(&config, &merger->writer);
+ TSDB_CHECK_CODE(code, lino, _exit);
+
_exit:
if (code) {
TSDB_ERROR_LOG(vid, lino, code);
@@ -477,15 +447,10 @@ static int32_t tsdbMergeFileSetBegin(SMerger *merger) {
ASSERT(TARRAY2_SIZE(merger->sttReaderArr) == 0);
ASSERT(TARRAY2_SIZE(merger->dataIterArr) == 0);
ASSERT(merger->dataIterMerger == NULL);
- ASSERT(merger->sttWriter == NULL);
- ASSERT(merger->dataWriter == NULL);
+ ASSERT(merger->writer == NULL);
merger->ctx->tbid->suid = 0;
merger->ctx->tbid->uid = 0;
- merger->ctx->blockDataIdx = 0;
- for (int32_t i = 0; i < ARRAY_SIZE(merger->ctx->blockData); ++i) {
- tBlockDataReset(merger->ctx->blockData + i);
- }
// open reader
code = tsdbMergeFileSetBeginOpenReader(merger);
@@ -507,23 +472,7 @@ _exit:
}
static int32_t tsdbMergeFileSetEndCloseWriter(SMerger *merger) {
- int32_t code = 0;
- int32_t lino = 0;
- int32_t vid = TD_VID(merger->tsdb->pVnode);
-
- code = tsdbSttFileWriterClose(&merger->sttWriter, 0, merger->fopArr);
- TSDB_CHECK_CODE(code, lino, _exit);
-
- if (merger->ctx->toData) {
- code = tsdbDataFileWriterClose(&merger->dataWriter, 0, merger->fopArr);
- TSDB_CHECK_CODE(code, lino, _exit);
- }
-
-_exit:
- if (code) {
- TSDB_ERROR_LOG(vid, lino, code);
- }
- return code;
+ return tsdbFSetWriterClose(&merger->writer, 0, merger->fopArr);
}
static int32_t tsdbMergeFileSetEndCloseIter(SMerger *merger) {
@@ -567,12 +516,49 @@ static int32_t tsdbMergeFileSet(SMerger *merger, STFileSet *fset) {
code = tsdbMergeFileSetBegin(merger);
TSDB_CHECK_CODE(code, lino, _exit);
- // do merge
- if (merger->ctx->toData) {
- code = tsdbMergeToDataLevel(merger);
+ // data
+ SMetaInfo info;
+ SRowInfo *row;
+ merger->ctx->tbid->suid = 0;
+ merger->ctx->tbid->uid = 0;
+ while ((row = tsdbIterMergerGetData(merger->dataIterMerger)) != NULL) {
+ if (row->uid != merger->ctx->tbid->uid) {
+ if (metaGetInfo(merger->tsdb->pVnode->pMeta, row->uid, &info, NULL) != 0) {
+ code = tsdbIterMergerSkipTableData(merger->dataIterMerger, (TABLEID *)row);
+ TSDB_CHECK_CODE(code, lino, _exit);
+ continue;
+ }
+
+ merger->ctx->tbid->uid = row->uid;
+ merger->ctx->tbid->suid = row->suid;
+ }
+
+ code = tsdbFSetWriteRow(merger->writer, row);
TSDB_CHECK_CODE(code, lino, _exit);
- } else {
- code = tsdbMergeToUpperLevel(merger);
+
+ code = tsdbIterMergerNext(merger->dataIterMerger);
+ TSDB_CHECK_CODE(code, lino, _exit);
+ }
+
+ // tomb
+ STombRecord *record;
+ merger->ctx->tbid->suid = 0;
+ merger->ctx->tbid->uid = 0;
+ while ((record = tsdbIterMergerGetTombRecord(merger->tombIterMerger)) != NULL) {
+ if (record->uid != merger->ctx->tbid->uid) {
+ merger->ctx->tbid->uid = record->uid;
+ merger->ctx->tbid->suid = record->suid;
+
+ if (metaGetInfo(merger->tsdb->pVnode->pMeta, record->uid, &info, NULL) != 0) {
+ code = tsdbIterMergerSkipTableData(merger->tombIterMerger, merger->ctx->tbid);
+ TSDB_CHECK_CODE(code, lino, _exit);
+ continue;
+ }
+ }
+ code = tsdbFSetWriteTombRecord(merger->writer, record);
+ TSDB_CHECK_CODE(code, lino, _exit);
+
+ code = tsdbIterMergerNext(merger->tombIterMerger);
TSDB_CHECK_CODE(code, lino, _exit);
}
diff --git a/source/dnode/vnode/src/tsdb/tsdbMerge.h b/source/dnode/vnode/src/tsdb/tsdbMerge.h
index e4c7aef614..69d802fd27 100644
--- a/source/dnode/vnode/src/tsdb/tsdbMerge.h
+++ b/source/dnode/vnode/src/tsdb/tsdbMerge.h
@@ -15,6 +15,7 @@
#include "tsdbDataFileRW.h"
#include "tsdbFS2.h"
+#include "tsdbFSetRW.h"
#include "tsdbIter.h"
#include "tsdbSttFileRW.h"
#include "tsdbUtil2.h"
diff --git a/source/dnode/vnode/src/tsdb/tsdbRetention.c b/source/dnode/vnode/src/tsdb/tsdbRetention.c
index 7c7e1bd0f7..a6b72e38bd 100644
--- a/source/dnode/vnode/src/tsdb/tsdbRetention.c
+++ b/source/dnode/vnode/src/tsdb/tsdbRetention.c
@@ -14,6 +14,7 @@
*/
#include "tsdb.h"
+#include "tsdbFS2.h"
static bool tsdbShouldDoRetentionImpl(STsdb *pTsdb, int64_t now) {
for (int32_t iSet = 0; iSet < taosArrayGetSize(pTsdb->fs.aDFileSet); iSet++) {
@@ -111,4 +112,238 @@ int32_t tsdbCommitRetention(STsdb *pTsdb) {
taosThreadRwlockUnlock(&pTsdb->rwLock);
tsdbInfo("vgId:%d %s done", TD_VID(pTsdb->pVnode), __func__);
return 0;
-}
\ No newline at end of file
+}
+
+// new ==============
+typedef struct {
+ STsdb *tsdb;
+ int32_t szPage;
+ int64_t now;
+ int64_t cid;
+
+ TFileSetArray *fsetArr;
+ TFileOpArray *fopArr;
+
+ struct {
+ int32_t fsetArrIdx;
+ STFileSet *fset;
+ } ctx[1];
+} SRTXer;
+
+static int32_t tsdbDoRemoveFileObject(SRTXer *rtxer, const STFileObj *fobj) {
+ STFileOp op = {
+ .optype = TSDB_FOP_REMOVE,
+ .fid = fobj->f->fid,
+ .of = fobj->f[0],
+ };
+
+ return TARRAY2_APPEND(rtxer->fopArr, op);
+}
+
+static int32_t tsdbDoCopyFile(SRTXer *rtxer, const STFileObj *from, const STFile *to) {
+ int32_t code = 0;
+ int32_t lino = 0;
+
+ char fname[TSDB_FILENAME_LEN];
+ TdFilePtr fdFrom = NULL;
+ TdFilePtr fdTo = NULL;
+
+ tsdbTFileName(rtxer->tsdb, to, fname);
+
+ fdFrom = taosOpenFile(from->fname, TD_FILE_READ);
+ if (fdFrom == NULL) code = terrno;
+ TSDB_CHECK_CODE(code, lino, _exit);
+
+ fdTo = taosOpenFile(fname, TD_FILE_WRITE | TD_FILE_CREATE | TD_FILE_TRUNC);
+ if (fdTo == NULL) code = terrno;
+ TSDB_CHECK_CODE(code, lino, _exit);
+
+ int64_t n = taosFSendFile(fdTo, fdFrom, 0, tsdbLogicToFileSize(from->f->size, rtxer->szPage));
+ if (n < 0) {
+ code = TAOS_SYSTEM_ERROR(errno);
+ TSDB_CHECK_CODE(code, lino, _exit);
+ }
+ taosCloseFile(&fdFrom);
+ taosCloseFile(&fdTo);
+
+_exit:
+ if (code) {
+ TSDB_ERROR_LOG(TD_VID(rtxer->tsdb->pVnode), lino, code);
+ taosCloseFile(&fdFrom);
+ taosCloseFile(&fdTo);
+ }
+ return code;
+}
+
+static int32_t tsdbDoMigrateFileObj(SRTXer *rtxer, const STFileObj *fobj, const SDiskID *did) {
+ int32_t code = 0;
+ int32_t lino = 0;
+ STFileOp op = {0};
+
+ // remove old
+ op = (STFileOp){
+ .optype = TSDB_FOP_REMOVE,
+ .fid = fobj->f->fid,
+ .of = fobj->f[0],
+ };
+
+ code = TARRAY2_APPEND(rtxer->fopArr, op);
+ TSDB_CHECK_CODE(code, lino, _exit);
+
+ // create new
+ op = (STFileOp){
+ .optype = TSDB_FOP_CREATE,
+ .fid = fobj->f->fid,
+ .nf =
+ {
+ .type = fobj->f->type,
+ .did = did[0],
+ .fid = fobj->f->fid,
+ .cid = rtxer->cid,
+ .size = fobj->f->size,
+ .stt[0] =
+ {
+ .level = fobj->f->stt[0].level,
+ },
+ },
+ };
+
+ code = TARRAY2_APPEND(rtxer->fopArr, op);
+ TSDB_CHECK_CODE(code, lino, _exit);
+
+ // do copy the file
+ code = tsdbDoCopyFile(rtxer, fobj, &op.nf);
+ TSDB_CHECK_CODE(code, lino, _exit);
+
+_exit:
+ if (code) {
+ TSDB_ERROR_LOG(TD_VID(rtxer->tsdb->pVnode), lino, code);
+ }
+ return code;
+}
+
+static int32_t tsdbDoRetentionBegin(STsdb *tsdb, SRTXer *rtxer) {
+ int32_t code = 0;
+ int32_t lino = 0;
+
+ // TODO: wait for merge and compact task done
+
+ rtxer->tsdb = tsdb;
+ rtxer->szPage = tsdb->pVnode->config.tsdbPageSize;
+ rtxer->now = taosGetTimestampMs();
+ rtxer->cid = tsdbFSAllocEid(tsdb->pFS);
+
+ code = tsdbFSCreateCopySnapshot(tsdb->pFS, &rtxer->fsetArr);
+ TSDB_CHECK_CODE(code, lino, _exit);
+
+_exit:
+ if (code) {
+ TSDB_ERROR_LOG(TD_VID(rtxer->tsdb->pVnode), lino, code);
+ } else {
+ tsdbInfo("vid:%d, cid:%" PRId64 ", %s done", TD_VID(rtxer->tsdb->pVnode), rtxer->cid, __func__);
+ }
+ return code;
+}
+
+static int32_t tsdbDoRetentionEnd(SRTXer *rtxer) {
+ int32_t code = 0;
+ int32_t lino = 0;
+
+ if (TARRAY2_SIZE(rtxer->fopArr) == 0) goto _exit;
+
+ code = tsdbFSEditBegin(rtxer->tsdb->pFS, rtxer->fopArr, TSDB_FEDIT_MERGE);
+ TSDB_CHECK_CODE(code, lino, _exit);
+
+ taosThreadRwlockWrlock(&rtxer->tsdb->rwLock);
+
+ code = tsdbFSEditCommit(rtxer->tsdb->pFS);
+ if (code) {
+ taosThreadRwlockUnlock(&rtxer->tsdb->rwLock);
+ TSDB_CHECK_CODE(code, lino, _exit);
+ }
+
+ taosThreadRwlockUnlock(&rtxer->tsdb->rwLock);
+
+ TARRAY2_DESTROY(rtxer->fopArr, NULL);
+ tsdbFSDestroyCopySnapshot(&rtxer->fsetArr);
+
+_exit:
+ if (code) {
+ TSDB_ERROR_LOG(TD_VID(rtxer->tsdb->pVnode), lino, code);
+ } else {
+ tsdbInfo("vid:%d, cid:%" PRId64 ", %s done", TD_VID(rtxer->tsdb->pVnode), rtxer->cid, __func__);
+ }
+ return code;
+}
+
+static int32_t tsdbDoRetention2(STsdb *tsdb) {
+ int32_t code = 0;
+ int32_t lino = 0;
+
+ SRTXer rtxer[1] = {0};
+
+ code = tsdbDoRetentionBegin(tsdb, rtxer);
+ TSDB_CHECK_CODE(code, lino, _exit);
+
+ while (rtxer->ctx->fsetArrIdx < TARRAY2_SIZE(rtxer->fsetArr)) {
+ rtxer->ctx->fset = TARRAY2_GET(rtxer->fsetArr, rtxer->ctx->fsetArrIdx);
+
+ STFileObj *fobj;
+ int32_t expLevel = tsdbFidLevel(rtxer->ctx->fset->fid, &rtxer->tsdb->keepCfg, rtxer->now);
+
+ if (expLevel < 0) { // remove the file set
+ for (int32_t ftype = 0; (ftype < TSDB_FTYPE_MAX) && (fobj = rtxer->ctx->fset->farr[ftype], 1); ++ftype) {
+ if (fobj == NULL) continue;
+
+ code = tsdbDoRemoveFileObject(rtxer, fobj);
+ TSDB_CHECK_CODE(code, lino, _exit);
+ }
+
+ SSttLvl *lvl;
+ TARRAY2_FOREACH(rtxer->ctx->fset->lvlArr, lvl) {
+ TARRAY2_FOREACH(lvl->fobjArr, fobj) {
+ code = tsdbDoRemoveFileObject(rtxer, fobj);
+ TSDB_CHECK_CODE(code, lino, _exit);
+ }
+ }
+ } else if (expLevel == 0) {
+ continue;
+ } else {
+ SDiskID did;
+
+ if (tfsAllocDisk(rtxer->tsdb->pVnode->pTfs, expLevel, &did) < 0) {
+ code = terrno;
+ TSDB_CHECK_CODE(code, lino, _exit);
+ }
+
+ // data
+ for (int32_t ftype = 0; ftype < TSDB_FTYPE_MAX && (fobj = rtxer->ctx->fset->farr[ftype], 1); ++ftype) {
+ if (fobj == NULL) continue;
+
+ if (fobj->f->did.level == did.level) continue;
+ code = tsdbDoMigrateFileObj(rtxer, fobj, &did);
+ TSDB_CHECK_CODE(code, lino, _exit);
+ }
+
+ // stt
+ SSttLvl *lvl;
+ TARRAY2_FOREACH(rtxer->ctx->fset->lvlArr, lvl) {
+ TARRAY2_FOREACH(lvl->fobjArr, fobj) {
+ if (fobj->f->did.level == did.level) continue;
+
+ code = tsdbDoMigrateFileObj(rtxer, fobj, &did);
+ TSDB_CHECK_CODE(code, lino, _exit);
+ }
+ }
+ }
+ }
+
+ code = tsdbDoRetentionEnd(rtxer);
+ TSDB_CHECK_CODE(code, lino, _exit);
+
+_exit:
+ if (code) {
+ TSDB_ERROR_LOG(TD_VID(rtxer->tsdb->pVnode), lino, code);
+ }
+ return code;
+}
diff --git a/source/dnode/vnode/src/tsdb/tsdbSnapshot.c b/source/dnode/vnode/src/tsdb/tsdbSnapshot.c
index b5ca716701..678a1f502e 100644
--- a/source/dnode/vnode/src/tsdb/tsdbSnapshot.c
+++ b/source/dnode/vnode/src/tsdb/tsdbSnapshot.c
@@ -14,6 +14,11 @@
*/
#include "tsdb.h"
+#include "tsdbDataFileRW.h"
+#include "tsdbFS2.h"
+#include "tsdbFSetRW.h"
+#include "tsdbIter.h"
+#include "tsdbSttFileRW.h"
extern int32_t tsdbUpdateTableSchema(SMeta* pMeta, int64_t suid, int64_t uid, SSkmInfo* pSkmInfo);
extern int32_t tsdbWriteDataBlock(SDataFWriter* pWriter, SBlockData* pBlockData, SMapData* mDataBlk, int8_t cmprAlg);
@@ -21,546 +26,484 @@ extern int32_t tsdbWriteSttBlock(SDataFWriter* pWriter, SBlockData* pBlockData,
// STsdbSnapReader ========================================
struct STsdbSnapReader {
- STsdb* pTsdb;
- int64_t sver;
- int64_t ever;
- int8_t type;
+ STsdb* tsdb;
+ int64_t sver;
+ int64_t ever;
+ int8_t type;
+
uint8_t* aBuf[5];
+ SSkmInfo skmTb[1];
- STsdbFS fs;
- TABLEID tbid;
- SSkmInfo skmTable;
+ TFileSetArray* fsetArr;
- // timeseries data
- int8_t dataDone;
- int32_t fid;
+ // context
+ struct {
+ int32_t fsetArrIdx;
+ STFileSet* fset;
+ bool isDataDone;
+ bool isTombDone;
+ } ctx[1];
- SDataFReader* pDataFReader;
- STsdbDataIter2* iterList;
- STsdbDataIter2* pIter;
- SRBTree rbt;
- SBlockData bData;
+ // reader
+ SDataFileReader* dataReader;
+ TSttFileReaderArray sttReaderArr[1];
- // tombstone data
- int8_t delDone;
- SDelFReader* pDelFReader;
- STsdbDataIter2* pTIter;
- SArray* aDelData;
+ // iter
+ TTsdbIterArray dataIterArr[1];
+ SIterMerger* dataIterMerger;
+ TTsdbIterArray tombIterArr[1];
+ SIterMerger* tombIterMerger;
+
+ // data
+ SBlockData blockData[1];
+ STombBlock tombBlock[1];
};
-static int32_t tsdbSnapReadFileDataStart(STsdbSnapReader* pReader) {
+static int32_t tsdbSnapReadFileSetOpenReader(STsdbSnapReader* reader) {
int32_t code = 0;
int32_t lino = 0;
- SDFileSet* pSet = taosArraySearch(pReader->fs.aDFileSet, &(SDFileSet){.fid = pReader->fid}, tDFileSetCmprFn, TD_GT);
- if (pSet == NULL) {
- pReader->fid = INT32_MAX;
- goto _exit;
- }
+ ASSERT(reader->dataReader == NULL);
+ ASSERT(TARRAY2_SIZE(reader->sttReaderArr) == 0);
- pReader->fid = pSet->fid;
-
- tRBTreeCreate(&pReader->rbt, tsdbDataIterCmprFn);
-
- code = tsdbDataFReaderOpen(&pReader->pDataFReader, pReader->pTsdb, pSet);
- TSDB_CHECK_CODE(code, lino, _exit);
-
- code = tsdbOpenDataFileDataIter(pReader->pDataFReader, &pReader->pIter);
- TSDB_CHECK_CODE(code, lino, _exit);
-
- if (pReader->pIter) {
- // iter to next with filter info (sver, ever)
- code = tsdbDataIterNext2(
- pReader->pIter,
- &(STsdbFilterInfo){.flag = TSDB_FILTER_FLAG_BY_VERSION | TSDB_FILTER_FLAG_IGNORE_DROPPED_TABLE, // flag
- .sver = pReader->sver,
- .ever = pReader->ever});
- TSDB_CHECK_CODE(code, lino, _exit);
-
- if (pReader->pIter->rowInfo.suid || pReader->pIter->rowInfo.uid) {
- // add to rbtree
- tRBTreePut(&pReader->rbt, &pReader->pIter->rbtn);
-
- // add to iterList
- pReader->pIter->next = pReader->iterList;
- pReader->iterList = pReader->pIter;
- } else {
- tsdbCloseDataIter2(pReader->pIter);
+ // data
+ SDataFileReaderConfig config = {
+ .tsdb = reader->tsdb,
+ .szPage = reader->tsdb->pVnode->config.tsdbPageSize,
+ .bufArr = reader->aBuf,
+ };
+ bool hasDataFile = false;
+ for (int32_t ftype = 0; ftype < TSDB_FTYPE_MAX; ftype++) {
+ if (reader->ctx->fset->farr[ftype] != NULL) {
+ hasDataFile = true;
+ config.files[ftype].exist = true;
+ config.files[ftype].file = reader->ctx->fset->farr[ftype]->f[0];
}
}
- for (int32_t iStt = 0; iStt < pSet->nSttF; ++iStt) {
- code = tsdbOpenSttFileDataIter(pReader->pDataFReader, iStt, &pReader->pIter);
+ if (hasDataFile) {
+ code = tsdbDataFileReaderOpen(NULL, &config, &reader->dataReader);
TSDB_CHECK_CODE(code, lino, _exit);
+ }
- if (pReader->pIter) {
- // iter to valid row
- code = tsdbDataIterNext2(
- pReader->pIter,
- &(STsdbFilterInfo){.flag = TSDB_FILTER_FLAG_BY_VERSION | TSDB_FILTER_FLAG_IGNORE_DROPPED_TABLE, // flag
- .sver = pReader->sver,
- .ever = pReader->ever});
+ // stt
+ SSttLvl* lvl;
+ TARRAY2_FOREACH(reader->ctx->fset->lvlArr, lvl) {
+ STFileObj* fobj;
+ TARRAY2_FOREACH(lvl->fobjArr, fobj) {
+ SSttFileReader* sttReader;
+ SSttFileReaderConfig config = {
+ .tsdb = reader->tsdb,
+ .szPage = reader->tsdb->pVnode->config.tsdbPageSize,
+ .file = fobj->f[0],
+ .bufArr = reader->aBuf,
+ };
+
+ code = tsdbSttFileReaderOpen(fobj->fname, &config, &sttReader);
TSDB_CHECK_CODE(code, lino, _exit);
- if (pReader->pIter->rowInfo.suid || pReader->pIter->rowInfo.uid) {
- // add to rbtree
- tRBTreePut(&pReader->rbt, &pReader->pIter->rbtn);
-
- // add to iterList
- pReader->pIter->next = pReader->iterList;
- pReader->iterList = pReader->pIter;
- } else {
- tsdbCloseDataIter2(pReader->pIter);
- }
+ code = TARRAY2_APPEND(reader->sttReaderArr, sttReader);
+ TSDB_CHECK_CODE(code, lino, _exit);
}
}
- pReader->pIter = NULL;
-
_exit:
if (code) {
- tsdbError("vgId:%d %s failed at line %d since %s", TD_VID(pReader->pTsdb->pVnode), __func__, lino, tstrerror(code));
- } else {
- tsdbInfo("vgId:%d %s done, fid:%d", TD_VID(pReader->pTsdb->pVnode), __func__, pReader->fid);
+ TSDB_ERROR_LOG(TD_VID(reader->tsdb->pVnode), code, lino);
}
return code;
}
-static void tsdbSnapReadFileDataEnd(STsdbSnapReader* pReader) {
- while (pReader->iterList) {
- STsdbDataIter2* pIter = pReader->iterList;
- pReader->iterList = pIter->next;
- tsdbCloseDataIter2(pIter);
- }
-
- tsdbDataFReaderClose(&pReader->pDataFReader);
-}
-
-static int32_t tsdbSnapReadNextRow(STsdbSnapReader* pReader, SRowInfo** ppRowInfo) {
+static int32_t tsdbSnapReadFileSetCloseReader(STsdbSnapReader* reader) {
int32_t code = 0;
int32_t lino = 0;
- if (pReader->pIter) {
- code = tsdbDataIterNext2(pReader->pIter, &(STsdbFilterInfo){.flag = TSDB_FILTER_FLAG_BY_VERSION |
- TSDB_FILTER_FLAG_IGNORE_DROPPED_TABLE, // flag
- .sver = pReader->sver,
- .ever = pReader->ever});
- TSDB_CHECK_CODE(code, lino, _exit);
-
- if (pReader->pIter->rowInfo.suid == 0 && pReader->pIter->rowInfo.uid == 0) {
- pReader->pIter = NULL;
- } else {
- SRBTreeNode* pNode = tRBTreeMin(&pReader->rbt);
- if (pNode) {
- int32_t c = tsdbDataIterCmprFn(&pReader->pIter->rbtn, pNode);
- if (c > 0) {
- tRBTreePut(&pReader->rbt, &pReader->pIter->rbtn);
- pReader->pIter = NULL;
- } else if (c == 0) {
- ASSERT(0);
- }
- }
- }
- }
-
- if (pReader->pIter == NULL) {
- SRBTreeNode* pNode = tRBTreeMin(&pReader->rbt);
- if (pNode) {
- tRBTreeDrop(&pReader->rbt, pNode);
- pReader->pIter = TSDB_RBTN_TO_DATA_ITER(pNode);
- }
- }
-
- if (ppRowInfo) {
- if (pReader->pIter) {
- *ppRowInfo = &pReader->pIter->rowInfo;
- } else {
- *ppRowInfo = NULL;
- }
- }
+ TARRAY2_CLEAR(reader->sttReaderArr, tsdbSttFileReaderClose);
+ tsdbDataFileReaderClose(&reader->dataReader);
_exit:
if (code) {
- tsdbError("vgId:%d %s failed at line %d since %s", TD_VID(pReader->pTsdb->pVnode), __func__, lino, tstrerror(code));
+ TSDB_ERROR_LOG(TD_VID(reader->tsdb->pVnode), code, lino);
}
return code;
}
-static int32_t tsdbSnapReadGetRow(STsdbSnapReader* pReader, SRowInfo** ppRowInfo) {
- if (pReader->pIter) {
- *ppRowInfo = &pReader->pIter->rowInfo;
- return 0;
+static int32_t tsdbSnapReadFileSetOpenIter(STsdbSnapReader* reader) {
+ int32_t code = 0;
+ int32_t lino = 0;
+
+ ASSERT(reader->dataIterMerger == NULL);
+ ASSERT(reader->tombIterMerger == NULL);
+ ASSERT(TARRAY2_SIZE(reader->dataIterArr) == 0);
+ ASSERT(TARRAY2_SIZE(reader->tombIterArr) == 0);
+
+ STsdbIter* iter;
+ STsdbIterConfig config = {
+ .filterByVersion = true,
+ .verRange[0] = reader->sver,
+ .verRange[1] = reader->ever,
+ };
+
+ // data file
+ if (reader->dataReader) {
+ // data
+ config.type = TSDB_ITER_TYPE_DATA;
+ config.dataReader = reader->dataReader;
+
+ code = tsdbIterOpen(&config, &iter);
+ TSDB_CHECK_CODE(code, lino, _exit);
+
+ code = TARRAY2_APPEND(reader->dataIterArr, iter);
+ TSDB_CHECK_CODE(code, lino, _exit);
+
+ // tomb
+ config.type = TSDB_ITER_TYPE_DATA_TOMB;
+ config.dataReader = reader->dataReader;
+
+ code = tsdbIterOpen(&config, &iter);
+ TSDB_CHECK_CODE(code, lino, _exit);
+
+ code = TARRAY2_APPEND(reader->tombIterArr, iter);
+ TSDB_CHECK_CODE(code, lino, _exit);
}
- return tsdbSnapReadNextRow(pReader, ppRowInfo);
+ // stt file
+ SSttFileReader* sttReader;
+ TARRAY2_FOREACH(reader->sttReaderArr, sttReader) {
+ // data
+ config.type = TSDB_ITER_TYPE_STT;
+ config.sttReader = sttReader;
+
+ code = tsdbIterOpen(&config, &iter);
+ TSDB_CHECK_CODE(code, lino, _exit);
+
+ code = TARRAY2_APPEND(reader->dataIterArr, iter);
+ TSDB_CHECK_CODE(code, lino, _exit);
+
+ // tomb
+ config.type = TSDB_ITER_TYPE_STT_TOMB;
+ config.sttReader = sttReader;
+
+ code = tsdbIterOpen(&config, &iter);
+ TSDB_CHECK_CODE(code, lino, _exit);
+
+ code = TARRAY2_APPEND(reader->tombIterArr, iter);
+ TSDB_CHECK_CODE(code, lino, _exit);
+ }
+
+ // merger
+ code = tsdbIterMergerOpen(reader->dataIterArr, &reader->dataIterMerger, false);
+ TSDB_CHECK_CODE(code, lino, _exit);
+
+ code = tsdbIterMergerOpen(reader->tombIterArr, &reader->dataIterMerger, true);
+ TSDB_CHECK_CODE(code, lino, _exit);
+
+_exit:
+ if (code) {
+ TSDB_ERROR_LOG(TD_VID(reader->tsdb->pVnode), code, lino);
+ }
+ return code;
}
-static int32_t tsdbSnapCmprData(STsdbSnapReader* pReader, uint8_t** ppData) {
- int32_t code = 0;
+static int32_t tsdbSnapReadFileSetCloseIter(STsdbSnapReader* reader) {
+ tsdbIterMergerClose(&reader->dataIterMerger);
+ tsdbIterMergerClose(&reader->tombIterMerger);
+ TARRAY2_CLEAR(reader->dataIterArr, tsdbIterClose);
+ TARRAY2_CLEAR(reader->tombIterArr, tsdbIterClose);
+ return 0;
+}
- ASSERT(pReader->bData.nRow);
+static int32_t tsdbSnapReadFileSetBegin(STsdbSnapReader* reader) {
+ int32_t code = 0;
+ int32_t lino = 0;
+
+ ASSERT(reader->ctx->fset == NULL);
+
+ if (reader->ctx->fsetArrIdx < TARRAY2_SIZE(reader->fsetArr)) {
+ reader->ctx->fset = TARRAY2_GET(reader->fsetArr, reader->ctx->fsetArrIdx++);
+ reader->ctx->isDataDone = false;
+ reader->ctx->isTombDone = false;
+
+ code = tsdbSnapReadFileSetOpenReader(reader);
+ TSDB_CHECK_CODE(code, lino, _exit);
+
+ code = tsdbSnapReadFileSetOpenIter(reader);
+ TSDB_CHECK_CODE(code, lino, _exit);
+ }
+
+_exit:
+ if (code) {
+ TSDB_ERROR_LOG(TD_VID(reader->tsdb->pVnode), code, lino);
+ }
+ return code;
+}
+
+static int32_t tsdbSnapReadFileSetEnd(STsdbSnapReader* reader) {
+ tsdbSnapReadFileSetCloseIter(reader);
+ tsdbSnapReadFileSetCloseReader(reader);
+ reader->ctx->fset = NULL;
+ return 0;
+}
+
+static int32_t tsdbSnapCmprData(STsdbSnapReader* reader, uint8_t** data) {
+ int32_t code = 0;
+ int32_t lino = 0;
int32_t aBufN[5] = {0};
- code = tCmprBlockData(&pReader->bData, NO_COMPRESSION, NULL, NULL, pReader->aBuf, aBufN);
- if (code) goto _exit;
+ code = tCmprBlockData(reader->blockData, NO_COMPRESSION, NULL, NULL, reader->aBuf, aBufN);
+ TSDB_CHECK_CODE(code, lino, _exit);
int32_t size = aBufN[0] + aBufN[1] + aBufN[2] + aBufN[3];
- *ppData = taosMemoryMalloc(sizeof(SSnapDataHdr) + size);
- if (*ppData == NULL) {
+ *data = taosMemoryMalloc(sizeof(SSnapDataHdr) + size);
+ if (*data == NULL) {
code = TSDB_CODE_OUT_OF_MEMORY;
- goto _exit;
+ TSDB_CHECK_CODE(code, lino, _exit);
}
- SSnapDataHdr* pHdr = (SSnapDataHdr*)*ppData;
- pHdr->type = pReader->type;
+ SSnapDataHdr* pHdr = (SSnapDataHdr*)*data;
+ pHdr->type = reader->type;
pHdr->size = size;
- memcpy(pHdr->data, pReader->aBuf[3], aBufN[3]);
- memcpy(pHdr->data + aBufN[3], pReader->aBuf[2], aBufN[2]);
+ memcpy(pHdr->data, reader->aBuf[3], aBufN[3]);
+ memcpy(pHdr->data + aBufN[3], reader->aBuf[2], aBufN[2]);
if (aBufN[1]) {
- memcpy(pHdr->data + aBufN[3] + aBufN[2], pReader->aBuf[1], aBufN[1]);
+ memcpy(pHdr->data + aBufN[3] + aBufN[2], reader->aBuf[1], aBufN[1]);
}
if (aBufN[0]) {
- memcpy(pHdr->data + aBufN[3] + aBufN[2] + aBufN[1], pReader->aBuf[0], aBufN[0]);
+ memcpy(pHdr->data + aBufN[3] + aBufN[2] + aBufN[1], reader->aBuf[0], aBufN[0]);
}
_exit:
+ if (code) {
+ TSDB_ERROR_LOG(TD_VID(reader->tsdb->pVnode), lino, code);
+ }
return code;
}
-static int32_t tsdbSnapReadTimeSeriesData(STsdbSnapReader* pReader, uint8_t** ppData) {
+static int32_t tsdbSnapReadTimeSeriesData(STsdbSnapReader* reader, uint8_t** data) {
int32_t code = 0;
int32_t lino = 0;
- STsdb* pTsdb = pReader->pTsdb;
+ tBlockDataReset(reader->blockData);
- tBlockDataReset(&pReader->bData);
+ for (SRowInfo* row; (row = tsdbIterMergerGetData(reader->dataIterMerger));) {
+ if (reader->blockData->suid == 0 && reader->blockData->uid == 0) {
+ code = tsdbUpdateSkmTb(reader->tsdb, (TABLEID*)row, reader->skmTb);
+ TSDB_CHECK_CODE(code, lino, _exit);
- for (;;) {
- // start a new file read if need
- if (pReader->pDataFReader == NULL) {
- code = tsdbSnapReadFileDataStart(pReader);
+ TABLEID tbid = {
+ .suid = row->suid,
+ .uid = row->suid ? 0 : row->uid,
+ };
+ code = tBlockDataInit(reader->blockData, &tbid, reader->skmTb->pTSchema, NULL, 0);
TSDB_CHECK_CODE(code, lino, _exit);
}
- if (pReader->pDataFReader == NULL) break;
-
- SRowInfo* pRowInfo;
- code = tsdbSnapReadGetRow(pReader, &pRowInfo);
- TSDB_CHECK_CODE(code, lino, _exit);
-
- if (pRowInfo == NULL) {
- tsdbSnapReadFileDataEnd(pReader);
- continue;
+ if (!TABLE_SAME_SCHEMA(reader->blockData->suid, reader->blockData->uid, row->suid, row->uid)) {
+ break;
}
- code = tsdbUpdateTableSchema(pTsdb->pVnode->pMeta, pRowInfo->suid, pRowInfo->uid, &pReader->skmTable);
+ code = tBlockDataAppendRow(reader->blockData, &row->row, NULL, row->uid);
TSDB_CHECK_CODE(code, lino, _exit);
- code = tBlockDataInit(&pReader->bData, (TABLEID*)pRowInfo, pReader->skmTable.pTSchema, NULL, 0);
+ code = tsdbIterMergerNext(reader->dataIterMerger);
TSDB_CHECK_CODE(code, lino, _exit);
- do {
- if (!TABLE_SAME_SCHEMA(pReader->bData.suid, pReader->bData.uid, pRowInfo->suid, pRowInfo->uid)) break;
-
- if (pReader->bData.uid && pReader->bData.uid != pRowInfo->uid) {
- code = tRealloc((uint8_t**)&pReader->bData.aUid, sizeof(int64_t) * (pReader->bData.nRow + 1));
- TSDB_CHECK_CODE(code, lino, _exit);
-
- for (int32_t iRow = 0; iRow < pReader->bData.nRow; ++iRow) {
- pReader->bData.aUid[iRow] = pReader->bData.uid;
- }
- pReader->bData.uid = 0;
- }
-
- code = tBlockDataAppendRow(&pReader->bData, &pRowInfo->row, NULL, pRowInfo->uid);
- TSDB_CHECK_CODE(code, lino, _exit);
-
- code = tsdbSnapReadNextRow(pReader, &pRowInfo);
- TSDB_CHECK_CODE(code, lino, _exit);
-
- if (pReader->bData.nRow >= 81920) break;
- } while (pRowInfo);
-
- ASSERT(pReader->bData.nRow > 0);
-
- break;
+ if (reader->blockData->nRow >= 81920) {
+ break;
+ }
}
- if (pReader->bData.nRow > 0) {
- ASSERT(pReader->bData.suid || pReader->bData.uid);
-
- code = tsdbSnapCmprData(pReader, ppData);
+ if (reader->blockData->nRow > 0) {
+ ASSERT(reader->blockData->suid || reader->blockData->uid);
+ code = tsdbSnapCmprData(reader, data);
TSDB_CHECK_CODE(code, lino, _exit);
}
_exit:
if (code) {
- tsdbError("vgId:%d %s failed at line %d since %s", TD_VID(pTsdb->pVnode), __func__, lino, tstrerror(code));
+ TSDB_ERROR_LOG(TD_VID(reader->tsdb->pVnode), code, lino);
}
return code;
}
-static int32_t tsdbSnapCmprTombData(STsdbSnapReader* pReader, uint8_t** ppData) {
+static int32_t tsdbSnapCmprTombData(STsdbSnapReader* reader, uint8_t** data) {
int32_t code = 0;
int32_t lino = 0;
- int64_t size = sizeof(TABLEID);
- for (int32_t iDelData = 0; iDelData < taosArrayGetSize(pReader->aDelData); ++iDelData) {
- size += tPutDelData(NULL, taosArrayGet(pReader->aDelData, iDelData));
+ int64_t size = sizeof(SSnapDataHdr);
+ for (int32_t i = 0; i < ARRAY_SIZE(reader->tombBlock->dataArr); i++) {
+ size += TARRAY2_DATA_LEN(reader->tombBlock->dataArr + i);
}
- uint8_t* pData = (uint8_t*)taosMemoryMalloc(sizeof(SSnapDataHdr) + size);
- if (pData == NULL) {
+ data[0] = taosMemoryMalloc(size);
+ if (data[0] == NULL) {
code = TSDB_CODE_OUT_OF_MEMORY;
TSDB_CHECK_CODE(code, lino, _exit);
}
- SSnapDataHdr* pHdr = (SSnapDataHdr*)pData;
- pHdr->type = SNAP_DATA_DEL;
- pHdr->size = size;
+ SSnapDataHdr* hdr = (SSnapDataHdr*)data[0];
+ hdr->type = SNAP_DATA_DEL;
+ hdr->size = size;
- TABLEID* pId = (TABLEID*)(pData + sizeof(SSnapDataHdr));
- *pId = pReader->tbid;
-
- size = sizeof(SSnapDataHdr) + sizeof(TABLEID);
- for (int32_t iDelData = 0; iDelData < taosArrayGetSize(pReader->aDelData); ++iDelData) {
- size += tPutDelData(pData + size, taosArrayGet(pReader->aDelData, iDelData));
+ uint8_t* tdata = hdr->data;
+ for (int32_t i = 0; i < TARRAY_SIZE(reader->tombBlock->dataArr); i++) {
+ memcpy(tdata, TARRAY2_DATA(reader->tombBlock->dataArr + i), TARRAY2_DATA_LEN(reader->tombBlock->dataArr + i));
+ tdata += TARRAY2_DATA_LEN(reader->tombBlock->dataArr + i);
}
_exit:
if (code) {
- tsdbError("vgId:%d %s failed at line %d since %s", TD_VID(pReader->pTsdb->pVnode), __func__, lino, tstrerror(code));
- }
- *ppData = pData;
- return code;
-}
-
-static void tsdbSnapReadGetTombData(STsdbSnapReader* pReader, SDelInfo** ppDelInfo) {
- if (pReader->pTIter == NULL || (pReader->pTIter->delInfo.suid == 0 && pReader->pTIter->delInfo.uid == 0)) {
- *ppDelInfo = NULL;
- } else {
- *ppDelInfo = &pReader->pTIter->delInfo;
- }
-}
-
-static int32_t tsdbSnapReadNextTombData(STsdbSnapReader* pReader, SDelInfo** ppDelInfo) {
- int32_t code = 0;
- int32_t lino = 0;
-
- code = tsdbDataIterNext2(
- pReader->pTIter, &(STsdbFilterInfo){.flag = TSDB_FILTER_FLAG_BY_VERSION | TSDB_FILTER_FLAG_IGNORE_DROPPED_TABLE,
- .sver = pReader->sver,
- .ever = pReader->ever});
- TSDB_CHECK_CODE(code, lino, _exit);
-
- if (ppDelInfo) {
- tsdbSnapReadGetTombData(pReader, ppDelInfo);
- }
-
-_exit:
- if (code) {
- tsdbError("vgId:%d %s failed at line %d since %s", TD_VID(pReader->pTsdb->pVnode), __func__, lino, tstrerror(code));
+ TSDB_ERROR_LOG(TD_VID(reader->tsdb->pVnode), code, lino);
}
return code;
}
-static int32_t tsdbSnapReadTombData(STsdbSnapReader* pReader, uint8_t** ppData) {
+static int32_t tsdbSnapReadTombData(STsdbSnapReader* reader, uint8_t** data) {
int32_t code = 0;
int32_t lino = 0;
- STsdb* pTsdb = pReader->pTsdb;
+ tTombBlockClear(reader->tombBlock);
- // open tombstone data iter if need
- if (pReader->pDelFReader == NULL) {
- if (pReader->fs.pDelFile == NULL) goto _exit;
-
- // open
- code = tsdbDelFReaderOpen(&pReader->pDelFReader, pReader->fs.pDelFile, pTsdb);
+ for (STombRecord* record; (record = tsdbIterMergerGetTombRecord(reader->tombIterMerger)) != NULL;) {
+ code = tTombBlockPut(reader->tombBlock, record);
TSDB_CHECK_CODE(code, lino, _exit);
- code = tsdbOpenTombFileDataIter(pReader->pDelFReader, &pReader->pTIter);
- TSDB_CHECK_CODE(code, lino, _exit);
-
- if (pReader->pTIter) {
- code = tsdbSnapReadNextTombData(pReader, NULL);
- TSDB_CHECK_CODE(code, lino, _exit);
+ if (TOMB_BLOCK_SIZE(reader->tombBlock) >= 81920) {
+ break;
}
}
- // loop to get tombstone data
- SDelInfo* pDelInfo;
- tsdbSnapReadGetTombData(pReader, &pDelInfo);
-
- if (pDelInfo == NULL) goto _exit;
-
- pReader->tbid = *(TABLEID*)pDelInfo;
-
- if (pReader->aDelData) {
- taosArrayClear(pReader->aDelData);
- } else if ((pReader->aDelData = taosArrayInit(16, sizeof(SDelData))) == NULL) {
- code = TSDB_CODE_OUT_OF_MEMORY;
- TSDB_CHECK_CODE(code, lino, _exit);
- }
-
- while (pDelInfo && pDelInfo->suid == pReader->tbid.suid && pDelInfo->uid == pReader->tbid.uid) {
- if (taosArrayPush(pReader->aDelData, &pDelInfo->delData) == NULL) {
- code = TSDB_CODE_OUT_OF_MEMORY;
- TSDB_CHECK_CODE(code, lino, _exit);
- }
-
- code = tsdbSnapReadNextTombData(pReader, &pDelInfo);
- TSDB_CHECK_CODE(code, lino, _exit);
- }
-
- // encode tombstone data
- if (taosArrayGetSize(pReader->aDelData) > 0) {
- code = tsdbSnapCmprTombData(pReader, ppData);
+ if (TOMB_BLOCK_SIZE(reader->tombBlock) > 0) {
+ code = tsdbSnapCmprTombData(reader, data);
TSDB_CHECK_CODE(code, lino, _exit);
}
_exit:
if (code) {
- tsdbError("vgId:%d %s failed at line %d since %s", TD_VID(pTsdb->pVnode), __func__, lino, tstrerror(code));
- } else {
- tsdbDebug("vgId:%d %s done", TD_VID(pTsdb->pVnode), __func__);
+ TSDB_ERROR_LOG(TD_VID(reader->tsdb->pVnode), code, lino);
}
return code;
}
-int32_t tsdbSnapReaderOpen(STsdb* pTsdb, int64_t sver, int64_t ever, int8_t type, STsdbSnapReader** ppReader) {
+int32_t tsdbSnapReaderOpen(STsdb* tsdb, int64_t sver, int64_t ever, int8_t type, STsdbSnapReader** reader) {
int32_t code = 0;
int32_t lino = 0;
- // alloc
- STsdbSnapReader* pReader = (STsdbSnapReader*)taosMemoryCalloc(1, sizeof(*pReader));
- if (pReader == NULL) {
- code = TSDB_CODE_OUT_OF_MEMORY;
- TSDB_CHECK_CODE(code, lino, _exit);
- }
- pReader->pTsdb = pTsdb;
- pReader->sver = sver;
- pReader->ever = ever;
- pReader->type = type;
+ reader[0] = (STsdbSnapReader*)taosMemoryCalloc(1, sizeof(*reader[0]));
+ if (reader[0] == NULL) return TSDB_CODE_OUT_OF_MEMORY;
- taosThreadRwlockRdlock(&pTsdb->rwLock);
- code = tsdbFSRef(pTsdb, &pReader->fs);
- if (code) {
- taosThreadRwlockUnlock(&pTsdb->rwLock);
- TSDB_CHECK_CODE(code, lino, _exit);
- }
- taosThreadRwlockUnlock(&pTsdb->rwLock);
+ reader[0]->tsdb = tsdb;
+ reader[0]->sver = sver;
+ reader[0]->ever = ever;
+ reader[0]->type = type;
- // init
- pReader->fid = INT32_MIN;
-
- code = tBlockDataCreate(&pReader->bData);
+ code = tsdbFSCreateRefSnapshot(tsdb->pFS, &reader[0]->fsetArr);
TSDB_CHECK_CODE(code, lino, _exit);
_exit:
if (code) {
- tsdbError("vgId:%d %s failed at line %d since %s, sver:%" PRId64 " ever:%" PRId64 " type:%d", TD_VID(pTsdb->pVnode),
+ tsdbError("vgId:%d %s failed at line %d since %s, sver:%" PRId64 " ever:%" PRId64 " type:%d", TD_VID(tsdb->pVnode),
__func__, lino, tstrerror(code), sver, ever, type);
- if (pReader) {
- tBlockDataDestroy(&pReader->bData);
- tsdbFSUnref(pTsdb, &pReader->fs);
- taosMemoryFree(pReader);
- pReader = NULL;
- }
+ tsdbFSDestroyRefSnapshot(&reader[0]->fsetArr);
+ taosMemoryFree(reader[0]);
+ reader[0] = NULL;
} else {
- tsdbInfo("vgId:%d %s done, sver:%" PRId64 " ever:%" PRId64 " type:%d", TD_VID(pTsdb->pVnode), __func__, sver, ever,
+ tsdbInfo("vgId:%d %s done, sver:%" PRId64 " ever:%" PRId64 " type:%d", TD_VID(tsdb->pVnode), __func__, sver, ever,
type);
}
- *ppReader = pReader;
return code;
}
-int32_t tsdbSnapReaderClose(STsdbSnapReader** ppReader) {
+int32_t tsdbSnapReaderClose(STsdbSnapReader** reader) {
+ if (reader[0] == NULL) return 0;
+
int32_t code = 0;
int32_t lino = 0;
- STsdbSnapReader* pReader = *ppReader;
- STsdb* pTsdb = pReader->pTsdb;
+ STsdb* tsdb = reader[0]->tsdb;
- // tombstone
- if (pReader->pTIter) {
- tsdbCloseDataIter2(pReader->pTIter);
- pReader->pTIter = NULL;
- }
- if (pReader->pDelFReader) {
- tsdbDelFReaderClose(&pReader->pDelFReader);
- }
- taosArrayDestroy(pReader->aDelData);
+ tTombBlockDestroy(reader[0]->tombBlock);
+ tBlockDataDestroy(reader[0]->blockData);
- // timeseries
- while (pReader->iterList) {
- STsdbDataIter2* pIter = pReader->iterList;
- pReader->iterList = pIter->next;
- tsdbCloseDataIter2(pIter);
- }
- if (pReader->pDataFReader) {
- tsdbDataFReaderClose(&pReader->pDataFReader);
- }
- tBlockDataDestroy(&pReader->bData);
+ tsdbIterMergerClose(&reader[0]->dataIterMerger);
+ tsdbIterMergerClose(&reader[0]->tombIterMerger);
+ TARRAY2_DESTROY(reader[0]->dataIterArr, tsdbIterClose);
+ TARRAY2_DESTROY(reader[0]->tombIterArr, tsdbIterClose);
+ TARRAY2_DESTROY(reader[0]->sttReaderArr, tsdbSttFileReaderClose);
+ tsdbDataFileReaderClose(&reader[0]->dataReader);
- // other
- tDestroyTSchema(pReader->skmTable.pTSchema);
- tsdbFSUnref(pReader->pTsdb, &pReader->fs);
- for (int32_t iBuf = 0; iBuf < sizeof(pReader->aBuf) / sizeof(pReader->aBuf[0]); iBuf++) {
- tFree(pReader->aBuf[iBuf]);
+ tsdbFSDestroyRefSnapshot(&reader[0]->fsetArr);
+ tDestroyTSchema(reader[0]->skmTb->pTSchema);
+
+ for (int32_t i = 0; i < ARRAY_SIZE(reader[0]->aBuf);) {
+ tFree(reader[0]->aBuf[i]);
}
- taosMemoryFree(pReader);
+
+ taosMemoryFree(reader[0]);
+ reader[0] = NULL;
_exit:
if (code) {
- tsdbError("vgId:%d %s failed at line %d since %s", TD_VID(pTsdb->pVnode), __func__, lino, tstrerror(code));
+ TSDB_ERROR_LOG(TD_VID(tsdb->pVnode), lino, code);
} else {
- tsdbDebug("vgId:%d %s done", TD_VID(pTsdb->pVnode), __func__);
+ tsdbDebug("vgId:%d %s done", TD_VID(tsdb->pVnode), __func__);
}
- *ppReader = NULL;
return code;
}
-int32_t tsdbSnapRead(STsdbSnapReader* pReader, uint8_t** ppData) {
+int32_t tsdbSnapRead(STsdbSnapReader* reader, uint8_t** data) {
int32_t code = 0;
int32_t lino = 0;
- *ppData = NULL;
+ data[0] = NULL;
- // read data file
- if (!pReader->dataDone) {
- code = tsdbSnapReadTimeSeriesData(pReader, ppData);
- TSDB_CHECK_CODE(code, lino, _exit);
- if (*ppData) {
- goto _exit;
- } else {
- pReader->dataDone = 1;
- }
- }
+ for (;;) {
+ if (reader->ctx->fset == NULL) {
+ code = tsdbSnapReadFileSetBegin(reader);
+ TSDB_CHECK_CODE(code, lino, _exit);
- // read del file
- if (!pReader->delDone) {
- code = tsdbSnapReadTombData(pReader, ppData);
- TSDB_CHECK_CODE(code, lino, _exit);
- if (*ppData) {
- goto _exit;
- } else {
- pReader->delDone = 1;
+ if (reader->ctx->fset == NULL) {
+ break;
+ }
}
+
+ if (!reader->ctx->isDataDone) {
+ code = tsdbSnapReadTimeSeriesData(reader, data);
+ TSDB_CHECK_CODE(code, lino, _exit);
+ if (data[0]) {
+ goto _exit;
+ } else {
+ reader->ctx->isDataDone = true;
+ }
+ }
+
+ if (!reader->ctx->isTombDone) {
+ code = tsdbSnapReadTombData(reader, data);
+ TSDB_CHECK_CODE(code, lino, _exit);
+ if (data[0]) {
+ goto _exit;
+ } else {
+ reader->ctx->isTombDone = true;
+ }
+ }
+
+ code = tsdbSnapReadFileSetEnd(reader);
+ TSDB_CHECK_CODE(code, lino, _exit);
}
_exit:
if (code) {
- tsdbError("vgId:%d %s failed at line %d since %s", TD_VID(pReader->pTsdb->pVnode), __func__, lino, tstrerror(code));
+ TSDB_ERROR_LOG(TD_VID(reader->tsdb->pVnode), code, lino);
} else {
- tsdbDebug("vgId:%d %s done", TD_VID(pReader->pTsdb->pVnode), __func__);
+ tsdbDebug("vgId:%d %s done", TD_VID(reader->tsdb->pVnode), __func__);
}
return code;
}
// STsdbSnapWriter ========================================
struct STsdbSnapWriter {
- STsdb* pTsdb;
+ STsdb* tsdb;
int64_t sver;
int64_t ever;
int32_t minutes;
@@ -569,971 +512,590 @@ struct STsdbSnapWriter {
int32_t maxRow;
int8_t cmprAlg;
int64_t commitID;
+ int32_t szPage;
+ int64_t compactVersion;
+ int64_t now;
uint8_t* aBuf[5];
- STsdbFS fs;
- TABLEID tbid;
+ TFileSetArray* fsetArr;
+ TFileOpArray fopArr[1];
- // time-series data
- SBlockData inData;
+ struct {
+ bool fsetWriteBegin;
+ int32_t fid;
+ STFileSet* fset;
+ SDiskID did;
+ bool hasData;
+ bool hasTomb;
- int32_t fid;
- SSkmInfo skmTable;
+ // reader
+ SDataFileReader* dataReader;
+ TSttFileReaderArray sttReaderArr[1];
- /* reader */
- SDataFReader* pDataFReader;
- STsdbDataIter2* iterList;
- STsdbDataIter2* pDIter;
- STsdbDataIter2* pSIter;
- SRBTree rbt; // SRBTree
+ // iter/merger
+ TTsdbIterArray dataIterArr[1];
+ SIterMerger* dataIterMerger;
+ TTsdbIterArray tombIterArr[1];
+ SIterMerger* tombIterMerger;
- /* writer */
- SDataFWriter* pDataFWriter;
- SArray* aBlockIdx;
- SMapData mDataBlk; // SMapData
- SArray* aSttBlk; // SArray
- SBlockData bData;
- SBlockData sData;
-
- // tombstone data
- /* reader */
- SDelFReader* pDelFReader;
- STsdbDataIter2* pTIter;
-
- /* writer */
- SDelFWriter* pDelFWriter;
- SArray* aDelIdx;
- SArray* aDelData;
+ // writer
+ SFSetWriter* fsetWriter;
+ } ctx[1];
};
-// SNAP_DATA_TSDB
-static int32_t tsdbSnapWriteTableDataStart(STsdbSnapWriter* pWriter, TABLEID* pId) {
+// APIs
+static int32_t tsdbSnapWriteTimeSeriesRow(STsdbSnapWriter* writer, SRowInfo* row) {
int32_t code = 0;
int32_t lino = 0;
- if (pId) {
- pWriter->tbid = *pId;
- } else {
- pWriter->tbid = (TABLEID){INT64_MAX, INT64_MAX};
- }
-
- if (pWriter->pDIter) {
- STsdbDataIter2* pIter = pWriter->pDIter;
-
- // assert last table data end
- ASSERT(pIter->dIter.iRow >= pIter->dIter.bData.nRow);
- ASSERT(pIter->dIter.iDataBlk >= pIter->dIter.mDataBlk.nItem);
-
- for (;;) {
- if (pIter->dIter.iBlockIdx >= taosArrayGetSize(pIter->dIter.aBlockIdx)) {
- pWriter->pDIter = NULL;
- break;
- }
-
- SBlockIdx* pBlockIdx = (SBlockIdx*)taosArrayGet(pIter->dIter.aBlockIdx, pIter->dIter.iBlockIdx);
-
- int32_t c = tTABLEIDCmprFn(pBlockIdx, &pWriter->tbid);
- if (c < 0) {
- code = tsdbReadDataBlk(pIter->dIter.pReader, pBlockIdx, &pIter->dIter.mDataBlk);
- TSDB_CHECK_CODE(code, lino, _exit);
-
- SBlockIdx* pNewBlockIdx = taosArrayReserve(pWriter->aBlockIdx, 1);
- if (pNewBlockIdx == NULL) {
- code = TSDB_CODE_OUT_OF_MEMORY;
- TSDB_CHECK_CODE(code, lino, _exit);
- }
-
- pNewBlockIdx->suid = pBlockIdx->suid;
- pNewBlockIdx->uid = pBlockIdx->uid;
-
- code = tsdbWriteDataBlk(pWriter->pDataFWriter, &pIter->dIter.mDataBlk, pNewBlockIdx);
- TSDB_CHECK_CODE(code, lino, _exit);
-
- pIter->dIter.iBlockIdx++;
- } else if (c == 0) {
- code = tsdbReadDataBlk(pIter->dIter.pReader, pBlockIdx, &pIter->dIter.mDataBlk);
- TSDB_CHECK_CODE(code, lino, _exit);
-
- pIter->dIter.iDataBlk = 0;
- pIter->dIter.iBlockIdx++;
-
- break;
- } else {
- pIter->dIter.iDataBlk = pIter->dIter.mDataBlk.nItem;
- break;
- }
+ while (writer->ctx->hasData) {
+ SRowInfo* row1 = tsdbIterMergerGetData(writer->ctx->dataIterMerger);
+ if (row1 == NULL) {
+ writer->ctx->hasData = false;
+ break;
}
- }
- if (pId) {
- code = tsdbUpdateTableSchema(pWriter->pTsdb->pVnode->pMeta, pId->suid, pId->uid, &pWriter->skmTable);
- TSDB_CHECK_CODE(code, lino, _exit);
-
- tMapDataReset(&pWriter->mDataBlk);
-
- code = tBlockDataInit(&pWriter->bData, pId, pWriter->skmTable.pTSchema, NULL, 0);
- TSDB_CHECK_CODE(code, lino, _exit);
- }
-
- if (!TABLE_SAME_SCHEMA(pWriter->tbid.suid, pWriter->tbid.uid, pWriter->sData.suid, pWriter->sData.uid)) {
- if ((pWriter->sData.nRow > 0)) {
- code = tsdbWriteSttBlock(pWriter->pDataFWriter, &pWriter->sData, pWriter->aSttBlk, pWriter->cmprAlg);
+ int32_t c = tRowInfoCmprFn(row1, row);
+ if (c <= 0) {
+ code = tsdbFSetWriteRow(writer->ctx->fsetWriter, row1);
TSDB_CHECK_CODE(code, lino, _exit);
- }
- if (pId) {
- TABLEID id = {.suid = pWriter->tbid.suid, .uid = pWriter->tbid.suid ? 0 : pWriter->tbid.uid};
- code = tBlockDataInit(&pWriter->sData, &id, pWriter->skmTable.pTSchema, NULL, 0);
+ code = tsdbIterMergerNext(writer->ctx->dataIterMerger);
TSDB_CHECK_CODE(code, lino, _exit);
- }
- }
-
-_exit:
- if (code) {
- tsdbError("vgId:%d %s failed at line %d since %s", TD_VID(pWriter->pTsdb->pVnode), __func__, lino, tstrerror(code));
- } else {
- tsdbTrace("vgId:%d %s done, suid:%" PRId64 " uid:%" PRId64, TD_VID(pWriter->pTsdb->pVnode), __func__,
- pWriter->tbid.suid, pWriter->tbid.uid);
- }
- return code;
-}
-
-static int32_t tsdbSnapWriteTableRowImpl(STsdbSnapWriter* pWriter, TSDBROW* pRow) {
- int32_t code = 0;
- int32_t lino = 0;
-
- code = tBlockDataAppendRow(&pWriter->bData, pRow, pWriter->skmTable.pTSchema, pWriter->tbid.uid);
- TSDB_CHECK_CODE(code, lino, _exit);
-
- if (pWriter->bData.nRow >= pWriter->maxRow) {
- code = tsdbWriteDataBlock(pWriter->pDataFWriter, &pWriter->bData, &pWriter->mDataBlk, pWriter->cmprAlg);
- TSDB_CHECK_CODE(code, lino, _exit);
- }
-
-_exit:
- if (code) {
- tsdbError("vgId:%d %s failed at line %d since %s", TD_VID(pWriter->pTsdb->pVnode), __func__, lino, tstrerror(code));
- }
- return code;
-}
-
-static int32_t tsdbSnapWriteTableRow(STsdbSnapWriter* pWriter, TSDBROW* pRow) {
- int32_t code = 0;
- int32_t lino = 0;
-
- TSDBKEY inKey = pRow ? TSDBROW_KEY(pRow) : TSDBKEY_MAX;
-
- if (pWriter->pDIter == NULL || (pWriter->pDIter->dIter.iRow >= pWriter->pDIter->dIter.bData.nRow &&
- pWriter->pDIter->dIter.iDataBlk >= pWriter->pDIter->dIter.mDataBlk.nItem)) {
- goto _write_row;
- } else {
- for (;;) {
- while (pWriter->pDIter->dIter.iRow < pWriter->pDIter->dIter.bData.nRow) {
- TSDBROW row = tsdbRowFromBlockData(&pWriter->pDIter->dIter.bData, pWriter->pDIter->dIter.iRow);
-
- int32_t c = tsdbKeyCmprFn(&inKey, &TSDBROW_KEY(&row));
- if (c < 0) {
- goto _write_row;
- } else if (c > 0) {
- code = tsdbSnapWriteTableRowImpl(pWriter, &row);
- TSDB_CHECK_CODE(code, lino, _exit);
-
- pWriter->pDIter->dIter.iRow++;
- } else {
- ASSERT(0);
- }
- }
-
- for (;;) {
- if (pWriter->pDIter->dIter.iDataBlk >= pWriter->pDIter->dIter.mDataBlk.nItem) goto _write_row;
-
- // FIXME: Here can be slow, use array instead
- SDataBlk dataBlk;
- tMapDataGetItemByIdx(&pWriter->pDIter->dIter.mDataBlk, pWriter->pDIter->dIter.iDataBlk, &dataBlk, tGetDataBlk);
-
- int32_t c = tDataBlkCmprFn(&dataBlk, &(SDataBlk){.minKey = inKey, .maxKey = inKey});
- if (c > 0) {
- goto _write_row;
- } else if (c < 0) {
- if (pWriter->bData.nRow > 0) {
- code = tsdbWriteDataBlock(pWriter->pDataFWriter, &pWriter->bData, &pWriter->mDataBlk, pWriter->cmprAlg);
- TSDB_CHECK_CODE(code, lino, _exit);
- }
-
- tMapDataPutItem(&pWriter->mDataBlk, &dataBlk, tPutDataBlk);
- pWriter->pDIter->dIter.iDataBlk++;
- } else {
- code = tsdbReadDataBlockEx(pWriter->pDataFReader, &dataBlk, &pWriter->pDIter->dIter.bData);
- TSDB_CHECK_CODE(code, lino, _exit);
-
- pWriter->pDIter->dIter.iRow = 0;
- pWriter->pDIter->dIter.iDataBlk++;
- break;
- }
- }
- }
- }
-
-_write_row:
- if (pRow) {
- code = tsdbSnapWriteTableRowImpl(pWriter, pRow);
- TSDB_CHECK_CODE(code, lino, _exit);
- }
-
-_exit:
- if (code) {
- tsdbError("vgId:%d %s failed at line %d since %s", TD_VID(pWriter->pTsdb->pVnode), __func__, lino, tstrerror(code));
- }
- return code;
-}
-
-static int32_t tsdbSnapWriteTableDataEnd(STsdbSnapWriter* pWriter) {
- int32_t code = 0;
- int32_t lino = 0;
-
- // write a NULL row to end current table data write
- code = tsdbSnapWriteTableRow(pWriter, NULL);
- TSDB_CHECK_CODE(code, lino, _exit);
-
- if (pWriter->bData.nRow > 0) {
- if (pWriter->bData.nRow < pWriter->minRow) {
- ASSERT(TABLE_SAME_SCHEMA(pWriter->sData.suid, pWriter->sData.uid, pWriter->tbid.suid, pWriter->tbid.uid));
- for (int32_t iRow = 0; iRow < pWriter->bData.nRow; iRow++) {
- code =
- tBlockDataAppendRow(&pWriter->sData, &tsdbRowFromBlockData(&pWriter->bData, iRow), NULL, pWriter->tbid.uid);
- TSDB_CHECK_CODE(code, lino, _exit);
-
- if (pWriter->sData.nRow >= pWriter->maxRow) {
- code = tsdbWriteSttBlock(pWriter->pDataFWriter, &pWriter->sData, pWriter->aSttBlk, pWriter->cmprAlg);
- TSDB_CHECK_CODE(code, lino, _exit);
- }
- }
-
- tBlockDataClear(&pWriter->bData);
} else {
- code = tsdbWriteDataBlock(pWriter->pDataFWriter, &pWriter->bData, &pWriter->mDataBlk, pWriter->cmprAlg);
- TSDB_CHECK_CODE(code, lino, _exit);
+ break;
}
}
- if (pWriter->mDataBlk.nItem) {
- SBlockIdx* pBlockIdx = taosArrayReserve(pWriter->aBlockIdx, 1);
- if (pBlockIdx == NULL) {
- code = TSDB_CODE_OUT_OF_MEMORY;
- TSDB_CHECK_CODE(code, lino, _exit);
- }
-
- pBlockIdx->suid = pWriter->tbid.suid;
- pBlockIdx->uid = pWriter->tbid.uid;
-
- code = tsdbWriteDataBlk(pWriter->pDataFWriter, &pWriter->mDataBlk, pBlockIdx);
- TSDB_CHECK_CODE(code, lino, _exit);
- }
-
-_exit:
- if (code) {
- tsdbError("vgId:%d %s failed at line %d since %s", TD_VID(pWriter->pTsdb->pVnode), __func__, lino, tstrerror(code));
- }
- return code;
-}
-
-static int32_t tsdbSnapWriteFileDataStart(STsdbSnapWriter* pWriter, int32_t fid) {
- int32_t code = 0;
- int32_t lino = 0;
-
- ASSERT(pWriter->pDataFWriter == NULL && pWriter->fid < fid);
-
- STsdb* pTsdb = pWriter->pTsdb;
-
- pWriter->fid = fid;
- pWriter->tbid = (TABLEID){0};
- SDFileSet* pSet = taosArraySearch(pWriter->fs.aDFileSet, &(SDFileSet){.fid = fid}, tDFileSetCmprFn, TD_EQ);
-
- // open reader
- pWriter->pDataFReader = NULL;
- pWriter->iterList = NULL;
- pWriter->pDIter = NULL;
- pWriter->pSIter = NULL;
- tRBTreeCreate(&pWriter->rbt, tsdbDataIterCmprFn);
- if (pSet) {
- code = tsdbDataFReaderOpen(&pWriter->pDataFReader, pTsdb, pSet);
- TSDB_CHECK_CODE(code, lino, _exit);
-
- code = tsdbOpenDataFileDataIter(pWriter->pDataFReader, &pWriter->pDIter);
- TSDB_CHECK_CODE(code, lino, _exit);
- if (pWriter->pDIter) {
- pWriter->pDIter->next = pWriter->iterList;
- pWriter->iterList = pWriter->pDIter;
- }
-
- for (int32_t iStt = 0; iStt < pSet->nSttF; iStt++) {
- code = tsdbOpenSttFileDataIter(pWriter->pDataFReader, iStt, &pWriter->pSIter);
- TSDB_CHECK_CODE(code, lino, _exit);
-
- if (pWriter->pSIter) {
- code = tsdbDataIterNext2(pWriter->pSIter, NULL);
- TSDB_CHECK_CODE(code, lino, _exit);
-
- // add to tree
- tRBTreePut(&pWriter->rbt, &pWriter->pSIter->rbtn);
-
- // add to list
- pWriter->pSIter->next = pWriter->iterList;
- pWriter->iterList = pWriter->pSIter;
- }
- }
-
- pWriter->pSIter = NULL;
- }
-
- // open writer
- SDiskID diskId;
- if (pSet) {
- diskId = pSet->diskId;
- } else {
- tfsAllocDisk(pTsdb->pVnode->pTfs, 0 /*TODO*/, &diskId);
- tfsMkdirRecurAt(pTsdb->pVnode->pTfs, pTsdb->path, diskId);
- }
- SDFileSet wSet = {.diskId = diskId,
- .fid = fid,
- .pHeadF = &(SHeadFile){.commitID = pWriter->commitID},
- .pDataF = (pSet) ? pSet->pDataF : &(SDataFile){.commitID = pWriter->commitID},
- .pSmaF = (pSet) ? pSet->pSmaF : &(SSmaFile){.commitID = pWriter->commitID},
- .nSttF = 1,
- .aSttF = {&(SSttFile){.commitID = pWriter->commitID}}};
- code = tsdbDataFWriterOpen(&pWriter->pDataFWriter, pTsdb, &wSet);
- TSDB_CHECK_CODE(code, lino, _exit);
-
- if (pWriter->aBlockIdx) {
- taosArrayClear(pWriter->aBlockIdx);
- } else if ((pWriter->aBlockIdx = taosArrayInit(0, sizeof(SBlockIdx))) == NULL) {
- code = TSDB_CODE_OUT_OF_MEMORY;
- TSDB_CHECK_CODE(code, lino, _exit);
- }
-
- tMapDataReset(&pWriter->mDataBlk);
-
- if (pWriter->aSttBlk) {
- taosArrayClear(pWriter->aSttBlk);
- } else if ((pWriter->aSttBlk = taosArrayInit(0, sizeof(SSttBlk))) == NULL) {
- code = TSDB_CODE_OUT_OF_MEMORY;
- TSDB_CHECK_CODE(code, lino, _exit);
- }
-
- tBlockDataReset(&pWriter->bData);
- tBlockDataReset(&pWriter->sData);
-
-_exit:
- if (code) {
- tsdbError("vgId:%d %s failed at line %d since %s, fid:%d", TD_VID(pTsdb->pVnode), __func__, lino, tstrerror(code),
- fid);
- } else {
- tsdbDebug("vgId:%d %s done, fid:%d", TD_VID(pTsdb->pVnode), __func__, fid);
- }
- return code;
-}
-
-static int32_t tsdbSnapWriteTableData(STsdbSnapWriter* pWriter, SRowInfo* pRowInfo) {
- int32_t code = 0;
- int32_t lino = 0;
-
- // switch to new table if need
- if (pRowInfo == NULL || pRowInfo->uid != pWriter->tbid.uid) {
- if (pWriter->tbid.uid) {
- code = tsdbSnapWriteTableDataEnd(pWriter);
- TSDB_CHECK_CODE(code, lino, _exit);
- }
-
- code = tsdbSnapWriteTableDataStart(pWriter, (TABLEID*)pRowInfo);
- TSDB_CHECK_CODE(code, lino, _exit);
- }
-
- if (pRowInfo == NULL) goto _exit;
-
- code = tsdbSnapWriteTableRow(pWriter, &pRowInfo->row);
- TSDB_CHECK_CODE(code, lino, _exit);
-
-_exit:
- if (code) {
- tsdbError("vgId:%d %s failed at line %d since %s", TD_VID(pWriter->pTsdb->pVnode), __func__, lino, tstrerror(code));
- }
- return code;
-}
-
-static int32_t tsdbSnapWriteNextRow(STsdbSnapWriter* pWriter, SRowInfo** ppRowInfo) {
- int32_t code = 0;
- int32_t lino = 0;
-
- if (pWriter->pSIter) {
- code = tsdbDataIterNext2(pWriter->pSIter, NULL);
- TSDB_CHECK_CODE(code, lino, _exit);
-
- if (pWriter->pSIter->rowInfo.suid == 0 && pWriter->pSIter->rowInfo.uid == 0) {
- pWriter->pSIter = NULL;
- } else {
- SRBTreeNode* pNode = tRBTreeMin(&pWriter->rbt);
- if (pNode) {
- int32_t c = tsdbDataIterCmprFn(&pWriter->pSIter->rbtn, pNode);
- if (c > 0) {
- tRBTreePut(&pWriter->rbt, &pWriter->pSIter->rbtn);
- pWriter->pSIter = NULL;
- } else if (c == 0) {
- ASSERT(0);
- }
- }
- }
- }
-
- if (pWriter->pSIter == NULL) {
- SRBTreeNode* pNode = tRBTreeMin(&pWriter->rbt);
- if (pNode) {
- tRBTreeDrop(&pWriter->rbt, pNode);
- pWriter->pSIter = TSDB_RBTN_TO_DATA_ITER(pNode);
- }
- }
-
- if (ppRowInfo) {
- if (pWriter->pSIter) {
- *ppRowInfo = &pWriter->pSIter->rowInfo;
- } else {
- *ppRowInfo = NULL;
- }
- }
-
-_exit:
- if (code) {
- tsdbError("vgId:%d %s failed at line %d since %s", TD_VID(pWriter->pTsdb->pVnode), __func__, lino, tstrerror(code));
- }
- return code;
-}
-
-static int32_t tsdbSnapWriteGetRow(STsdbSnapWriter* pWriter, SRowInfo** ppRowInfo) {
- int32_t code = 0;
- int32_t lino = 0;
-
- if (pWriter->pSIter) {
- *ppRowInfo = &pWriter->pSIter->rowInfo;
+ if (row->suid == INT64_MAX) {
+ ASSERT(writer->ctx->hasData == false);
goto _exit;
}
- code = tsdbSnapWriteNextRow(pWriter, ppRowInfo);
+ code = tsdbFSetWriteRow(writer->ctx->fsetWriter, row);
TSDB_CHECK_CODE(code, lino, _exit);
_exit:
if (code) {
- tsdbError("vgId:%d %s failed at line %d since %s", TD_VID(pWriter->pTsdb->pVnode), __func__, lino, tstrerror(code));
+ TSDB_ERROR_LOG(TD_VID(writer->tsdb->pVnode), lino, code);
}
return code;
}
-static int32_t tsdbSnapWriteFileDataEnd(STsdbSnapWriter* pWriter) {
+static int32_t tsdbSnapWriteFileSetOpenReader(STsdbSnapWriter* writer) {
int32_t code = 0;
int32_t lino = 0;
- ASSERT(pWriter->pDataFWriter);
+ ASSERT(writer->ctx->dataReader == NULL);
+ ASSERT(TARRAY2_SIZE(writer->ctx->sttReaderArr) == 0);
- // consume remain data and end with a NULL table row
- SRowInfo* pRowInfo;
- code = tsdbSnapWriteGetRow(pWriter, &pRowInfo);
- TSDB_CHECK_CODE(code, lino, _exit);
- for (;;) {
- code = tsdbSnapWriteTableData(pWriter, pRowInfo);
- TSDB_CHECK_CODE(code, lino, _exit);
+ if (writer->ctx->fset) {
+ // open data reader
+ SDataFileReaderConfig dataFileReaderConfig = {
+ .tsdb = writer->tsdb,
+ .bufArr = writer->aBuf,
+ .szPage = writer->szPage,
+ };
- if (pRowInfo == NULL) break;
+ for (int32_t ftype = 0; ftype < TSDB_FTYPE_MAX; ++ftype) {
+ if (writer->ctx->fset->farr[ftype] == NULL) {
+ continue;
+ }
- code = tsdbSnapWriteNextRow(pWriter, &pRowInfo);
- TSDB_CHECK_CODE(code, lino, _exit);
- }
-
- // do file-level updates
- code = tsdbWriteSttBlk(pWriter->pDataFWriter, pWriter->aSttBlk);
- TSDB_CHECK_CODE(code, lino, _exit);
-
- code = tsdbWriteBlockIdx(pWriter->pDataFWriter, pWriter->aBlockIdx);
- TSDB_CHECK_CODE(code, lino, _exit);
-
- code = tsdbUpdateDFileSetHeader(pWriter->pDataFWriter);
- TSDB_CHECK_CODE(code, lino, _exit);
-
- code = tsdbFSUpsertFSet(&pWriter->fs, &pWriter->pDataFWriter->wSet);
- TSDB_CHECK_CODE(code, lino, _exit);
-
- code = tsdbDataFWriterClose(&pWriter->pDataFWriter, 1);
- TSDB_CHECK_CODE(code, lino, _exit);
-
- if (pWriter->pDataFReader) {
- code = tsdbDataFReaderClose(&pWriter->pDataFReader);
- TSDB_CHECK_CODE(code, lino, _exit);
- }
-
- // clear sources
- while (pWriter->iterList) {
- STsdbDataIter2* pIter = pWriter->iterList;
- pWriter->iterList = pIter->next;
- tsdbCloseDataIter2(pIter);
- }
-
-_exit:
- if (code) {
- tsdbError("vgId:%d %s failed since %s", TD_VID(pWriter->pTsdb->pVnode), __func__, tstrerror(code));
- } else {
- tsdbDebug("vgId:%d %s is done", TD_VID(pWriter->pTsdb->pVnode), __func__);
- }
- return code;
-}
-
-static int32_t tsdbSnapWriteTimeSeriesData(STsdbSnapWriter* pWriter, SSnapDataHdr* pHdr) {
- int32_t code = 0;
- int32_t lino = 0;
-
- code = tDecmprBlockData(pHdr->data, pHdr->size, &pWriter->inData, pWriter->aBuf);
- TSDB_CHECK_CODE(code, lino, _exit);
-
- ASSERT(pWriter->inData.nRow > 0);
-
- // switch to new data file if need
- int32_t fid = tsdbKeyFid(pWriter->inData.aTSKEY[0], pWriter->minutes, pWriter->precision);
- if (pWriter->fid != fid) {
- if (pWriter->pDataFWriter) {
- code = tsdbSnapWriteFileDataEnd(pWriter);
- TSDB_CHECK_CODE(code, lino, _exit);
+ dataFileReaderConfig.files[ftype].exist = true;
+ dataFileReaderConfig.files[ftype].file = writer->ctx->fset->farr[ftype]->f[0];
}
- code = tsdbSnapWriteFileDataStart(pWriter, fid);
+ code = tsdbDataFileReaderOpen(NULL, &dataFileReaderConfig, &writer->ctx->dataReader);
TSDB_CHECK_CODE(code, lino, _exit);
- }
- // loop write each row
- SRowInfo* pRowInfo;
- code = tsdbSnapWriteGetRow(pWriter, &pRowInfo);
- TSDB_CHECK_CODE(code, lino, _exit);
- for (int32_t iRow = 0; iRow < pWriter->inData.nRow; ++iRow) {
- SRowInfo rInfo = {.suid = pWriter->inData.suid,
- .uid = pWriter->inData.uid ? pWriter->inData.uid : pWriter->inData.aUid[iRow],
- .row = tsdbRowFromBlockData(&pWriter->inData, iRow)};
+ // open stt reader array
+ SSttLvl* lvl;
+ TARRAY2_FOREACH(writer->ctx->fset->lvlArr, lvl) {
+ STFileObj* fobj;
+ TARRAY2_FOREACH(lvl->fobjArr, fobj) {
+ SSttFileReader* reader;
+ SSttFileReaderConfig sttFileReaderConfig = {
+ .tsdb = writer->tsdb,
+ .szPage = writer->szPage,
+ .bufArr = writer->aBuf,
+ .file = fobj->f[0],
+ };
- for (;;) {
- if (pRowInfo == NULL) {
- code = tsdbSnapWriteTableData(pWriter, &rInfo);
+ code = tsdbSttFileReaderOpen(fobj->fname, &sttFileReaderConfig, &reader);
TSDB_CHECK_CODE(code, lino, _exit);
- break;
- } else {
- int32_t c = tRowInfoCmprFn(&rInfo, pRowInfo);
- if (c < 0) {
- code = tsdbSnapWriteTableData(pWriter, &rInfo);
- TSDB_CHECK_CODE(code, lino, _exit);
- break;
- } else if (c > 0) {
- code = tsdbSnapWriteTableData(pWriter, pRowInfo);
- TSDB_CHECK_CODE(code, lino, _exit);
- code = tsdbSnapWriteNextRow(pWriter, &pRowInfo);
- TSDB_CHECK_CODE(code, lino, _exit);
- } else {
- ASSERT(0);
- }
+ code = TARRAY2_APPEND(writer->ctx->sttReaderArr, reader);
+ TSDB_CHECK_CODE(code, lino, _exit);
}
}
}
_exit:
if (code) {
- tsdbError("vgId:%d %s failed at line %d since %s", TD_VID(pWriter->pTsdb->pVnode), __func__, lino, tstrerror(code));
- } else {
- tsdbDebug("vgId:%d %s done, suid:%" PRId64 " uid:%" PRId64 " nRow:%d", TD_VID(pWriter->pTsdb->pVnode), __func__,
- pWriter->inData.suid, pWriter->inData.uid, pWriter->inData.nRow);
+ TSDB_ERROR_LOG(TD_VID(writer->tsdb->pVnode), lino, code);
}
return code;
}
-// SNAP_DATA_DEL
-static int32_t tsdbSnapWriteDelTableDataStart(STsdbSnapWriter* pWriter, TABLEID* pId) {
- int32_t code = 0;
- int32_t lino = 0;
-
- if (pId) {
- pWriter->tbid = *pId;
- } else {
- pWriter->tbid = (TABLEID){.suid = INT64_MAX, .uid = INT64_MAX};
- }
-
- taosArrayClear(pWriter->aDelData);
-
- if (pWriter->pTIter) {
- while (pWriter->pTIter->tIter.iDelIdx < taosArrayGetSize(pWriter->pTIter->tIter.aDelIdx)) {
- SDelIdx* pDelIdx = taosArrayGet(pWriter->pTIter->tIter.aDelIdx, pWriter->pTIter->tIter.iDelIdx);
-
- int32_t c = tTABLEIDCmprFn(pDelIdx, &pWriter->tbid);
- if (c < 0) {
- code = tsdbReadDelDatav1(pWriter->pDelFReader, pDelIdx, pWriter->pTIter->tIter.aDelData, INT64_MAX);
- TSDB_CHECK_CODE(code, lino, _exit);
-
- SDelIdx* pDelIdxNew = taosArrayReserve(pWriter->aDelIdx, 1);
- if (pDelIdxNew == NULL) {
- code = TSDB_CODE_OUT_OF_MEMORY;
- TSDB_CHECK_CODE(code, lino, _exit);
- }
-
- pDelIdxNew->suid = pDelIdx->suid;
- pDelIdxNew->uid = pDelIdx->uid;
-
- code = tsdbWriteDelData(pWriter->pDelFWriter, pWriter->pTIter->tIter.aDelData, pDelIdxNew);
- TSDB_CHECK_CODE(code, lino, _exit);
-
- pWriter->pTIter->tIter.iDelIdx++;
- } else if (c == 0) {
- code = tsdbReadDelDatav1(pWriter->pDelFReader, pDelIdx, pWriter->aDelData, INT64_MAX);
- TSDB_CHECK_CODE(code, lino, _exit);
-
- pWriter->pTIter->tIter.iDelIdx++;
- break;
- } else {
- break;
- }
- }
- }
-
-_exit:
- if (code) {
- tsdbError("vgId:%d %s failed at line %d since %s", TD_VID(pWriter->pTsdb->pVnode), __func__, lino, tstrerror(code));
- } else {
- tsdbTrace("vgId:%d %s done, suid:%" PRId64 " uid:%" PRId64, TD_VID(pWriter->pTsdb->pVnode), __func__,
- pWriter->tbid.suid, pWriter->tbid.uid);
- }
- return code;
+static int32_t tsdbSnapWriteFileSetCloseReader(STsdbSnapWriter* writer) {
+ TARRAY2_CLEAR(writer->ctx->sttReaderArr, tsdbSttFileReaderClose);
+ tsdbDataFileReaderClose(&writer->ctx->dataReader);
+ return 0;
}
-static int32_t tsdbSnapWriteDelTableDataEnd(STsdbSnapWriter* pWriter) {
+static int32_t tsdbSnapWriteFileSetOpenIter(STsdbSnapWriter* writer) {
int32_t code = 0;
int32_t lino = 0;
- if (taosArrayGetSize(pWriter->aDelData) > 0) {
- SDelIdx* pDelIdx = taosArrayReserve(pWriter->aDelIdx, 1);
- if (pDelIdx == NULL) {
- code = TSDB_CODE_OUT_OF_MEMORY;
- TSDB_CHECK_CODE(code, lino, _exit);
- }
+ // data ieter
+ if (writer->ctx->dataReader) {
+ STsdbIter* iter;
+ STsdbIterConfig config = {0};
- pDelIdx->suid = pWriter->tbid.suid;
- pDelIdx->uid = pWriter->tbid.uid;
+ // data
+ config.type = TSDB_ITER_TYPE_DATA;
+ config.dataReader = writer->ctx->dataReader;
- code = tsdbWriteDelData(pWriter->pDelFWriter, pWriter->aDelData, pDelIdx);
+ code = tsdbIterOpen(&config, &iter);
+ TSDB_CHECK_CODE(code, lino, _exit);
+
+ code = TARRAY2_APPEND(writer->ctx->dataIterArr, iter);
+ TSDB_CHECK_CODE(code, lino, _exit);
+
+ // tome
+ config.type = TSDB_ITER_TYPE_DATA_TOMB;
+ config.dataReader = writer->ctx->dataReader;
+
+ code = tsdbIterOpen(&config, &iter);
+ TSDB_CHECK_CODE(code, lino, _exit);
+
+ code = TARRAY2_APPEND(writer->ctx->tombIterArr, iter);
TSDB_CHECK_CODE(code, lino, _exit);
}
-_exit:
- if (code) {
- tsdbError("vgId:%d %s failed at line %d since %s", TD_VID(pWriter->pTsdb->pVnode), __func__, lino, tstrerror(code));
- } else {
- tsdbTrace("vgId:%d %s done", TD_VID(pWriter->pTsdb->pVnode), __func__);
- }
- return code;
-}
+ // stt iter
+ SSttFileReader* sttFileReader;
+ TARRAY2_FOREACH(writer->ctx->sttReaderArr, sttFileReader) {
+ STsdbIter* iter;
+ STsdbIterConfig config = {0};
-static int32_t tsdbSnapWriteDelTableData(STsdbSnapWriter* pWriter, TABLEID* pId, uint8_t* pData, int64_t size) {
- int32_t code = 0;
- int32_t lino = 0;
+ // data
+ config.type = TSDB_ITER_TYPE_STT;
+ config.sttReader = sttFileReader;
- if (pId == NULL || pId->uid != pWriter->tbid.uid) {
- if (pWriter->tbid.uid) {
- code = tsdbSnapWriteDelTableDataEnd(pWriter);
- TSDB_CHECK_CODE(code, lino, _exit);
- }
+ code = tsdbIterOpen(&config, &iter);
+ TSDB_CHECK_CODE(code, lino, _exit);
- code = tsdbSnapWriteDelTableDataStart(pWriter, pId);
+ code = TARRAY2_APPEND(writer->ctx->dataIterArr, iter);
+ TSDB_CHECK_CODE(code, lino, _exit);
+
+ // tomb
+ config.type = TSDB_ITER_TYPE_STT_TOMB;
+ config.sttReader = sttFileReader;
+
+ code = tsdbIterOpen(&config, &iter);
+ TSDB_CHECK_CODE(code, lino, _exit);
+
+ code = TARRAY2_APPEND(writer->ctx->tombIterArr, iter);
TSDB_CHECK_CODE(code, lino, _exit);
}
- if (pId == NULL) goto _exit;
-
- int64_t n = 0;
- while (n < size) {
- SDelData delData;
- n += tGetDelData(pData + n, &delData);
-
- if (taosArrayPush(pWriter->aDelData, &delData) == NULL) {
- code = TSDB_CODE_OUT_OF_MEMORY;
- TSDB_CHECK_CODE(code, lino, _exit);
- }
- }
- ASSERT(n == size);
-
-_exit:
- if (code) {
- tsdbError("vgId:%d %s failed at line %d since %s", TD_VID(pWriter->pTsdb->pVnode), __func__, lino, tstrerror(code));
- }
- return code;
-}
-
-static int32_t tsdbSnapWriteDelDataStart(STsdbSnapWriter* pWriter) {
- int32_t code = 0;
- int32_t lino = 0;
-
- STsdb* pTsdb = pWriter->pTsdb;
- SDelFile* pDelFile = pWriter->fs.pDelFile;
-
- pWriter->tbid = (TABLEID){0};
-
- // reader
- if (pDelFile) {
- code = tsdbDelFReaderOpen(&pWriter->pDelFReader, pDelFile, pTsdb);
- TSDB_CHECK_CODE(code, lino, _exit);
-
- code = tsdbOpenTombFileDataIter(pWriter->pDelFReader, &pWriter->pTIter);
- TSDB_CHECK_CODE(code, lino, _exit);
- }
-
- // writer
- code = tsdbDelFWriterOpen(&pWriter->pDelFWriter, &(SDelFile){.commitID = pWriter->commitID}, pTsdb);
+ // open merger
+ code = tsdbIterMergerOpen(writer->ctx->dataIterArr, &writer->ctx->dataIterMerger, false);
TSDB_CHECK_CODE(code, lino, _exit);
- if ((pWriter->aDelIdx = taosArrayInit(0, sizeof(SDelIdx))) == NULL) {
- code = TSDB_CODE_OUT_OF_MEMORY;
+ code = tsdbIterMergerOpen(writer->ctx->tombIterArr, &writer->ctx->dataIterMerger, true);
+ TSDB_CHECK_CODE(code, lino, _exit);
+
+_exit:
+ if (code) {
+ TSDB_ERROR_LOG(TD_VID(writer->tsdb->pVnode), lino, code);
+ }
+ return code;
+}
+
+static int32_t tsdbSnapWriteFileSetCloseIter(STsdbSnapWriter* writer) {
+ tsdbIterMergerClose(&writer->ctx->dataIterMerger);
+ tsdbIterMergerClose(&writer->ctx->tombIterMerger);
+ TARRAY2_CLEAR(writer->ctx->dataIterArr, tsdbIterClose);
+ TARRAY2_CLEAR(writer->ctx->tombIterArr, tsdbIterClose);
+ return 0;
+}
+
+static int32_t tsdbSnapWriteFileSetOpenWriter(STsdbSnapWriter* writer) {
+ int32_t code = 0;
+ int32_t lino = 0;
+
+ SFSetWriterConfig config = {
+ .tsdb = writer->tsdb,
+ .toSttOnly = false,
+ .compactVersion = writer->compactVersion,
+ .minRow = writer->minRow,
+ .maxRow = writer->maxRow,
+ .szPage = writer->szPage,
+ .cmprAlg = writer->cmprAlg,
+ .fid = writer->ctx->fid,
+ .cid = writer->commitID,
+ .did = writer->ctx->did,
+ .level = 0,
+ };
+
+ code = tsdbFSetWriterOpen(&config, &writer->ctx->fsetWriter);
+ TSDB_CHECK_CODE(code, lino, _exit);
+
+_exit:
+ if (code) {
+ TSDB_ERROR_LOG(TD_VID(writer->tsdb->pVnode), lino, code);
+ }
+ return code;
+}
+
+static int32_t tsdbSnapWriteFileSetCloseWriter(STsdbSnapWriter* writer) {
+ return tsdbFSetWriterClose(&writer->ctx->fsetWriter, 0, writer->fopArr);
+}
+
+static int32_t tsdbSnapWriteFileSetBegin(STsdbSnapWriter* writer, int32_t fid) {
+ int32_t code = 0;
+ int32_t lino = 0;
+
+ ASSERT(writer->ctx->fsetWriteBegin == false);
+
+ STFileSet* fset = &(STFileSet){.fid = fid};
+
+ writer->ctx->fid = fid;
+ writer->ctx->fset = TARRAY2_SEARCH_EX(writer->fsetArr, &fset, tsdbTFileSetCmprFn, TD_EQ);
+
+ int32_t level = tsdbFidLevel(fid, &writer->tsdb->keepCfg, writer->now);
+ if (tfsAllocDisk(writer->tsdb->pVnode->pTfs, level, &writer->ctx->did)) {
+ code = TSDB_CODE_NO_AVAIL_DISK;
TSDB_CHECK_CODE(code, lino, _exit);
}
- if ((pWriter->aDelData = taosArrayInit(0, sizeof(SDelData))) == NULL) {
- code = TSDB_CODE_OUT_OF_MEMORY;
+
+ writer->ctx->hasData = true;
+ writer->ctx->hasTomb = true;
+
+ code = tsdbSnapWriteFileSetOpenReader(writer);
+ TSDB_CHECK_CODE(code, lino, _exit);
+
+ code = tsdbSnapWriteFileSetOpenIter(writer);
+ TSDB_CHECK_CODE(code, lino, _exit);
+
+ code = tsdbSnapWriteFileSetOpenWriter(writer);
+ TSDB_CHECK_CODE(code, lino, _exit);
+
+ writer->ctx->fsetWriteBegin = true;
+
+_exit:
+ if (code) {
+ TSDB_ERROR_LOG(TD_VID(writer->tsdb->pVnode), lino, code);
+ }
+ return code;
+}
+
+static int32_t tsdbSnapWriteTombRecord(STsdbSnapWriter* writer, const STombRecord* record) {
+ int32_t code = 0;
+ int32_t lino = 0;
+
+ while (writer->ctx->hasTomb) {
+ STombRecord* record1 = tsdbIterMergerGetTombRecord(writer->ctx->tombIterMerger);
+ if (record1 == NULL) {
+ writer->ctx->hasTomb = false;
+ break;
+ }
+
+ int32_t c = tTombRecordCompare(record1, record);
+ if (c <= 0) {
+ code = tsdbFSetWriteTombRecord(writer->ctx->fsetWriter, record1);
+ TSDB_CHECK_CODE(code, lino, _exit);
+ } else {
+ break;
+ }
+ }
+
+ if (record->suid == INT64_MAX) {
+ ASSERT(writer->ctx->hasTomb == false);
+ goto _exit;
+ }
+
+ code = tsdbFSetWriteTombRecord(writer->ctx->fsetWriter, record);
+ TSDB_CHECK_CODE(code, lino, _exit);
+
+_exit:
+ if (code) {
+ TSDB_ERROR_LOG(TD_VID(writer->tsdb->pVnode), lino, code);
+ }
+ return code;
+}
+
+static int32_t tsdbSnapWriteFileSetEnd(STsdbSnapWriter* writer) {
+ if (!writer->ctx->fsetWriteBegin) return 0;
+
+ int32_t code = 0;
+ int32_t lino = 0;
+
+ SRowInfo row = {
+ .suid = INT64_MAX,
+ .uid = INT64_MAX,
+ };
+
+ code = tsdbSnapWriteTimeSeriesRow(writer, &row);
+ TSDB_CHECK_CODE(code, lino, _exit);
+
+ STombRecord record = {
+ .suid = INT64_MAX,
+ .uid = INT64_MAX,
+ };
+
+ code = tsdbSnapWriteTombRecord(writer, &record);
+ TSDB_CHECK_CODE(code, lino, _exit);
+
+ // close write
+ code = tsdbSnapWriteFileSetCloseWriter(writer);
+ TSDB_CHECK_CODE(code, lino, _exit);
+
+ code = tsdbSnapWriteFileSetCloseIter(writer);
+ TSDB_CHECK_CODE(code, lino, _exit);
+
+ code = tsdbSnapWriteFileSetCloseReader(writer);
+ TSDB_CHECK_CODE(code, lino, _exit);
+
+ writer->ctx->fsetWriteBegin = false;
+
+_exit:
+ if (code) {
+ TSDB_ERROR_LOG(TD_VID(writer->tsdb->pVnode), lino, code);
+ }
+ return code;
+}
+
+static int32_t tsdbSnapWriteTimeSeriesData(STsdbSnapWriter* writer, SSnapDataHdr* hdr) {
+ int32_t code = 0;
+ int32_t lino = 0;
+
+ SBlockData blockData[1] = {0};
+
+ code = tDecmprBlockData(hdr->data, hdr->size - sizeof(*hdr), blockData, writer->aBuf);
+ TSDB_CHECK_CODE(code, lino, _exit);
+
+ int32_t fid = tsdbKeyFid(blockData->aTSKEY[0], writer->minutes, writer->precision);
+ if (!writer->ctx->fsetWriteBegin || fid != writer->ctx->fid) {
+ code = tsdbSnapWriteFileSetEnd(writer);
+ TSDB_CHECK_CODE(code, lino, _exit);
+
+ code = tsdbSnapWriteFileSetBegin(writer, fid);
TSDB_CHECK_CODE(code, lino, _exit);
}
+ for (int32_t i = 0; i < blockData->nRow; ++i) {
+ SRowInfo rowInfo = {
+ .suid = blockData->suid,
+ .uid = blockData->uid ? blockData->uid : blockData->aUid[i],
+ .row = tsdbRowFromBlockData(blockData, i),
+ };
+
+ code = tsdbSnapWriteTimeSeriesRow(writer, &rowInfo);
+ TSDB_CHECK_CODE(code, lino, _exit);
+ }
+
+_exit:
+ if (code) {
+ TSDB_ERROR_LOG(TD_VID(writer->tsdb->pVnode), lino, code);
+ } else {
+ tsdbDebug("vgId:%d %s done, suid:%" PRId64 " uid:%" PRId64 " nRow:%d", TD_VID(writer->tsdb->pVnode), __func__,
+ blockData->suid, blockData->uid, blockData->nRow);
+ }
+ tBlockDataDestroy(blockData);
+ return code;
+}
+
+static int32_t tsdbSnapWriteDecmprTombBlock(SSnapDataHdr* hdr, STombBlock* tombBlock) {
+ int32_t code = 0;
+ int32_t lino = 0;
+
+ int64_t size = hdr->size - sizeof(*hdr);
+ ASSERT(size % TOMB_RECORD_ELEM_NUM == 0);
+ size = size / TOMB_RECORD_ELEM_NUM;
+ ASSERT(size % sizeof(int64_t) == 0);
+
+ int64_t* data = (int64_t*)hdr->data;
+ for (int32_t i = 0; i < TOMB_RECORD_ELEM_NUM; ++i) {
+ code = TARRAY2_APPEND_BATCH(&tombBlock->dataArr[i], hdr->data + i * size, size / sizeof(int64_t));
+ TSDB_CHECK_CODE(code, lino, _exit);
+ }
+
+_exit:
+ return code;
+}
+
+static int32_t tsdbSnapWriteTombData(STsdbSnapWriter* writer, SSnapDataHdr* hdr) {
+ int32_t code = 0;
+ int32_t lino = 0;
+
+ STombRecord record;
+ STombBlock tombBlock[1] = {0};
+
+ code = tsdbSnapWriteDecmprTombBlock(hdr, tombBlock);
+ TSDB_CHECK_CODE(code, lino, _exit);
+
+ tTombBlockGet(tombBlock, 0, &record);
+ int32_t fid = tsdbKeyFid(record.skey, writer->minutes, writer->precision);
+ if (!writer->ctx->fsetWriteBegin || fid != writer->ctx->fid) {
+ code = tsdbSnapWriteFileSetEnd(writer);
+ TSDB_CHECK_CODE(code, lino, _exit);
+
+ code = tsdbSnapWriteFileSetBegin(writer, fid);
+ TSDB_CHECK_CODE(code, lino, _exit);
+ }
+
+ if (writer->ctx->hasData) {
+ SRowInfo row = {
+ .suid = INT64_MAX,
+ .uid = INT64_MAX,
+ };
+
+ code = tsdbSnapWriteTimeSeriesRow(writer, &row);
+ TSDB_CHECK_CODE(code, lino, _exit);
+ }
+
+ ASSERT(writer->ctx->hasData == false);
+
+ for (int32_t i = 0; i < TOMB_BLOCK_SIZE(tombBlock); ++i) {
+ tTombBlockGet(tombBlock, i, &record);
+
+ code = tsdbSnapWriteTombRecord(writer, &record);
+ TSDB_CHECK_CODE(code, lino, _exit);
+ }
+
+ tTombBlockDestroy(tombBlock);
+
+_exit:
+ if (code) {
+ TSDB_ERROR_LOG(TD_VID(writer->tsdb->pVnode), lino, code);
+ }
+ return code;
+}
+
+int32_t tsdbSnapWriterOpen(STsdb* pTsdb, int64_t sver, int64_t ever, STsdbSnapWriter** writer) {
+ int32_t code = 0;
+ int32_t lino = 0;
+
+ writer[0] = taosMemoryCalloc(1, sizeof(*writer[0]));
+ if (writer[0] == NULL) return TSDB_CODE_OUT_OF_MEMORY;
+
+ writer[0]->tsdb = pTsdb;
+ writer[0]->sver = sver;
+ writer[0]->ever = ever;
+ writer[0]->minutes = pTsdb->keepCfg.days;
+ writer[0]->precision = pTsdb->keepCfg.precision;
+ writer[0]->minRow = pTsdb->pVnode->config.tsdbCfg.minRows;
+ writer[0]->maxRow = pTsdb->pVnode->config.tsdbCfg.maxRows;
+ writer[0]->commitID = tsdbFSAllocEid(pTsdb->pFS);
+ writer[0]->szPage = pTsdb->pVnode->config.tsdbPageSize;
+ writer[0]->compactVersion = INT64_MAX;
+ writer[0]->now = taosGetTimestampMs();
+
+ code = tsdbFSCreateCopySnapshot(pTsdb->pFS, &writer[0]->fsetArr);
+ TSDB_CHECK_CODE(code, lino, _exit);
+
_exit:
if (code) {
tsdbError("vgId:%d %s failed at line %d since %s", TD_VID(pTsdb->pVnode), __func__, lino, tstrerror(code));
- } else {
- tsdbDebug("vgId:%d %s done", TD_VID(pTsdb->pVnode), __func__);
- }
- return code;
-}
-
-static int32_t tsdbSnapWriteDelDataEnd(STsdbSnapWriter* pWriter) {
- int32_t code = 0;
- int32_t lino = 0;
-
- STsdb* pTsdb = pWriter->pTsdb;
-
- // end remaining table with NULL data
- code = tsdbSnapWriteDelTableData(pWriter, NULL, NULL, 0);
- TSDB_CHECK_CODE(code, lino, _exit);
-
- // update file-level info
- code = tsdbWriteDelIdx(pWriter->pDelFWriter, pWriter->aDelIdx);
- TSDB_CHECK_CODE(code, lino, _exit);
-
- code = tsdbUpdateDelFileHdr(pWriter->pDelFWriter);
- TSDB_CHECK_CODE(code, lino, _exit);
-
- code = tsdbFSUpsertDelFile(&pWriter->fs, &pWriter->pDelFWriter->fDel);
- TSDB_CHECK_CODE(code, lino, _exit);
-
- code = tsdbDelFWriterClose(&pWriter->pDelFWriter, 1);
- TSDB_CHECK_CODE(code, lino, _exit);
-
- if (pWriter->pDelFReader) {
- code = tsdbDelFReaderClose(&pWriter->pDelFReader);
- TSDB_CHECK_CODE(code, lino, _exit);
- }
-
- if (pWriter->pTIter) {
- tsdbCloseDataIter2(pWriter->pTIter);
- pWriter->pTIter = NULL;
- }
-
-_exit:
- if (code) {
- tsdbError("vgId:%d %s failed at line %d since %s", TD_VID(pTsdb->pVnode), __func__, lino, tstrerror(code));
- } else {
- tsdbInfo("vgId:%d %s done", TD_VID(pTsdb->pVnode), __func__);
- }
- return code;
-}
-
-static int32_t tsdbSnapWriteDelData(STsdbSnapWriter* pWriter, SSnapDataHdr* pHdr) {
- int32_t code = 0;
- int32_t lino = 0;
-
- STsdb* pTsdb = pWriter->pTsdb;
-
- // start to write del data if need
- if (pWriter->pDelFWriter == NULL) {
- code = tsdbSnapWriteDelDataStart(pWriter);
- TSDB_CHECK_CODE(code, lino, _exit);
- }
-
- // do write del data
- code = tsdbSnapWriteDelTableData(pWriter, (TABLEID*)pHdr->data, pHdr->data + sizeof(TABLEID),
- pHdr->size - sizeof(TABLEID));
- TSDB_CHECK_CODE(code, lino, _exit);
-
-_exit:
- if (code) {
- tsdbError("vgId:%d %s failed since %s", TD_VID(pTsdb->pVnode), __func__, tstrerror(code));
- } else {
- tsdbTrace("vgId:%d %s done", TD_VID(pTsdb->pVnode), __func__);
- }
- return code;
-}
-
-// APIs
-int32_t tsdbSnapWriterOpen(STsdb* pTsdb, int64_t sver, int64_t ever, STsdbSnapWriter** ppWriter) {
- int32_t code = 0;
- int32_t lino = 0;
-
- // alloc
- STsdbSnapWriter* pWriter = (STsdbSnapWriter*)taosMemoryCalloc(1, sizeof(*pWriter));
- if (pWriter == NULL) {
- code = TSDB_CODE_OUT_OF_MEMORY;
- TSDB_CHECK_CODE(code, lino, _exit);
- }
- pWriter->pTsdb = pTsdb;
- pWriter->sver = sver;
- pWriter->ever = ever;
- pWriter->minutes = pTsdb->keepCfg.days;
- pWriter->precision = pTsdb->keepCfg.precision;
- pWriter->minRow = pTsdb->pVnode->config.tsdbCfg.minRows;
- pWriter->maxRow = pTsdb->pVnode->config.tsdbCfg.maxRows;
- pWriter->cmprAlg = pTsdb->pVnode->config.tsdbCfg.compression;
- pWriter->commitID = pTsdb->pVnode->state.commitID;
-
- code = tsdbFSCopy(pTsdb, &pWriter->fs);
- TSDB_CHECK_CODE(code, lino, _exit);
-
- // SNAP_DATA_TSDB
- code = tBlockDataCreate(&pWriter->inData);
- TSDB_CHECK_CODE(code, lino, _exit);
-
- pWriter->fid = INT32_MIN;
-
- code = tBlockDataCreate(&pWriter->bData);
- TSDB_CHECK_CODE(code, lino, _exit);
-
- code = tBlockDataCreate(&pWriter->sData);
- TSDB_CHECK_CODE(code, lino, _exit);
-
- // SNAP_DATA_DEL
-
-_exit:
- if (code) {
- tsdbError("vgId:%d %s failed at line %d since %s", TD_VID(pTsdb->pVnode), __func__, lino, tstrerror(code));
- if (pWriter) {
- tBlockDataDestroy(&pWriter->sData);
- tBlockDataDestroy(&pWriter->bData);
- tBlockDataDestroy(&pWriter->inData);
- tsdbFSDestroy(&pWriter->fs);
- taosMemoryFree(pWriter);
- pWriter = NULL;
- }
} else {
tsdbInfo("vgId:%d %s done, sver:%" PRId64 " ever:%" PRId64, TD_VID(pTsdb->pVnode), __func__, sver, ever);
}
- *ppWriter = pWriter;
return code;
}
-int32_t tsdbSnapWriterPrepareClose(STsdbSnapWriter* pWriter) {
+int32_t tsdbSnapWriterPrepareClose(STsdbSnapWriter* writer) {
int32_t code = 0;
int32_t lino = 0;
- if (pWriter->pDataFWriter) {
- code = tsdbSnapWriteFileDataEnd(pWriter);
- TSDB_CHECK_CODE(code, lino, _exit);
- }
+ code = tsdbSnapWriteFileSetEnd(writer);
+ TSDB_CHECK_CODE(code, lino, _exit);
- if (pWriter->pDelFWriter) {
- code = tsdbSnapWriteDelDataEnd(pWriter);
- TSDB_CHECK_CODE(code, lino, _exit);
- }
-
- code = tsdbFSPrepareCommit(pWriter->pTsdb, &pWriter->fs);
+ code = tsdbFSEditBegin(writer->tsdb->pFS, writer->fopArr, TSDB_FEDIT_COMMIT);
TSDB_CHECK_CODE(code, lino, _exit);
_exit:
if (code) {
- tsdbError("vgId:%d %s failed at line %d since %s", TD_VID(pWriter->pTsdb->pVnode), __func__, lino, tstrerror(code));
+ TSDB_ERROR_LOG(TD_VID(writer->tsdb->pVnode), lino, code);
} else {
- tsdbDebug("vgId:%d %s done", TD_VID(pWriter->pTsdb->pVnode), __func__);
+ tsdbDebug("vgId:%d %s done", TD_VID(writer->tsdb->pVnode), __func__);
}
return code;
}
-int32_t tsdbSnapWriterClose(STsdbSnapWriter** ppWriter, int8_t rollback) {
+int32_t tsdbSnapWriterClose(STsdbSnapWriter** writer, int8_t rollback) {
+ if (writer[0] == NULL) return 0;
+
int32_t code = 0;
int32_t lino = 0;
- STsdbSnapWriter* pWriter = *ppWriter;
- STsdb* pTsdb = pWriter->pTsdb;
+ STsdb* tsdb = writer[0]->tsdb;
if (rollback) {
- tsdbRollbackCommit(pWriter->pTsdb);
+ code = tsdbFSEditAbort(writer[0]->tsdb->pFS);
+ TSDB_CHECK_CODE(code, lino, _exit);
} else {
- // lock
- taosThreadRwlockWrlock(&pTsdb->rwLock);
+ taosThreadRwlockWrlock(&writer[0]->tsdb->rwLock);
- code = tsdbFSCommit(pWriter->pTsdb);
+ code = tsdbFSEditCommit(writer[0]->tsdb->pFS);
if (code) {
- taosThreadRwlockUnlock(&pTsdb->rwLock);
+ taosThreadRwlockUnlock(&writer[0]->tsdb->rwLock);
TSDB_CHECK_CODE(code, lino, _exit);
}
- // unlock
- taosThreadRwlockUnlock(&pTsdb->rwLock);
+ taosThreadRwlockUnlock(&writer[0]->tsdb->rwLock);
}
- // SNAP_DATA_DEL
- taosArrayDestroy(pWriter->aDelData);
- taosArrayDestroy(pWriter->aDelIdx);
+ tsdbIterMergerClose(&writer[0]->ctx->tombIterMerger);
+ tsdbIterMergerClose(&writer[0]->ctx->dataIterMerger);
+ TARRAY2_DESTROY(writer[0]->ctx->tombIterArr, tsdbIterClose);
+ TARRAY2_DESTROY(writer[0]->ctx->dataIterArr, tsdbIterClose);
+ TARRAY2_DESTROY(writer[0]->ctx->sttReaderArr, tsdbSttFileReaderClose);
+ tsdbDataFileReaderClose(&writer[0]->ctx->dataReader);
- // SNAP_DATA_TSDB
- tBlockDataDestroy(&pWriter->sData);
- tBlockDataDestroy(&pWriter->bData);
- taosArrayDestroy(pWriter->aSttBlk);
- tMapDataClear(&pWriter->mDataBlk);
- taosArrayDestroy(pWriter->aBlockIdx);
- tDestroyTSchema(pWriter->skmTable.pTSchema);
- tBlockDataDestroy(&pWriter->inData);
+ TARRAY2_DESTROY(writer[0]->fopArr, NULL);
+ tsdbFSDestroyCopySnapshot(&writer[0]->fsetArr);
- for (int32_t iBuf = 0; iBuf < sizeof(pWriter->aBuf) / sizeof(uint8_t*); iBuf++) {
- tFree(pWriter->aBuf[iBuf]);
+ for (int32_t i = 0; i < ARRAY_SIZE(writer[0]->aBuf); ++i) {
+ tFree(writer[0]->aBuf[i]);
}
- tsdbFSDestroy(&pWriter->fs);
- taosMemoryFree(pWriter);
- *ppWriter = NULL;
+
+ taosMemoryFree(writer[0]);
+ writer[0] = NULL;
_exit:
if (code) {
- tsdbError("vgId:%d %s failed at line %d since %s", TD_VID(pTsdb->pVnode), __func__, lino, tstrerror(code));
+ TSDB_ERROR_LOG(TD_VID(tsdb->pVnode), lino, code);
} else {
- tsdbInfo("vgId:%d %s done", TD_VID(pTsdb->pVnode), __func__);
+ tsdbInfo("vgId:%d %s done", TD_VID(tsdb->pVnode), __func__);
}
return code;
}
-int32_t tsdbSnapWrite(STsdbSnapWriter* pWriter, SSnapDataHdr* pHdr) {
+int32_t tsdbSnapWrite(STsdbSnapWriter* writer, SSnapDataHdr* hdr) {
int32_t code = 0;
int32_t lino = 0;
- if (pHdr->type == SNAP_DATA_TSDB) {
- code = tsdbSnapWriteTimeSeriesData(pWriter, pHdr);
+ if (hdr->type == SNAP_DATA_TSDB) {
+ code = tsdbSnapWriteTimeSeriesData(writer, hdr);
TSDB_CHECK_CODE(code, lino, _exit);
- goto _exit;
- } else if (pWriter->pDataFWriter) {
- code = tsdbSnapWriteFileDataEnd(pWriter);
+ } else if (hdr->type == SNAP_DATA_DEL) {
+ code = tsdbSnapWriteTombData(writer, hdr);
TSDB_CHECK_CODE(code, lino, _exit);
- }
-
- if (pHdr->type == SNAP_DATA_DEL) {
- code = tsdbSnapWriteDelData(pWriter, pHdr);
- TSDB_CHECK_CODE(code, lino, _exit);
- goto _exit;
+ } else {
+ ASSERT(0);
}
_exit:
if (code) {
tsdbError("vgId:%d %s failed at line %d since %s, type:%d index:%" PRId64 " size:%" PRId64,
- TD_VID(pWriter->pTsdb->pVnode), __func__, lino, tstrerror(code), pHdr->type, pHdr->index, pHdr->size);
+ TD_VID(writer->tsdb->pVnode), __func__, lino, tstrerror(code), hdr->type, hdr->index, hdr->size);
} else {
- tsdbDebug("vgId:%d %s done, type:%d index:%" PRId64 " size:%" PRId64, TD_VID(pWriter->pTsdb->pVnode), __func__,
- pHdr->type, pHdr->index, pHdr->size);
+ tsdbDebug("vgId:%d %s done, type:%d index:%" PRId64 " size:%" PRId64, TD_VID(writer->tsdb->pVnode), __func__,
+ hdr->type, hdr->index, hdr->size);
}
return code;
}
diff --git a/source/dnode/vnode/src/tsdb/tsdbSttFileRW.c b/source/dnode/vnode/src/tsdb/tsdbSttFileRW.c
index 3ff0191ce6..97a2a8b478 100644
--- a/source/dnode/vnode/src/tsdb/tsdbSttFileRW.c
+++ b/source/dnode/vnode/src/tsdb/tsdbSttFileRW.c
@@ -654,7 +654,17 @@ static int32_t tsdbSttFWriterDoOpen(SSttFileWriter *writer) {
if (!writer->config->skmRow) writer->config->skmRow = writer->skmRow;
if (!writer->config->bufArr) writer->config->bufArr = writer->bufArr;
- writer->file[0] = writer->config->file;
+ writer->file[0] = (STFile){
+ .type = TSDB_FTYPE_STT,
+ .did = writer->config->did,
+ .fid = writer->config->fid,
+ .cid = writer->config->cid,
+ .size = 0,
+ .stt[0] =
+ {
+ .level = writer->config->level,
+ },
+ };
// open file
int32_t flag = TD_FILE_READ | TD_FILE_WRITE | TD_FILE_CREATE | TD_FILE_TRUNC;
@@ -735,7 +745,7 @@ static int32_t tsdbSttFWriterCloseCommit(SSttFileWriter *writer, TFileOpArray *o
ASSERT(writer->file->size > 0);
STFileOp op = (STFileOp){
.optype = TSDB_FOP_CREATE,
- .fid = writer->config->file.fid,
+ .fid = writer->config->fid,
.nf = writer->file[0],
};
@@ -751,16 +761,13 @@ _exit:
static int32_t tsdbSttFWriterCloseAbort(SSttFileWriter *writer) {
char fname[TSDB_FILENAME_LEN];
- tsdbTFileName(writer->config->tsdb, &writer->config->file, fname);
+ tsdbTFileName(writer->config->tsdb, writer->file, fname);
tsdbCloseFile(&writer->fd);
taosRemoveFile(fname);
return 0;
}
int32_t tsdbSttFileWriterOpen(const SSttFileWriterConfig *config, SSttFileWriter **writer) {
- ASSERT(config->file.type == TSDB_FTYPE_STT);
- ASSERT(config->file.size == 0);
-
writer[0] = taosMemoryCalloc(1, sizeof(*writer[0]));
if (writer[0] == NULL) return TSDB_CODE_OUT_OF_MEMORY;
diff --git a/source/dnode/vnode/src/tsdb/tsdbSttFileRW.h b/source/dnode/vnode/src/tsdb/tsdbSttFileRW.h
index f3b2e66ab2..b26d2f743a 100644
--- a/source/dnode/vnode/src/tsdb/tsdbSttFileRW.h
+++ b/source/dnode/vnode/src/tsdb/tsdbSttFileRW.h
@@ -71,7 +71,10 @@ struct SSttFileWriterConfig {
int32_t szPage;
int8_t cmprAlg;
int64_t compactVersion;
- STFile file;
+ SDiskID did;
+ int32_t fid;
+ int64_t cid;
+ int32_t level;
SSkmInfo *skmTb;
SSkmInfo *skmRow;
uint8_t **bufArr;
diff --git a/source/dnode/vnode/src/vnd/vnodeSvr.c b/source/dnode/vnode/src/vnd/vnodeSvr.c
index c2e577848b..5f866dee69 100644
--- a/source/dnode/vnode/src/vnd/vnodeSvr.c
+++ b/source/dnode/vnode/src/vnd/vnodeSvr.c
@@ -593,9 +593,7 @@ int32_t vnodeProcessFetchMsg(SVnode *pVnode, SRpcMsg *pMsg, SQueueInfo *pInfo) {
}
}
-// TODO: remove the function
void smaHandleRes(void *pVnode, int64_t smaId, const SArray *data) {
- // TODO
// blockDebugShowDataBlocks(data, __func__);
tdProcessTSmaInsert(((SVnode *)pVnode)->pSma, smaId, (const char *)data);
}
diff --git a/source/libs/command/inc/commandInt.h b/source/libs/command/inc/commandInt.h
index 2a435b43e8..2a7aeb0060 100644
--- a/source/libs/command/inc/commandInt.h
+++ b/source/libs/command/inc/commandInt.h
@@ -145,7 +145,7 @@ typedef struct SExplainCtx {
SHashObj *groupHash; // Hash
} SExplainCtx;
-#define EXPLAIN_ORDER_STRING(_order) ((ORDER_ASC == _order) ? "asc" : "desc")
+#define EXPLAIN_ORDER_STRING(_order) ((ORDER_ASC == _order) ? "asc" : ORDER_DESC == _order ? "desc" : "unknown")
#define EXPLAIN_JOIN_STRING(_type) ((JOIN_TYPE_INNER == _type) ? "Inner join" : "Join")
#define INVERAL_TIME_FROM_PRECISION_TO_UNIT(_t, _u, _p) (((_u) == 'n' || (_u) == 'y') ? (_t) : (convertTimeFromPrecisionToUnit(_t, _p, _u)))
diff --git a/source/libs/command/src/explain.c b/source/libs/command/src/explain.c
index c5b9eb7475..884c0f7b20 100644
--- a/source/libs/command/src/explain.c
+++ b/source/libs/command/src/explain.c
@@ -499,6 +499,9 @@ int32_t qExplainResNodeToRowsImpl(SExplainResNode *pResNode, SExplainCtx *ctx, i
EXPLAIN_ROW_APPEND(EXPLAIN_COLUMNS_FORMAT, pPrjNode->pProjections->length);
EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
EXPLAIN_ROW_APPEND(EXPLAIN_WIDTH_FORMAT, pPrjNode->node.pOutputDataBlockDesc->totalRowSize);
+ EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
+ EXPLAIN_ROW_APPEND(EXPLAIN_INPUT_ORDER_FORMAT, EXPLAIN_ORDER_STRING(pPrjNode->node.inputTsOrder));
+ EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
EXPLAIN_ROW_APPEND(EXPLAIN_RIGHT_PARENTHESIS_FORMAT);
EXPLAIN_ROW_END();
QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level));
@@ -544,6 +547,9 @@ int32_t qExplainResNodeToRowsImpl(SExplainResNode *pResNode, SExplainCtx *ctx, i
EXPLAIN_ROW_APPEND(EXPLAIN_COLUMNS_FORMAT, pJoinNode->pTargets->length);
EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
EXPLAIN_ROW_APPEND(EXPLAIN_WIDTH_FORMAT, pJoinNode->node.pOutputDataBlockDesc->totalRowSize);
+ EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
+ EXPLAIN_ROW_APPEND(EXPLAIN_INPUT_ORDER_FORMAT, EXPLAIN_ORDER_STRING(pJoinNode->node.inputTsOrder));
+ EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
EXPLAIN_ROW_APPEND(EXPLAIN_RIGHT_PARENTHESIS_FORMAT);
EXPLAIN_ROW_END();
QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level));
@@ -597,6 +603,9 @@ int32_t qExplainResNodeToRowsImpl(SExplainResNode *pResNode, SExplainCtx *ctx, i
EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
EXPLAIN_ROW_APPEND(EXPLAIN_GROUPS_FORMAT, pAggNode->pGroupKeys->length);
}
+ EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
+ EXPLAIN_ROW_APPEND(EXPLAIN_INPUT_ORDER_FORMAT, EXPLAIN_ORDER_STRING(pAggNode->node.inputTsOrder));
+ EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
EXPLAIN_ROW_APPEND(EXPLAIN_RIGHT_PARENTHESIS_FORMAT);
EXPLAIN_ROW_END();
QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level));
@@ -716,6 +725,11 @@ int32_t qExplainResNodeToRowsImpl(SExplainResNode *pResNode, SExplainCtx *ctx, i
case QUERY_NODE_PHYSICAL_PLAN_SORT: {
SSortPhysiNode *pSortNode = (SSortPhysiNode *)pNode;
EXPLAIN_ROW_NEW(level, EXPLAIN_SORT_FORMAT);
+ EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
+ EXPLAIN_ROW_APPEND(EXPLAIN_INPUT_ORDER_FORMAT, EXPLAIN_ORDER_STRING(pSortNode->node.inputTsOrder));
+ EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
+ EXPLAIN_ROW_APPEND(EXPLAIN_OUTPUT_ORDER_TYPE_FORMAT, EXPLAIN_ORDER_STRING(pSortNode->node.outputTsOrder));
+ EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
EXPLAIN_ROW_APPEND(EXPLAIN_LEFT_PARENTHESIS_FORMAT);
if (pResNode->pExecInfo) {
QRY_ERR_RET(qExplainBufAppendExecInfo(pResNode->pExecInfo, tbuf, &tlen));
@@ -796,9 +810,10 @@ int32_t qExplainResNodeToRowsImpl(SExplainResNode *pResNode, SExplainCtx *ctx, i
EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
EXPLAIN_ROW_APPEND(EXPLAIN_WIDTH_FORMAT, pIntNode->window.node.pOutputDataBlockDesc->totalRowSize);
EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
- EXPLAIN_ROW_APPEND(EXPLAIN_INPUT_ORDER_FORMAT, EXPLAIN_ORDER_STRING(pIntNode->window.inputTsOrder));
+ EXPLAIN_ROW_APPEND(EXPLAIN_INPUT_ORDER_FORMAT, EXPLAIN_ORDER_STRING(pIntNode->window.node.inputTsOrder));
+ EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
+ EXPLAIN_ROW_APPEND(EXPLAIN_OUTPUT_ORDER_TYPE_FORMAT, EXPLAIN_ORDER_STRING(pIntNode->window.node.outputTsOrder));
EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
- EXPLAIN_ROW_APPEND(EXPLAIN_OUTPUT_ORDER_TYPE_FORMAT, EXPLAIN_ORDER_STRING(pIntNode->window.outputTsOrder));
EXPLAIN_ROW_APPEND(EXPLAIN_RIGHT_PARENTHESIS_FORMAT);
EXPLAIN_ROW_END();
QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level));
@@ -847,6 +862,10 @@ int32_t qExplainResNodeToRowsImpl(SExplainResNode *pResNode, SExplainCtx *ctx, i
EXPLAIN_ROW_APPEND(EXPLAIN_FUNCTIONS_FORMAT, pIntNode->window.pFuncs->length);
EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
EXPLAIN_ROW_APPEND(EXPLAIN_WIDTH_FORMAT, pIntNode->window.node.pOutputDataBlockDesc->totalRowSize);
+ EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
+ EXPLAIN_ROW_APPEND(EXPLAIN_INPUT_ORDER_FORMAT, EXPLAIN_ORDER_STRING(pIntNode->window.node.inputTsOrder));
+ EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
+ EXPLAIN_ROW_APPEND(EXPLAIN_OUTPUT_ORDER_TYPE_FORMAT, EXPLAIN_ORDER_STRING(pIntNode->window.node.outputTsOrder));
EXPLAIN_ROW_APPEND(EXPLAIN_RIGHT_PARENTHESIS_FORMAT);
EXPLAIN_ROW_END();
QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level));
@@ -895,6 +914,9 @@ int32_t qExplainResNodeToRowsImpl(SExplainResNode *pResNode, SExplainCtx *ctx, i
EXPLAIN_ROW_APPEND(EXPLAIN_MODE_FORMAT, nodesGetFillModeString(pFillNode->mode));
EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
EXPLAIN_ROW_APPEND(EXPLAIN_WIDTH_FORMAT, pFillNode->node.pOutputDataBlockDesc->totalRowSize);
+ EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
+ EXPLAIN_ROW_APPEND(EXPLAIN_INPUT_ORDER_FORMAT, EXPLAIN_ORDER_STRING(pFillNode->node.inputTsOrder));
+ EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
EXPLAIN_ROW_APPEND(EXPLAIN_RIGHT_PARENTHESIS_FORMAT);
EXPLAIN_ROW_END();
QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level));
@@ -1080,6 +1102,10 @@ int32_t qExplainResNodeToRowsImpl(SExplainResNode *pResNode, SExplainCtx *ctx, i
EXPLAIN_ROW_APPEND(EXPLAIN_COLUMNS_FORMAT, nodesGetOutputNumFromSlotList(pDescNode->pSlots));
EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
EXPLAIN_ROW_APPEND(EXPLAIN_WIDTH_FORMAT, pDescNode->totalRowSize);
+ EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
+ EXPLAIN_ROW_APPEND(EXPLAIN_INPUT_ORDER_FORMAT, EXPLAIN_ORDER_STRING(pMergeNode->node.inputTsOrder));
+ EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT);
+ EXPLAIN_ROW_APPEND(EXPLAIN_OUTPUT_ORDER_TYPE_FORMAT, EXPLAIN_ORDER_STRING(pMergeNode->node.outputTsOrder));
EXPLAIN_ROW_APPEND(EXPLAIN_RIGHT_PARENTHESIS_FORMAT);
EXPLAIN_ROW_END();
QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level));
diff --git a/source/libs/executor/inc/executorInt.h b/source/libs/executor/inc/executorInt.h
index 38890f8c34..5d663df50e 100644
--- a/source/libs/executor/inc/executorInt.h
+++ b/source/libs/executor/inc/executorInt.h
@@ -399,6 +399,8 @@ typedef struct SOptrBasicInfo {
SResultRowInfo resultRowInfo;
SSDataBlock* pRes;
bool mergeResultBlock;
+ int32_t inputTsOrder;
+ int32_t outputTsOrder;
} SOptrBasicInfo;
typedef struct SIntervalAggOperatorInfo {
@@ -411,8 +413,6 @@ typedef struct SIntervalAggOperatorInfo {
STimeWindow win; // query time range
bool timeWindowInterpo; // interpolation needed or not
SArray* pInterpCols; // interpolation columns
- int32_t resultTsOrder; // result timestamp order
- int32_t inputOrder; // input data ts order
EOPTR_EXEC_MODEL execModel; // operator execution model [batch model|stream model]
STimeWindowAggSupp twAggSup;
SArray* pPrevValues; // SArray used to keep the previous not null value for interpolation.
diff --git a/source/libs/executor/inc/tsort.h b/source/libs/executor/inc/tsort.h
index d51a24bb43..e0718a0c0a 100644
--- a/source/libs/executor/inc/tsort.h
+++ b/source/libs/executor/inc/tsort.h
@@ -146,7 +146,7 @@ void* tsortGetValue(STupleHandle* pVHandle, int32_t colId);
* @return
*/
uint64_t tsortGetGroupId(STupleHandle* pVHandle);
-
+void* tsortGetBlockInfo(STupleHandle* pVHandle);
/**
*
* @param pSortHandle
diff --git a/source/libs/executor/src/aggregateoperator.c b/source/libs/executor/src/aggregateoperator.c
index a32f482007..be0ad1c239 100644
--- a/source/libs/executor/src/aggregateoperator.c
+++ b/source/libs/executor/src/aggregateoperator.c
@@ -108,6 +108,8 @@ SOperatorInfo* createAggregateOperatorInfo(SOperatorInfo* downstream, SAggPhysiN
pInfo->binfo.mergeResultBlock = pAggNode->mergeDataBlock;
pInfo->groupKeyOptimized = pAggNode->groupKeyOptimized;
pInfo->groupId = UINT64_MAX;
+ pInfo->binfo.inputTsOrder = pAggNode->node.inputTsOrder;
+ pInfo->binfo.outputTsOrder = pAggNode->node.outputTsOrder;
setOperatorInfo(pOperator, "TableAggregate", QUERY_NODE_PHYSICAL_PLAN_HASH_AGG, true, OP_NOT_OPENED, pInfo,
pTaskInfo);
@@ -164,10 +166,8 @@ int32_t doOpenAggregateOptr(SOperatorInfo* pOperator) {
SOperatorInfo* downstream = pOperator->pDownstream[0];
int64_t st = taosGetTimestampUs();
-
- int32_t order = TSDB_ORDER_ASC;
- int32_t scanFlag = MAIN_SCAN;
-
+ int32_t code = TSDB_CODE_SUCCESS;
+ int32_t order = pAggInfo->binfo.inputTsOrder;
bool hasValidBlock = false;
while (1) {
@@ -185,12 +185,7 @@ int32_t doOpenAggregateOptr(SOperatorInfo* pOperator) {
}
}
hasValidBlock = true;
-
- int32_t code = getTableScanInfo(pOperator, &order, &scanFlag, false);
- if (code != TSDB_CODE_SUCCESS) {
- destroyDataBlockForEmptyInput(blockAllocated, &pBlock);
- T_LONG_JMP(pTaskInfo->env, code);
- }
+ pAggInfo->binfo.pRes->info.scanFlag = pBlock->info.scanFlag;
// there is an scalar expression that needs to be calculated before apply the group aggregation.
if (pAggInfo->scalarExprSup.pExprInfo != NULL && !blockAllocated) {
@@ -204,7 +199,7 @@ int32_t doOpenAggregateOptr(SOperatorInfo* pOperator) {
// the pDataBlock are always the same one, no need to call this again
setExecutionContext(pOperator, pOperator->exprSupp.numOfExprs, pBlock->info.id.groupId);
- setInputDataBlock(pSup, pBlock, order, scanFlag, true);
+ setInputDataBlock(pSup, pBlock, order, pBlock->info.scanFlag, true);
code = doAggregateImpl(pOperator, pSup->pCtx);
if (code != 0) {
destroyDataBlockForEmptyInput(blockAllocated, &pBlock);
diff --git a/source/libs/executor/src/cachescanoperator.c b/source/libs/executor/src/cachescanoperator.c
index 48003b277b..ce39ebab59 100644
--- a/source/libs/executor/src/cachescanoperator.c
+++ b/source/libs/executor/src/cachescanoperator.c
@@ -208,6 +208,7 @@ SSDataBlock* doScanCache(SOperatorInfo* pOperator) {
pRes->info.id.uid = *(tb_uid_t*)taosArrayGet(pInfo->pUidList, pInfo->indexOfBufferedRes);
pRes->info.rows = 1;
+ pRes->info.scanFlag = MAIN_SCAN;
SExprSupp* pSup = &pInfo->pseudoExprSup;
int32_t code = addTagPseudoColumnData(&pInfo->readHandle, pSup->pExprInfo, pSup->numOfExprs, pRes,
diff --git a/source/libs/executor/src/eventwindowoperator.c b/source/libs/executor/src/eventwindowoperator.c
index f7dddf6b29..bbdc50183e 100644
--- a/source/libs/executor/src/eventwindowoperator.c
+++ b/source/libs/executor/src/eventwindowoperator.c
@@ -120,6 +120,8 @@ SOperatorInfo* createEventwindowOperatorInfo(SOperatorInfo* downstream, SPhysiNo
initBasicInfo(&pInfo->binfo, pResBlock);
initResultRowInfo(&pInfo->binfo.resultRowInfo);
+ pInfo->binfo.inputTsOrder = physiNode->inputTsOrder;
+ pInfo->binfo.outputTsOrder = physiNode->outputTsOrder;
pInfo->twAggSup = (STimeWindowAggSupp){.waterMark = pEventWindowNode->window.watermark,
.calTrigger = pEventWindowNode->window.triggerType};
@@ -183,7 +185,7 @@ static SSDataBlock* eventWindowAggregate(SOperatorInfo* pOperator) {
SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
SExprSupp* pSup = &pOperator->exprSupp;
- int32_t order = TSDB_ORDER_ASC;
+ int32_t order = pInfo->binfo.inputTsOrder;
SSDataBlock* pRes = pInfo->binfo.pRes;
@@ -196,6 +198,7 @@ static SSDataBlock* eventWindowAggregate(SOperatorInfo* pOperator) {
break;
}
+ pRes->info.scanFlag = pBlock->info.scanFlag;
setInputDataBlock(pSup, pBlock, order, MAIN_SCAN, true);
blockDataUpdateTsWindow(pBlock, pInfo->tsSlotId);
diff --git a/source/libs/executor/src/exchangeoperator.c b/source/libs/executor/src/exchangeoperator.c
index 94041140d4..4fbe6785a3 100644
--- a/source/libs/executor/src/exchangeoperator.c
+++ b/source/libs/executor/src/exchangeoperator.c
@@ -520,6 +520,7 @@ int32_t extractDataBlockFromFetchRsp(SSDataBlock* pRes, char* pData, SArray* pCo
// data from mnode
pRes->info.dataLoad = 1;
pRes->info.rows = pBlock->info.rows;
+ pRes->info.scanFlag = MAIN_SCAN;
relocateColumnData(pRes, pColList, pBlock->pDataBlock, false);
blockDataDestroy(pBlock);
}
diff --git a/source/libs/executor/src/filloperator.c b/source/libs/executor/src/filloperator.c
index f9e8a32520..1106c6e29f 100644
--- a/source/libs/executor/src/filloperator.c
+++ b/source/libs/executor/src/filloperator.c
@@ -178,16 +178,15 @@ static SSDataBlock* doFillImpl(SOperatorInfo* pOperator) {
blockDataCleanup(pResBlock);
- int32_t order = TSDB_ORDER_ASC;
- int32_t scanFlag = MAIN_SCAN;
- getTableScanInfo(pOperator, &order, &scanFlag, false);
+ int32_t order = pInfo->pFillInfo->order;
SOperatorInfo* pDownstream = pOperator->pDownstream[0];
-
+#if 0
// the scan order may be different from the output result order for agg interval operator.
if (pDownstream->operatorType == QUERY_NODE_PHYSICAL_PLAN_HASH_INTERVAL) {
order = ((SIntervalAggOperatorInfo*) pDownstream->info)->resultTsOrder;
}
+#endif
doHandleRemainBlockFromNewGroup(pOperator, pInfo, pResultInfo, order);
if (pResBlock->info.rows > 0) {
@@ -206,13 +205,14 @@ static SSDataBlock* doFillImpl(SOperatorInfo* pOperator) {
taosFillSetStartInfo(pInfo->pFillInfo, 0, pInfo->win.ekey);
} else {
+ pResBlock->info.scanFlag = pBlock->info.scanFlag;
pBlock->info.dataLoad = 1;
blockDataUpdateTsWindow(pBlock, pInfo->primarySrcSlotId);
blockDataCleanup(pInfo->pRes);
blockDataEnsureCapacity(pInfo->pRes, pBlock->info.rows);
blockDataEnsureCapacity(pInfo->pFinalRes, pBlock->info.rows);
- doApplyScalarCalculation(pOperator, pBlock, order, scanFlag);
+ doApplyScalarCalculation(pOperator, pBlock, order, pBlock->info.scanFlag);
if (pInfo->curGroupId == 0 || (pInfo->curGroupId == pInfo->pRes->info.id.groupId)) {
if (pInfo->curGroupId == 0 && taosFillNotStarted(pInfo->pFillInfo)) {
@@ -405,7 +405,7 @@ SOperatorInfo* createFillOperatorInfo(SOperatorInfo* downstream, SFillPhysiNode*
? &((SMergeAlignedIntervalAggOperatorInfo*)downstream->info)->intervalAggOperatorInfo->interval
: &((SIntervalAggOperatorInfo*)downstream->info)->interval;
- int32_t order = (pPhyFillNode->inputTsOrder == ORDER_ASC) ? TSDB_ORDER_ASC : TSDB_ORDER_DESC;
+ int32_t order = (pPhyFillNode->node.inputTsOrder == ORDER_ASC) ? TSDB_ORDER_ASC : TSDB_ORDER_DESC;
int32_t type = convertFillType(pPhyFillNode->mode);
SResultInfo* pResultInfo = &pOperator->resultInfo;
diff --git a/source/libs/executor/src/groupoperator.c b/source/libs/executor/src/groupoperator.c
index e3292bb063..57c22d56d3 100644
--- a/source/libs/executor/src/groupoperator.c
+++ b/source/libs/executor/src/groupoperator.c
@@ -378,9 +378,7 @@ static SSDataBlock* hashGroupbyAggregate(SOperatorInfo* pOperator) {
return buildGroupResultDataBlock(pOperator);
}
- int32_t order = TSDB_ORDER_ASC;
- int32_t scanFlag = MAIN_SCAN;
-
+ int32_t order = pInfo->binfo.inputTsOrder;
int64_t st = taosGetTimestampUs();
SOperatorInfo* downstream = pOperator->pDownstream[0];
@@ -390,13 +388,10 @@ static SSDataBlock* hashGroupbyAggregate(SOperatorInfo* pOperator) {
break;
}
- int32_t code = getTableScanInfo(pOperator, &order, &scanFlag, false);
- if (code != TSDB_CODE_SUCCESS) {
- T_LONG_JMP(pTaskInfo->env, code);
- }
+ pInfo->binfo.pRes->info.scanFlag = pBlock->info.scanFlag;
// the pDataBlock are always the same one, no need to call this again
- setInputDataBlock(&pOperator->exprSupp, pBlock, order, scanFlag, true);
+ setInputDataBlock(&pOperator->exprSupp, pBlock, order, pBlock->info.scanFlag, true);
// there is an scalar expression that needs to be calculated right before apply the group aggregation.
if (pInfo->scalarSup.pExprInfo != NULL) {
@@ -481,6 +476,8 @@ SOperatorInfo* createGroupOperatorInfo(SOperatorInfo* downstream, SAggPhysiNode*
setOperatorInfo(pOperator, "GroupbyAggOperator", 0, true, OP_NOT_OPENED, pInfo, pTaskInfo);
pInfo->binfo.mergeResultBlock = pAggNode->mergeDataBlock;
+ pInfo->binfo.inputTsOrder = pAggNode->node.inputTsOrder;
+ pInfo->binfo.outputTsOrder = pAggNode->node.outputTsOrder;
pOperator->fpSet = createOperatorFpSet(optrDummyOpenFn, hashGroupbyAggregate, NULL, destroyGroupOperatorInfo,
optrDefaultBufFn, NULL);
@@ -762,6 +759,7 @@ static SSDataBlock* hashPartition(SOperatorInfo* pOperator) {
break;
}
+ pInfo->binfo.pRes->info.scanFlag = pBlock->info.scanFlag;
// there is an scalar expression that needs to be calculated right before apply the group aggregation.
if (pInfo->scalarSup.pExprInfo != NULL) {
pTaskInfo->code = projectApplyFunctions(pInfo->scalarSup.pExprInfo, pBlock, pBlock, pInfo->scalarSup.pCtx,
diff --git a/source/libs/executor/src/joinoperator.c b/source/libs/executor/src/joinoperator.c
index 73143fdba7..13ab5d05a5 100644
--- a/source/libs/executor/src/joinoperator.c
+++ b/source/libs/executor/src/joinoperator.c
@@ -253,9 +253,9 @@ SOperatorInfo* createMergeJoinOperatorInfo(SOperatorInfo** pDownstream, int32_t
}
pInfo->inputOrder = TSDB_ORDER_ASC;
- if (pJoinNode->inputTsOrder == ORDER_ASC) {
+ if (pJoinNode->node.inputTsOrder == ORDER_ASC) {
pInfo->inputOrder = TSDB_ORDER_ASC;
- } else if (pJoinNode->inputTsOrder == ORDER_DESC) {
+ } else if (pJoinNode->node.inputTsOrder == ORDER_DESC) {
pInfo->inputOrder = TSDB_ORDER_DESC;
}
@@ -684,6 +684,7 @@ static void doMergeJoinImpl(struct SOperatorInfo* pOperator, SSDataBlock* pRes)
// the pDataBlock are always the same one, no need to call this again
pRes->info.rows = nrows;
pRes->info.dataLoad = 1;
+ pRes->info.scanFlag = MAIN_SCAN;
if (pRes->info.rows >= pOperator->resultInfo.threshold) {
break;
}
diff --git a/source/libs/executor/src/projectoperator.c b/source/libs/executor/src/projectoperator.c
index e7de826d4b..cd450c5bb7 100644
--- a/source/libs/executor/src/projectoperator.c
+++ b/source/libs/executor/src/projectoperator.c
@@ -93,6 +93,8 @@ SOperatorInfo* createProjectOperatorInfo(SOperatorInfo* downstream, SProjectPhys
pInfo->binfo.pRes = pResBlock;
pInfo->pFinalRes = createOneDataBlock(pResBlock, false);
+ pInfo->binfo.inputTsOrder = pProjPhyNode->node.inputTsOrder;
+ pInfo->binfo.outputTsOrder = pProjPhyNode->node.outputTsOrder;
if (pTaskInfo->execModel == OPTR_EXEC_MODEL_STREAM) {
pInfo->mergeDataBlocks = false;
@@ -238,8 +240,9 @@ SSDataBlock* doProjectOperation(SOperatorInfo* pOperator) {
}
int64_t st = 0;
- int32_t order = 0;
+ int32_t order = pInfo->inputTsOrder;
int32_t scanFlag = 0;
+ int32_t code = TSDB_CODE_SUCCESS;
if (pOperator->cost.openCost == 0) {
st = taosGetTimestampUs();
@@ -284,10 +287,10 @@ SSDataBlock* doProjectOperation(SOperatorInfo* pOperator) {
break;
}
- // the pDataBlock are always the same one, no need to call this again
- int32_t code = getTableScanInfo(downstream, &order, &scanFlag, false);
- if (code != TSDB_CODE_SUCCESS) {
- T_LONG_JMP(pTaskInfo->env, code);
+ if (pProjectInfo->mergeDataBlocks) {
+ pFinalRes->info.scanFlag = scanFlag = pBlock->info.scanFlag;
+ } else {
+ pRes->info.scanFlag = scanFlag = pBlock->info.scanFlag;
}
setInputDataBlock(pSup, pBlock, order, scanFlag, false);
@@ -406,6 +409,8 @@ SOperatorInfo* createIndefinitOutputOperatorInfo(SOperatorInfo* downstream, SPhy
}
pInfo->binfo.pRes = pResBlock;
+ pInfo->binfo.inputTsOrder = pNode->inputTsOrder;
+ pInfo->binfo.outputTsOrder = pNode->outputTsOrder;
pInfo->pPseudoColInfo = setRowTsColumnOutputInfo(pSup->pCtx, numOfExpr);
setOperatorInfo(pOperator, "IndefinitOperator", QUERY_NODE_PHYSICAL_PLAN_INDEF_ROWS_FUNC, false, OP_NOT_OPENED, pInfo,
@@ -429,18 +434,13 @@ _error:
static void doHandleDataBlock(SOperatorInfo* pOperator, SSDataBlock* pBlock, SOperatorInfo* downstream,
SExecTaskInfo* pTaskInfo) {
- int32_t order = 0;
- int32_t scanFlag = 0;
-
SIndefOperatorInfo* pIndefInfo = pOperator->info;
SOptrBasicInfo* pInfo = &pIndefInfo->binfo;
SExprSupp* pSup = &pOperator->exprSupp;
- // the pDataBlock are always the same one, no need to call this again
- int32_t code = getTableScanInfo(downstream, &order, &scanFlag, false);
- if (code != TSDB_CODE_SUCCESS) {
- T_LONG_JMP(pTaskInfo->env, code);
- }
+ int32_t order = pInfo->inputTsOrder;
+ int32_t scanFlag = pBlock->info.scanFlag;
+ int32_t code = TSDB_CODE_SUCCESS;
// there is an scalar expression that needs to be calculated before apply the group aggregation.
SExprSupp* pScalarSup = &pIndefInfo->scalarSup;
@@ -506,6 +506,7 @@ SSDataBlock* doApplyIndefinitFunction(SOperatorInfo* pOperator) {
setOperatorCompleted(pOperator);
break;
}
+ pInfo->pRes->info.scanFlag = pBlock->info.scanFlag;
if (pIndefInfo->groupId == 0 && pBlock->info.id.groupId != 0) {
pIndefInfo->groupId = pBlock->info.id.groupId; // this is the initial group result
diff --git a/source/libs/executor/src/scanoperator.c b/source/libs/executor/src/scanoperator.c
index 2702cf6861..2f108c83b0 100644
--- a/source/libs/executor/src/scanoperator.c
+++ b/source/libs/executor/src/scanoperator.c
@@ -712,6 +712,7 @@ static SSDataBlock* doTableScanImpl(SOperatorInfo* pOperator) {
pTableScanInfo->base.readRecorder.elapsedTime += (taosGetTimestampUs() - st) / 1000.0;
pOperator->cost.totalCost = pTableScanInfo->base.readRecorder.elapsedTime;
+ pBlock->info.scanFlag = pTableScanInfo->base.scanFlag;
return pBlock;
}
return NULL;
diff --git a/source/libs/executor/src/sortoperator.c b/source/libs/executor/src/sortoperator.c
index 0395b9ec08..8f287946f0 100644
--- a/source/libs/executor/src/sortoperator.c
+++ b/source/libs/executor/src/sortoperator.c
@@ -69,6 +69,8 @@ SOperatorInfo* createSortOperatorInfo(SOperatorInfo* downstream, SSortPhysiNode*
pInfo->binfo.pRes = createDataBlockFromDescNode(pDescNode);
pInfo->pSortInfo = createSortInfo(pSortNode->pSortKeys);
+ pInfo->binfo.inputTsOrder = pSortNode->node.inputTsOrder;
+ pInfo->binfo.outputTsOrder = pSortNode->node.outputTsOrder;
initLimitInfo(pSortNode->node.pLimit, pSortNode->node.pSlimit, &pInfo->limitInfo);
setOperatorInfo(pOperator, "SortOperator", QUERY_NODE_PHYSICAL_PLAN_SORT, true, OP_NOT_OPENED, pInfo, pTaskInfo);
@@ -114,6 +116,7 @@ void appendOneRowToDataBlock(SSDataBlock* pBlock, STupleHandle* pTupleHandle) {
}
pBlock->info.dataLoad = 1;
+ pBlock->info.scanFlag = ((SDataBlockInfo*)tsortGetBlockInfo(pTupleHandle))->scanFlag;
pBlock->info.rows += 1;
}
@@ -155,6 +158,7 @@ SSDataBlock* getSortedBlockData(SSortHandle* pHandle, SSDataBlock* pDataBlock, i
pDataBlock->info.dataLoad = 1;
pDataBlock->info.rows = p->info.rows;
+ pDataBlock->info.scanFlag = p->info.scanFlag;
}
blockDataDestroy(p);
@@ -331,6 +335,7 @@ SSDataBlock* getGroupSortedBlockData(SSortHandle* pHandle, SSDataBlock* pDataBlo
pDataBlock->info.rows = p->info.rows;
pDataBlock->info.capacity = p->info.rows;
+ pDataBlock->info.scanFlag = p->info.scanFlag;
}
blockDataDestroy(p);
@@ -505,6 +510,8 @@ SOperatorInfo* createGroupSortOperatorInfo(SOperatorInfo* downstream, SGroupSort
pInfo->binfo.pRes = createDataBlockFromDescNode(pDescNode);
blockDataEnsureCapacity(pInfo->binfo.pRes, pOperator->resultInfo.capacity);
+ pInfo->binfo.inputTsOrder = pSortPhyNode->node.inputTsOrder;
+ pInfo->binfo.outputTsOrder = pSortPhyNode->node.outputTsOrder;
int32_t numOfOutputCols = 0;
int32_t code = extractColMatchInfo(pSortPhyNode->pTargets, pDescNode, &numOfOutputCols, COL_MATCH_FROM_SLOT_ID,
@@ -698,6 +705,7 @@ SSDataBlock* getMultiwaySortedBlockData(SSortHandle* pHandle, SSDataBlock* pData
}
pDataBlock->info.rows = p->info.rows;
+ pDataBlock->info.scanFlag = p->info.scanFlag;
if (pInfo->ignoreGroupId) {
pDataBlock->info.id.groupId = 0;
} else {
@@ -799,6 +807,8 @@ SOperatorInfo* createMultiwayMergeOperatorInfo(SOperatorInfo** downStreams, size
size_t numOfCols = taosArrayGetSize(pInfo->binfo.pRes->pDataBlock);
pInfo->bufPageSize = getProperSortPageSize(rowSize, numOfCols);
pInfo->sortBufSize = pInfo->bufPageSize * (numStreams + 1); // one additional is reserved for merged result.
+ pInfo->binfo.inputTsOrder = pMergePhyNode->node.inputTsOrder;
+ pInfo->binfo.outputTsOrder = pMergePhyNode->node.outputTsOrder;
setOperatorInfo(pOperator, "MultiwayMergeOperator", QUERY_NODE_PHYSICAL_PLAN_MERGE, false, OP_NOT_OPENED, pInfo, pTaskInfo);
pOperator->fpSet = createOperatorFpSet(openMultiwayMergeOperator, doMultiwayMerge, NULL,
diff --git a/source/libs/executor/src/timesliceoperator.c b/source/libs/executor/src/timesliceoperator.c
index 2421343bd7..022440b2ad 100644
--- a/source/libs/executor/src/timesliceoperator.c
+++ b/source/libs/executor/src/timesliceoperator.c
@@ -44,6 +44,8 @@ typedef struct STimeSliceOperatorInfo {
uint64_t groupId;
SGroupKeys* pPrevGroupKey;
SSDataBlock* pNextGroupRes;
+ SSDataBlock* pRemainRes; // save block unfinished processing
+ int32_t remainIndex; // the remaining index in the block to be processed
} STimeSliceOperatorInfo;
static void destroyTimeSliceOperatorInfo(void* param);
@@ -644,13 +646,47 @@ static int32_t resetKeeperInfo(STimeSliceOperatorInfo* pInfo) {
return TSDB_CODE_SUCCESS;
}
+static bool checkThresholdReached(STimeSliceOperatorInfo* pSliceInfo, int32_t threshold) {
+ SSDataBlock* pResBlock = pSliceInfo->pRes;
+ if (pResBlock->info.rows > threshold) {
+ return true;
+ }
+
+ return false;
+}
+
+static bool checkWindowBoundReached(STimeSliceOperatorInfo* pSliceInfo) {
+ if (pSliceInfo->current > pSliceInfo->win.ekey) {
+ return true;
+ }
+
+ return false;
+}
+
+static void saveBlockStatus(STimeSliceOperatorInfo* pSliceInfo, SSDataBlock* pBlock, int32_t curIndex) {
+ SSDataBlock* pResBlock = pSliceInfo->pRes;
+
+ SColumnInfoData* pTsCol = taosArrayGet(pBlock->pDataBlock, pSliceInfo->tsCol.slotId);
+ if (curIndex < pBlock->info.rows - 1) {
+ pSliceInfo->pRemainRes = pBlock;
+ pSliceInfo->remainIndex = curIndex + 1;
+ return;
+ }
+
+ // all data in remaining block processed
+ pSliceInfo->pRemainRes = NULL;
+
+}
+
static void doTimesliceImpl(SOperatorInfo* pOperator, STimeSliceOperatorInfo* pSliceInfo, SSDataBlock* pBlock,
SExecTaskInfo* pTaskInfo, bool ignoreNull) {
SSDataBlock* pResBlock = pSliceInfo->pRes;
SInterval* pInterval = &pSliceInfo->interval;
SColumnInfoData* pTsCol = taosArrayGet(pBlock->pDataBlock, pSliceInfo->tsCol.slotId);
- for (int32_t i = 0; i < pBlock->info.rows; ++i) {
+
+ 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
@@ -662,10 +698,6 @@ static void doTimesliceImpl(SOperatorInfo* pOperator, STimeSliceOperatorInfo* pS
continue;
}
- if (pSliceInfo->current > pSliceInfo->win.ekey) {
- break;
- }
-
if (ts == pSliceInfo->current) {
addCurrentRowToResult(pSliceInfo, &pOperator->exprSupp, pResBlock, pBlock, i);
@@ -674,9 +706,14 @@ static void doTimesliceImpl(SOperatorInfo* pOperator, STimeSliceOperatorInfo* pS
pSliceInfo->current =
taosTimeAdd(pSliceInfo->current, pInterval->interval, pInterval->intervalUnit, pInterval->precision);
- if (pSliceInfo->current > pSliceInfo->win.ekey) {
+
+ if (checkWindowBoundReached(pSliceInfo)) {
break;
}
+ if (checkThresholdReached(pSliceInfo, pOperator->resultInfo.threshold)) {
+ saveBlockStatus(pSliceInfo, pBlock, i);
+ return;
+ }
} else if (ts < pSliceInfo->current) {
// in case of interpolation window starts and ends between two datapoints, fill(prev) need to interpolate
doKeepPrevRows(pSliceInfo, pBlock, i);
@@ -697,9 +734,13 @@ static void doTimesliceImpl(SOperatorInfo* pOperator, STimeSliceOperatorInfo* pS
}
}
- if (pSliceInfo->current > pSliceInfo->win.ekey) {
+ if (checkWindowBoundReached(pSliceInfo)) {
break;
}
+ if (checkThresholdReached(pSliceInfo, pOperator->resultInfo.threshold)) {
+ saveBlockStatus(pSliceInfo, pBlock, i);
+ return;
+ }
} else {
// ignore current row, and do nothing
}
@@ -730,11 +771,20 @@ static void doTimesliceImpl(SOperatorInfo* pOperator, STimeSliceOperatorInfo* pS
}
doKeepPrevRows(pSliceInfo, pBlock, i);
- if (pSliceInfo->current > pSliceInfo->win.ekey) {
+ if (checkWindowBoundReached(pSliceInfo)) {
break;
}
+ if (checkThresholdReached(pSliceInfo, pOperator->resultInfo.threshold)) {
+ saveBlockStatus(pSliceInfo, pBlock, i);
+ return;
+ }
}
}
+
+ // if reached here, meaning block processing finished naturally,
+ // or interpolation reach window upper bound
+ pSliceInfo->pRemainRes = NULL;
+
}
static void genInterpAfterDataBlock(STimeSliceOperatorInfo* pSliceInfo, SOperatorInfo* pOperator, int32_t index) {
@@ -781,39 +831,69 @@ static void resetTimesliceInfo(STimeSliceOperatorInfo* pSliceInfo) {
resetKeeperInfo(pSliceInfo);
}
+static void doHandleTimeslice(SOperatorInfo* pOperator, SSDataBlock* pBlock) {
+ SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
+
+ STimeSliceOperatorInfo* pSliceInfo = pOperator->info;
+ SExprSupp* pSup = &pOperator->exprSupp;
+ bool ignoreNull = getIgoreNullRes(pSup);
+ int32_t order = TSDB_ORDER_ASC;
+
+ int32_t code = initKeeperInfo(pSliceInfo, pBlock, &pOperator->exprSupp);
+ if (code != TSDB_CODE_SUCCESS) {
+ T_LONG_JMP(pTaskInfo->env, code);
+ }
+
+ if (pSliceInfo->scalarSup.pExprInfo != NULL) {
+ SExprSupp* pExprSup = &pSliceInfo->scalarSup;
+ projectApplyFunctions(pExprSup->pExprInfo, pBlock, pBlock, pExprSup->pCtx, pExprSup->numOfExprs, NULL);
+ }
+
+ // the pDataBlock are always the same one, no need to call this again
+ setInputDataBlock(pSup, pBlock, order, MAIN_SCAN, true);
+ doTimesliceImpl(pOperator, pSliceInfo, pBlock, pTaskInfo, ignoreNull);
+ copyPrevGroupKey(&pOperator->exprSupp, pSliceInfo->pPrevGroupKey, pBlock);
+}
+
static SSDataBlock* doTimeslice(SOperatorInfo* pOperator) {
if (pOperator->status == OP_EXEC_DONE) {
return NULL;
}
- SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
-
+ SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
STimeSliceOperatorInfo* pSliceInfo = pOperator->info;
SSDataBlock* pResBlock = pSliceInfo->pRes;
- SExprSupp* pSup = &pOperator->exprSupp;
- bool ignoreNull = getIgoreNullRes(pSup);
- int32_t order = TSDB_ORDER_ASC;
- SInterval* pInterval = &pSliceInfo->interval;
SOperatorInfo* downstream = pOperator->pDownstream[0];
-
blockDataCleanup(pResBlock);
while (1) {
if (pSliceInfo->pNextGroupRes != NULL) {
- setInputDataBlock(pSup, pSliceInfo->pNextGroupRes, order, MAIN_SCAN, true);
- doTimesliceImpl(pOperator, pSliceInfo, pSliceInfo->pNextGroupRes, pTaskInfo, ignoreNull);
- copyPrevGroupKey(&pOperator->exprSupp, pSliceInfo->pPrevGroupKey, pSliceInfo->pNextGroupRes);
+ doHandleTimeslice(pOperator, pSliceInfo->pNextGroupRes);
+ if (checkWindowBoundReached(pSliceInfo) || checkThresholdReached(pSliceInfo, pOperator->resultInfo.threshold)) {
+ doFilter(pResBlock, pOperator->exprSupp.pFilterInfo, NULL);
+ if (pSliceInfo->pRemainRes == NULL) {
+ pSliceInfo->pNextGroupRes = NULL;
+ }
+ if (pResBlock->info.rows != 0) {
+ goto _finished;
+ } else {
+ // after fillter if result block has 0 rows, go back to
+ // process pNextGroupRes again for unfinished data
+ continue;
+ }
+ }
pSliceInfo->pNextGroupRes = NULL;
}
while (1) {
- SSDataBlock* pBlock = downstream->fpSet.getNextFn(downstream);
+ SSDataBlock* pBlock = pSliceInfo->pRemainRes ? pSliceInfo->pRemainRes : downstream->fpSet.getNextFn(downstream);
if (pBlock == NULL) {
setOperatorCompleted(pOperator);
break;
}
+ pResBlock->info.scanFlag = pBlock->info.scanFlag;
if (pSliceInfo->groupId == 0 && pBlock->info.id.groupId != 0) {
pSliceInfo->groupId = pBlock->info.id.groupId;
} else {
@@ -824,21 +904,15 @@ static SSDataBlock* doTimeslice(SOperatorInfo* pOperator) {
}
}
- if (pSliceInfo->scalarSup.pExprInfo != NULL) {
- SExprSupp* pExprSup = &pSliceInfo->scalarSup;
- projectApplyFunctions(pExprSup->pExprInfo, pBlock, pBlock, pExprSup->pCtx, pExprSup->numOfExprs, NULL);
+ doHandleTimeslice(pOperator, pBlock);
+ if (checkWindowBoundReached(pSliceInfo) || checkThresholdReached(pSliceInfo, pOperator->resultInfo.threshold)) {
+ doFilter(pResBlock, pOperator->exprSupp.pFilterInfo, NULL);
+ if (pResBlock->info.rows != 0) {
+ goto _finished;
+ }
}
-
- int32_t code = initKeeperInfo(pSliceInfo, pBlock, &pOperator->exprSupp);
- if (code != TSDB_CODE_SUCCESS) {
- T_LONG_JMP(pTaskInfo->env, code);
- }
-
- // the pDataBlock are always the same one, no need to call this again
- setInputDataBlock(pSup, pBlock, order, MAIN_SCAN, true);
- doTimesliceImpl(pOperator, pSliceInfo, pBlock, pTaskInfo, ignoreNull);
- copyPrevGroupKey(&pOperator->exprSupp, pSliceInfo->pPrevGroupKey, pBlock);
}
+ // post work for a specific group
// check if need to interpolate after last datablock
// except for fill(next), fill(linear)
@@ -851,11 +925,12 @@ static SSDataBlock* doTimeslice(SOperatorInfo* pOperator) {
// restore initial value for next group
resetTimesliceInfo(pSliceInfo);
- if (pResBlock->info.rows >= 4096) {
+ if (pResBlock->info.rows != 0) {
break;
}
}
+_finished:
// restore the value
setTaskStatus(pOperator->pTaskInfo, TASK_COMPLETED);
if (pResBlock->info.rows == 0) {
@@ -911,6 +986,8 @@ SOperatorInfo* createTimeSliceOperatorInfo(SOperatorInfo* downstream, SPhysiNode
pInfo->groupId = 0;
pInfo->pPrevGroupKey = NULL;
pInfo->pNextGroupRes = NULL;
+ pInfo->pRemainRes = NULL;
+ pInfo->remainIndex = 0;
if (downstream->operatorType == QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN) {
STableScanInfo* pScanInfo = (STableScanInfo*)downstream->info;
diff --git a/source/libs/executor/src/timewindowoperator.c b/source/libs/executor/src/timewindowoperator.c
index 2676e097f9..f29ea5057e 100644
--- a/source/libs/executor/src/timewindowoperator.c
+++ b/source/libs/executor/src/timewindowoperator.c
@@ -355,7 +355,7 @@ static void setNotInterpoWindowKey(SqlFunctionCtx* pCtx, int32_t numOfOutput, in
static bool setTimeWindowInterpolationStartTs(SIntervalAggOperatorInfo* pInfo, int32_t pos, SSDataBlock* pBlock,
const TSKEY* tsCols, STimeWindow* win, SExprSupp* pSup) {
- bool ascQuery = (pInfo->inputOrder == TSDB_ORDER_ASC);
+ bool ascQuery = (pInfo->binfo.inputTsOrder == TSDB_ORDER_ASC);
TSKEY curTs = tsCols[pos];
@@ -385,7 +385,7 @@ static bool setTimeWindowInterpolationStartTs(SIntervalAggOperatorInfo* pInfo, i
static bool setTimeWindowInterpolationEndTs(SIntervalAggOperatorInfo* pInfo, SExprSupp* pSup, int32_t endRowIndex,
SArray* pDataBlock, const TSKEY* tsCols, TSKEY blockEkey,
STimeWindow* win) {
- int32_t order = pInfo->inputOrder;
+ int32_t order = pInfo->binfo.inputTsOrder;
TSKEY actualEndKey = tsCols[endRowIndex];
TSKEY key = (order == TSDB_ORDER_ASC) ? win->ekey : win->skey;
@@ -547,7 +547,7 @@ static void doWindowBorderInterpolation(SIntervalAggOperatorInfo* pInfo, SSDataB
if (!done) {
int32_t endRowIndex = startPos + forwardRows - 1;
- TSKEY endKey = (pInfo->inputOrder == TSDB_ORDER_ASC) ? pBlock->info.window.ekey : pBlock->info.window.skey;
+ TSKEY endKey = (pInfo->binfo.inputTsOrder == TSDB_ORDER_ASC) ? pBlock->info.window.ekey : pBlock->info.window.skey;
bool interp = setTimeWindowInterpolationEndTs(pInfo, pSup, endRowIndex, pBlock->pDataBlock, tsCols, endKey, win);
if (interp) {
setResultRowInterpo(pResult, RESULT_ROW_END_INTERP);
@@ -885,12 +885,12 @@ static void hashIntervalAgg(SOperatorInfo* pOperatorInfo, SResultRowInfo* pResul
int32_t numOfOutput = pSup->numOfExprs;
int64_t* tsCols = extractTsCol(pBlock, pInfo);
uint64_t tableGroupId = pBlock->info.id.groupId;
- bool ascScan = (pInfo->inputOrder == TSDB_ORDER_ASC);
+ bool ascScan = (pInfo->binfo.inputTsOrder == TSDB_ORDER_ASC);
TSKEY ts = getStartTsKey(&pBlock->info.window, tsCols);
SResultRow* pResult = NULL;
STimeWindow win =
- getActiveTimeWindow(pInfo->aggSup.pResultBuf, pResultRowInfo, ts, &pInfo->interval, pInfo->inputOrder);
+ getActiveTimeWindow(pInfo->aggSup.pResultBuf, pResultRowInfo, ts, &pInfo->interval, pInfo->binfo.inputTsOrder);
int32_t ret = setTimeWindowOutputBuf(pResultRowInfo, &win, (scanFlag == MAIN_SCAN), &pResult, tableGroupId,
pSup->pCtx, numOfOutput, pSup->rowEntryInfoOffset, &pInfo->aggSup, pTaskInfo);
if (ret != TSDB_CODE_SUCCESS || pResult == NULL) {
@@ -899,7 +899,7 @@ static void hashIntervalAgg(SOperatorInfo* pOperatorInfo, SResultRowInfo* pResul
TSKEY ekey = ascScan ? win.ekey : win.skey;
int32_t forwardRows =
- getNumOfRowsInTimeWindow(&pBlock->info, tsCols, startPos, ekey, binarySearchForKey, NULL, pInfo->inputOrder);
+ getNumOfRowsInTimeWindow(&pBlock->info, tsCols, startPos, ekey, binarySearchForKey, NULL, pInfo->binfo.inputTsOrder);
// prev time window not interpolation yet.
if (pInfo->timeWindowInterpo) {
@@ -926,7 +926,7 @@ static void hashIntervalAgg(SOperatorInfo* pOperatorInfo, SResultRowInfo* pResul
STimeWindow nextWin = win;
while (1) {
int32_t prevEndPos = forwardRows - 1 + startPos;
- startPos = getNextQualifiedWindow(&pInfo->interval, &nextWin, &pBlock->info, tsCols, prevEndPos, pInfo->inputOrder);
+ startPos = getNextQualifiedWindow(&pInfo->interval, &nextWin, &pBlock->info, tsCols, prevEndPos, pInfo->binfo.inputTsOrder);
if (startPos < 0) {
break;
}
@@ -939,7 +939,7 @@ static void hashIntervalAgg(SOperatorInfo* pOperatorInfo, SResultRowInfo* pResul
ekey = ascScan ? nextWin.ekey : nextWin.skey;
forwardRows =
- getNumOfRowsInTimeWindow(&pBlock->info, tsCols, startPos, ekey, binarySearchForKey, NULL, pInfo->inputOrder);
+ getNumOfRowsInTimeWindow(&pBlock->info, tsCols, startPos, ekey, binarySearchForKey, NULL, pInfo->binfo.inputTsOrder);
// window start(end) key interpolation
doWindowBorderInterpolation(pInfo, pBlock, pResult, &nextWin, startPos, forwardRows, pSup);
// TODO: add to open window? how to close the open windows after input blocks exhausted?
@@ -1032,7 +1032,7 @@ static int32_t doOpenIntervalAgg(SOperatorInfo* pOperator) {
break;
}
- getTableScanInfo(pOperator, &pInfo->inputOrder, &scanFlag, true);
+ pInfo->binfo.pRes->info.scanFlag = scanFlag = pBlock->info.scanFlag;
if (pInfo->scalarSupp.pExprInfo != NULL) {
SExprSupp* pExprSup = &pInfo->scalarSupp;
@@ -1040,11 +1040,11 @@ static int32_t doOpenIntervalAgg(SOperatorInfo* pOperator) {
}
// the pDataBlock are always the same one, no need to call this again
- setInputDataBlock(pSup, pBlock, pInfo->inputOrder, scanFlag, true);
+ setInputDataBlock(pSup, pBlock, pInfo->binfo.inputTsOrder, scanFlag, true);
hashIntervalAgg(pOperator, &pInfo->binfo.resultRowInfo, pBlock, scanFlag);
}
- initGroupedResultInfo(&pInfo->groupResInfo, pInfo->aggSup.pResultRowHashTable, pInfo->resultTsOrder);
+ initGroupedResultInfo(&pInfo->groupResInfo, pInfo->aggSup.pResultRowHashTable, pInfo->binfo.outputTsOrder);
OPTR_SET_OPENED(pOperator);
pOperator->cost.openCost = (taosGetTimestampUs() - st) / 1000.0;
@@ -1158,7 +1158,7 @@ static int32_t openStateWindowAggOptr(SOperatorInfo* pOperator) {
SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
SExprSupp* pSup = &pOperator->exprSupp;
- int32_t order = TSDB_ORDER_ASC;
+ int32_t order = pInfo->binfo.inputTsOrder;
int64_t st = taosGetTimestampUs();
SOperatorInfo* downstream = pOperator->pDownstream[0];
@@ -1168,6 +1168,7 @@ static int32_t openStateWindowAggOptr(SOperatorInfo* pOperator) {
break;
}
+ pInfo->binfo.pRes->info.scanFlag = pBlock->info.scanFlag;
setInputDataBlock(pSup, pBlock, order, MAIN_SCAN, true);
blockDataUpdateTsWindow(pBlock, pInfo->tsSlotId);
@@ -1650,8 +1651,8 @@ SOperatorInfo* createIntervalOperatorInfo(SOperatorInfo* downstream, SIntervalPh
};
pInfo->win = pTaskInfo->window;
- pInfo->inputOrder = (pPhyNode->window.inputTsOrder == ORDER_ASC) ? TSDB_ORDER_ASC : TSDB_ORDER_DESC;
- pInfo->resultTsOrder = (pPhyNode->window.outputTsOrder == ORDER_ASC) ? TSDB_ORDER_ASC : TSDB_ORDER_DESC;
+ pInfo->binfo.inputTsOrder = pPhyNode->window.node.inputTsOrder;
+ pInfo->binfo.outputTsOrder = pPhyNode->window.node.outputTsOrder;
pInfo->interval = interval;
pInfo->twAggSup = as;
pInfo->binfo.mergeResultBlock = pPhyNode->window.mergeDataBlock;
@@ -1802,7 +1803,7 @@ static SSDataBlock* doSessionWindowAgg(SOperatorInfo* pOperator) {
}
int64_t st = taosGetTimestampUs();
- int32_t order = TSDB_ORDER_ASC;
+ int32_t order = pInfo->binfo.inputTsOrder;
SOperatorInfo* downstream = pOperator->pDownstream[0];
@@ -1812,6 +1813,7 @@ static SSDataBlock* doSessionWindowAgg(SOperatorInfo* pOperator) {
break;
}
+ pBInfo->pRes->info.scanFlag = pBlock->info.scanFlag;
// the pDataBlock are always the same one, no need to call this again
setInputDataBlock(pSup, pBlock, order, MAIN_SCAN, true);
blockDataUpdateTsWindow(pBlock, pInfo->tsSlotId);
@@ -1872,6 +1874,8 @@ SOperatorInfo* createStatewindowOperatorInfo(SOperatorInfo* downstream, SStateWi
if (pInfo->stateKey.pData == NULL) {
goto _error;
}
+ pInfo->binfo.inputTsOrder = pStateNode->window.node.inputTsOrder;
+ pInfo->binfo.outputTsOrder = pStateNode->window.node.outputTsOrder;
int32_t code = filterInitFromNode((SNode*)pStateNode->window.node.pConditions, &pOperator->exprSupp.pFilterInfo, 0);
if (code != TSDB_CODE_SUCCESS) {
@@ -1970,6 +1974,8 @@ SOperatorInfo* createSessionAggOperatorInfo(SOperatorInfo* downstream, SSessionW
pInfo->binfo.pRes = pResBlock;
pInfo->winSup.prevTs = INT64_MIN;
pInfo->reptScan = false;
+ pInfo->binfo.inputTsOrder = pSessionNode->window.node.inputTsOrder;
+ pInfo->binfo.outputTsOrder = pSessionNode->window.node.outputTsOrder;
code = filterInitFromNode((SNode*)pSessionNode->window.node.pConditions, &pOperator->exprSupp.pFilterInfo, 0);
if (code != TSDB_CODE_SUCCESS) {
goto _error;
@@ -4318,7 +4324,6 @@ static void doMergeAlignedIntervalAgg(SOperatorInfo* pOperator) {
SSDataBlock* pRes = pIaInfo->binfo.pRes;
SResultRowInfo* pResultRowInfo = &pIaInfo->binfo.resultRowInfo;
SOperatorInfo* downstream = pOperator->pDownstream[0];
- int32_t scanFlag = MAIN_SCAN;
while (1) {
SSDataBlock* pBlock = NULL;
@@ -4365,8 +4370,8 @@ static void doMergeAlignedIntervalAgg(SOperatorInfo* pOperator) {
}
}
- getTableScanInfo(pOperator, &pIaInfo->inputOrder, &scanFlag, false);
- setInputDataBlock(pSup, pBlock, pIaInfo->inputOrder, scanFlag, true);
+ pRes->info.scanFlag = pBlock->info.scanFlag;
+ setInputDataBlock(pSup, pBlock, pIaInfo->binfo.inputTsOrder, pBlock->info.scanFlag, true);
doMergeAlignedIntervalAggImpl(pOperator, &pIaInfo->binfo.resultRowInfo, pBlock, pRes);
doFilter(pRes, pOperator->exprSupp.pFilterInfo, NULL);
@@ -4439,7 +4444,8 @@ SOperatorInfo* createMergeAlignedIntervalOperatorInfo(SOperatorInfo* downstream,
miaInfo->curTs = INT64_MIN;
iaInfo->win = pTaskInfo->window;
- iaInfo->inputOrder = TSDB_ORDER_ASC;
+ iaInfo->binfo.inputTsOrder = pNode->window.node.inputTsOrder;
+ iaInfo->binfo.outputTsOrder = pNode->window.node.outputTsOrder;
iaInfo->interval = interval;
iaInfo->primaryTsIndex = ((SColumnNode*)pNode->window.pTspk)->slotId;
iaInfo->binfo.mergeResultBlock = pNode->window.mergeDataBlock;
@@ -4516,7 +4522,7 @@ static int32_t outputPrevIntervalResult(SOperatorInfo* pOperatorInfo, uint64_t t
STimeWindow* newWin) {
SMergeIntervalAggOperatorInfo* miaInfo = pOperatorInfo->info;
SIntervalAggOperatorInfo* iaInfo = &miaInfo->intervalAggOperatorInfo;
- bool ascScan = (iaInfo->inputOrder == TSDB_ORDER_ASC);
+ bool ascScan = (iaInfo->binfo.inputTsOrder == TSDB_ORDER_ASC);
SGroupTimeWindow groupTimeWindow = {.groupId = tableGroupId, .window = *newWin};
tdListAppend(miaInfo->groupIntervals, &groupTimeWindow);
@@ -4551,12 +4557,12 @@ static void doMergeIntervalAggImpl(SOperatorInfo* pOperatorInfo, SResultRowInfo*
int32_t numOfOutput = pExprSup->numOfExprs;
int64_t* tsCols = extractTsCol(pBlock, iaInfo);
uint64_t tableGroupId = pBlock->info.id.groupId;
- bool ascScan = (iaInfo->inputOrder == TSDB_ORDER_ASC);
+ bool ascScan = (iaInfo->binfo.inputTsOrder == TSDB_ORDER_ASC);
TSKEY blockStartTs = getStartTsKey(&pBlock->info.window, tsCols);
SResultRow* pResult = NULL;
STimeWindow win = getActiveTimeWindow(iaInfo->aggSup.pResultBuf, pResultRowInfo, blockStartTs, &iaInfo->interval,
- iaInfo->inputOrder);
+ iaInfo->binfo.inputTsOrder);
int32_t ret =
setTimeWindowOutputBuf(pResultRowInfo, &win, (scanFlag == MAIN_SCAN), &pResult, tableGroupId, pExprSup->pCtx,
@@ -4567,7 +4573,7 @@ static void doMergeIntervalAggImpl(SOperatorInfo* pOperatorInfo, SResultRowInfo*
TSKEY ekey = ascScan ? win.ekey : win.skey;
int32_t forwardRows =
- getNumOfRowsInTimeWindow(&pBlock->info, tsCols, startPos, ekey, binarySearchForKey, NULL, iaInfo->inputOrder);
+ getNumOfRowsInTimeWindow(&pBlock->info, tsCols, startPos, ekey, binarySearchForKey, NULL, iaInfo->binfo.inputTsOrder);
ASSERT(forwardRows > 0);
// prev time window not interpolation yet.
@@ -4598,7 +4604,7 @@ static void doMergeIntervalAggImpl(SOperatorInfo* pOperatorInfo, SResultRowInfo*
while (1) {
int32_t prevEndPos = forwardRows - 1 + startPos;
startPos =
- getNextQualifiedWindow(&iaInfo->interval, &nextWin, &pBlock->info, tsCols, prevEndPos, iaInfo->inputOrder);
+ getNextQualifiedWindow(&iaInfo->interval, &nextWin, &pBlock->info, tsCols, prevEndPos, iaInfo->binfo.inputTsOrder);
if (startPos < 0) {
break;
}
@@ -4613,7 +4619,7 @@ static void doMergeIntervalAggImpl(SOperatorInfo* pOperatorInfo, SResultRowInfo*
ekey = ascScan ? nextWin.ekey : nextWin.skey;
forwardRows =
- getNumOfRowsInTimeWindow(&pBlock->info, tsCols, startPos, ekey, binarySearchForKey, NULL, iaInfo->inputOrder);
+ getNumOfRowsInTimeWindow(&pBlock->info, tsCols, startPos, ekey, binarySearchForKey, NULL, iaInfo->binfo.inputTsOrder);
// window start(end) key interpolation
doWindowBorderInterpolation(iaInfo, pBlock, pResult, &nextWin, startPos, forwardRows, pExprSup);
@@ -4649,7 +4655,6 @@ static SSDataBlock* doMergeIntervalAgg(SOperatorInfo* pOperator) {
if (!miaInfo->inputBlocksFinished) {
SOperatorInfo* downstream = pOperator->pDownstream[0];
- int32_t scanFlag = MAIN_SCAN;
while (1) {
SSDataBlock* pBlock = NULL;
if (miaInfo->prefetchedBlock == NULL) {
@@ -4674,9 +4679,9 @@ static SSDataBlock* doMergeIntervalAgg(SOperatorInfo* pOperator) {
break;
}
- getTableScanInfo(pOperator, &iaInfo->inputOrder, &scanFlag, false);
- setInputDataBlock(pExpSupp, pBlock, iaInfo->inputOrder, scanFlag, true);
- doMergeIntervalAggImpl(pOperator, &iaInfo->binfo.resultRowInfo, pBlock, scanFlag, pRes);
+ pRes->info.scanFlag = pBlock->info.scanFlag;
+ setInputDataBlock(pExpSupp, pBlock, iaInfo->binfo.inputTsOrder, pBlock->info.scanFlag, true);
+ doMergeIntervalAggImpl(pOperator, &iaInfo->binfo.resultRowInfo, pBlock, pBlock->info.scanFlag, pRes);
if (pRes->info.rows >= pOperator->resultInfo.threshold) {
break;
@@ -4726,10 +4731,11 @@ SOperatorInfo* createMergeIntervalOperatorInfo(SOperatorInfo* downstream, SMerge
SIntervalAggOperatorInfo* pIntervalInfo = &pMergeIntervalInfo->intervalAggOperatorInfo;
pIntervalInfo->win = pTaskInfo->window;
- pIntervalInfo->inputOrder = TSDB_ORDER_ASC;
+ pIntervalInfo->binfo.inputTsOrder = pIntervalPhyNode->window.node.inputTsOrder;
pIntervalInfo->interval = interval;
pIntervalInfo->binfo.mergeResultBlock = pIntervalPhyNode->window.mergeDataBlock;
pIntervalInfo->primaryTsIndex = ((SColumnNode*)pIntervalPhyNode->window.pTspk)->slotId;
+ pIntervalInfo->binfo.outputTsOrder = pIntervalPhyNode->window.node.outputTsOrder;
SExprSupp* pExprSupp = &pOperator->exprSupp;
diff --git a/source/libs/executor/src/tsort.c b/source/libs/executor/src/tsort.c
index 3033441aad..f26aa8a97c 100644
--- a/source/libs/executor/src/tsort.c
+++ b/source/libs/executor/src/tsort.c
@@ -887,6 +887,7 @@ void* tsortGetValue(STupleHandle* pVHandle, int32_t colIndex) {
}
uint64_t tsortGetGroupId(STupleHandle* pVHandle) { return pVHandle->pBlock->info.id.groupId; }
+void* tsortGetBlockInfo(STupleHandle* pVHandle) { return &pVHandle->pBlock->info; }
SSortExecInfo tsortGetSortExecInfo(SSortHandle* pHandle) {
SSortExecInfo info = {0};
diff --git a/source/libs/nodes/src/nodesCloneFuncs.c b/source/libs/nodes/src/nodesCloneFuncs.c
index a8e4f692ab..6e4dde4ec1 100644
--- a/source/libs/nodes/src/nodesCloneFuncs.c
+++ b/source/libs/nodes/src/nodesCloneFuncs.c
@@ -110,6 +110,7 @@ static int32_t columnNodeCopy(const SColumnNode* pSrc, SColumnNode* pDst) {
COPY_SCALAR_FIELD(tableId);
COPY_SCALAR_FIELD(tableType);
COPY_SCALAR_FIELD(colId);
+ COPY_SCALAR_FIELD(projIdx);
COPY_SCALAR_FIELD(colType);
COPY_SCALAR_FIELD(hasIndex);
COPY_CHAR_ARRAY_FIELD(dbName);
@@ -358,6 +359,8 @@ static int32_t logicNodeCopy(const SLogicNode* pSrc, SLogicNode* pDst) {
COPY_SCALAR_FIELD(requireDataOrder);
COPY_SCALAR_FIELD(resultDataOrder);
COPY_SCALAR_FIELD(groupAction);
+ COPY_SCALAR_FIELD(inputTsOrder);
+ COPY_SCALAR_FIELD(outputTsOrder);
return TSDB_CODE_SUCCESS;
}
@@ -404,7 +407,6 @@ static int32_t logicJoinCopy(const SJoinLogicNode* pSrc, SJoinLogicNode* pDst) {
CLONE_NODE_FIELD(pOnConditions);
CLONE_NODE_FIELD(pColEqualOnConditions);
COPY_SCALAR_FIELD(isSingleTableJoin);
- COPY_SCALAR_FIELD(inputTsOrder);
return TSDB_CODE_SUCCESS;
}
@@ -482,8 +484,6 @@ static int32_t logicWindowCopy(const SWindowLogicNode* pSrc, SWindowLogicNode* p
COPY_SCALAR_FIELD(igExpired);
COPY_SCALAR_FIELD(igCheckUpdate);
COPY_SCALAR_FIELD(windowAlgo);
- COPY_SCALAR_FIELD(inputTsOrder);
- COPY_SCALAR_FIELD(outputTsOrder);
return TSDB_CODE_SUCCESS;
}
@@ -495,7 +495,6 @@ static int32_t logicFillCopy(const SFillLogicNode* pSrc, SFillLogicNode* pDst) {
CLONE_NODE_FIELD(pWStartTs);
CLONE_NODE_FIELD(pValues);
COPY_OBJECT_FIELD(timeRange, sizeof(STimeWindow));
- COPY_SCALAR_FIELD(inputTsOrder);
return TSDB_CODE_SUCCESS;
}
@@ -544,6 +543,8 @@ static int32_t physiNodeCopy(const SPhysiNode* pSrc, SPhysiNode* pDst) {
CLONE_NODE_FIELD_EX(pOutputDataBlockDesc, SDataBlockDescNode*);
CLONE_NODE_FIELD(pConditions);
CLONE_NODE_LIST_FIELD(pChildren);
+ COPY_SCALAR_FIELD(inputTsOrder);
+ COPY_SCALAR_FIELD(outputTsOrder);
return TSDB_CODE_SUCCESS;
}
diff --git a/source/libs/nodes/src/nodesCodeFuncs.c b/source/libs/nodes/src/nodesCodeFuncs.c
index 6bf1ad01a8..0b449c5bfe 100644
--- a/source/libs/nodes/src/nodesCodeFuncs.c
+++ b/source/libs/nodes/src/nodesCodeFuncs.c
@@ -1904,9 +1904,6 @@ static int32_t physiJoinNodeToJson(const void* pObj, SJson* pJson) {
if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddIntegerToObject(pJson, jkJoinPhysiPlanJoinType, pNode->joinType);
}
- if (TSDB_CODE_SUCCESS == code) {
- code = tjsonAddIntegerToObject(pJson, jkJoinPhysiPlanInputTsOrder, pNode->inputTsOrder);
- }
if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddObject(pJson, jkJoinPhysiPlanMergeCondition, nodeToJson, pNode->pMergeCondition);
}
@@ -1929,9 +1926,6 @@ static int32_t jsonToPhysiJoinNode(const SJson* pJson, void* pObj) {
if (TSDB_CODE_SUCCESS == code) {
tjsonGetNumberValue(pJson, jkJoinPhysiPlanJoinType, pNode->joinType, code);
}
- if (TSDB_CODE_SUCCESS == code) {
- tjsonGetNumberValue(pJson, jkJoinPhysiPlanInputTsOrder, pNode->inputTsOrder, code);
- }
if (TSDB_CODE_SUCCESS == code) {
code = jsonToNodeObject(pJson, jkJoinPhysiPlanOnConditions, &pNode->pOnConditions);
}
@@ -2150,7 +2144,6 @@ static const char* jkWindowPhysiPlanWatermark = "Watermark";
static const char* jkWindowPhysiPlanDeleteMark = "DeleteMark";
static const char* jkWindowPhysiPlanIgnoreExpired = "IgnoreExpired";
static const char* jkWindowPhysiPlanInputTsOrder = "InputTsOrder";
-static const char* jkWindowPhysiPlanOutputTsOrder = "outputTsOrder";
static const char* jkWindowPhysiPlanMergeDataBlock = "MergeDataBlock";
static int32_t physiWindowNodeToJson(const void* pObj, SJson* pJson) {
@@ -2181,12 +2174,6 @@ static int32_t physiWindowNodeToJson(const void* pObj, SJson* pJson) {
if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddIntegerToObject(pJson, jkWindowPhysiPlanIgnoreExpired, pNode->igExpired);
}
- if (TSDB_CODE_SUCCESS == code) {
- code = tjsonAddIntegerToObject(pJson, jkWindowPhysiPlanInputTsOrder, pNode->inputTsOrder);
- }
- if (TSDB_CODE_SUCCESS == code) {
- code = tjsonAddIntegerToObject(pJson, jkWindowPhysiPlanOutputTsOrder, pNode->outputTsOrder);
- }
if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddBoolToObject(pJson, jkWindowPhysiPlanMergeDataBlock, pNode->mergeDataBlock);
}
@@ -2222,12 +2209,6 @@ static int32_t jsonToPhysiWindowNode(const SJson* pJson, void* pObj) {
if (TSDB_CODE_SUCCESS == code) {
code = tjsonGetTinyIntValue(pJson, jkWindowPhysiPlanIgnoreExpired, &pNode->igExpired);
}
- if (TSDB_CODE_SUCCESS == code) {
- tjsonGetNumberValue(pJson, jkWindowPhysiPlanInputTsOrder, pNode->inputTsOrder, code);
- }
- if (TSDB_CODE_SUCCESS == code) {
- tjsonGetNumberValue(pJson, jkWindowPhysiPlanOutputTsOrder, pNode->outputTsOrder, code);
- }
if (TSDB_CODE_SUCCESS == code) {
code = tjsonGetBoolValue(pJson, jkWindowPhysiPlanMergeDataBlock, &pNode->mergeDataBlock);
}
@@ -2294,7 +2275,6 @@ static const char* jkFillPhysiPlanWStartTs = "WStartTs";
static const char* jkFillPhysiPlanValues = "Values";
static const char* jkFillPhysiPlanStartTime = "StartTime";
static const char* jkFillPhysiPlanEndTime = "EndTime";
-static const char* jkFillPhysiPlanInputTsOrder = "inputTsOrder";
static int32_t physiFillNodeToJson(const void* pObj, SJson* pJson) {
const SFillPhysiNode* pNode = (const SFillPhysiNode*)pObj;
@@ -2321,9 +2301,6 @@ static int32_t physiFillNodeToJson(const void* pObj, SJson* pJson) {
if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddIntegerToObject(pJson, jkFillPhysiPlanEndTime, pNode->timeRange.ekey);
}
- if (TSDB_CODE_SUCCESS == code) {
- code = tjsonAddIntegerToObject(pJson, jkFillPhysiPlanInputTsOrder, pNode->inputTsOrder);
- }
return code;
}
@@ -2353,9 +2330,6 @@ static int32_t jsonToPhysiFillNode(const SJson* pJson, void* pObj) {
if (TSDB_CODE_SUCCESS == code) {
code = tjsonGetBigIntValue(pJson, jkFillPhysiPlanEndTime, &pNode->timeRange.ekey);
}
- if (TSDB_CODE_SUCCESS == code) {
- tjsonGetNumberValue(pJson, jkFillPhysiPlanInputTsOrder, pNode->inputTsOrder, code);
- }
return code;
}
@@ -3053,6 +3027,7 @@ static const char* jkColumnTableId = "TableId";
static const char* jkColumnTableType = "TableType";
static const char* jkColumnColId = "ColId";
static const char* jkColumnColType = "ColType";
+static const char* jkColumnProjId = "ProjId";
static const char* jkColumnDbName = "DbName";
static const char* jkColumnTableName = "TableName";
static const char* jkColumnTableAlias = "TableAlias";
@@ -3073,6 +3048,9 @@ static int32_t columnNodeToJson(const void* pObj, SJson* pJson) {
if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddIntegerToObject(pJson, jkColumnColId, pNode->colId);
}
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonAddIntegerToObject(pJson, jkColumnProjId, pNode->projIdx);
+ }
if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddIntegerToObject(pJson, jkColumnColType, pNode->colType);
}
@@ -3111,6 +3089,9 @@ static int32_t jsonToColumnNode(const SJson* pJson, void* pObj) {
if (TSDB_CODE_SUCCESS == code) {
code = tjsonGetSmallIntValue(pJson, jkColumnColId, &pNode->colId);
}
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tjsonGetSmallIntValue(pJson, jkColumnProjId, &pNode->projIdx);
+ }
if (TSDB_CODE_SUCCESS == code) {
tjsonGetNumberValue(pJson, jkColumnColType, pNode->colType, code);
}
diff --git a/source/libs/nodes/src/nodesMsgFuncs.c b/source/libs/nodes/src/nodesMsgFuncs.c
index 0631b91323..1ca37defa4 100644
--- a/source/libs/nodes/src/nodesMsgFuncs.c
+++ b/source/libs/nodes/src/nodesMsgFuncs.c
@@ -1851,7 +1851,9 @@ enum {
PHY_NODE_CODE_CONDITIONS,
PHY_NODE_CODE_CHILDREN,
PHY_NODE_CODE_LIMIT,
- PHY_NODE_CODE_SLIMIT
+ PHY_NODE_CODE_SLIMIT,
+ PHY_NODE_CODE_INPUT_TS_ORDER,
+ PHY_NODE_CODE_OUTPUT_TS_ORDER
};
static int32_t physiNodeToMsg(const void* pObj, STlvEncoder* pEncoder) {
@@ -1870,6 +1872,12 @@ static int32_t physiNodeToMsg(const void* pObj, STlvEncoder* pEncoder) {
if (TSDB_CODE_SUCCESS == code) {
code = tlvEncodeObj(pEncoder, PHY_NODE_CODE_SLIMIT, nodeToMsg, pNode->pSlimit);
}
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tlvEncodeEnum(pEncoder, PHY_NODE_CODE_INPUT_TS_ORDER, pNode->inputTsOrder);
+ }
+ if (TSDB_CODE_SUCCESS == code) {
+ code = tlvEncodeEnum(pEncoder, PHY_NODE_CODE_OUTPUT_TS_ORDER, pNode->outputTsOrder);
+ }
return code;
}
@@ -1896,6 +1904,12 @@ static int32_t msgToPhysiNode(STlvDecoder* pDecoder, void* pObj) {
case PHY_NODE_CODE_SLIMIT:
code = msgToNodeFromTlv(pTlv, (void**)&pNode->pSlimit);
break;
+ case PHY_NODE_CODE_INPUT_TS_ORDER:
+ code = tlvDecodeEnum(pTlv, &pNode->inputTsOrder, sizeof(pNode->inputTsOrder));
+ break;
+ case PHY_NODE_CODE_OUTPUT_TS_ORDER:
+ code = tlvDecodeEnum(pTlv, &pNode->outputTsOrder, sizeof(pNode->outputTsOrder));
+ break;
default:
break;
}
@@ -2339,9 +2353,6 @@ static int32_t physiJoinNodeToMsg(const void* pObj, STlvEncoder* pEncoder) {
if (TSDB_CODE_SUCCESS == code) {
code = tlvEncodeObj(pEncoder, PHY_SORT_MERGE_JOIN_CODE_TARGETS, nodeListToMsg, pNode->pTargets);
}
- if (TSDB_CODE_SUCCESS == code) {
- code = tlvEncodeEnum(pEncoder, PHY_SORT_MERGE_JOIN_CODE_INPUT_TS_ORDER, pNode->inputTsOrder);
- }
if (TSDB_CODE_SUCCESS == code) {
code = tlvEncodeObj(pEncoder, PHY_SORT_MERGE_JOIN_CODE_TAG_EQUAL_CONDITIONS, nodeToMsg, pNode->pColEqualOnConditions);
}
@@ -2370,9 +2381,6 @@ static int32_t msgToPhysiJoinNode(STlvDecoder* pDecoder, void* pObj) {
case PHY_SORT_MERGE_JOIN_CODE_TARGETS:
code = msgToNodeListFromTlv(pTlv, (void**)&pNode->pTargets);
break;
- case PHY_SORT_MERGE_JOIN_CODE_INPUT_TS_ORDER:
- code = tlvDecodeEnum(pTlv, &pNode->inputTsOrder, sizeof(pNode->inputTsOrder));
- break;
case PHY_SORT_MERGE_JOIN_CODE_TAG_EQUAL_CONDITIONS:
code = msgToNodeFromTlv(pTlv, (void**)&pNode->pColEqualOnConditions);
break;
@@ -2675,12 +2683,6 @@ static int32_t physiWindowNodeToMsg(const void* pObj, STlvEncoder* pEncoder) {
if (TSDB_CODE_SUCCESS == code) {
code = tlvEncodeI8(pEncoder, PHY_WINDOW_CODE_IG_EXPIRED, pNode->igExpired);
}
- if (TSDB_CODE_SUCCESS == code) {
- code = tlvEncodeEnum(pEncoder, PHY_WINDOW_CODE_INPUT_TS_ORDER, pNode->inputTsOrder);
- }
- if (TSDB_CODE_SUCCESS == code) {
- code = tlvEncodeEnum(pEncoder, PHY_WINDOW_CODE_OUTPUT_TS_ORDER, pNode->outputTsOrder);
- }
if (TSDB_CODE_SUCCESS == code) {
code = tlvEncodeBool(pEncoder, PHY_WINDOW_CODE_MERGE_DATA_BLOCK, pNode->mergeDataBlock);
}
@@ -2722,12 +2724,6 @@ static int32_t msgToPhysiWindowNode(STlvDecoder* pDecoder, void* pObj) {
case PHY_WINDOW_CODE_IG_EXPIRED:
code = tlvDecodeI8(pTlv, &pNode->igExpired);
break;
- case PHY_WINDOW_CODE_INPUT_TS_ORDER:
- code = tlvDecodeEnum(pTlv, &pNode->inputTsOrder, sizeof(pNode->inputTsOrder));
- break;
- case PHY_WINDOW_CODE_OUTPUT_TS_ORDER:
- code = tlvDecodeEnum(pTlv, &pNode->outputTsOrder, sizeof(pNode->outputTsOrder));
- break;
case PHY_WINDOW_CODE_MERGE_DATA_BLOCK:
code = tlvDecodeBool(pTlv, &pNode->mergeDataBlock);
break;
@@ -2846,9 +2842,6 @@ static int32_t physiFillNodeToMsg(const void* pObj, STlvEncoder* pEncoder) {
if (TSDB_CODE_SUCCESS == code) {
code = tlvEncodeObj(pEncoder, PHY_FILL_CODE_TIME_RANGE, timeWindowToMsg, &pNode->timeRange);
}
- if (TSDB_CODE_SUCCESS == code) {
- code = tlvEncodeEnum(pEncoder, PHY_FILL_CODE_INPUT_TS_ORDER, pNode->inputTsOrder);
- }
return code;
}
@@ -2881,9 +2874,6 @@ static int32_t msgToPhysiFillNode(STlvDecoder* pDecoder, void* pObj) {
case PHY_FILL_CODE_TIME_RANGE:
code = tlvDecodeObjFromTlv(pTlv, msgToTimeWindow, (void**)&pNode->timeRange);
break;
- case PHY_FILL_CODE_INPUT_TS_ORDER:
- code = tlvDecodeEnum(pTlv, &pNode->inputTsOrder, sizeof(pNode->inputTsOrder));
- break;
default:
break;
}
diff --git a/source/libs/planner/src/planLogicCreater.c b/source/libs/planner/src/planLogicCreater.c
index 5bbc9acdad..713f12e229 100644
--- a/source/libs/planner/src/planLogicCreater.c
+++ b/source/libs/planner/src/planLogicCreater.c
@@ -436,7 +436,7 @@ static int32_t createJoinLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect
pJoin->joinType = pJoinTable->joinType;
pJoin->isSingleTableJoin = pJoinTable->table.singleTable;
- pJoin->inputTsOrder = ORDER_ASC;
+ pJoin->node.inputTsOrder = ORDER_ASC;
pJoin->node.groupAction = GROUP_ACTION_CLEAR;
pJoin->node.requireDataOrder = DATA_ORDER_LEVEL_GLOBAL;
pJoin->node.resultDataOrder = DATA_ORDER_LEVEL_GLOBAL;
@@ -741,8 +741,8 @@ static int32_t createWindowLogicNodeFinalize(SLogicPlanContext* pCxt, SSelectStm
pWindow->igExpired = pCxt->pPlanCxt->igExpired;
pWindow->igCheckUpdate = pCxt->pPlanCxt->igCheckUpdate;
}
- pWindow->inputTsOrder = ORDER_ASC;
- pWindow->outputTsOrder = ORDER_ASC;
+ pWindow->node.inputTsOrder = ORDER_ASC;
+ pWindow->node.outputTsOrder = ORDER_ASC;
int32_t code = nodesCollectFuncs(pSelect, SQL_CLAUSE_WINDOW, fmIsWindowClauseFunc, &pWindow->pFuncs);
if (TSDB_CODE_SUCCESS == code) {
@@ -972,7 +972,7 @@ static int32_t createFillLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect
pFill->node.groupAction = getGroupAction(pCxt, pSelect);
pFill->node.requireDataOrder = getRequireDataOrder(true, pSelect);
pFill->node.resultDataOrder = pFill->node.requireDataOrder;
- pFill->inputTsOrder = ORDER_ASC;
+ pFill->node.inputTsOrder = 0;
int32_t code = partFillExprs(pSelect, &pFill->pFillExprs, &pFill->pNotFillExprs);
if (TSDB_CODE_SUCCESS == code) {
@@ -1045,6 +1045,19 @@ static int32_t createSortLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect
if (NULL == pSort->pSortKeys) {
code = TSDB_CODE_OUT_OF_MEMORY;
}
+ SNode* pNode = NULL;
+ SOrderByExprNode* firstSortKey = (SOrderByExprNode*)nodesListGetNode(pSort->pSortKeys, 0);
+ if (firstSortKey->pExpr->type == QUERY_NODE_COLUMN) {
+ SColumnNode* pCol = (SColumnNode*)firstSortKey->pExpr;
+ int16_t projIdx = 1;
+ FOREACH(pNode, pSelect->pProjectionList) {
+ SExprNode* pExpr = (SExprNode*)pNode;
+ if (0 == strcmp(pCol->node.aliasName, pExpr->aliasName)) {
+ pCol->projIdx = projIdx; break;
+ }
+ projIdx++;
+ }
+ }
}
if (TSDB_CODE_SUCCESS == code) {
diff --git a/source/libs/planner/src/planOptimizer.c b/source/libs/planner/src/planOptimizer.c
index 8b75fe6b33..2371731467 100644
--- a/source/libs/planner/src/planOptimizer.c
+++ b/source/libs/planner/src/planOptimizer.c
@@ -116,25 +116,33 @@ static EDealRes optRebuildTbanme(SNode** pNode, void* pContext) {
return DEAL_RES_CONTINUE;
}
-static void optSetParentOrder(SLogicNode* pNode, EOrder order) {
+static void optSetParentOrder(SLogicNode* pNode, EOrder order, SLogicNode* pNodeForcePropagate) {
if (NULL == pNode) {
return;
}
+ pNode->inputTsOrder = order;
switch (nodeType(pNode)) {
- case QUERY_NODE_LOGIC_PLAN_WINDOW:
- ((SWindowLogicNode*)pNode)->inputTsOrder = order;
- // window has a sorting function, and the operator behind it uses its output order
- return;
+ // for those nodes that will change the order, stop propagating
+ //case QUERY_NODE_LOGIC_PLAN_WINDOW:
case QUERY_NODE_LOGIC_PLAN_JOIN:
- ((SJoinLogicNode*)pNode)->inputTsOrder = order;
- break;
- case QUERY_NODE_LOGIC_PLAN_FILL:
- ((SFillLogicNode*)pNode)->inputTsOrder = order;
+ case QUERY_NODE_LOGIC_PLAN_AGG:
+ case QUERY_NODE_LOGIC_PLAN_SORT:
+ if (pNode == pNodeForcePropagate) {
+ pNode->outputTsOrder = order;
+ break;
+ } else
+ return;
+ case QUERY_NODE_LOGIC_PLAN_WINDOW:
+ // Window output ts order default to be asc, and changed when doing sort by primary key optimization.
+ // We stop propagate the original order to parents.
+ // Use window output ts order instead.
+ order = pNode->outputTsOrder;
break;
default:
+ pNode->outputTsOrder = order;
break;
}
- optSetParentOrder(pNode->pParent, order);
+ optSetParentOrder(pNode->pParent, order, pNodeForcePropagate);
}
EDealRes scanPathOptHaveNormalColImpl(SNode* pNode, void* pContext) {
@@ -339,12 +347,12 @@ static void scanPathOptSetScanOrder(EScanOrder scanOrder, SScanLogicNode* pScan)
case SCAN_ORDER_ASC:
pScan->scanSeq[0] = 1;
pScan->scanSeq[1] = 0;
- optSetParentOrder(pScan->node.pParent, ORDER_ASC);
+ optSetParentOrder(pScan->node.pParent, ORDER_ASC, NULL);
break;
case SCAN_ORDER_DESC:
pScan->scanSeq[0] = 0;
pScan->scanSeq[1] = 1;
- optSetParentOrder(pScan->node.pParent, ORDER_DESC);
+ optSetParentOrder(pScan->node.pParent, ORDER_DESC, NULL);
break;
case SCAN_ORDER_BOTH:
pScan->scanSeq[0] = 1;
@@ -1239,6 +1247,7 @@ static int32_t sortPriKeyOptApply(SOptimizeContext* pCxt, SLogicSubplan* pLogicS
if ((ORDER_DESC == order && pScan->scanSeq[0] > 0) || (ORDER_ASC == order && pScan->scanSeq[1] > 0)) {
TSWAP(pScan->scanSeq[0], pScan->scanSeq[1]);
}
+ pScan->node.outputTsOrder = order;
if (TSDB_SUPER_TABLE == pScan->tableType) {
pScan->scanType = SCAN_TYPE_TABLE_MERGE;
pScan->node.resultDataOrder = DATA_ORDER_LEVEL_GLOBAL;
@@ -1246,9 +1255,9 @@ static int32_t sortPriKeyOptApply(SOptimizeContext* pCxt, SLogicSubplan* pLogicS
}
pScan->sortPrimaryKey = true;
} else if (QUERY_NODE_LOGIC_PLAN_WINDOW == nodeType(pSequencingNode)) {
- ((SWindowLogicNode*)pSequencingNode)->outputTsOrder = order;
+ ((SLogicNode*)pSequencingNode)->outputTsOrder = order;
}
- optSetParentOrder(((SLogicNode*)pSequencingNode)->pParent, order);
+ optSetParentOrder(((SLogicNode*)pSequencingNode)->pParent, order, (SLogicNode*)pSort);
}
SLogicNode* pChild = (SLogicNode*)nodesListGetNode(pSort->node.pChildren, 0);
@@ -2881,10 +2890,62 @@ static int32_t tableCountScanOptimize(SOptimizeContext* pCxt, SLogicSubplan* pLo
return code;
}
+static SSortLogicNode* sortNonPriKeySatisfied(SLogicNode* pNode) {
+ if (QUERY_NODE_LOGIC_PLAN_SORT != nodeType(pNode)) {
+ return NULL;
+ }
+ SSortLogicNode* pSort = (SSortLogicNode*)pNode;
+ if (sortPriKeyOptIsPriKeyOrderBy(pSort->pSortKeys)) {
+ return NULL;
+ }
+ SNode* pSortKeyNode = NULL, *pSortKeyExpr = NULL;
+ FOREACH(pSortKeyNode, pSort->pSortKeys) {
+ pSortKeyExpr = ((SOrderByExprNode*)pSortKeyNode)->pExpr;
+ switch (nodeType(pSortKeyExpr)) {
+ case QUERY_NODE_COLUMN:
+ break;
+ case QUERY_NODE_VALUE:
+ continue;
+ default:
+ return NULL;
+ }
+ }
+
+ if (!pSortKeyExpr || ((SColumnNode*)pSortKeyExpr)->projIdx != 1 ||
+ ((SColumnNode*)pSortKeyExpr)->node.resType.type != TSDB_DATA_TYPE_TIMESTAMP) {
+ return NULL;
+ }
+ return pSort;
+}
+
+static bool sortNonPriKeyShouldOptimize(SLogicNode* pNode, void* pInfo) {
+ SSortLogicNode* pSort = sortNonPriKeySatisfied(pNode);
+ if (!pSort) return false;
+ SNodeList* pSortNodeList = pInfo;
+ nodesListAppend(pSortNodeList, (SNode*)pSort);
+ return false;
+}
+
+static int32_t sortNonPriKeyOptimize(SOptimizeContext* pCxt, SLogicSubplan* pLogicSubplan) {
+ SNodeList* pNodeList = nodesMakeList();
+ optFindEligibleNode(pLogicSubplan->pNode, sortNonPriKeyShouldOptimize, pNodeList);
+ SNode* pNode = NULL;
+ FOREACH(pNode, pNodeList) {
+ SSortLogicNode* pSort = (SSortLogicNode*)pNode;
+ SOrderByExprNode* pOrderByExpr = (SOrderByExprNode*)nodesListGetNode(pSort->pSortKeys, 0);
+ pSort->node.outputTsOrder = pOrderByExpr->order;
+ optSetParentOrder(pSort->node.pParent, pOrderByExpr->order, NULL);
+ }
+ pCxt->optimized = false;
+ nodesClearList(pNodeList);
+ return TSDB_CODE_SUCCESS;
+}
+
// clang-format off
static const SOptimizeRule optimizeRuleSet[] = {
{.pName = "ScanPath", .optimizeFunc = scanPathOptimize},
{.pName = "PushDownCondition", .optimizeFunc = pushDownCondOptimize},
+ {.pName = "sortNonPriKeyOptimize", .optimizeFunc = sortNonPriKeyOptimize},
{.pName = "SortPrimaryKey", .optimizeFunc = sortPrimaryKeyOptimize},
{.pName = "SmaIndex", .optimizeFunc = smaIndexOptimize},
{.pName = "PartitionTags", .optimizeFunc = partTagsOptimize},
diff --git a/source/libs/planner/src/planPhysiCreater.c b/source/libs/planner/src/planPhysiCreater.c
index 4f57193856..b3d94a5e47 100644
--- a/source/libs/planner/src/planPhysiCreater.c
+++ b/source/libs/planner/src/planPhysiCreater.c
@@ -366,6 +366,8 @@ static SPhysiNode* makePhysiNode(SPhysiPlanContext* pCxt, SLogicNode* pLogicNode
TSWAP(pPhysiNode->pLimit, pLogicNode->pLimit);
TSWAP(pPhysiNode->pSlimit, pLogicNode->pSlimit);
+ pPhysiNode->inputTsOrder = pLogicNode->inputTsOrder;
+ pPhysiNode->outputTsOrder = pLogicNode->outputTsOrder;
int32_t code = createDataBlockDesc(pCxt, pLogicNode->pTargets, &pPhysiNode->pOutputDataBlockDesc);
if (TSDB_CODE_SUCCESS != code) {
@@ -676,7 +678,7 @@ static int32_t createJoinPhysiNode(SPhysiPlanContext* pCxt, SNodeList* pChildren
int32_t code = TSDB_CODE_SUCCESS;
pJoin->joinType = pJoinLogicNode->joinType;
- pJoin->inputTsOrder = pJoinLogicNode->inputTsOrder;
+ pJoin->node.inputTsOrder = pJoinLogicNode->node.inputTsOrder;
setNodeSlotId(pCxt, pLeftDesc->dataBlockId, pRightDesc->dataBlockId, pJoinLogicNode->pMergeCondition,
&pJoin->pMergeCondition);
if (TSDB_CODE_SUCCESS == code) {
@@ -939,6 +941,11 @@ static int32_t createIndefRowsFuncPhysiNode(SPhysiPlanContext* pCxt, SNodeList*
SNodeList* pFuncs = NULL;
int32_t code = rewritePrecalcExprs(pCxt, pFuncLogicNode->pFuncs, &pPrecalcExprs, &pFuncs);
+ if (pIdfRowsFunc->node.inputTsOrder == 0) {
+ // default to asc
+ pIdfRowsFunc->node.inputTsOrder = TSDB_ORDER_ASC;
+ }
+
SDataBlockDescNode* pChildTupe = (((SPhysiNode*)nodesListGetNode(pChildren, 0))->pOutputDataBlockDesc);
// push down expression to pOutputDataBlockDesc of child node
if (TSDB_CODE_SUCCESS == code && NULL != pPrecalcExprs) {
@@ -1156,9 +1163,12 @@ static int32_t createWindowPhysiNodeFinalize(SPhysiPlanContext* pCxt, SNodeList*
pWindow->watermark = pWindowLogicNode->watermark;
pWindow->deleteMark = pWindowLogicNode->deleteMark;
pWindow->igExpired = pWindowLogicNode->igExpired;
- pWindow->inputTsOrder = pWindowLogicNode->inputTsOrder;
- pWindow->outputTsOrder = pWindowLogicNode->outputTsOrder;
pWindow->mergeDataBlock = (GROUP_ACTION_KEEP == pWindowLogicNode->node.groupAction ? false : true);
+ pWindow->node.inputTsOrder = pWindowLogicNode->node.inputTsOrder;
+ pWindow->node.outputTsOrder = pWindowLogicNode->node.outputTsOrder;
+ if (nodeType(pWindow) == QUERY_NODE_PHYSICAL_PLAN_MERGE_ALIGNED_INTERVAL) {
+ pWindow->node.inputTsOrder = pWindowLogicNode->node.outputTsOrder;
+ }
SNodeList* pPrecalcExprs = NULL;
SNodeList* pFuncs = NULL;
@@ -1492,7 +1502,7 @@ static int32_t createFillPhysiNode(SPhysiPlanContext* pCxt, SNodeList* pChildren
pFill->mode = pFillNode->mode;
pFill->timeRange = pFillNode->timeRange;
- pFill->inputTsOrder = pFillNode->inputTsOrder;
+ pFill->node.inputTsOrder = pFillNode->node.inputTsOrder;
SDataBlockDescNode* pChildTupe = (((SPhysiNode*)nodesListGetNode(pChildren, 0))->pOutputDataBlockDesc);
int32_t code = setListSlotId(pCxt, pChildTupe->dataBlockId, -1, pFillNode->pFillExprs, &pFill->pFillExprs);
diff --git a/source/libs/planner/src/planSpliter.c b/source/libs/planner/src/planSpliter.c
index 504db0d07b..246ee13fb0 100644
--- a/source/libs/planner/src/planSpliter.c
+++ b/source/libs/planner/src/planSpliter.c
@@ -534,7 +534,9 @@ static int32_t stbSplGetNumOfVgroups(SLogicNode* pNode) {
static int32_t stbSplRewriteFromMergeNode(SMergeLogicNode* pMerge, SLogicNode* pNode) {
int32_t code = TSDB_CODE_SUCCESS;
-
+ pMerge->node.inputTsOrder = pNode->outputTsOrder;
+ pMerge->node.outputTsOrder = pNode->outputTsOrder;
+
switch (nodeType(pNode)) {
case QUERY_NODE_LOGIC_PLAN_PROJECT: {
SProjectLogicNode *pLogicNode = (SProjectLogicNode*)pNode;
@@ -631,7 +633,7 @@ static int32_t stbSplSplitIntervalForBatch(SSplitContext* pCxt, SStableSplitInfo
((SWindowLogicNode*)pInfo->pSplitNode)->windowAlgo = INTERVAL_ALGO_MERGE;
SNodeList* pMergeKeys = NULL;
code = stbSplCreateMergeKeysByPrimaryKey(((SWindowLogicNode*)pInfo->pSplitNode)->pTspk,
- ((SWindowLogicNode*)pInfo->pSplitNode)->outputTsOrder, &pMergeKeys);
+ ((SWindowLogicNode*)pInfo->pSplitNode)->node.outputTsOrder, &pMergeKeys);
if (TSDB_CODE_SUCCESS == code) {
code = stbSplCreateMergeNode(pCxt, NULL, pInfo->pSplitNode, pMergeKeys, pPartWindow, true);
}
@@ -721,7 +723,7 @@ static int32_t stbSplSplitSessionOrStateForBatch(SSplitContext* pCxt, SStableSpl
SNodeList* pMergeKeys = NULL;
int32_t code = stbSplCreateMergeKeysByPrimaryKey(((SWindowLogicNode*)pWindow)->pTspk,
- ((SWindowLogicNode*)pWindow)->inputTsOrder, &pMergeKeys);
+ ((SWindowLogicNode*)pWindow)->node.inputTsOrder, &pMergeKeys);
if (TSDB_CODE_SUCCESS == code) {
code = stbSplCreateMergeNode(pCxt, pInfo->pSubplan, pChild, pMergeKeys, (SLogicNode*)pChild, true);
diff --git a/source/libs/scheduler/src/schTask.c b/source/libs/scheduler/src/schTask.c
index 207753ae25..78e28bce49 100644
--- a/source/libs/scheduler/src/schTask.c
+++ b/source/libs/scheduler/src/schTask.c
@@ -765,7 +765,7 @@ int32_t schSetTaskCandidateAddrs(SSchJob *pJob, SSchTask *pTask) {
if (SCH_IS_DATA_BIND_TASK(pTask)) {
SCH_TASK_ELOG("no execNode specifed for data src task, numOfEps:%d", pTask->plan->execNode.epSet.numOfEps);
- SCH_ERR_RET(TSDB_CODE_APP_ERROR);
+ SCH_ERR_RET(TSDB_CODE_MND_INVALID_SCHEMA_VER);
}
SCH_ERR_RET(schSetAddrsFromNodeList(pJob, pTask));
diff --git a/source/util/src/terror.c b/source/util/src/terror.c
index a66af6e732..d7571b9283 100644
--- a/source/util/src/terror.c
+++ b/source/util/src/terror.c
@@ -261,8 +261,8 @@ TAOS_DEFINE_ERROR(TSDB_CODE_MND_INVALID_STB_ALTER_OPTION, "Invalid stable alter
TAOS_DEFINE_ERROR(TSDB_CODE_MND_STB_OPTION_UNCHNAGED, "STable option unchanged")
TAOS_DEFINE_ERROR(TSDB_CODE_MND_FIELD_CONFLICT_WITH_TOPIC,"Field used by topic")
TAOS_DEFINE_ERROR(TSDB_CODE_MND_SINGLE_STB_MODE_DB, "Database is single stable mode")
-TAOS_DEFINE_ERROR(TSDB_CODE_MND_INVALID_SCHEMA_VER, "Invalid schema version while alter stb")
-TAOS_DEFINE_ERROR(TSDB_CODE_MND_STABLE_UID_NOT_MATCH, "Invalid stable uid while alter stb")
+TAOS_DEFINE_ERROR(TSDB_CODE_MND_INVALID_SCHEMA_VER, "Invalid schema version")
+TAOS_DEFINE_ERROR(TSDB_CODE_MND_STABLE_UID_NOT_MATCH, "Invalid stable uid")
TAOS_DEFINE_ERROR(TSDB_CODE_MND_FIELD_CONFLICT_WITH_TSMA, "Field used by tsma")
TAOS_DEFINE_ERROR(TSDB_CODE_MND_DNODE_IN_CREATING, "Dnode in creating status")
TAOS_DEFINE_ERROR(TSDB_CODE_MND_DNODE_IN_DROPPING, "Dnode in dropping status")
diff --git a/tests/parallel_test/cases.task b/tests/parallel_test/cases.task
index cd47cb2d16..00b1f3b72c 100644
--- a/tests/parallel_test/cases.task
+++ b/tests/parallel_test/cases.task
@@ -184,6 +184,7 @@
,,y,script,./test.sh -f tsim/query/forceFill.sim
,,y,script,./test.sh -f tsim/query/emptyTsRange.sim
,,y,script,./test.sh -f tsim/query/partitionby.sim
+,,y,script,./test.sh -f tsim/query/explain_tsorder.sim
,,y,script,./test.sh -f tsim/qnode/basic1.sim
,,y,script,./test.sh -f tsim/snode/basic1.sim
,,y,script,./test.sh -f tsim/mnode/basic1.sim
diff --git a/tests/script/tsim/query/explain_tsorder.sim b/tests/script/tsim/query/explain_tsorder.sim
new file mode 100644
index 0000000000..202f85bcf0
--- /dev/null
+++ b/tests/script/tsim/query/explain_tsorder.sim
@@ -0,0 +1,37 @@
+system sh/stop_dnodes.sh
+system sh/deploy.sh -n dnode1 -i 1
+system sh/exec.sh -n dnode1 -s start
+sql connect
+
+sql create database test
+sql use test
+sql CREATE STABLE `meters` (`ts` TIMESTAMP, `c2` INT) TAGS (`cc` VARCHAR(3))
+
+
+sql insert into d1 using meters tags("MY") values("2022-05-15 00:01:08.000 ",234)
+sql insert into d1 using meters tags("MY") values("2022-05-16 00:01:08.000 ",136)
+sql insert into d1 using meters tags("MY") values("2022-05-17 00:01:08.000 ", 59)
+sql insert into d1 using meters tags("MY") values("2022-05-18 00:01:08.000 ", 58)
+sql insert into d1 using meters tags("MY") values("2022-05-19 00:01:08.000 ",243)
+sql insert into d1 using meters tags("MY") values("2022-05-20 00:01:08.000 ",120)
+sql insert into d1 using meters tags("MY") values("2022-05-21 00:01:08.000 ", 11)
+sql insert into d1 using meters tags("MY") values("2022-05-22 00:01:08.000 ",196)
+sql insert into d1 using meters tags("MY") values("2022-05-23 00:01:08.000 ",116)
+sql insert into d1 using meters tags("MY") values("2022-05-24 00:01:08.000 ",210)
+
+sql insert into d2 using meters tags("HT") values("2022-05-15 00:01:08.000", 234)
+sql insert into d2 using meters tags("HT") values("2022-05-16 00:01:08.000", 136)
+sql insert into d2 using meters tags("HT") values("2022-05-17 00:01:08.000", 59)
+sql insert into d2 using meters tags("HT") values("2022-05-18 00:01:08.000", 58)
+sql insert into d2 using meters tags("HT") values("2022-05-19 00:01:08.000", 243)
+sql insert into d2 using meters tags("HT") values("2022-05-20 00:01:08.000", 120)
+sql insert into d2 using meters tags("HT") values("2022-05-21 00:01:08.000", 11)
+sql insert into d2 using meters tags("HT") values("2022-05-22 00:01:08.000", 196)
+sql insert into d2 using meters tags("HT") values("2022-05-23 00:01:08.000", 116)
+sql insert into d2 using meters tags("HT") values("2022-05-24 00:01:08.000", 210)
+
+#sleep 10000000
+system taos -P7100 -s 'source tsim/query/t/explain_tsorder.sql' | grep -v 'Query OK' | grep -v 'Client Version' > /tmp/explain_tsorder.result
+system echo ----------------------diff start-----------------------
+system git diff --exit-code --color tsim/query/r/explain_tsorder.result /tmp/explain_tsorder.result
+system echo ----------------------diff succeed-----------------------
diff --git a/tests/script/tsim/query/r/explain_tsorder.result b/tests/script/tsim/query/r/explain_tsorder.result
new file mode 100644
index 0000000000..a31a05e66f
--- /dev/null
+++ b/tests/script/tsim/query/r/explain_tsorder.result
@@ -0,0 +1,2560 @@
+Copyright (c) 2022 by TDengine, all rights reserved.
+
+taos> source tsim/query/t/explain_tsorder.sql
+taos> use test;
+Database changed.
+
+taos> explain verbose true select _wstart, last(ts), avg(c2) from meters interval(10s) order by _wstart desc\G;
+*************************** 1.row ***************************
+QUERY_PLAN: -> Merge Aligned Interval on Column (functions=3 width=24 input_order=desc output_order=desc)
+*************************** 2.row ***************************
+QUERY_PLAN: Output: columns=3 width=24
+*************************** 3.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 4.row ***************************
+QUERY_PLAN: Merge ResBlocks: True
+*************************** 5.row ***************************
+QUERY_PLAN: -> SortMerge (columns=3 width=108 input_order=desc output_order=desc)
+*************************** 6.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 7.row ***************************
+QUERY_PLAN: Output: Ignore Group Id: false
+*************************** 8.row ***************************
+QUERY_PLAN: Merge Key: _group_id asc, desc
+*************************** 9.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=108)
+*************************** 10.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 11.row ***************************
+QUERY_PLAN: -> Interval on Column ts (functions=3 width=108 input_order=desc output_order=desc )
+*************************** 12.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 13.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 14.row ***************************
+QUERY_PLAN: Merge ResBlocks: False
+*************************** 15.row ***************************
+QUERY_PLAN: -> Table Scan on meters (columns=2 width=12 order=[asc|0 desc|1])
+*************************** 16.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 17.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+*************************** 18.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=108)
+*************************** 19.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 20.row ***************************
+QUERY_PLAN: -> Interval on Column ts (functions=3 width=108 input_order=desc output_order=desc )
+*************************** 21.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 22.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 23.row ***************************
+QUERY_PLAN: Merge ResBlocks: False
+*************************** 24.row ***************************
+QUERY_PLAN: -> Table Scan on meters (columns=2 width=12 order=[asc|0 desc|1])
+*************************** 25.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 26.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+
+taos> explain verbose true select _wstart, last(ts), avg(c2) from meters interval(10s) order by _wstart asc\G;
+*************************** 1.row ***************************
+QUERY_PLAN: -> Merge Aligned Interval on Column (functions=3 width=24 input_order=asc output_order=asc)
+*************************** 2.row ***************************
+QUERY_PLAN: Output: columns=3 width=24
+*************************** 3.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 4.row ***************************
+QUERY_PLAN: Merge ResBlocks: True
+*************************** 5.row ***************************
+QUERY_PLAN: -> SortMerge (columns=3 width=108 input_order=asc output_order=asc)
+*************************** 6.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 7.row ***************************
+QUERY_PLAN: Output: Ignore Group Id: false
+*************************** 8.row ***************************
+QUERY_PLAN: Merge Key: _group_id asc, asc
+*************************** 9.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=108)
+*************************** 10.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 11.row ***************************
+QUERY_PLAN: -> Interval on Column ts (functions=3 width=108 input_order=desc output_order=asc )
+*************************** 12.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 13.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 14.row ***************************
+QUERY_PLAN: Merge ResBlocks: False
+*************************** 15.row ***************************
+QUERY_PLAN: -> Table Scan on meters (columns=2 width=12 order=[asc|0 desc|1])
+*************************** 16.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 17.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+*************************** 18.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=108)
+*************************** 19.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 20.row ***************************
+QUERY_PLAN: -> Interval on Column ts (functions=3 width=108 input_order=desc output_order=asc )
+*************************** 21.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 22.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 23.row ***************************
+QUERY_PLAN: Merge ResBlocks: False
+*************************** 24.row ***************************
+QUERY_PLAN: -> Table Scan on meters (columns=2 width=12 order=[asc|0 desc|1])
+*************************** 25.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 26.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+
+taos> explain verbose true select _wstart, first(ts), avg(c2) from meters interval(10s) order by _wstart asc\G;
+*************************** 1.row ***************************
+QUERY_PLAN: -> Merge Aligned Interval on Column (functions=3 width=24 input_order=asc output_order=asc)
+*************************** 2.row ***************************
+QUERY_PLAN: Output: columns=3 width=24
+*************************** 3.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 4.row ***************************
+QUERY_PLAN: Merge ResBlocks: True
+*************************** 5.row ***************************
+QUERY_PLAN: -> SortMerge (columns=3 width=108 input_order=asc output_order=asc)
+*************************** 6.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 7.row ***************************
+QUERY_PLAN: Output: Ignore Group Id: false
+*************************** 8.row ***************************
+QUERY_PLAN: Merge Key: _group_id asc, asc
+*************************** 9.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=108)
+*************************** 10.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 11.row ***************************
+QUERY_PLAN: -> Interval on Column ts (functions=3 width=108 input_order=asc output_order=asc )
+*************************** 12.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 13.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 14.row ***************************
+QUERY_PLAN: Merge ResBlocks: False
+*************************** 15.row ***************************
+QUERY_PLAN: -> Table Scan on meters (columns=2 width=12 order=[asc|1 desc|0])
+*************************** 16.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 17.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+*************************** 18.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=108)
+*************************** 19.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 20.row ***************************
+QUERY_PLAN: -> Interval on Column ts (functions=3 width=108 input_order=asc output_order=asc )
+*************************** 21.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 22.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 23.row ***************************
+QUERY_PLAN: Merge ResBlocks: False
+*************************** 24.row ***************************
+QUERY_PLAN: -> Table Scan on meters (columns=2 width=12 order=[asc|1 desc|0])
+*************************** 25.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 26.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+
+taos> explain verbose true select _wstart, first(ts), avg(c2) from meters interval(10s) order by _wstart desc\G;
+*************************** 1.row ***************************
+QUERY_PLAN: -> Merge Aligned Interval on Column (functions=3 width=24 input_order=desc output_order=desc)
+*************************** 2.row ***************************
+QUERY_PLAN: Output: columns=3 width=24
+*************************** 3.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 4.row ***************************
+QUERY_PLAN: Merge ResBlocks: True
+*************************** 5.row ***************************
+QUERY_PLAN: -> SortMerge (columns=3 width=108 input_order=desc output_order=desc)
+*************************** 6.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 7.row ***************************
+QUERY_PLAN: Output: Ignore Group Id: false
+*************************** 8.row ***************************
+QUERY_PLAN: Merge Key: _group_id asc, desc
+*************************** 9.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=108)
+*************************** 10.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 11.row ***************************
+QUERY_PLAN: -> Interval on Column ts (functions=3 width=108 input_order=asc output_order=desc )
+*************************** 12.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 13.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 14.row ***************************
+QUERY_PLAN: Merge ResBlocks: False
+*************************** 15.row ***************************
+QUERY_PLAN: -> Table Scan on meters (columns=2 width=12 order=[asc|1 desc|0])
+*************************** 16.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 17.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+*************************** 18.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=108)
+*************************** 19.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 20.row ***************************
+QUERY_PLAN: -> Interval on Column ts (functions=3 width=108 input_order=asc output_order=desc )
+*************************** 21.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 22.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 23.row ***************************
+QUERY_PLAN: Merge ResBlocks: False
+*************************** 24.row ***************************
+QUERY_PLAN: -> Table Scan on meters (columns=2 width=12 order=[asc|1 desc|0])
+*************************** 25.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 26.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+
+taos> explain verbose true select last(a) as d from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s)) order by d\G;
+*************************** 1.row ***************************
+QUERY_PLAN: -> Sort input_order=unknown output_order=asc (columns=1 width=8)
+*************************** 2.row ***************************
+QUERY_PLAN: Output: columns=1 width=8
+*************************** 3.row ***************************
+QUERY_PLAN: -> Aggragate (functions=1 width=8 input_order=asc )
+*************************** 4.row ***************************
+QUERY_PLAN: Output: columns=1 width=8
+*************************** 5.row ***************************
+QUERY_PLAN: Merge ResBlocks: True
+*************************** 6.row ***************************
+QUERY_PLAN: -> Projection (columns=3 width=24 input_order=asc )
+*************************** 7.row ***************************
+QUERY_PLAN: Output: columns=3 width=24
+*************************** 8.row ***************************
+QUERY_PLAN: Output: Ignore Group Id: true
+*************************** 9.row ***************************
+QUERY_PLAN: Merge ResBlocks: True
+*************************** 10.row ***************************
+QUERY_PLAN: -> Merge Aligned Interval on Column (functions=3 width=24 input_order=asc output_order=asc)
+*************************** 11.row ***************************
+QUERY_PLAN: Output: columns=3 width=24
+*************************** 12.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 13.row ***************************
+QUERY_PLAN: Merge ResBlocks: True
+*************************** 14.row ***************************
+QUERY_PLAN: -> SortMerge (columns=3 width=108 input_order=asc output_order=asc)
+*************************** 15.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 16.row ***************************
+QUERY_PLAN: Output: Ignore Group Id: false
+*************************** 17.row ***************************
+QUERY_PLAN: Merge Key: _group_id asc, asc
+*************************** 18.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=108)
+*************************** 19.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 20.row ***************************
+QUERY_PLAN: -> Interval on Column ts (functions=3 width=108 input_order=desc output_order=asc )
+*************************** 21.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 22.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 23.row ***************************
+QUERY_PLAN: Merge ResBlocks: False
+*************************** 24.row ***************************
+QUERY_PLAN: -> Table Scan on meters (columns=2 width=12 order=[asc|0 desc|1])
+*************************** 25.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 26.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+*************************** 27.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=108)
+*************************** 28.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 29.row ***************************
+QUERY_PLAN: -> Interval on Column ts (functions=3 width=108 input_order=desc output_order=asc )
+*************************** 30.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 31.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 32.row ***************************
+QUERY_PLAN: Merge ResBlocks: False
+*************************** 33.row ***************************
+QUERY_PLAN: -> Table Scan on meters (columns=2 width=12 order=[asc|0 desc|1])
+*************************** 34.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 35.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+
+taos> explain verbose true select last(a) as d from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s)) order by d desc\G;
+*************************** 1.row ***************************
+QUERY_PLAN: -> Sort input_order=unknown output_order=desc (columns=1 width=8)
+*************************** 2.row ***************************
+QUERY_PLAN: Output: columns=1 width=8
+*************************** 3.row ***************************
+QUERY_PLAN: -> Aggragate (functions=1 width=8 input_order=asc )
+*************************** 4.row ***************************
+QUERY_PLAN: Output: columns=1 width=8
+*************************** 5.row ***************************
+QUERY_PLAN: Merge ResBlocks: True
+*************************** 6.row ***************************
+QUERY_PLAN: -> Projection (columns=3 width=24 input_order=asc )
+*************************** 7.row ***************************
+QUERY_PLAN: Output: columns=3 width=24
+*************************** 8.row ***************************
+QUERY_PLAN: Output: Ignore Group Id: true
+*************************** 9.row ***************************
+QUERY_PLAN: Merge ResBlocks: True
+*************************** 10.row ***************************
+QUERY_PLAN: -> Merge Aligned Interval on Column (functions=3 width=24 input_order=asc output_order=asc)
+*************************** 11.row ***************************
+QUERY_PLAN: Output: columns=3 width=24
+*************************** 12.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 13.row ***************************
+QUERY_PLAN: Merge ResBlocks: True
+*************************** 14.row ***************************
+QUERY_PLAN: -> SortMerge (columns=3 width=108 input_order=asc output_order=asc)
+*************************** 15.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 16.row ***************************
+QUERY_PLAN: Output: Ignore Group Id: false
+*************************** 17.row ***************************
+QUERY_PLAN: Merge Key: _group_id asc, asc
+*************************** 18.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=108)
+*************************** 19.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 20.row ***************************
+QUERY_PLAN: -> Interval on Column ts (functions=3 width=108 input_order=desc output_order=asc )
+*************************** 21.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 22.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 23.row ***************************
+QUERY_PLAN: Merge ResBlocks: False
+*************************** 24.row ***************************
+QUERY_PLAN: -> Table Scan on meters (columns=2 width=12 order=[asc|0 desc|1])
+*************************** 25.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 26.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+*************************** 27.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=108)
+*************************** 28.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 29.row ***************************
+QUERY_PLAN: -> Interval on Column ts (functions=3 width=108 input_order=desc output_order=asc )
+*************************** 30.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 31.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 32.row ***************************
+QUERY_PLAN: Merge ResBlocks: False
+*************************** 33.row ***************************
+QUERY_PLAN: -> Table Scan on meters (columns=2 width=12 order=[asc|0 desc|1])
+*************************** 34.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 35.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+
+taos> explain verbose true select last(a) as d from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s) order by a) order by d\G;
+*************************** 1.row ***************************
+QUERY_PLAN: -> Sort input_order=unknown output_order=asc (columns=1 width=8)
+*************************** 2.row ***************************
+QUERY_PLAN: Output: columns=1 width=8
+*************************** 3.row ***************************
+QUERY_PLAN: -> Aggragate (functions=1 width=8 input_order=asc )
+*************************** 4.row ***************************
+QUERY_PLAN: Output: columns=1 width=8
+*************************** 5.row ***************************
+QUERY_PLAN: Merge ResBlocks: True
+*************************** 6.row ***************************
+QUERY_PLAN: -> Projection (columns=3 width=24 input_order=asc )
+*************************** 7.row ***************************
+QUERY_PLAN: Output: columns=3 width=24
+*************************** 8.row ***************************
+QUERY_PLAN: Output: Ignore Group Id: true
+*************************** 9.row ***************************
+QUERY_PLAN: Merge ResBlocks: True
+*************************** 10.row ***************************
+QUERY_PLAN: -> Merge Aligned Interval on Column (functions=3 width=24 input_order=asc output_order=asc)
+*************************** 11.row ***************************
+QUERY_PLAN: Output: columns=3 width=24
+*************************** 12.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 13.row ***************************
+QUERY_PLAN: Merge ResBlocks: True
+*************************** 14.row ***************************
+QUERY_PLAN: -> SortMerge (columns=3 width=108 input_order=asc output_order=asc)
+*************************** 15.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 16.row ***************************
+QUERY_PLAN: Output: Ignore Group Id: false
+*************************** 17.row ***************************
+QUERY_PLAN: Merge Key: _group_id asc, asc
+*************************** 18.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=108)
+*************************** 19.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 20.row ***************************
+QUERY_PLAN: -> Interval on Column ts (functions=3 width=108 input_order=desc output_order=asc )
+*************************** 21.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 22.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 23.row ***************************
+QUERY_PLAN: Merge ResBlocks: False
+*************************** 24.row ***************************
+QUERY_PLAN: -> Table Scan on meters (columns=2 width=12 order=[asc|0 desc|1])
+*************************** 25.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 26.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+*************************** 27.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=108)
+*************************** 28.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 29.row ***************************
+QUERY_PLAN: -> Interval on Column ts (functions=3 width=108 input_order=desc output_order=asc )
+*************************** 30.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 31.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 32.row ***************************
+QUERY_PLAN: Merge ResBlocks: False
+*************************** 33.row ***************************
+QUERY_PLAN: -> Table Scan on meters (columns=2 width=12 order=[asc|0 desc|1])
+*************************** 34.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 35.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+
+taos> explain verbose true select last(a) as d from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s) order by a desc) order by d\G;
+*************************** 1.row ***************************
+QUERY_PLAN: -> Sort input_order=unknown output_order=asc (columns=1 width=8)
+*************************** 2.row ***************************
+QUERY_PLAN: Output: columns=1 width=8
+*************************** 3.row ***************************
+QUERY_PLAN: -> Aggragate (functions=1 width=8 input_order=desc )
+*************************** 4.row ***************************
+QUERY_PLAN: Output: columns=1 width=8
+*************************** 5.row ***************************
+QUERY_PLAN: Merge ResBlocks: True
+*************************** 6.row ***************************
+QUERY_PLAN: -> Projection (columns=3 width=24 input_order=desc )
+*************************** 7.row ***************************
+QUERY_PLAN: Output: columns=3 width=24
+*************************** 8.row ***************************
+QUERY_PLAN: Output: Ignore Group Id: true
+*************************** 9.row ***************************
+QUERY_PLAN: Merge ResBlocks: True
+*************************** 10.row ***************************
+QUERY_PLAN: -> Merge Aligned Interval on Column (functions=3 width=24 input_order=desc output_order=desc)
+*************************** 11.row ***************************
+QUERY_PLAN: Output: columns=3 width=24
+*************************** 12.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 13.row ***************************
+QUERY_PLAN: Merge ResBlocks: True
+*************************** 14.row ***************************
+QUERY_PLAN: -> SortMerge (columns=3 width=108 input_order=desc output_order=desc)
+*************************** 15.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 16.row ***************************
+QUERY_PLAN: Output: Ignore Group Id: false
+*************************** 17.row ***************************
+QUERY_PLAN: Merge Key: _group_id asc, desc
+*************************** 18.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=108)
+*************************** 19.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 20.row ***************************
+QUERY_PLAN: -> Interval on Column ts (functions=3 width=108 input_order=desc output_order=desc )
+*************************** 21.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 22.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 23.row ***************************
+QUERY_PLAN: Merge ResBlocks: False
+*************************** 24.row ***************************
+QUERY_PLAN: -> Table Scan on meters (columns=2 width=12 order=[asc|0 desc|1])
+*************************** 25.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 26.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+*************************** 27.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=108)
+*************************** 28.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 29.row ***************************
+QUERY_PLAN: -> Interval on Column ts (functions=3 width=108 input_order=desc output_order=desc )
+*************************** 30.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 31.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 32.row ***************************
+QUERY_PLAN: Merge ResBlocks: False
+*************************** 33.row ***************************
+QUERY_PLAN: -> Table Scan on meters (columns=2 width=12 order=[asc|0 desc|1])
+*************************** 34.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 35.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+
+taos> explain verbose true select last(a) as d from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s) order by a) order by d desc\G;
+*************************** 1.row ***************************
+QUERY_PLAN: -> Sort input_order=unknown output_order=desc (columns=1 width=8)
+*************************** 2.row ***************************
+QUERY_PLAN: Output: columns=1 width=8
+*************************** 3.row ***************************
+QUERY_PLAN: -> Aggragate (functions=1 width=8 input_order=asc )
+*************************** 4.row ***************************
+QUERY_PLAN: Output: columns=1 width=8
+*************************** 5.row ***************************
+QUERY_PLAN: Merge ResBlocks: True
+*************************** 6.row ***************************
+QUERY_PLAN: -> Projection (columns=3 width=24 input_order=asc )
+*************************** 7.row ***************************
+QUERY_PLAN: Output: columns=3 width=24
+*************************** 8.row ***************************
+QUERY_PLAN: Output: Ignore Group Id: true
+*************************** 9.row ***************************
+QUERY_PLAN: Merge ResBlocks: True
+*************************** 10.row ***************************
+QUERY_PLAN: -> Merge Aligned Interval on Column (functions=3 width=24 input_order=asc output_order=asc)
+*************************** 11.row ***************************
+QUERY_PLAN: Output: columns=3 width=24
+*************************** 12.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 13.row ***************************
+QUERY_PLAN: Merge ResBlocks: True
+*************************** 14.row ***************************
+QUERY_PLAN: -> SortMerge (columns=3 width=108 input_order=asc output_order=asc)
+*************************** 15.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 16.row ***************************
+QUERY_PLAN: Output: Ignore Group Id: false
+*************************** 17.row ***************************
+QUERY_PLAN: Merge Key: _group_id asc, asc
+*************************** 18.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=108)
+*************************** 19.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 20.row ***************************
+QUERY_PLAN: -> Interval on Column ts (functions=3 width=108 input_order=desc output_order=asc )
+*************************** 21.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 22.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 23.row ***************************
+QUERY_PLAN: Merge ResBlocks: False
+*************************** 24.row ***************************
+QUERY_PLAN: -> Table Scan on meters (columns=2 width=12 order=[asc|0 desc|1])
+*************************** 25.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 26.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+*************************** 27.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=108)
+*************************** 28.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 29.row ***************************
+QUERY_PLAN: -> Interval on Column ts (functions=3 width=108 input_order=desc output_order=asc )
+*************************** 30.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 31.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 32.row ***************************
+QUERY_PLAN: Merge ResBlocks: False
+*************************** 33.row ***************************
+QUERY_PLAN: -> Table Scan on meters (columns=2 width=12 order=[asc|0 desc|1])
+*************************** 34.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 35.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+
+taos> explain verbose true select last(a) as d from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s) order by a desc) order by d desc\G;
+*************************** 1.row ***************************
+QUERY_PLAN: -> Sort input_order=unknown output_order=desc (columns=1 width=8)
+*************************** 2.row ***************************
+QUERY_PLAN: Output: columns=1 width=8
+*************************** 3.row ***************************
+QUERY_PLAN: -> Aggragate (functions=1 width=8 input_order=desc )
+*************************** 4.row ***************************
+QUERY_PLAN: Output: columns=1 width=8
+*************************** 5.row ***************************
+QUERY_PLAN: Merge ResBlocks: True
+*************************** 6.row ***************************
+QUERY_PLAN: -> Projection (columns=3 width=24 input_order=desc )
+*************************** 7.row ***************************
+QUERY_PLAN: Output: columns=3 width=24
+*************************** 8.row ***************************
+QUERY_PLAN: Output: Ignore Group Id: true
+*************************** 9.row ***************************
+QUERY_PLAN: Merge ResBlocks: True
+*************************** 10.row ***************************
+QUERY_PLAN: -> Merge Aligned Interval on Column (functions=3 width=24 input_order=desc output_order=desc)
+*************************** 11.row ***************************
+QUERY_PLAN: Output: columns=3 width=24
+*************************** 12.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 13.row ***************************
+QUERY_PLAN: Merge ResBlocks: True
+*************************** 14.row ***************************
+QUERY_PLAN: -> SortMerge (columns=3 width=108 input_order=desc output_order=desc)
+*************************** 15.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 16.row ***************************
+QUERY_PLAN: Output: Ignore Group Id: false
+*************************** 17.row ***************************
+QUERY_PLAN: Merge Key: _group_id asc, desc
+*************************** 18.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=108)
+*************************** 19.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 20.row ***************************
+QUERY_PLAN: -> Interval on Column ts (functions=3 width=108 input_order=desc output_order=desc )
+*************************** 21.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 22.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 23.row ***************************
+QUERY_PLAN: Merge ResBlocks: False
+*************************** 24.row ***************************
+QUERY_PLAN: -> Table Scan on meters (columns=2 width=12 order=[asc|0 desc|1])
+*************************** 25.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 26.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+*************************** 27.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=108)
+*************************** 28.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 29.row ***************************
+QUERY_PLAN: -> Interval on Column ts (functions=3 width=108 input_order=desc output_order=desc )
+*************************** 30.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 31.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 32.row ***************************
+QUERY_PLAN: Merge ResBlocks: False
+*************************** 33.row ***************************
+QUERY_PLAN: -> Table Scan on meters (columns=2 width=12 order=[asc|0 desc|1])
+*************************** 34.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 35.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+
+taos> explain verbose true select last(a) as d from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s) order by b) order by d\G;
+*************************** 1.row ***************************
+QUERY_PLAN: -> Sort input_order=unknown output_order=asc (columns=1 width=8)
+*************************** 2.row ***************************
+QUERY_PLAN: Output: columns=1 width=8
+*************************** 3.row ***************************
+QUERY_PLAN: -> Aggragate (functions=1 width=8 input_order=unknown )
+*************************** 4.row ***************************
+QUERY_PLAN: Output: columns=1 width=8
+*************************** 5.row ***************************
+QUERY_PLAN: Merge ResBlocks: True
+*************************** 6.row ***************************
+QUERY_PLAN: -> Projection (columns=3 width=24 input_order=unknown )
+*************************** 7.row ***************************
+QUERY_PLAN: Output: columns=3 width=24
+*************************** 8.row ***************************
+QUERY_PLAN: Output: Ignore Group Id: true
+*************************** 9.row ***************************
+QUERY_PLAN: Merge ResBlocks: True
+*************************** 10.row ***************************
+QUERY_PLAN: -> Sort input_order=asc output_order=unknown (columns=3 width=24)
+*************************** 11.row ***************************
+QUERY_PLAN: Output: columns=3 width=24
+*************************** 12.row ***************************
+QUERY_PLAN: -> Merge Aligned Interval on Column (functions=3 width=24 input_order=asc output_order=asc)
+*************************** 13.row ***************************
+QUERY_PLAN: Output: columns=3 width=24
+*************************** 14.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 15.row ***************************
+QUERY_PLAN: Merge ResBlocks: True
+*************************** 16.row ***************************
+QUERY_PLAN: -> SortMerge (columns=3 width=108 input_order=asc output_order=asc)
+*************************** 17.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 18.row ***************************
+QUERY_PLAN: Output: Ignore Group Id: false
+*************************** 19.row ***************************
+QUERY_PLAN: Merge Key: _group_id asc, asc
+*************************** 20.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=108)
+*************************** 21.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 22.row ***************************
+QUERY_PLAN: -> Interval on Column ts (functions=3 width=108 input_order=desc output_order=asc )
+*************************** 23.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 24.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 25.row ***************************
+QUERY_PLAN: Merge ResBlocks: False
+*************************** 26.row ***************************
+QUERY_PLAN: -> Table Scan on meters (columns=2 width=12 order=[asc|0 desc|1])
+*************************** 27.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 28.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+*************************** 29.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=108)
+*************************** 30.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 31.row ***************************
+QUERY_PLAN: -> Interval on Column ts (functions=3 width=108 input_order=desc output_order=asc )
+*************************** 32.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 33.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 34.row ***************************
+QUERY_PLAN: Merge ResBlocks: False
+*************************** 35.row ***************************
+QUERY_PLAN: -> Table Scan on meters (columns=2 width=12 order=[asc|0 desc|1])
+*************************** 36.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 37.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+
+taos> explain verbose true select last(a) as d from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s) order by b desc) order by d\G;
+*************************** 1.row ***************************
+QUERY_PLAN: -> Sort input_order=unknown output_order=asc (columns=1 width=8)
+*************************** 2.row ***************************
+QUERY_PLAN: Output: columns=1 width=8
+*************************** 3.row ***************************
+QUERY_PLAN: -> Aggragate (functions=1 width=8 input_order=unknown )
+*************************** 4.row ***************************
+QUERY_PLAN: Output: columns=1 width=8
+*************************** 5.row ***************************
+QUERY_PLAN: Merge ResBlocks: True
+*************************** 6.row ***************************
+QUERY_PLAN: -> Projection (columns=3 width=24 input_order=unknown )
+*************************** 7.row ***************************
+QUERY_PLAN: Output: columns=3 width=24
+*************************** 8.row ***************************
+QUERY_PLAN: Output: Ignore Group Id: true
+*************************** 9.row ***************************
+QUERY_PLAN: Merge ResBlocks: True
+*************************** 10.row ***************************
+QUERY_PLAN: -> Sort input_order=asc output_order=unknown (columns=3 width=24)
+*************************** 11.row ***************************
+QUERY_PLAN: Output: columns=3 width=24
+*************************** 12.row ***************************
+QUERY_PLAN: -> Merge Aligned Interval on Column (functions=3 width=24 input_order=asc output_order=asc)
+*************************** 13.row ***************************
+QUERY_PLAN: Output: columns=3 width=24
+*************************** 14.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 15.row ***************************
+QUERY_PLAN: Merge ResBlocks: True
+*************************** 16.row ***************************
+QUERY_PLAN: -> SortMerge (columns=3 width=108 input_order=asc output_order=asc)
+*************************** 17.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 18.row ***************************
+QUERY_PLAN: Output: Ignore Group Id: false
+*************************** 19.row ***************************
+QUERY_PLAN: Merge Key: _group_id asc, asc
+*************************** 20.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=108)
+*************************** 21.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 22.row ***************************
+QUERY_PLAN: -> Interval on Column ts (functions=3 width=108 input_order=desc output_order=asc )
+*************************** 23.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 24.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 25.row ***************************
+QUERY_PLAN: Merge ResBlocks: False
+*************************** 26.row ***************************
+QUERY_PLAN: -> Table Scan on meters (columns=2 width=12 order=[asc|0 desc|1])
+*************************** 27.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 28.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+*************************** 29.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=108)
+*************************** 30.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 31.row ***************************
+QUERY_PLAN: -> Interval on Column ts (functions=3 width=108 input_order=desc output_order=asc )
+*************************** 32.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 33.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 34.row ***************************
+QUERY_PLAN: Merge ResBlocks: False
+*************************** 35.row ***************************
+QUERY_PLAN: -> Table Scan on meters (columns=2 width=12 order=[asc|0 desc|1])
+*************************** 36.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 37.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+
+taos> explain verbose true select last(a) as d from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s) order by b) order by d desc\G;
+*************************** 1.row ***************************
+QUERY_PLAN: -> Sort input_order=unknown output_order=desc (columns=1 width=8)
+*************************** 2.row ***************************
+QUERY_PLAN: Output: columns=1 width=8
+*************************** 3.row ***************************
+QUERY_PLAN: -> Aggragate (functions=1 width=8 input_order=unknown )
+*************************** 4.row ***************************
+QUERY_PLAN: Output: columns=1 width=8
+*************************** 5.row ***************************
+QUERY_PLAN: Merge ResBlocks: True
+*************************** 6.row ***************************
+QUERY_PLAN: -> Projection (columns=3 width=24 input_order=unknown )
+*************************** 7.row ***************************
+QUERY_PLAN: Output: columns=3 width=24
+*************************** 8.row ***************************
+QUERY_PLAN: Output: Ignore Group Id: true
+*************************** 9.row ***************************
+QUERY_PLAN: Merge ResBlocks: True
+*************************** 10.row ***************************
+QUERY_PLAN: -> Sort input_order=asc output_order=unknown (columns=3 width=24)
+*************************** 11.row ***************************
+QUERY_PLAN: Output: columns=3 width=24
+*************************** 12.row ***************************
+QUERY_PLAN: -> Merge Aligned Interval on Column (functions=3 width=24 input_order=asc output_order=asc)
+*************************** 13.row ***************************
+QUERY_PLAN: Output: columns=3 width=24
+*************************** 14.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 15.row ***************************
+QUERY_PLAN: Merge ResBlocks: True
+*************************** 16.row ***************************
+QUERY_PLAN: -> SortMerge (columns=3 width=108 input_order=asc output_order=asc)
+*************************** 17.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 18.row ***************************
+QUERY_PLAN: Output: Ignore Group Id: false
+*************************** 19.row ***************************
+QUERY_PLAN: Merge Key: _group_id asc, asc
+*************************** 20.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=108)
+*************************** 21.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 22.row ***************************
+QUERY_PLAN: -> Interval on Column ts (functions=3 width=108 input_order=desc output_order=asc )
+*************************** 23.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 24.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 25.row ***************************
+QUERY_PLAN: Merge ResBlocks: False
+*************************** 26.row ***************************
+QUERY_PLAN: -> Table Scan on meters (columns=2 width=12 order=[asc|0 desc|1])
+*************************** 27.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 28.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+*************************** 29.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=108)
+*************************** 30.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 31.row ***************************
+QUERY_PLAN: -> Interval on Column ts (functions=3 width=108 input_order=desc output_order=asc )
+*************************** 32.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 33.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 34.row ***************************
+QUERY_PLAN: Merge ResBlocks: False
+*************************** 35.row ***************************
+QUERY_PLAN: -> Table Scan on meters (columns=2 width=12 order=[asc|0 desc|1])
+*************************** 36.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 37.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+
+taos> explain verbose true select last(a) as d from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s) order by b desc) order by d desc\G;
+*************************** 1.row ***************************
+QUERY_PLAN: -> Sort input_order=unknown output_order=desc (columns=1 width=8)
+*************************** 2.row ***************************
+QUERY_PLAN: Output: columns=1 width=8
+*************************** 3.row ***************************
+QUERY_PLAN: -> Aggragate (functions=1 width=8 input_order=unknown )
+*************************** 4.row ***************************
+QUERY_PLAN: Output: columns=1 width=8
+*************************** 5.row ***************************
+QUERY_PLAN: Merge ResBlocks: True
+*************************** 6.row ***************************
+QUERY_PLAN: -> Projection (columns=3 width=24 input_order=unknown )
+*************************** 7.row ***************************
+QUERY_PLAN: Output: columns=3 width=24
+*************************** 8.row ***************************
+QUERY_PLAN: Output: Ignore Group Id: true
+*************************** 9.row ***************************
+QUERY_PLAN: Merge ResBlocks: True
+*************************** 10.row ***************************
+QUERY_PLAN: -> Sort input_order=asc output_order=unknown (columns=3 width=24)
+*************************** 11.row ***************************
+QUERY_PLAN: Output: columns=3 width=24
+*************************** 12.row ***************************
+QUERY_PLAN: -> Merge Aligned Interval on Column (functions=3 width=24 input_order=asc output_order=asc)
+*************************** 13.row ***************************
+QUERY_PLAN: Output: columns=3 width=24
+*************************** 14.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 15.row ***************************
+QUERY_PLAN: Merge ResBlocks: True
+*************************** 16.row ***************************
+QUERY_PLAN: -> SortMerge (columns=3 width=108 input_order=asc output_order=asc)
+*************************** 17.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 18.row ***************************
+QUERY_PLAN: Output: Ignore Group Id: false
+*************************** 19.row ***************************
+QUERY_PLAN: Merge Key: _group_id asc, asc
+*************************** 20.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=108)
+*************************** 21.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 22.row ***************************
+QUERY_PLAN: -> Interval on Column ts (functions=3 width=108 input_order=desc output_order=asc )
+*************************** 23.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 24.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 25.row ***************************
+QUERY_PLAN: Merge ResBlocks: False
+*************************** 26.row ***************************
+QUERY_PLAN: -> Table Scan on meters (columns=2 width=12 order=[asc|0 desc|1])
+*************************** 27.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 28.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+*************************** 29.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=108)
+*************************** 30.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 31.row ***************************
+QUERY_PLAN: -> Interval on Column ts (functions=3 width=108 input_order=desc output_order=asc )
+*************************** 32.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 33.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 34.row ***************************
+QUERY_PLAN: Merge ResBlocks: False
+*************************** 35.row ***************************
+QUERY_PLAN: -> Table Scan on meters (columns=2 width=12 order=[asc|0 desc|1])
+*************************** 36.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 37.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+
+taos> explain verbose true select last(a) as d from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s) order by b) group by c order by d\G;
+*************************** 1.row ***************************
+QUERY_PLAN: -> Sort input_order=unknown output_order=asc (columns=1 width=8)
+*************************** 2.row ***************************
+QUERY_PLAN: Output: columns=1 width=8
+*************************** 3.row ***************************
+QUERY_PLAN: -> Aggragate (functions=1 width=16 groups=1 input_order=unknown )
+*************************** 4.row ***************************
+QUERY_PLAN: Output: columns=1 width=8
+*************************** 5.row ***************************
+QUERY_PLAN: Merge ResBlocks: True
+*************************** 6.row ***************************
+QUERY_PLAN: -> Projection (columns=3 width=24 input_order=unknown )
+*************************** 7.row ***************************
+QUERY_PLAN: Output: columns=3 width=24
+*************************** 8.row ***************************
+QUERY_PLAN: Output: Ignore Group Id: true
+*************************** 9.row ***************************
+QUERY_PLAN: Merge ResBlocks: True
+*************************** 10.row ***************************
+QUERY_PLAN: -> Sort input_order=asc output_order=unknown (columns=3 width=24)
+*************************** 11.row ***************************
+QUERY_PLAN: Output: columns=3 width=24
+*************************** 12.row ***************************
+QUERY_PLAN: -> Merge Aligned Interval on Column (functions=3 width=24 input_order=asc output_order=asc)
+*************************** 13.row ***************************
+QUERY_PLAN: Output: columns=3 width=24
+*************************** 14.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 15.row ***************************
+QUERY_PLAN: Merge ResBlocks: True
+*************************** 16.row ***************************
+QUERY_PLAN: -> SortMerge (columns=3 width=108 input_order=asc output_order=asc)
+*************************** 17.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 18.row ***************************
+QUERY_PLAN: Output: Ignore Group Id: false
+*************************** 19.row ***************************
+QUERY_PLAN: Merge Key: _group_id asc, asc
+*************************** 20.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=108)
+*************************** 21.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 22.row ***************************
+QUERY_PLAN: -> Interval on Column ts (functions=3 width=108 input_order=desc output_order=asc )
+*************************** 23.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 24.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 25.row ***************************
+QUERY_PLAN: Merge ResBlocks: False
+*************************** 26.row ***************************
+QUERY_PLAN: -> Table Scan on meters (columns=2 width=12 order=[asc|0 desc|1])
+*************************** 27.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 28.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+*************************** 29.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=108)
+*************************** 30.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 31.row ***************************
+QUERY_PLAN: -> Interval on Column ts (functions=3 width=108 input_order=desc output_order=asc )
+*************************** 32.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 33.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 34.row ***************************
+QUERY_PLAN: Merge ResBlocks: False
+*************************** 35.row ***************************
+QUERY_PLAN: -> Table Scan on meters (columns=2 width=12 order=[asc|0 desc|1])
+*************************** 36.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 37.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+
+taos> explain verbose true select last(a) as d from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s) order by b desc) group by c order by d\G;
+*************************** 1.row ***************************
+QUERY_PLAN: -> Sort input_order=unknown output_order=asc (columns=1 width=8)
+*************************** 2.row ***************************
+QUERY_PLAN: Output: columns=1 width=8
+*************************** 3.row ***************************
+QUERY_PLAN: -> Aggragate (functions=1 width=16 groups=1 input_order=unknown )
+*************************** 4.row ***************************
+QUERY_PLAN: Output: columns=1 width=8
+*************************** 5.row ***************************
+QUERY_PLAN: Merge ResBlocks: True
+*************************** 6.row ***************************
+QUERY_PLAN: -> Projection (columns=3 width=24 input_order=unknown )
+*************************** 7.row ***************************
+QUERY_PLAN: Output: columns=3 width=24
+*************************** 8.row ***************************
+QUERY_PLAN: Output: Ignore Group Id: true
+*************************** 9.row ***************************
+QUERY_PLAN: Merge ResBlocks: True
+*************************** 10.row ***************************
+QUERY_PLAN: -> Sort input_order=asc output_order=unknown (columns=3 width=24)
+*************************** 11.row ***************************
+QUERY_PLAN: Output: columns=3 width=24
+*************************** 12.row ***************************
+QUERY_PLAN: -> Merge Aligned Interval on Column (functions=3 width=24 input_order=asc output_order=asc)
+*************************** 13.row ***************************
+QUERY_PLAN: Output: columns=3 width=24
+*************************** 14.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 15.row ***************************
+QUERY_PLAN: Merge ResBlocks: True
+*************************** 16.row ***************************
+QUERY_PLAN: -> SortMerge (columns=3 width=108 input_order=asc output_order=asc)
+*************************** 17.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 18.row ***************************
+QUERY_PLAN: Output: Ignore Group Id: false
+*************************** 19.row ***************************
+QUERY_PLAN: Merge Key: _group_id asc, asc
+*************************** 20.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=108)
+*************************** 21.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 22.row ***************************
+QUERY_PLAN: -> Interval on Column ts (functions=3 width=108 input_order=desc output_order=asc )
+*************************** 23.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 24.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 25.row ***************************
+QUERY_PLAN: Merge ResBlocks: False
+*************************** 26.row ***************************
+QUERY_PLAN: -> Table Scan on meters (columns=2 width=12 order=[asc|0 desc|1])
+*************************** 27.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 28.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+*************************** 29.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=108)
+*************************** 30.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 31.row ***************************
+QUERY_PLAN: -> Interval on Column ts (functions=3 width=108 input_order=desc output_order=asc )
+*************************** 32.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 33.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 34.row ***************************
+QUERY_PLAN: Merge ResBlocks: False
+*************************** 35.row ***************************
+QUERY_PLAN: -> Table Scan on meters (columns=2 width=12 order=[asc|0 desc|1])
+*************************** 36.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 37.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+
+taos> explain verbose true select last(a) as d from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s) order by b) group by c order by d desc\G;
+*************************** 1.row ***************************
+QUERY_PLAN: -> Sort input_order=unknown output_order=desc (columns=1 width=8)
+*************************** 2.row ***************************
+QUERY_PLAN: Output: columns=1 width=8
+*************************** 3.row ***************************
+QUERY_PLAN: -> Aggragate (functions=1 width=16 groups=1 input_order=unknown )
+*************************** 4.row ***************************
+QUERY_PLAN: Output: columns=1 width=8
+*************************** 5.row ***************************
+QUERY_PLAN: Merge ResBlocks: True
+*************************** 6.row ***************************
+QUERY_PLAN: -> Projection (columns=3 width=24 input_order=unknown )
+*************************** 7.row ***************************
+QUERY_PLAN: Output: columns=3 width=24
+*************************** 8.row ***************************
+QUERY_PLAN: Output: Ignore Group Id: true
+*************************** 9.row ***************************
+QUERY_PLAN: Merge ResBlocks: True
+*************************** 10.row ***************************
+QUERY_PLAN: -> Sort input_order=asc output_order=unknown (columns=3 width=24)
+*************************** 11.row ***************************
+QUERY_PLAN: Output: columns=3 width=24
+*************************** 12.row ***************************
+QUERY_PLAN: -> Merge Aligned Interval on Column (functions=3 width=24 input_order=asc output_order=asc)
+*************************** 13.row ***************************
+QUERY_PLAN: Output: columns=3 width=24
+*************************** 14.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 15.row ***************************
+QUERY_PLAN: Merge ResBlocks: True
+*************************** 16.row ***************************
+QUERY_PLAN: -> SortMerge (columns=3 width=108 input_order=asc output_order=asc)
+*************************** 17.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 18.row ***************************
+QUERY_PLAN: Output: Ignore Group Id: false
+*************************** 19.row ***************************
+QUERY_PLAN: Merge Key: _group_id asc, asc
+*************************** 20.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=108)
+*************************** 21.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 22.row ***************************
+QUERY_PLAN: -> Interval on Column ts (functions=3 width=108 input_order=desc output_order=asc )
+*************************** 23.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 24.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 25.row ***************************
+QUERY_PLAN: Merge ResBlocks: False
+*************************** 26.row ***************************
+QUERY_PLAN: -> Table Scan on meters (columns=2 width=12 order=[asc|0 desc|1])
+*************************** 27.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 28.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+*************************** 29.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=108)
+*************************** 30.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 31.row ***************************
+QUERY_PLAN: -> Interval on Column ts (functions=3 width=108 input_order=desc output_order=asc )
+*************************** 32.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 33.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 34.row ***************************
+QUERY_PLAN: Merge ResBlocks: False
+*************************** 35.row ***************************
+QUERY_PLAN: -> Table Scan on meters (columns=2 width=12 order=[asc|0 desc|1])
+*************************** 36.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 37.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+
+taos> explain verbose true select last(a) as d from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s) order by b desc) group by c order by d desc\G;
+*************************** 1.row ***************************
+QUERY_PLAN: -> Sort input_order=unknown output_order=desc (columns=1 width=8)
+*************************** 2.row ***************************
+QUERY_PLAN: Output: columns=1 width=8
+*************************** 3.row ***************************
+QUERY_PLAN: -> Aggragate (functions=1 width=16 groups=1 input_order=unknown )
+*************************** 4.row ***************************
+QUERY_PLAN: Output: columns=1 width=8
+*************************** 5.row ***************************
+QUERY_PLAN: Merge ResBlocks: True
+*************************** 6.row ***************************
+QUERY_PLAN: -> Projection (columns=3 width=24 input_order=unknown )
+*************************** 7.row ***************************
+QUERY_PLAN: Output: columns=3 width=24
+*************************** 8.row ***************************
+QUERY_PLAN: Output: Ignore Group Id: true
+*************************** 9.row ***************************
+QUERY_PLAN: Merge ResBlocks: True
+*************************** 10.row ***************************
+QUERY_PLAN: -> Sort input_order=asc output_order=unknown (columns=3 width=24)
+*************************** 11.row ***************************
+QUERY_PLAN: Output: columns=3 width=24
+*************************** 12.row ***************************
+QUERY_PLAN: -> Merge Aligned Interval on Column (functions=3 width=24 input_order=asc output_order=asc)
+*************************** 13.row ***************************
+QUERY_PLAN: Output: columns=3 width=24
+*************************** 14.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 15.row ***************************
+QUERY_PLAN: Merge ResBlocks: True
+*************************** 16.row ***************************
+QUERY_PLAN: -> SortMerge (columns=3 width=108 input_order=asc output_order=asc)
+*************************** 17.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 18.row ***************************
+QUERY_PLAN: Output: Ignore Group Id: false
+*************************** 19.row ***************************
+QUERY_PLAN: Merge Key: _group_id asc, asc
+*************************** 20.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=108)
+*************************** 21.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 22.row ***************************
+QUERY_PLAN: -> Interval on Column ts (functions=3 width=108 input_order=desc output_order=asc )
+*************************** 23.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 24.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 25.row ***************************
+QUERY_PLAN: Merge ResBlocks: False
+*************************** 26.row ***************************
+QUERY_PLAN: -> Table Scan on meters (columns=2 width=12 order=[asc|0 desc|1])
+*************************** 27.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 28.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+*************************** 29.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=108)
+*************************** 30.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 31.row ***************************
+QUERY_PLAN: -> Interval on Column ts (functions=3 width=108 input_order=desc output_order=asc )
+*************************** 32.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 33.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 34.row ***************************
+QUERY_PLAN: Merge ResBlocks: False
+*************************** 35.row ***************************
+QUERY_PLAN: -> Table Scan on meters (columns=2 width=12 order=[asc|0 desc|1])
+*************************** 36.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 37.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+
+taos> explain verbose true select last(a) as d from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s) order by b) where a > 10000 and a < 20000 interval(10s) fill(NULL) order by d\G;
+*************************** 1.row ***************************
+QUERY_PLAN: -> Sort input_order=unknown output_order=asc (columns=1 width=8)
+*************************** 2.row ***************************
+QUERY_PLAN: Output: columns=1 width=8
+*************************** 3.row ***************************
+QUERY_PLAN: -> Fill (mode=null width=24 input_order=unknown )
+*************************** 4.row ***************************
+QUERY_PLAN: Output: columns=2 width=16
+*************************** 5.row ***************************
+QUERY_PLAN: Time Range: [10001, 19999]
+*************************** 6.row ***************************
+QUERY_PLAN: -> Interval on Column a (functions=2 width=16 input_order=asc output_order=asc )
+*************************** 7.row ***************************
+QUERY_PLAN: Output: columns=2 width=16
+*************************** 8.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 9.row ***************************
+QUERY_PLAN: Merge ResBlocks: False
+*************************** 10.row ***************************
+QUERY_PLAN: -> Projection (columns=3 width=24 input_order=unknown )
+*************************** 11.row ***************************
+QUERY_PLAN: Output: columns=3 width=24
+*************************** 12.row ***************************
+QUERY_PLAN: Output: Ignore Group Id: true
+*************************** 13.row ***************************
+QUERY_PLAN: Merge ResBlocks: False
+*************************** 14.row ***************************
+QUERY_PLAN: -> Sort input_order=asc output_order=unknown (columns=3 width=24)
+*************************** 15.row ***************************
+QUERY_PLAN: Output: columns=3 width=24
+*************************** 16.row ***************************
+QUERY_PLAN: -> Merge Aligned Interval on Column (functions=3 width=24 input_order=asc output_order=asc)
+*************************** 17.row ***************************
+QUERY_PLAN: Output: columns=3 width=24
+*************************** 18.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 19.row ***************************
+QUERY_PLAN: Filter: ((a > 10000) AND (a < 20000))
+*************************** 20.row ***************************
+QUERY_PLAN: Merge ResBlocks: True
+*************************** 21.row ***************************
+QUERY_PLAN: -> SortMerge (columns=3 width=108 input_order=asc output_order=asc)
+*************************** 22.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 23.row ***************************
+QUERY_PLAN: Output: Ignore Group Id: false
+*************************** 24.row ***************************
+QUERY_PLAN: Merge Key: _group_id asc, asc
+*************************** 25.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=108)
+*************************** 26.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 27.row ***************************
+QUERY_PLAN: -> Interval on Column ts (functions=3 width=108 input_order=desc output_order=asc )
+*************************** 28.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 29.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 30.row ***************************
+QUERY_PLAN: Merge ResBlocks: False
+*************************** 31.row ***************************
+QUERY_PLAN: -> Table Scan on meters (columns=2 width=12 order=[asc|0 desc|1])
+*************************** 32.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 33.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+*************************** 34.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=108)
+*************************** 35.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 36.row ***************************
+QUERY_PLAN: -> Interval on Column ts (functions=3 width=108 input_order=desc output_order=asc )
+*************************** 37.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 38.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 39.row ***************************
+QUERY_PLAN: Merge ResBlocks: False
+*************************** 40.row ***************************
+QUERY_PLAN: -> Table Scan on meters (columns=2 width=12 order=[asc|0 desc|1])
+*************************** 41.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 42.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+
+taos> explain verbose true select last(a) as d from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s) order by a desc) where a > 10000 and a < 20000 interval(10s) fill(NULL) order by d\G;
+*************************** 1.row ***************************
+QUERY_PLAN: -> Sort input_order=asc output_order=asc (columns=1 width=8)
+*************************** 2.row ***************************
+QUERY_PLAN: Output: columns=1 width=8
+*************************** 3.row ***************************
+QUERY_PLAN: -> Fill (mode=null width=24 input_order=asc )
+*************************** 4.row ***************************
+QUERY_PLAN: Output: columns=2 width=16
+*************************** 5.row ***************************
+QUERY_PLAN: Time Range: [10001, 19999]
+*************************** 6.row ***************************
+QUERY_PLAN: -> Interval on Column a (functions=2 width=16 input_order=desc output_order=asc )
+*************************** 7.row ***************************
+QUERY_PLAN: Output: columns=2 width=16
+*************************** 8.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 9.row ***************************
+QUERY_PLAN: Merge ResBlocks: False
+*************************** 10.row ***************************
+QUERY_PLAN: -> Projection (columns=3 width=24 input_order=desc )
+*************************** 11.row ***************************
+QUERY_PLAN: Output: columns=3 width=24
+*************************** 12.row ***************************
+QUERY_PLAN: Output: Ignore Group Id: true
+*************************** 13.row ***************************
+QUERY_PLAN: Merge ResBlocks: False
+*************************** 14.row ***************************
+QUERY_PLAN: -> Merge Aligned Interval on Column (functions=3 width=24 input_order=desc output_order=desc)
+*************************** 15.row ***************************
+QUERY_PLAN: Output: columns=3 width=24
+*************************** 16.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 17.row ***************************
+QUERY_PLAN: Filter: ((a > 10000) AND (a < 20000))
+*************************** 18.row ***************************
+QUERY_PLAN: Merge ResBlocks: True
+*************************** 19.row ***************************
+QUERY_PLAN: -> SortMerge (columns=3 width=108 input_order=desc output_order=desc)
+*************************** 20.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 21.row ***************************
+QUERY_PLAN: Output: Ignore Group Id: false
+*************************** 22.row ***************************
+QUERY_PLAN: Merge Key: _group_id asc, desc
+*************************** 23.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=108)
+*************************** 24.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 25.row ***************************
+QUERY_PLAN: -> Interval on Column ts (functions=3 width=108 input_order=desc output_order=desc )
+*************************** 26.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 27.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 28.row ***************************
+QUERY_PLAN: Merge ResBlocks: False
+*************************** 29.row ***************************
+QUERY_PLAN: -> Table Scan on meters (columns=2 width=12 order=[asc|0 desc|1])
+*************************** 30.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 31.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+*************************** 32.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=108)
+*************************** 33.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 34.row ***************************
+QUERY_PLAN: -> Interval on Column ts (functions=3 width=108 input_order=desc output_order=desc )
+*************************** 35.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 36.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 37.row ***************************
+QUERY_PLAN: Merge ResBlocks: False
+*************************** 38.row ***************************
+QUERY_PLAN: -> Table Scan on meters (columns=2 width=12 order=[asc|0 desc|1])
+*************************** 39.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 40.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+
+taos> explain verbose true select last(b) as d from (select last(ts) as b, avg(c2) as c from meters interval(10s) order by b desc) where b > 10000 and b < 20000 interval(10s) fill(NULL) order by d\G;
+*************************** 1.row ***************************
+QUERY_PLAN: -> Sort input_order=asc output_order=asc (columns=1 width=8)
+*************************** 2.row ***************************
+QUERY_PLAN: Output: columns=1 width=8
+*************************** 3.row ***************************
+QUERY_PLAN: -> Fill (mode=null width=24 input_order=asc )
+*************************** 4.row ***************************
+QUERY_PLAN: Output: columns=2 width=16
+*************************** 5.row ***************************
+QUERY_PLAN: Time Range: [10001, 19999]
+*************************** 6.row ***************************
+QUERY_PLAN: -> Interval on Column b (functions=2 width=16 input_order=desc output_order=asc )
+*************************** 7.row ***************************
+QUERY_PLAN: Output: columns=2 width=16
+*************************** 8.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 9.row ***************************
+QUERY_PLAN: Merge ResBlocks: False
+*************************** 10.row ***************************
+QUERY_PLAN: -> Projection (columns=2 width=16 input_order=desc )
+*************************** 11.row ***************************
+QUERY_PLAN: Output: columns=2 width=16
+*************************** 12.row ***************************
+QUERY_PLAN: Output: Ignore Group Id: true
+*************************** 13.row ***************************
+QUERY_PLAN: Merge ResBlocks: False
+*************************** 14.row ***************************
+QUERY_PLAN: -> Sort input_order=asc output_order=desc (columns=2 width=16)
+*************************** 15.row ***************************
+QUERY_PLAN: Output: columns=2 width=16
+*************************** 16.row ***************************
+QUERY_PLAN: -> Merge Aligned Interval on Column (functions=2 width=16 input_order=asc output_order=asc)
+*************************** 17.row ***************************
+QUERY_PLAN: Output: columns=2 width=16
+*************************** 18.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 19.row ***************************
+QUERY_PLAN: Filter: ((b > 10000) AND (b < 20000))
+*************************** 20.row ***************************
+QUERY_PLAN: Merge ResBlocks: True
+*************************** 21.row ***************************
+QUERY_PLAN: -> SortMerge (columns=3 width=108 input_order=asc output_order=asc)
+*************************** 22.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 23.row ***************************
+QUERY_PLAN: Output: Ignore Group Id: false
+*************************** 24.row ***************************
+QUERY_PLAN: Merge Key: _group_id asc, asc
+*************************** 25.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=108)
+*************************** 26.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 27.row ***************************
+QUERY_PLAN: -> Interval on Column ts (functions=3 width=108 input_order=desc output_order=asc )
+*************************** 28.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 29.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 30.row ***************************
+QUERY_PLAN: Merge ResBlocks: False
+*************************** 31.row ***************************
+QUERY_PLAN: -> Table Scan on meters (columns=2 width=12 order=[asc|0 desc|1])
+*************************** 32.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 33.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+*************************** 34.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=108)
+*************************** 35.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 36.row ***************************
+QUERY_PLAN: -> Interval on Column ts (functions=3 width=108 input_order=desc output_order=asc )
+*************************** 37.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 38.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 39.row ***************************
+QUERY_PLAN: Merge ResBlocks: False
+*************************** 40.row ***************************
+QUERY_PLAN: -> Table Scan on meters (columns=2 width=12 order=[asc|0 desc|1])
+*************************** 41.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 42.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+
+taos> explain verbose true select last(b) as d from (select last(ts) as b, avg(c2) as c from meters interval(10s) order by b desc) where b > 10000 and b < 20000 interval(10s) fill(NULL) order by d desc\G;
+*************************** 1.row ***************************
+QUERY_PLAN: -> Sort input_order=asc output_order=desc (columns=1 width=8)
+*************************** 2.row ***************************
+QUERY_PLAN: Output: columns=1 width=8
+*************************** 3.row ***************************
+QUERY_PLAN: -> Fill (mode=null width=24 input_order=asc )
+*************************** 4.row ***************************
+QUERY_PLAN: Output: columns=2 width=16
+*************************** 5.row ***************************
+QUERY_PLAN: Time Range: [10001, 19999]
+*************************** 6.row ***************************
+QUERY_PLAN: -> Interval on Column b (functions=2 width=16 input_order=desc output_order=asc )
+*************************** 7.row ***************************
+QUERY_PLAN: Output: columns=2 width=16
+*************************** 8.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 9.row ***************************
+QUERY_PLAN: Merge ResBlocks: False
+*************************** 10.row ***************************
+QUERY_PLAN: -> Projection (columns=2 width=16 input_order=desc )
+*************************** 11.row ***************************
+QUERY_PLAN: Output: columns=2 width=16
+*************************** 12.row ***************************
+QUERY_PLAN: Output: Ignore Group Id: true
+*************************** 13.row ***************************
+QUERY_PLAN: Merge ResBlocks: False
+*************************** 14.row ***************************
+QUERY_PLAN: -> Sort input_order=asc output_order=desc (columns=2 width=16)
+*************************** 15.row ***************************
+QUERY_PLAN: Output: columns=2 width=16
+*************************** 16.row ***************************
+QUERY_PLAN: -> Merge Aligned Interval on Column (functions=2 width=16 input_order=asc output_order=asc)
+*************************** 17.row ***************************
+QUERY_PLAN: Output: columns=2 width=16
+*************************** 18.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 19.row ***************************
+QUERY_PLAN: Filter: ((b > 10000) AND (b < 20000))
+*************************** 20.row ***************************
+QUERY_PLAN: Merge ResBlocks: True
+*************************** 21.row ***************************
+QUERY_PLAN: -> SortMerge (columns=3 width=108 input_order=asc output_order=asc)
+*************************** 22.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 23.row ***************************
+QUERY_PLAN: Output: Ignore Group Id: false
+*************************** 24.row ***************************
+QUERY_PLAN: Merge Key: _group_id asc, asc
+*************************** 25.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=108)
+*************************** 26.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 27.row ***************************
+QUERY_PLAN: -> Interval on Column ts (functions=3 width=108 input_order=desc output_order=asc )
+*************************** 28.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 29.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 30.row ***************************
+QUERY_PLAN: Merge ResBlocks: False
+*************************** 31.row ***************************
+QUERY_PLAN: -> Table Scan on meters (columns=2 width=12 order=[asc|0 desc|1])
+*************************** 32.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 33.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+*************************** 34.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=108)
+*************************** 35.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 36.row ***************************
+QUERY_PLAN: -> Interval on Column ts (functions=3 width=108 input_order=desc output_order=asc )
+*************************** 37.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 38.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 39.row ***************************
+QUERY_PLAN: Merge ResBlocks: False
+*************************** 40.row ***************************
+QUERY_PLAN: -> Table Scan on meters (columns=2 width=12 order=[asc|0 desc|1])
+*************************** 41.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 42.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+
+taos> select _wstart, last(ts), avg(c2) from meters interval(10s) order by _wstart desc;
+ _wstart | last(ts) | avg(c2) |
+================================================================================
+ 2022-05-24 00:01:00.000 | 2022-05-24 00:01:08.000 | 210.000000000 |
+ 2022-05-23 00:01:00.000 | 2022-05-23 00:01:08.000 | 116.000000000 |
+ 2022-05-22 00:01:00.000 | 2022-05-22 00:01:08.000 | 196.000000000 |
+ 2022-05-21 00:01:00.000 | 2022-05-21 00:01:08.000 | 11.000000000 |
+ 2022-05-20 00:01:00.000 | 2022-05-20 00:01:08.000 | 120.000000000 |
+ 2022-05-19 00:01:00.000 | 2022-05-19 00:01:08.000 | 243.000000000 |
+ 2022-05-18 00:01:00.000 | 2022-05-18 00:01:08.000 | 58.000000000 |
+ 2022-05-17 00:01:00.000 | 2022-05-17 00:01:08.000 | 59.000000000 |
+ 2022-05-16 00:01:00.000 | 2022-05-16 00:01:08.000 | 136.000000000 |
+ 2022-05-15 00:01:00.000 | 2022-05-15 00:01:08.000 | 234.000000000 |
+
+taos> select _wstart, last(ts), avg(c2) from meters interval(10s) order by _wstart asc;
+ _wstart | last(ts) | avg(c2) |
+================================================================================
+ 2022-05-15 00:01:00.000 | 2022-05-15 00:01:08.000 | 234.000000000 |
+ 2022-05-16 00:01:00.000 | 2022-05-16 00:01:08.000 | 136.000000000 |
+ 2022-05-17 00:01:00.000 | 2022-05-17 00:01:08.000 | 59.000000000 |
+ 2022-05-18 00:01:00.000 | 2022-05-18 00:01:08.000 | 58.000000000 |
+ 2022-05-19 00:01:00.000 | 2022-05-19 00:01:08.000 | 243.000000000 |
+ 2022-05-20 00:01:00.000 | 2022-05-20 00:01:08.000 | 120.000000000 |
+ 2022-05-21 00:01:00.000 | 2022-05-21 00:01:08.000 | 11.000000000 |
+ 2022-05-22 00:01:00.000 | 2022-05-22 00:01:08.000 | 196.000000000 |
+ 2022-05-23 00:01:00.000 | 2022-05-23 00:01:08.000 | 116.000000000 |
+ 2022-05-24 00:01:00.000 | 2022-05-24 00:01:08.000 | 210.000000000 |
+
+taos> select _wstart, first(ts), avg(c2) from meters interval(10s) order by _wstart asc;
+ _wstart | first(ts) | avg(c2) |
+================================================================================
+ 2022-05-15 00:01:00.000 | 2022-05-15 00:01:08.000 | 234.000000000 |
+ 2022-05-16 00:01:00.000 | 2022-05-16 00:01:08.000 | 136.000000000 |
+ 2022-05-17 00:01:00.000 | 2022-05-17 00:01:08.000 | 59.000000000 |
+ 2022-05-18 00:01:00.000 | 2022-05-18 00:01:08.000 | 58.000000000 |
+ 2022-05-19 00:01:00.000 | 2022-05-19 00:01:08.000 | 243.000000000 |
+ 2022-05-20 00:01:00.000 | 2022-05-20 00:01:08.000 | 120.000000000 |
+ 2022-05-21 00:01:00.000 | 2022-05-21 00:01:08.000 | 11.000000000 |
+ 2022-05-22 00:01:00.000 | 2022-05-22 00:01:08.000 | 196.000000000 |
+ 2022-05-23 00:01:00.000 | 2022-05-23 00:01:08.000 | 116.000000000 |
+ 2022-05-24 00:01:00.000 | 2022-05-24 00:01:08.000 | 210.000000000 |
+
+taos> select _wstart, first(ts), avg(c2) from meters interval(10s) order by _wstart desc;
+ _wstart | first(ts) | avg(c2) |
+================================================================================
+ 2022-05-24 00:01:00.000 | 2022-05-24 00:01:08.000 | 210.000000000 |
+ 2022-05-23 00:01:00.000 | 2022-05-23 00:01:08.000 | 116.000000000 |
+ 2022-05-22 00:01:00.000 | 2022-05-22 00:01:08.000 | 196.000000000 |
+ 2022-05-21 00:01:00.000 | 2022-05-21 00:01:08.000 | 11.000000000 |
+ 2022-05-20 00:01:00.000 | 2022-05-20 00:01:08.000 | 120.000000000 |
+ 2022-05-19 00:01:00.000 | 2022-05-19 00:01:08.000 | 243.000000000 |
+ 2022-05-18 00:01:00.000 | 2022-05-18 00:01:08.000 | 58.000000000 |
+ 2022-05-17 00:01:00.000 | 2022-05-17 00:01:08.000 | 59.000000000 |
+ 2022-05-16 00:01:00.000 | 2022-05-16 00:01:08.000 | 136.000000000 |
+ 2022-05-15 00:01:00.000 | 2022-05-15 00:01:08.000 | 234.000000000 |
+
+taos> select last(a) as d from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s)) order by d;
+ d |
+==========================
+ 2022-05-24 00:01:00.000 |
+
+taos> select last(a) as d from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s)) order by d desc;
+ d |
+==========================
+ 2022-05-24 00:01:00.000 |
+
+taos> select last(a) as d from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s) order by a) order by d;
+ d |
+==========================
+ 2022-05-24 00:01:00.000 |
+
+taos> select last(a) as d from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s) order by a desc) order by d;
+ d |
+==========================
+ 2022-05-24 00:01:00.000 |
+
+taos> select last(a) as d from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s) order by a) order by d desc;
+ d |
+==========================
+ 2022-05-24 00:01:00.000 |
+
+taos> select last(a) as d from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s) order by a desc) order by d desc;
+ d |
+==========================
+ 2022-05-24 00:01:00.000 |
+
+taos> select last(a) as d from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s) order by b) order by d;
+ d |
+==========================
+ 2022-05-24 00:01:00.000 |
+
+taos> select last(a) as d from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s) order by b desc) order by d;
+ d |
+==========================
+ 2022-05-24 00:01:00.000 |
+
+taos> select last(a) as d from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s) order by b) order by d desc;
+ d |
+==========================
+ 2022-05-24 00:01:00.000 |
+
+taos> select last(a) as d from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s) order by b desc) order by d desc;
+ d |
+==========================
+ 2022-05-24 00:01:00.000 |
+
+taos> select last(a) as d from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s) order by b) group by c order by d
+ d |
+==========================
+ 2022-05-15 00:01:00.000 |
+ 2022-05-16 00:01:00.000 |
+ 2022-05-17 00:01:00.000 |
+ 2022-05-18 00:01:00.000 |
+ 2022-05-19 00:01:00.000 |
+ 2022-05-20 00:01:00.000 |
+ 2022-05-21 00:01:00.000 |
+ 2022-05-22 00:01:00.000 |
+ 2022-05-23 00:01:00.000 |
+ 2022-05-24 00:01:00.000 |
+
+taos> select last(a) as d from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s) order by b desc) group by c order by d;
+ d |
+==========================
+ 2022-05-15 00:01:00.000 |
+ 2022-05-16 00:01:00.000 |
+ 2022-05-17 00:01:00.000 |
+ 2022-05-18 00:01:00.000 |
+ 2022-05-19 00:01:00.000 |
+ 2022-05-20 00:01:00.000 |
+ 2022-05-21 00:01:00.000 |
+ 2022-05-22 00:01:00.000 |
+ 2022-05-23 00:01:00.000 |
+ 2022-05-24 00:01:00.000 |
+
+taos> select last(a) as d from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s) order by b) group by c order by d desc;
+ d |
+==========================
+ 2022-05-24 00:01:00.000 |
+ 2022-05-23 00:01:00.000 |
+ 2022-05-22 00:01:00.000 |
+ 2022-05-21 00:01:00.000 |
+ 2022-05-20 00:01:00.000 |
+ 2022-05-19 00:01:00.000 |
+ 2022-05-18 00:01:00.000 |
+ 2022-05-17 00:01:00.000 |
+ 2022-05-16 00:01:00.000 |
+ 2022-05-15 00:01:00.000 |
+
+taos> select last(a) as d from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s) order by b desc) group by c order by d desc;
+ d |
+==========================
+ 2022-05-24 00:01:00.000 |
+ 2022-05-23 00:01:00.000 |
+ 2022-05-22 00:01:00.000 |
+ 2022-05-21 00:01:00.000 |
+ 2022-05-20 00:01:00.000 |
+ 2022-05-19 00:01:00.000 |
+ 2022-05-18 00:01:00.000 |
+ 2022-05-17 00:01:00.000 |
+ 2022-05-16 00:01:00.000 |
+ 2022-05-15 00:01:00.000 |
+
+taos> select last(a) as d from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s) order by a desc) where a > '2022-05-15 00:01:00.000' and a < '2022-05-19 00:01:08.000' interval(10s) order by d;
+ d |
+==========================
+ 2022-05-15 00:01:00.000 |
+ 2022-05-16 00:01:00.000 |
+ 2022-05-17 00:01:00.000 |
+ 2022-05-18 00:01:00.000 |
+ 2022-05-19 00:01:00.000 |
+
+taos> select last(b) as d from (select last(ts) as b, avg(c2) as c from meters interval(10s) order by b desc) where b > '2022-05-15 00:01:00.000' and b < '2022-05-19 00:01:08.000' interval(10s) order by d;
+ d |
+==========================
+ 2022-05-15 00:01:08.000 |
+ 2022-05-16 00:01:08.000 |
+ 2022-05-17 00:01:08.000 |
+ 2022-05-18 00:01:08.000 |
+ 2022-05-24 00:01:08.000 |
+
+taos> select last(b) as d from (select last(ts) as b, avg(c2) as c from meters interval(10s) order by b desc) where b > '2022-05-15 00:01:00.000' and b < '2022-05-19 00:01:08.000' interval(10s) order by d desc;
+ d |
+==========================
+ 2022-05-24 00:01:08.000 |
+ 2022-05-18 00:01:08.000 |
+ 2022-05-17 00:01:08.000 |
+ 2022-05-16 00:01:08.000 |
+ 2022-05-15 00:01:08.000 |
+
+taos> select _wstart, first(a) as d, avg(c) from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s) order by a desc) where a > '2022-05-15 00:01:00.000' and a < '2022-05-21 00:01:08.000' interval(5h) fill(linear) order by d desc;
+ _wstart | d | avg(c) |
+================================================================================
+ 2022-05-20 20:00:00.000 | 2022-05-21 00:01:00.000 | 11.000000000 |
+ 2022-05-20 15:00:00.000 | 2022-05-20 18:01:00.000 | 38.250000000 |
+ 2022-05-20 10:00:00.000 | 2022-05-20 12:01:00.000 | 65.500000000 |
+ 2022-05-20 05:00:00.000 | 2022-05-20 06:01:00.000 | 92.750000000 |
+ 2022-05-20 00:00:00.000 | 2022-05-20 00:01:00.000 | 120.000000000 |
+ 2022-05-19 19:00:00.000 | 2022-05-19 19:13:00.000 | 144.600000000 |
+ 2022-05-19 14:00:00.000 | 2022-05-19 14:25:00.000 | 169.200000000 |
+ 2022-05-19 09:00:00.000 | 2022-05-19 09:37:00.000 | 193.800000000 |
+ 2022-05-19 04:00:00.000 | 2022-05-19 04:49:00.000 | 218.400000000 |
+ 2022-05-18 23:00:00.000 | 2022-05-19 00:01:00.000 | 243.000000000 |
+ 2022-05-18 18:00:00.000 | 2022-05-18 19:13:00.000 | 206.000000000 |
+ 2022-05-18 13:00:00.000 | 2022-05-18 14:25:00.000 | 169.000000000 |
+ 2022-05-18 08:00:00.000 | 2022-05-18 09:37:00.000 | 132.000000000 |
+ 2022-05-18 03:00:00.000 | 2022-05-18 04:49:00.000 | 95.000000000 |
+ 2022-05-17 22:00:00.000 | 2022-05-18 00:01:00.000 | 58.000000000 |
+ 2022-05-17 17:00:00.000 | 2022-05-17 19:13:00.000 | 58.200000000 |
+ 2022-05-17 12:00:00.000 | 2022-05-17 14:25:00.000 | 58.400000000 |
+ 2022-05-17 07:00:00.000 | 2022-05-17 09:37:00.000 | 58.600000000 |
+ 2022-05-17 02:00:00.000 | 2022-05-17 04:49:00.000 | 58.800000000 |
+ 2022-05-16 21:00:00.000 | 2022-05-17 00:01:00.000 | 59.000000000 |
+ 2022-05-16 16:00:00.000 | 2022-05-16 19:13:00.000 | 74.400000000 |
+ 2022-05-16 11:00:00.000 | 2022-05-16 14:25:00.000 | 89.800000000 |
+ 2022-05-16 06:00:00.000 | 2022-05-16 09:37:00.000 | 105.200000000 |
+ 2022-05-16 01:00:00.000 | 2022-05-16 04:49:00.000 | 120.600000000 |
+ 2022-05-15 20:00:00.000 | 2022-05-16 00:01:00.000 | 136.000000000 |
+ 2022-05-15 15:00:00.000 | 2022-05-15 18:01:00.000 | 160.500000000 |
+ 2022-05-15 10:00:00.000 | 2022-05-15 12:01:00.000 | 185.000000000 |
+ 2022-05-15 05:00:00.000 | 2022-05-15 06:01:00.000 | 209.500000000 |
+ 2022-05-15 00:00:00.000 | 2022-05-15 00:01:00.000 | 234.000000000 |
+
+taos> explain verbose true select _wstart, first(a) as d, avg(c) from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s) order by a desc) where a > '2022-05-15 00:01:00.000' and a < '2022-05-21 00:01:08.000' interval(5h) fill(linear) order by d desc\G;
+*************************** 1.row ***************************
+QUERY_PLAN: -> Sort input_order=asc output_order=unknown (columns=3 width=24)
+*************************** 2.row ***************************
+QUERY_PLAN: Output: columns=3 width=24
+*************************** 3.row ***************************
+QUERY_PLAN: -> Fill (mode=linear width=32 input_order=asc )
+*************************** 4.row ***************************
+QUERY_PLAN: Output: columns=4 width=32
+*************************** 5.row ***************************
+QUERY_PLAN: Time Range: [1652544060001, 1653062467999]
+*************************** 6.row ***************************
+QUERY_PLAN: -> Interval on Column a (functions=4 width=32 input_order=desc output_order=asc )
+*************************** 7.row ***************************
+QUERY_PLAN: Output: columns=4 width=32
+*************************** 8.row ***************************
+QUERY_PLAN: Time Window: interval=5h offset=0a sliding=5h
+*************************** 9.row ***************************
+QUERY_PLAN: Merge ResBlocks: False
+*************************** 10.row ***************************
+QUERY_PLAN: -> Projection (columns=3 width=24 input_order=desc )
+*************************** 11.row ***************************
+QUERY_PLAN: Output: columns=3 width=24
+*************************** 12.row ***************************
+QUERY_PLAN: Output: Ignore Group Id: true
+*************************** 13.row ***************************
+QUERY_PLAN: Merge ResBlocks: False
+*************************** 14.row ***************************
+QUERY_PLAN: -> Merge Aligned Interval on Column (functions=3 width=24 input_order=desc output_order=desc)
+*************************** 15.row ***************************
+QUERY_PLAN: Output: columns=3 width=24
+*************************** 16.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 17.row ***************************
+QUERY_PLAN: Filter: ((a > 1652544060000) AND (a < 1653062468000))
+*************************** 18.row ***************************
+QUERY_PLAN: Merge ResBlocks: True
+*************************** 19.row ***************************
+QUERY_PLAN: -> SortMerge (columns=3 width=108 input_order=desc output_order=desc)
+*************************** 20.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 21.row ***************************
+QUERY_PLAN: Output: Ignore Group Id: false
+*************************** 22.row ***************************
+QUERY_PLAN: Merge Key: _group_id asc, desc
+*************************** 23.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=108)
+*************************** 24.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 25.row ***************************
+QUERY_PLAN: -> Interval on Column ts (functions=3 width=108 input_order=desc output_order=desc )
+*************************** 26.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 27.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 28.row ***************************
+QUERY_PLAN: Merge ResBlocks: False
+*************************** 29.row ***************************
+QUERY_PLAN: -> Table Scan on meters (columns=2 width=12 order=[asc|0 desc|1])
+*************************** 30.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 31.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+*************************** 32.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=108)
+*************************** 33.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 34.row ***************************
+QUERY_PLAN: -> Interval on Column ts (functions=3 width=108 input_order=desc output_order=desc )
+*************************** 35.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 36.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 37.row ***************************
+QUERY_PLAN: Merge ResBlocks: False
+*************************** 38.row ***************************
+QUERY_PLAN: -> Table Scan on meters (columns=2 width=12 order=[asc|0 desc|1])
+*************************** 39.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 40.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+
+taos> explain verbose true select _wstart, first(a) as d, avg(c) from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s) order by a asc) where a > '2022-05-15 00:01:00.000' and a < '2022-05-21 00:01:08.000' interval(5h) fill(linear) order by d desc\G;
+*************************** 1.row ***************************
+QUERY_PLAN: -> Sort input_order=asc output_order=unknown (columns=3 width=24)
+*************************** 2.row ***************************
+QUERY_PLAN: Output: columns=3 width=24
+*************************** 3.row ***************************
+QUERY_PLAN: -> Fill (mode=linear width=32 input_order=asc )
+*************************** 4.row ***************************
+QUERY_PLAN: Output: columns=4 width=32
+*************************** 5.row ***************************
+QUERY_PLAN: Time Range: [1652544060001, 1653062467999]
+*************************** 6.row ***************************
+QUERY_PLAN: -> Interval on Column a (functions=4 width=32 input_order=asc output_order=asc )
+*************************** 7.row ***************************
+QUERY_PLAN: Output: columns=4 width=32
+*************************** 8.row ***************************
+QUERY_PLAN: Time Window: interval=5h offset=0a sliding=5h
+*************************** 9.row ***************************
+QUERY_PLAN: Merge ResBlocks: False
+*************************** 10.row ***************************
+QUERY_PLAN: -> Projection (columns=3 width=24 input_order=asc )
+*************************** 11.row ***************************
+QUERY_PLAN: Output: columns=3 width=24
+*************************** 12.row ***************************
+QUERY_PLAN: Output: Ignore Group Id: true
+*************************** 13.row ***************************
+QUERY_PLAN: Merge ResBlocks: False
+*************************** 14.row ***************************
+QUERY_PLAN: -> Merge Aligned Interval on Column (functions=3 width=24 input_order=asc output_order=asc)
+*************************** 15.row ***************************
+QUERY_PLAN: Output: columns=3 width=24
+*************************** 16.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 17.row ***************************
+QUERY_PLAN: Filter: ((a > 1652544060000) AND (a < 1653062468000))
+*************************** 18.row ***************************
+QUERY_PLAN: Merge ResBlocks: True
+*************************** 19.row ***************************
+QUERY_PLAN: -> SortMerge (columns=3 width=108 input_order=asc output_order=asc)
+*************************** 20.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 21.row ***************************
+QUERY_PLAN: Output: Ignore Group Id: false
+*************************** 22.row ***************************
+QUERY_PLAN: Merge Key: _group_id asc, asc
+*************************** 23.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=108)
+*************************** 24.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 25.row ***************************
+QUERY_PLAN: -> Interval on Column ts (functions=3 width=108 input_order=desc output_order=asc )
+*************************** 26.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 27.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 28.row ***************************
+QUERY_PLAN: Merge ResBlocks: False
+*************************** 29.row ***************************
+QUERY_PLAN: -> Table Scan on meters (columns=2 width=12 order=[asc|0 desc|1])
+*************************** 30.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 31.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+*************************** 32.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=108)
+*************************** 33.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 34.row ***************************
+QUERY_PLAN: -> Interval on Column ts (functions=3 width=108 input_order=desc output_order=asc )
+*************************** 35.row ***************************
+QUERY_PLAN: Output: columns=3 width=108
+*************************** 36.row ***************************
+QUERY_PLAN: Time Window: interval=10s offset=0a sliding=10s
+*************************** 37.row ***************************
+QUERY_PLAN: Merge ResBlocks: False
+*************************** 38.row ***************************
+QUERY_PLAN: -> Table Scan on meters (columns=2 width=12 order=[asc|0 desc|1])
+*************************** 39.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 40.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+
+taos> explain verbose true select * from (select ts as a, c2 as b from meters order by c2 desc)\G;
+*************************** 1.row ***************************
+QUERY_PLAN: -> SortMerge (columns=2 width=12 input_order=unknown output_order=unknown)
+*************************** 2.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 3.row ***************************
+QUERY_PLAN: Output: Ignore Group Id: false
+*************************** 4.row ***************************
+QUERY_PLAN: Merge Key: b desc
+*************************** 5.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=12)
+*************************** 6.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 7.row ***************************
+QUERY_PLAN: -> Sort input_order=unknown output_order=unknown (columns=2 width=12)
+*************************** 8.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 9.row ***************************
+QUERY_PLAN: -> Table Scan on meters (columns=2 width=12 order=[asc|1 desc|0])
+*************************** 10.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 11.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+*************************** 12.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=12)
+*************************** 13.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 14.row ***************************
+QUERY_PLAN: -> Sort input_order=unknown output_order=unknown (columns=2 width=12)
+*************************** 15.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 16.row ***************************
+QUERY_PLAN: -> Table Scan on meters (columns=2 width=12 order=[asc|1 desc|0])
+*************************** 17.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 18.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+
+taos> select * from (select ts as a, c2 as b from meters order by c2 desc);
+ a | b |
+========================================
+ 2022-05-19 00:01:08.000 | 243 |
+ 2022-05-19 00:01:08.000 | 243 |
+ 2022-05-15 00:01:08.000 | 234 |
+ 2022-05-15 00:01:08.000 | 234 |
+ 2022-05-24 00:01:08.000 | 210 |
+ 2022-05-24 00:01:08.000 | 210 |
+ 2022-05-22 00:01:08.000 | 196 |
+ 2022-05-22 00:01:08.000 | 196 |
+ 2022-05-16 00:01:08.000 | 136 |
+ 2022-05-16 00:01:08.000 | 136 |
+ 2022-05-20 00:01:08.000 | 120 |
+ 2022-05-20 00:01:08.000 | 120 |
+ 2022-05-23 00:01:08.000 | 116 |
+ 2022-05-23 00:01:08.000 | 116 |
+ 2022-05-17 00:01:08.000 | 59 |
+ 2022-05-17 00:01:08.000 | 59 |
+ 2022-05-18 00:01:08.000 | 58 |
+ 2022-05-18 00:01:08.000 | 58 |
+ 2022-05-21 00:01:08.000 | 11 |
+ 2022-05-21 00:01:08.000 | 11 |
+
+taos> explain verbose true select * from (select ts as a, c2 as b from meters order by c2 desc) order by a desc\G;
+*************************** 1.row ***************************
+QUERY_PLAN: -> Sort input_order=unknown output_order=desc (columns=2 width=12)
+*************************** 2.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 3.row ***************************
+QUERY_PLAN: -> Projection (columns=2 width=12 input_order=unknown )
+*************************** 4.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 5.row ***************************
+QUERY_PLAN: Output: Ignore Group Id: true
+*************************** 6.row ***************************
+QUERY_PLAN: Merge ResBlocks: True
+*************************** 7.row ***************************
+QUERY_PLAN: -> SortMerge (columns=2 width=12 input_order=unknown output_order=unknown)
+*************************** 8.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 9.row ***************************
+QUERY_PLAN: Output: Ignore Group Id: false
+*************************** 10.row ***************************
+QUERY_PLAN: Merge Key: b desc
+*************************** 11.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=12)
+*************************** 12.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 13.row ***************************
+QUERY_PLAN: -> Sort input_order=unknown output_order=unknown (columns=2 width=12)
+*************************** 14.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 15.row ***************************
+QUERY_PLAN: -> Table Scan on meters (columns=2 width=12 order=[asc|1 desc|0])
+*************************** 16.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 17.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+*************************** 18.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=12)
+*************************** 19.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 20.row ***************************
+QUERY_PLAN: -> Sort input_order=unknown output_order=unknown (columns=2 width=12)
+*************************** 21.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 22.row ***************************
+QUERY_PLAN: -> Table Scan on meters (columns=2 width=12 order=[asc|1 desc|0])
+*************************** 23.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 24.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+
+taos> select * from (select ts as a, c2 as b from meters order by c2 desc) order by a desc;
+ a | b |
+========================================
+ 2022-05-24 00:01:08.000 | 210 |
+ 2022-05-24 00:01:08.000 | 210 |
+ 2022-05-23 00:01:08.000 | 116 |
+ 2022-05-23 00:01:08.000 | 116 |
+ 2022-05-22 00:01:08.000 | 196 |
+ 2022-05-22 00:01:08.000 | 196 |
+ 2022-05-21 00:01:08.000 | 11 |
+ 2022-05-21 00:01:08.000 | 11 |
+ 2022-05-20 00:01:08.000 | 120 |
+ 2022-05-20 00:01:08.000 | 120 |
+ 2022-05-19 00:01:08.000 | 243 |
+ 2022-05-19 00:01:08.000 | 243 |
+ 2022-05-18 00:01:08.000 | 58 |
+ 2022-05-18 00:01:08.000 | 58 |
+ 2022-05-17 00:01:08.000 | 59 |
+ 2022-05-17 00:01:08.000 | 59 |
+ 2022-05-16 00:01:08.000 | 136 |
+ 2022-05-16 00:01:08.000 | 136 |
+ 2022-05-15 00:01:08.000 | 234 |
+ 2022-05-15 00:01:08.000 | 234 |
+
+taos> explain verbose true select a.ts, a.c2, b.c2 from meters as a join meters as b on a.ts = b.ts\G;
+*************************** 1.row ***************************
+QUERY_PLAN: -> Projection (columns=3 width=16 input_order=unknown )
+*************************** 2.row ***************************
+QUERY_PLAN: Output: columns=3 width=16
+*************************** 3.row ***************************
+QUERY_PLAN: Output: Ignore Group Id: true
+*************************** 4.row ***************************
+QUERY_PLAN: Merge ResBlocks: True
+*************************** 5.row ***************************
+QUERY_PLAN: -> Inner join (columns=4 width=24 input_order=asc )
+*************************** 6.row ***************************
+QUERY_PLAN: Output: columns=4 width=24
+*************************** 7.row ***************************
+QUERY_PLAN: Join Cond: (`test`.`a`.`ts` = `test`.`b`.`ts`)
+*************************** 8.row ***************************
+QUERY_PLAN: -> SortMerge (columns=2 width=12 input_order=unknown output_order=unknown)
+*************************** 9.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 10.row ***************************
+QUERY_PLAN: Output: Ignore Group Id: false
+*************************** 11.row ***************************
+QUERY_PLAN: Merge Key: ts asc
+*************************** 12.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=12)
+*************************** 13.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 14.row ***************************
+QUERY_PLAN: -> Table Merge Scan on meters (columns=2 width=12 order=[asc|1 desc|0])
+*************************** 15.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 16.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+*************************** 17.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=12)
+*************************** 18.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 19.row ***************************
+QUERY_PLAN: -> Table Merge Scan on meters (columns=2 width=12 order=[asc|1 desc|0])
+*************************** 20.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 21.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+*************************** 22.row ***************************
+QUERY_PLAN: -> SortMerge (columns=2 width=12 input_order=unknown output_order=unknown)
+*************************** 23.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 24.row ***************************
+QUERY_PLAN: Output: Ignore Group Id: false
+*************************** 25.row ***************************
+QUERY_PLAN: Merge Key: ts asc
+*************************** 26.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=12)
+*************************** 27.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 28.row ***************************
+QUERY_PLAN: -> Table Merge Scan on meters (columns=2 width=12 order=[asc|1 desc|0])
+*************************** 29.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 30.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+*************************** 31.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=12)
+*************************** 32.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 33.row ***************************
+QUERY_PLAN: -> Table Merge Scan on meters (columns=2 width=12 order=[asc|1 desc|0])
+*************************** 34.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 35.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+
+taos> explain verbose true select a.ts, a.c2, b.c2 from meters as a join meters as b on a.ts = b.ts order by a.ts\G;
+*************************** 1.row ***************************
+QUERY_PLAN: -> Projection (columns=3 width=16 input_order=unknown )
+*************************** 2.row ***************************
+QUERY_PLAN: Output: columns=3 width=16
+*************************** 3.row ***************************
+QUERY_PLAN: Output: Ignore Group Id: true
+*************************** 4.row ***************************
+QUERY_PLAN: Merge ResBlocks: True
+*************************** 5.row ***************************
+QUERY_PLAN: -> Inner join (columns=4 width=24 input_order=asc )
+*************************** 6.row ***************************
+QUERY_PLAN: Output: columns=4 width=24
+*************************** 7.row ***************************
+QUERY_PLAN: Join Cond: (`test`.`a`.`ts` = `test`.`b`.`ts`)
+*************************** 8.row ***************************
+QUERY_PLAN: -> SortMerge (columns=2 width=12 input_order=asc output_order=asc)
+*************************** 9.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 10.row ***************************
+QUERY_PLAN: Output: Ignore Group Id: false
+*************************** 11.row ***************************
+QUERY_PLAN: Merge Key: ts asc
+*************************** 12.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=12)
+*************************** 13.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 14.row ***************************
+QUERY_PLAN: -> Table Merge Scan on meters (columns=2 width=12 order=[asc|1 desc|0])
+*************************** 15.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 16.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+*************************** 17.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=12)
+*************************** 18.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 19.row ***************************
+QUERY_PLAN: -> Table Merge Scan on meters (columns=2 width=12 order=[asc|1 desc|0])
+*************************** 20.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 21.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+*************************** 22.row ***************************
+QUERY_PLAN: -> SortMerge (columns=2 width=12 input_order=asc output_order=asc)
+*************************** 23.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 24.row ***************************
+QUERY_PLAN: Output: Ignore Group Id: false
+*************************** 25.row ***************************
+QUERY_PLAN: Merge Key: ts asc
+*************************** 26.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=12)
+*************************** 27.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 28.row ***************************
+QUERY_PLAN: -> Table Merge Scan on meters (columns=2 width=12 order=[asc|1 desc|0])
+*************************** 29.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 30.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+*************************** 31.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=12)
+*************************** 32.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 33.row ***************************
+QUERY_PLAN: -> Table Merge Scan on meters (columns=2 width=12 order=[asc|1 desc|0])
+*************************** 34.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 35.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+
+taos> select a.ts, a.c2, b.c2 from meters as a join meters as b on a.ts = b.ts;
+ ts | c2 | c2 |
+======================================================
+ 2022-05-15 00:01:08.000 | 234 | 234 |
+ 2022-05-15 00:01:08.000 | 234 | 234 |
+ 2022-05-15 00:01:08.000 | 234 | 234 |
+ 2022-05-15 00:01:08.000 | 234 | 234 |
+ 2022-05-16 00:01:08.000 | 136 | 136 |
+ 2022-05-16 00:01:08.000 | 136 | 136 |
+ 2022-05-16 00:01:08.000 | 136 | 136 |
+ 2022-05-16 00:01:08.000 | 136 | 136 |
+ 2022-05-17 00:01:08.000 | 59 | 59 |
+ 2022-05-17 00:01:08.000 | 59 | 59 |
+ 2022-05-17 00:01:08.000 | 59 | 59 |
+ 2022-05-17 00:01:08.000 | 59 | 59 |
+ 2022-05-18 00:01:08.000 | 58 | 58 |
+ 2022-05-18 00:01:08.000 | 58 | 58 |
+ 2022-05-18 00:01:08.000 | 58 | 58 |
+ 2022-05-18 00:01:08.000 | 58 | 58 |
+ 2022-05-19 00:01:08.000 | 243 | 243 |
+ 2022-05-19 00:01:08.000 | 243 | 243 |
+ 2022-05-19 00:01:08.000 | 243 | 243 |
+ 2022-05-19 00:01:08.000 | 243 | 243 |
+ 2022-05-20 00:01:08.000 | 120 | 120 |
+ 2022-05-20 00:01:08.000 | 120 | 120 |
+ 2022-05-20 00:01:08.000 | 120 | 120 |
+ 2022-05-20 00:01:08.000 | 120 | 120 |
+ 2022-05-21 00:01:08.000 | 11 | 11 |
+ 2022-05-21 00:01:08.000 | 11 | 11 |
+ 2022-05-21 00:01:08.000 | 11 | 11 |
+ 2022-05-21 00:01:08.000 | 11 | 11 |
+ 2022-05-22 00:01:08.000 | 196 | 196 |
+ 2022-05-22 00:01:08.000 | 196 | 196 |
+ 2022-05-22 00:01:08.000 | 196 | 196 |
+ 2022-05-22 00:01:08.000 | 196 | 196 |
+ 2022-05-23 00:01:08.000 | 116 | 116 |
+ 2022-05-23 00:01:08.000 | 116 | 116 |
+ 2022-05-23 00:01:08.000 | 116 | 116 |
+ 2022-05-23 00:01:08.000 | 116 | 116 |
+ 2022-05-24 00:01:08.000 | 210 | 210 |
+ 2022-05-24 00:01:08.000 | 210 | 210 |
+ 2022-05-24 00:01:08.000 | 210 | 210 |
+ 2022-05-24 00:01:08.000 | 210 | 210 |
+
+taos> select a.ts, a.c2, b.c2 from meters as a join meters as b on a.ts = b.ts order by a.ts desc;
+ ts | c2 | c2 |
+======================================================
+ 2022-05-24 00:01:08.000 | 210 | 210 |
+ 2022-05-24 00:01:08.000 | 210 | 210 |
+ 2022-05-24 00:01:08.000 | 210 | 210 |
+ 2022-05-24 00:01:08.000 | 210 | 210 |
+ 2022-05-23 00:01:08.000 | 116 | 116 |
+ 2022-05-23 00:01:08.000 | 116 | 116 |
+ 2022-05-23 00:01:08.000 | 116 | 116 |
+ 2022-05-23 00:01:08.000 | 116 | 116 |
+ 2022-05-22 00:01:08.000 | 196 | 196 |
+ 2022-05-22 00:01:08.000 | 196 | 196 |
+ 2022-05-22 00:01:08.000 | 196 | 196 |
+ 2022-05-22 00:01:08.000 | 196 | 196 |
+ 2022-05-21 00:01:08.000 | 11 | 11 |
+ 2022-05-21 00:01:08.000 | 11 | 11 |
+ 2022-05-21 00:01:08.000 | 11 | 11 |
+ 2022-05-21 00:01:08.000 | 11 | 11 |
+ 2022-05-20 00:01:08.000 | 120 | 120 |
+ 2022-05-20 00:01:08.000 | 120 | 120 |
+ 2022-05-20 00:01:08.000 | 120 | 120 |
+ 2022-05-20 00:01:08.000 | 120 | 120 |
+ 2022-05-19 00:01:08.000 | 243 | 243 |
+ 2022-05-19 00:01:08.000 | 243 | 243 |
+ 2022-05-19 00:01:08.000 | 243 | 243 |
+ 2022-05-19 00:01:08.000 | 243 | 243 |
+ 2022-05-18 00:01:08.000 | 58 | 58 |
+ 2022-05-18 00:01:08.000 | 58 | 58 |
+ 2022-05-18 00:01:08.000 | 58 | 58 |
+ 2022-05-18 00:01:08.000 | 58 | 58 |
+ 2022-05-17 00:01:08.000 | 59 | 59 |
+ 2022-05-17 00:01:08.000 | 59 | 59 |
+ 2022-05-17 00:01:08.000 | 59 | 59 |
+ 2022-05-17 00:01:08.000 | 59 | 59 |
+ 2022-05-16 00:01:08.000 | 136 | 136 |
+ 2022-05-16 00:01:08.000 | 136 | 136 |
+ 2022-05-16 00:01:08.000 | 136 | 136 |
+ 2022-05-16 00:01:08.000 | 136 | 136 |
+ 2022-05-15 00:01:08.000 | 234 | 234 |
+ 2022-05-15 00:01:08.000 | 234 | 234 |
+ 2022-05-15 00:01:08.000 | 234 | 234 |
+ 2022-05-15 00:01:08.000 | 234 | 234 |
+
+taos> explain verbose true select a.ts, a.c2, b.c2 from meters as a join (select ts, c2 from meters order by ts desc) b on a.ts = b.ts order by a.ts desc\G;
+*************************** 1.row ***************************
+QUERY_PLAN: -> Projection (columns=3 width=16 input_order=unknown )
+*************************** 2.row ***************************
+QUERY_PLAN: Output: columns=3 width=16
+*************************** 3.row ***************************
+QUERY_PLAN: Output: Ignore Group Id: true
+*************************** 4.row ***************************
+QUERY_PLAN: Merge ResBlocks: True
+*************************** 5.row ***************************
+QUERY_PLAN: -> Inner join (columns=4 width=24 input_order=desc )
+*************************** 6.row ***************************
+QUERY_PLAN: Output: columns=4 width=24
+*************************** 7.row ***************************
+QUERY_PLAN: Join Cond: (`test`.`a`.`ts` = `b`.`ts`)
+*************************** 8.row ***************************
+QUERY_PLAN: -> SortMerge (columns=2 width=12 input_order=desc output_order=desc)
+*************************** 9.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 10.row ***************************
+QUERY_PLAN: Output: Ignore Group Id: false
+*************************** 11.row ***************************
+QUERY_PLAN: Merge Key: _group_id asc, ts desc
+*************************** 12.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=12)
+*************************** 13.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 14.row ***************************
+QUERY_PLAN: -> Table Merge Scan on meters (columns=2 width=12 order=[asc|0 desc|1])
+*************************** 15.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 16.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+*************************** 17.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=12)
+*************************** 18.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 19.row ***************************
+QUERY_PLAN: -> Table Merge Scan on meters (columns=2 width=12 order=[asc|0 desc|1])
+*************************** 20.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 21.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+*************************** 22.row ***************************
+QUERY_PLAN: -> Projection (columns=2 width=12 input_order=desc )
+*************************** 23.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 24.row ***************************
+QUERY_PLAN: Output: Ignore Group Id: true
+*************************** 25.row ***************************
+QUERY_PLAN: Merge ResBlocks: False
+*************************** 26.row ***************************
+QUERY_PLAN: -> SortMerge (columns=2 width=12 input_order=desc output_order=desc)
+*************************** 27.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 28.row ***************************
+QUERY_PLAN: Output: Ignore Group Id: false
+*************************** 29.row ***************************
+QUERY_PLAN: Merge Key: _group_id asc, ts desc
+*************************** 30.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=12)
+*************************** 31.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 32.row ***************************
+QUERY_PLAN: -> Table Merge Scan on meters (columns=2 width=12 order=[asc|0 desc|1])
+*************************** 33.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 34.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+*************************** 35.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=12)
+*************************** 36.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 37.row ***************************
+QUERY_PLAN: -> Table Merge Scan on meters (columns=2 width=12 order=[asc|0 desc|1])
+*************************** 38.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 39.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+
+taos> explain verbose true select a.ts, a.c2, b.c2 from meters as a join (select ts, c2 from meters order by ts desc) b on a.ts = b.ts order by a.ts asc\G;
+*************************** 1.row ***************************
+QUERY_PLAN: -> Projection (columns=3 width=16 input_order=unknown )
+*************************** 2.row ***************************
+QUERY_PLAN: Output: columns=3 width=16
+*************************** 3.row ***************************
+QUERY_PLAN: Output: Ignore Group Id: true
+*************************** 4.row ***************************
+QUERY_PLAN: Merge ResBlocks: True
+*************************** 5.row ***************************
+QUERY_PLAN: -> Inner join (columns=4 width=24 input_order=asc )
+*************************** 6.row ***************************
+QUERY_PLAN: Output: columns=4 width=24
+*************************** 7.row ***************************
+QUERY_PLAN: Join Cond: (`test`.`a`.`ts` = `b`.`ts`)
+*************************** 8.row ***************************
+QUERY_PLAN: -> SortMerge (columns=2 width=12 input_order=asc output_order=asc)
+*************************** 9.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 10.row ***************************
+QUERY_PLAN: Output: Ignore Group Id: false
+*************************** 11.row ***************************
+QUERY_PLAN: Merge Key: _group_id asc, ts asc
+*************************** 12.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=12)
+*************************** 13.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 14.row ***************************
+QUERY_PLAN: -> Table Merge Scan on meters (columns=2 width=12 order=[asc|1 desc|0])
+*************************** 15.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 16.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+*************************** 17.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=12)
+*************************** 18.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 19.row ***************************
+QUERY_PLAN: -> Table Merge Scan on meters (columns=2 width=12 order=[asc|1 desc|0])
+*************************** 20.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 21.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+*************************** 22.row ***************************
+QUERY_PLAN: -> Projection (columns=2 width=12 input_order=asc )
+*************************** 23.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 24.row ***************************
+QUERY_PLAN: Output: Ignore Group Id: true
+*************************** 25.row ***************************
+QUERY_PLAN: Merge ResBlocks: False
+*************************** 26.row ***************************
+QUERY_PLAN: -> SortMerge (columns=2 width=12 input_order=asc output_order=asc)
+*************************** 27.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 28.row ***************************
+QUERY_PLAN: Output: Ignore Group Id: false
+*************************** 29.row ***************************
+QUERY_PLAN: Merge Key: _group_id asc, ts asc
+*************************** 30.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=12)
+*************************** 31.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 32.row ***************************
+QUERY_PLAN: -> Table Merge Scan on meters (columns=2 width=12 order=[asc|1 desc|0])
+*************************** 33.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 34.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+*************************** 35.row ***************************
+QUERY_PLAN: -> Data Exchange 1:1 (width=12)
+*************************** 36.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 37.row ***************************
+QUERY_PLAN: -> Table Merge Scan on meters (columns=2 width=12 order=[asc|1 desc|0])
+*************************** 38.row ***************************
+QUERY_PLAN: Output: columns=2 width=12
+*************************** 39.row ***************************
+QUERY_PLAN: Time Range: [-9223372036854775808, 9223372036854775807]
+
+taos> select a.ts, a.c2, b.c2 from meters as a join (select * from meters order by ts desc) b on a.ts = b.ts order by a.ts asc;
+ ts | c2 | c2 |
+======================================================
+ 2022-05-15 00:01:08.000 | 234 | 234 |
+ 2022-05-15 00:01:08.000 | 234 | 234 |
+ 2022-05-15 00:01:08.000 | 234 | 234 |
+ 2022-05-15 00:01:08.000 | 234 | 234 |
+ 2022-05-16 00:01:08.000 | 136 | 136 |
+ 2022-05-16 00:01:08.000 | 136 | 136 |
+ 2022-05-16 00:01:08.000 | 136 | 136 |
+ 2022-05-16 00:01:08.000 | 136 | 136 |
+ 2022-05-17 00:01:08.000 | 59 | 59 |
+ 2022-05-17 00:01:08.000 | 59 | 59 |
+ 2022-05-17 00:01:08.000 | 59 | 59 |
+ 2022-05-17 00:01:08.000 | 59 | 59 |
+ 2022-05-18 00:01:08.000 | 58 | 58 |
+ 2022-05-18 00:01:08.000 | 58 | 58 |
+ 2022-05-18 00:01:08.000 | 58 | 58 |
+ 2022-05-18 00:01:08.000 | 58 | 58 |
+ 2022-05-19 00:01:08.000 | 243 | 243 |
+ 2022-05-19 00:01:08.000 | 243 | 243 |
+ 2022-05-19 00:01:08.000 | 243 | 243 |
+ 2022-05-19 00:01:08.000 | 243 | 243 |
+ 2022-05-20 00:01:08.000 | 120 | 120 |
+ 2022-05-20 00:01:08.000 | 120 | 120 |
+ 2022-05-20 00:01:08.000 | 120 | 120 |
+ 2022-05-20 00:01:08.000 | 120 | 120 |
+ 2022-05-21 00:01:08.000 | 11 | 11 |
+ 2022-05-21 00:01:08.000 | 11 | 11 |
+ 2022-05-21 00:01:08.000 | 11 | 11 |
+ 2022-05-21 00:01:08.000 | 11 | 11 |
+ 2022-05-22 00:01:08.000 | 196 | 196 |
+ 2022-05-22 00:01:08.000 | 196 | 196 |
+ 2022-05-22 00:01:08.000 | 196 | 196 |
+ 2022-05-22 00:01:08.000 | 196 | 196 |
+ 2022-05-23 00:01:08.000 | 116 | 116 |
+ 2022-05-23 00:01:08.000 | 116 | 116 |
+ 2022-05-23 00:01:08.000 | 116 | 116 |
+ 2022-05-23 00:01:08.000 | 116 | 116 |
+ 2022-05-24 00:01:08.000 | 210 | 210 |
+ 2022-05-24 00:01:08.000 | 210 | 210 |
+ 2022-05-24 00:01:08.000 | 210 | 210 |
+ 2022-05-24 00:01:08.000 | 210 | 210 |
+
diff --git a/tests/script/tsim/query/t/explain_tsorder.sql b/tests/script/tsim/query/t/explain_tsorder.sql
new file mode 100644
index 0000000000..d3264d8895
--- /dev/null
+++ b/tests/script/tsim/query/t/explain_tsorder.sql
@@ -0,0 +1,73 @@
+use test;
+explain verbose true select _wstart, last(ts), avg(c2) from meters interval(10s) order by _wstart desc\G;
+explain verbose true select _wstart, last(ts), avg(c2) from meters interval(10s) order by _wstart asc\G;
+explain verbose true select _wstart, first(ts), avg(c2) from meters interval(10s) order by _wstart asc\G;
+explain verbose true select _wstart, first(ts), avg(c2) from meters interval(10s) order by _wstart desc\G;
+explain verbose true select last(a) as d from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s)) order by d\G;
+explain verbose true select last(a) as d from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s)) order by d desc\G;
+explain verbose true select last(a) as d from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s) order by a) order by d\G;
+explain verbose true select last(a) as d from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s) order by a desc) order by d\G;
+explain verbose true select last(a) as d from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s) order by a) order by d desc\G;
+explain verbose true select last(a) as d from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s) order by a desc) order by d desc\G;
+
+
+explain verbose true select last(a) as d from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s) order by b) order by d\G;
+explain verbose true select last(a) as d from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s) order by b desc) order by d\G;
+explain verbose true select last(a) as d from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s) order by b) order by d desc\G;
+explain verbose true select last(a) as d from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s) order by b desc) order by d desc\G;
+
+explain verbose true select last(a) as d from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s) order by b) group by c order by d\G;
+explain verbose true select last(a) as d from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s) order by b desc) group by c order by d\G;
+explain verbose true select last(a) as d from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s) order by b) group by c order by d desc\G;
+explain verbose true select last(a) as d from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s) order by b desc) group by c order by d desc\G;
+
+
+explain verbose true select last(a) as d from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s) order by b) where a > 10000 and a < 20000 interval(10s) fill(NULL) order by d\G;
+explain verbose true select last(a) as d from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s) order by a desc) where a > 10000 and a < 20000 interval(10s) fill(NULL) order by d\G;
+explain verbose true select last(b) as d from (select last(ts) as b, avg(c2) as c from meters interval(10s) order by b desc) where b > 10000 and b < 20000 interval(10s) fill(NULL) order by d\G;
+explain verbose true select last(b) as d from (select last(ts) as b, avg(c2) as c from meters interval(10s) order by b desc) where b > 10000 and b < 20000 interval(10s) fill(NULL) order by d desc\G;
+
+
+select _wstart, last(ts), avg(c2) from meters interval(10s) order by _wstart desc;
+select _wstart, last(ts), avg(c2) from meters interval(10s) order by _wstart asc;
+select _wstart, first(ts), avg(c2) from meters interval(10s) order by _wstart asc;
+select _wstart, first(ts), avg(c2) from meters interval(10s) order by _wstart desc;
+select last(a) as d from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s)) order by d;
+select last(a) as d from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s)) order by d desc;
+select last(a) as d from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s) order by a) order by d;
+select last(a) as d from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s) order by a desc) order by d;
+select last(a) as d from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s) order by a) order by d desc;
+select last(a) as d from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s) order by a desc) order by d desc;
+
+
+select last(a) as d from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s) order by b) order by d;
+select last(a) as d from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s) order by b desc) order by d;
+select last(a) as d from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s) order by b) order by d desc;
+select last(a) as d from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s) order by b desc) order by d desc;
+
+select last(a) as d from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s) order by b) group by c order by d
+select last(a) as d from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s) order by b desc) group by c order by d;
+select last(a) as d from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s) order by b) group by c order by d desc;
+select last(a) as d from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s) order by b desc) group by c order by d desc;
+
+select last(a) as d from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s) order by a desc) where a > '2022-05-15 00:01:00.000' and a < '2022-05-19 00:01:08.000' interval(10s) order by d;
+select last(b) as d from (select last(ts) as b, avg(c2) as c from meters interval(10s) order by b desc) where b > '2022-05-15 00:01:00.000' and b < '2022-05-19 00:01:08.000' interval(10s) order by d;
+select last(b) as d from (select last(ts) as b, avg(c2) as c from meters interval(10s) order by b desc) where b > '2022-05-15 00:01:00.000' and b < '2022-05-19 00:01:08.000' interval(10s) order by d desc;
+select _wstart, first(a) as d, avg(c) from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s) order by a desc) where a > '2022-05-15 00:01:00.000' and a < '2022-05-21 00:01:08.000' interval(5h) fill(linear) order by d desc;
+
+explain verbose true select _wstart, first(a) as d, avg(c) from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s) order by a desc) where a > '2022-05-15 00:01:00.000' and a < '2022-05-21 00:01:08.000' interval(5h) fill(linear) order by d desc\G;
+explain verbose true select _wstart, first(a) as d, avg(c) from (select _wstart as a, last(ts) as b, avg(c2) as c from meters interval(10s) order by a asc) where a > '2022-05-15 00:01:00.000' and a < '2022-05-21 00:01:08.000' interval(5h) fill(linear) order by d desc\G;
+
+explain verbose true select * from (select ts as a, c2 as b from meters order by c2 desc)\G;
+select * from (select ts as a, c2 as b from meters order by c2 desc);
+
+explain verbose true select * from (select ts as a, c2 as b from meters order by c2 desc) order by a desc\G;
+select * from (select ts as a, c2 as b from meters order by c2 desc) order by a desc;
+
+explain verbose true select a.ts, a.c2, b.c2 from meters as a join meters as b on a.ts = b.ts\G;
+explain verbose true select a.ts, a.c2, b.c2 from meters as a join meters as b on a.ts = b.ts order by a.ts\G;
+select a.ts, a.c2, b.c2 from meters as a join meters as b on a.ts = b.ts;
+select a.ts, a.c2, b.c2 from meters as a join meters as b on a.ts = b.ts order by a.ts desc;
+explain verbose true select a.ts, a.c2, b.c2 from meters as a join (select ts, c2 from meters order by ts desc) b on a.ts = b.ts order by a.ts desc\G;
+explain verbose true select a.ts, a.c2, b.c2 from meters as a join (select ts, c2 from meters order by ts desc) b on a.ts = b.ts order by a.ts asc\G;
+select a.ts, a.c2, b.c2 from meters as a join (select * from meters order by ts desc) b on a.ts = b.ts order by a.ts asc;
diff --git a/tests/script/tsim/sma/tsmaCreateInsertQuery.sim b/tests/script/tsim/sma/tsmaCreateInsertQuery.sim
index 60f769d2ae..692212d511 100644
--- a/tests/script/tsim/sma/tsmaCreateInsertQuery.sim
+++ b/tests/script/tsim/sma/tsmaCreateInsertQuery.sim
@@ -414,6 +414,21 @@ if $data05 != 30.000000000 then
return -1
endi
-system sh/exec.sh -n dnode1 -s stop -x SIGINT
+sql delete from stb;
+print =============== query after delete in common vgroups
+sql select _wstart, _wend, min(c1),max(c2),max(c1),max(c3) from stb interval(5m,10s) sliding(5m) order by _wstart;
+if $rows != 0 then
+ print rows $rows != 0
+ return -1
+endi
+sleep 2000
+print =============== query after delete in designated vgroups
+sql select _wend, min(c1),max(c2),max(c1) from stb interval(5m,10s) sliding(5m) order by _wstart;
+if $rows != 0 then
+ print rows $rows != 0
+ return -1
+endi
+
+system sh/exec.sh -n dnode1 -s stop -x SIGINT
\ No newline at end of file
diff --git a/utils/tsim/src/simExe.c b/utils/tsim/src/simExe.c
index c1f0f502f3..9a0a156717 100644
--- a/utils/tsim/src/simExe.c
+++ b/utils/tsim/src/simExe.c
@@ -434,7 +434,7 @@ bool simExecuteSystemCmd(SScript *script, char *option) {
simLogSql(buf, true);
int32_t code = system(buf);
int32_t repeatTimes = 0;
- while (code < 0) {
+ while (code != 0) {
simError("script:%s, failed to execute %s , code %d, errno:%d %s, repeatTimes:%d", script->fileName, buf, code,
errno, strerror(errno), repeatTimes);
taosMsleep(1000);