From e1a91107ce2c847be498ddaffd513055f00b2364 Mon Sep 17 00:00:00 2001 From: hjxilinx Date: Sat, 29 Feb 2020 11:21:10 +0800 Subject: [PATCH] fix bugs founded in regression test(limit offset on interval query failed). --- src/client/src/tscSQLParser.c | 8 +- src/client/src/tscUtil.c | 11 +- src/system/detail/src/vnodeQueryImpl.c | 181 +++++++++++++++++-------- 3 files changed, 141 insertions(+), 59 deletions(-) diff --git a/src/client/src/tscSQLParser.c b/src/client/src/tscSQLParser.c index 2c2f0793e8..cb199a16b6 100644 --- a/src/client/src/tscSQLParser.c +++ b/src/client/src/tscSQLParser.c @@ -4596,9 +4596,11 @@ int32_t parseLimitClause(SQueryInfo* pQueryInfo, int32_t clauseIndex, SQuerySQL* // handle the limit offset value, validate the limit pQueryInfo->limit = pQuerySql->limit; pQueryInfo->clauseLimit = pQueryInfo->limit.limit; - pQueryInfo->slimit = pQuerySql->slimit; - + + tscTrace("%p limit:%d, offset:%" PRId64 " slimit:%d, soffset:%" PRId64, pSql, pQueryInfo->limit.limit, + pQueryInfo->limit.offset, pQueryInfo->slimit.limit, pQueryInfo->slimit.offset); + if (pQueryInfo->slimit.offset < 0 || pQueryInfo->limit.offset < 0) { return invalidSqlErrMsg(pQueryInfo->msg, msg0); } @@ -4631,7 +4633,7 @@ int32_t parseLimitClause(SQueryInfo* pQueryInfo, int32_t clauseIndex, SQuerySQL* } if (pQueryInfo->slimit.limit == 0) { - tscTrace("%p limit 0, no output result", pSql); + tscTrace("%p slimit 0, no output result", pSql); pQueryInfo->command = TSDB_SQL_RETRIEVE_EMPTY_RESULT; return TSDB_CODE_SUCCESS; } diff --git a/src/client/src/tscUtil.c b/src/client/src/tscUtil.c index fd6210ee56..5b13cae3cb 100644 --- a/src/client/src/tscUtil.c +++ b/src/client/src/tscUtil.c @@ -215,7 +215,16 @@ bool tscIsTwoStageMergeMetricQuery(SQueryInfo* pQueryInfo, int32_t tableIndex) { } SMeterMetaInfo* pMeterMetaInfo = tscGetMeterMetaInfoFromQueryInfo(pQueryInfo, tableIndex); - if (pMeterMetaInfo == NULL || pMeterMetaInfo->pMetricMeta == NULL) { + if (pMeterMetaInfo == NULL) { + return false; + } + + // for select query super table, the metricmeta can not be null in any cases. + if (pQueryInfo->command == TSDB_SQL_SELECT && UTIL_METER_IS_SUPERTABLE(pMeterMetaInfo)) { + assert(pMeterMetaInfo->pMetricMeta != NULL); + } + + if (pMeterMetaInfo->pMetricMeta == NULL) { return false; } diff --git a/src/system/detail/src/vnodeQueryImpl.c b/src/system/detail/src/vnodeQueryImpl.c index 8ed5623895..722266db2c 100644 --- a/src/system/detail/src/vnodeQueryImpl.c +++ b/src/system/detail/src/vnodeQueryImpl.c @@ -1784,12 +1784,12 @@ static int32_t getNextQualifiedWindow(SQueryRuntimeEnv *pRuntimeEnv, STimeWindow continue; } - if (pNextWin->ekey > pQuery->ekey && QUERY_IS_ASC_QUERY(pQuery)) { - pNextWin->ekey = pQuery->ekey; - } - if (pNextWin->skey < pQuery->ekey && !QUERY_IS_ASC_QUERY(pQuery)) { - pNextWin->skey = pQuery->ekey; - } +// if (pNextWin->ekey > pQuery->ekey && QUERY_IS_ASC_QUERY(pQuery)) { +// pNextWin->ekey = pQuery->ekey; +// } +// if (pNextWin->skey < pQuery->ekey && !QUERY_IS_ASC_QUERY(pQuery)) { +// pNextWin->skey = pQuery->ekey; +// } return startPos; } @@ -4112,65 +4112,135 @@ static bool forwardQueryStartPosIfNeeded(SQInfo *pQInfo, STableQuerySupportObj * while (pQuery->limit.offset > 0) { SBlockInfo blockInfo = getBlockInfo(pRuntimeEnv); + + STimeWindow tw = win; + getNextTimeWindow(pQuery, &tw); + + // next time window starts from current data block + if ((tw.skey <= blockInfo.keyLast && QUERY_IS_ASC_QUERY(pQuery)) || + (tw.ekey >= blockInfo.keyFirst && !QUERY_IS_ASC_QUERY(pQuery))) { + + // query completed + if ((tw.skey > pQuery->ekey && QUERY_IS_ASC_QUERY(pQuery)) || + (tw.ekey < pQuery->ekey && !QUERY_IS_ASC_QUERY(pQuery))) { + setQueryStatus(pQuery, QUERY_COMPLETED); + break; + } - // time window ended in current data block - if (win.ekey <= blockInfo.keyLast) { - pQuery->limit.offset -= 1; + // check its position in this block to make sure this time window covers data. + if (IS_DISK_DATA_BLOCK(pQuery)) { + getTimestampInDiskBlock(pRuntimeEnv, 0); + } - if (win.ekey == blockInfo.keyLast) { - moveToNextBlock(pRuntimeEnv, step, searchFn, false); - if (Q_STATUS_EQUAL(pQuery->over, QUERY_NO_DATA_TO_CHECK)) { - break; - } + tw = win; + int32_t startPos = getNextQualifiedWindow(pRuntimeEnv, &tw, pWindowResInfo, &blockInfo, primaryKey, searchFn); + assert(startPos > 0); - // next block does not included in time range, abort query - blockInfo = getBlockInfo(pRuntimeEnv); - if ((blockInfo.keyFirst > pQuery->ekey && QUERY_IS_ASC_QUERY(pQuery)) || - (blockInfo.keyLast < pQuery->ekey && !QUERY_IS_ASC_QUERY(pQuery))) { + pQuery->limit.offset -= 1; + + // set the abort info + pQuery->pos = startPos; + pQuery->lastKey = primaryKey[startPos]; + win = tw; + continue; + } else { + moveToNextBlock(pRuntimeEnv, step, searchFn, false); + if (Q_STATUS_EQUAL(pQuery->over, QUERY_NO_DATA_TO_CHECK)) { + break; + } + + blockInfo = getBlockInfo(pRuntimeEnv); + if ((blockInfo.keyFirst > pQuery->ekey && QUERY_IS_ASC_QUERY(pQuery)) || + (blockInfo.keyLast < pQuery->ekey && !QUERY_IS_ASC_QUERY(pQuery))) { + setQueryStatus(pQuery, QUERY_COMPLETED); + break; + } + + // set the window that start from the next data block + TSKEY key = (QUERY_IS_ASC_QUERY(pQuery))? blockInfo.keyFirst:blockInfo.keyLast; + STimeWindow n = getActiveTimeWindow(pWindowResInfo, key, pQuery); + + // next data block are still covered by current time window + if (n.skey == win.skey && n.ekey == win.ekey) { + // do nothing + } else { + pQuery->limit.offset -= 1; + + // query completed + if ((n.skey > pQuery->ekey && QUERY_IS_ASC_QUERY(pQuery)) || + (n.ekey < pQuery->ekey && !QUERY_IS_ASC_QUERY(pQuery))) { setQueryStatus(pQuery, QUERY_COMPLETED); break; } - - // set the window that start from the next data block - win = getActiveTimeWindow(pWindowResInfo, blockInfo.keyFirst, pQuery); - } else { - // the time window is closed in current data block, load disk file block into memory to - // check the next time window - if (IS_DISK_DATA_BLOCK(pQuery)) { + + // set the abort info + pQuery->pos = QUERY_IS_ASC_QUERY(pQuery)? 0:blockInfo.size-1; + pQuery->lastKey = QUERY_IS_ASC_QUERY(pQuery)? blockInfo.keyFirst:blockInfo.keyLast; + win = n; + + if (pQuery->limit.offset == 0 && IS_DISK_DATA_BLOCK(pQuery)) { getTimestampInDiskBlock(pRuntimeEnv, 0); } - - STimeWindow nextWin = win; - int32_t startPos = - getNextQualifiedWindow(pRuntimeEnv, &nextWin, pWindowResInfo, &blockInfo, primaryKey, searchFn); - - if (startPos < 0) { // failed to find the qualified time window - assert((nextWin.skey > pQuery->ekey && QUERY_IS_ASC_QUERY(pQuery)) || - (nextWin.ekey < pQuery->ekey && !QUERY_IS_ASC_QUERY(pQuery))); - - setQueryStatus(pQuery, QUERY_COMPLETED); - break; - } else { // set the abort info - pQuery->pos = startPos; - pQuery->lastKey = primaryKey[startPos]; - win = nextWin; - } } - - continue; - } - - moveToNextBlock(pRuntimeEnv, step, searchFn, false); - if (Q_STATUS_EQUAL(pQuery->over, QUERY_NO_DATA_TO_CHECK)) { - break; - } - - blockInfo = getBlockInfo(pRuntimeEnv); - if ((blockInfo.keyFirst > pQuery->ekey && QUERY_IS_ASC_QUERY(pQuery)) || - (blockInfo.keyLast < pQuery->ekey && !QUERY_IS_ASC_QUERY(pQuery))) { - setQueryStatus(pQuery, QUERY_COMPLETED); - break; } + +// if (win.ekey <= blockInfo.keyLast) { +// pQuery->limit.offset -= 1; +// +// if (win.ekey == blockInfo.keyLast) { +// moveToNextBlock(pRuntimeEnv, step, searchFn, false); +// if (Q_STATUS_EQUAL(pQuery->over, QUERY_NO_DATA_TO_CHECK)) { +// break; +// } +// +// // next block does not included in time range, abort query +// blockInfo = getBlockInfo(pRuntimeEnv); +// if ((blockInfo.keyFirst > pQuery->ekey && QUERY_IS_ASC_QUERY(pQuery)) || +// (blockInfo.keyLast < pQuery->ekey && !QUERY_IS_ASC_QUERY(pQuery))) { +// setQueryStatus(pQuery, QUERY_COMPLETED); +// break; +// } +// +// // set the window that start from the next data block +// win = getActiveTimeWindow(pWindowResInfo, blockInfo.keyFirst, pQuery); +// } else { +// // the time window is closed in current data block, load disk file block into memory to +// // check the next time window +// if (IS_DISK_DATA_BLOCK(pQuery)) { +// getTimestampInDiskBlock(pRuntimeEnv, 0); +// } +// +// STimeWindow nextWin = win; +// int32_t startPos = +// getNextQualifiedWindow(pRuntimeEnv, &nextWin, pWindowResInfo, &blockInfo, primaryKey, searchFn); +// +// if (startPos < 0) { // failed to find the qualified time window +// assert((nextWin.skey > pQuery->ekey && QUERY_IS_ASC_QUERY(pQuery)) || +// (nextWin.ekey < pQuery->ekey && !QUERY_IS_ASC_QUERY(pQuery))); +// +// setQueryStatus(pQuery, QUERY_COMPLETED); +// break; +// } else { // set the abort info +// pQuery->pos = startPos; +// pQuery->lastKey = primaryKey[startPos]; +// win = nextWin; +// } +// } +// +// continue; +// } +// +// moveToNextBlock(pRuntimeEnv, step, searchFn, false); +// if (Q_STATUS_EQUAL(pQuery->over, QUERY_NO_DATA_TO_CHECK)) { +// break; +// } +// +// blockInfo = getBlockInfo(pRuntimeEnv); +// if ((blockInfo.keyFirst > pQuery->ekey && QUERY_IS_ASC_QUERY(pQuery)) || +// (blockInfo.keyLast < pQuery->ekey && !QUERY_IS_ASC_QUERY(pQuery))) { +// setQueryStatus(pQuery, QUERY_COMPLETED); +// break; +// } } if (Q_STATUS_EQUAL(pQuery->over, QUERY_NO_DATA_TO_CHECK | QUERY_COMPLETED) || pQuery->limit.offset > 0) { @@ -5291,6 +5361,7 @@ static int64_t doScanAllDataBlocks(SQueryRuntimeEnv *pRuntimeEnv) { if (isIntervalQuery(pQuery) && IS_MASTER_SCAN(pRuntimeEnv)) { if (Q_STATUS_EQUAL(pQuery->over, QUERY_COMPLETED | QUERY_NO_DATA_TO_CHECK)) { closeAllTimeWindow(&pRuntimeEnv->windowResInfo); + pRuntimeEnv->windowResInfo.curIndex = pRuntimeEnv->windowResInfo.size - 1; } else if (Q_STATUS_EQUAL(pQuery->over, QUERY_RESBUF_FULL)) { // check if window needs to be closed SBlockInfo blockInfo = getBlockInfo(pRuntimeEnv); -- GitLab