提交 5a7e631c 编写于 作者: H Haojun Liao

[TD-2615]<fix>: fix limit offset query caused crash.

上级 050e41b8
...@@ -15,19 +15,15 @@ ...@@ -15,19 +15,15 @@
#include "os.h" #include "os.h"
#include "qAst.h" #include "qAst.h"
#include "qExtbuffer.h"
#include "qFill.h" #include "qFill.h"
#include "qHistogram.h" #include "qHistogram.h"
#include "qPercentile.h" #include "qPercentile.h"
#include "qSyntaxtreefunction.h"
#include "qTsbuf.h" #include "qTsbuf.h"
#include "taosdef.h" #include "taosdef.h"
#include "taosmsg.h" #include "taosmsg.h"
#include "tscLog.h" #include "tscLog.h"
#include "tscSubquery.h" #include "tscSubquery.h"
#include "tscompression.h"
#include "tsqlfunction.h" #include "tsqlfunction.h"
#include "tutil.h"
#include "ttype.h" #include "ttype.h"
#define GET_INPUT_CHAR(x) (((char *)((x)->aInputElemBuf)) + ((x)->startOffset) * ((x)->inputBytes)) #define GET_INPUT_CHAR(x) (((char *)((x)->aInputElemBuf)) + ((x)->startOffset) * ((x)->inputBytes))
...@@ -920,6 +916,10 @@ static void minMax_function(SQLFunctionCtx *pCtx, char *pOutput, int32_t isMin, ...@@ -920,6 +916,10 @@ static void minMax_function(SQLFunctionCtx *pCtx, char *pOutput, int32_t isMin,
if (pCtx->preAggVals.isSet) { if (pCtx->preAggVals.isSet) {
*notNullElems = pCtx->size - pCtx->preAggVals.statis.numOfNull; *notNullElems = pCtx->size - pCtx->preAggVals.statis.numOfNull;
assert(*notNullElems >= 0); assert(*notNullElems >= 0);
if (*notNullElems == 0) {
return;
}
void * tval = NULL; void * tval = NULL;
int16_t index = 0; int16_t index = 0;
......
...@@ -4498,8 +4498,9 @@ static TSKEY doSkipIntervalProcess(SQueryRuntimeEnv* pRuntimeEnv, STimeWindow* w ...@@ -4498,8 +4498,9 @@ static TSKEY doSkipIntervalProcess(SQueryRuntimeEnv* pRuntimeEnv, STimeWindow* w
return key; return key;
} else { // do nothing } else { // do nothing
pQuery->window.skey = tw.skey; pQuery->window.skey = tw.skey;
pWindowResInfo->prevSKey = tw.skey; pWindowResInfo->prevSKey = tw.skey;
pTableQueryInfo->lastKey = tw.skey;
return tw.skey; return tw.skey;
} }
...@@ -4509,22 +4510,6 @@ static TSKEY doSkipIntervalProcess(SQueryRuntimeEnv* pRuntimeEnv, STimeWindow* w ...@@ -4509,22 +4510,6 @@ static TSKEY doSkipIntervalProcess(SQueryRuntimeEnv* pRuntimeEnv, STimeWindow* w
static bool skipTimeInterval(SQueryRuntimeEnv *pRuntimeEnv, TSKEY* start) { static bool skipTimeInterval(SQueryRuntimeEnv *pRuntimeEnv, TSKEY* start) {
SQuery *pQuery = pRuntimeEnv->pQuery; SQuery *pQuery = pRuntimeEnv->pQuery;
// get the first unclosed time window
bool assign = false;
for(int32_t i = 0; i < pRuntimeEnv->windowResInfo.size; ++i) {
if (pRuntimeEnv->windowResInfo.pResult[i]->closed) {
continue;
}
assign = true;
*start = pRuntimeEnv->windowResInfo.pResult[i]->win.skey;
}
if (!assign) {
*start = pQuery->current->lastKey;
}
assert(*start <= pQuery->current->lastKey); assert(*start <= pQuery->current->lastKey);
// if queried with value filter, do NOT forward query start position // if queried with value filter, do NOT forward query start position
...@@ -4540,6 +4525,7 @@ static bool skipTimeInterval(SQueryRuntimeEnv *pRuntimeEnv, TSKEY* start) { ...@@ -4540,6 +4525,7 @@ static bool skipTimeInterval(SQueryRuntimeEnv *pRuntimeEnv, TSKEY* start) {
assert(pRuntimeEnv->windowResInfo.prevSKey == TSKEY_INITIAL_VAL); assert(pRuntimeEnv->windowResInfo.prevSKey == TSKEY_INITIAL_VAL);
STimeWindow w = TSWINDOW_INITIALIZER; STimeWindow w = TSWINDOW_INITIALIZER;
bool ascQuery = QUERY_IS_ASC_QUERY(pQuery);
SResultRowInfo *pWindowResInfo = &pRuntimeEnv->windowResInfo; SResultRowInfo *pWindowResInfo = &pRuntimeEnv->windowResInfo;
STableQueryInfo *pTableQueryInfo = pQuery->current; STableQueryInfo *pTableQueryInfo = pQuery->current;
...@@ -4564,19 +4550,25 @@ static bool skipTimeInterval(SQueryRuntimeEnv *pRuntimeEnv, TSKEY* start) { ...@@ -4564,19 +4550,25 @@ static bool skipTimeInterval(SQueryRuntimeEnv *pRuntimeEnv, TSKEY* start) {
while (pQuery->limit.offset > 0) { while (pQuery->limit.offset > 0) {
STimeWindow tw = win; STimeWindow tw = win;
if ((win.ekey <= blockInfo.window.ekey && QUERY_IS_ASC_QUERY(pQuery)) || if ((win.ekey <= blockInfo.window.ekey && ascQuery) || (win.ekey >= blockInfo.window.skey && !ascQuery)) {
(win.ekey >= blockInfo.window.skey && !QUERY_IS_ASC_QUERY(pQuery))) {
pQuery->limit.offset -= 1; pQuery->limit.offset -= 1;
pWindowResInfo->prevSKey = win.skey; pWindowResInfo->prevSKey = win.skey;
// current time window is aligned with blockInfo.window.ekey
// restart it from next data block by set prevSKey to be TSKEY_INITIAL_VAL;
if ((win.ekey == blockInfo.window.ekey && ascQuery) || (win.ekey == blockInfo.window.skey && !ascQuery)) {
pWindowResInfo->prevSKey = TSKEY_INITIAL_VAL;
}
} }
// current window does not ended in current data block, try next data block
getNextTimeWindow(pQuery, &tw);
if (pQuery->limit.offset == 0) { if (pQuery->limit.offset == 0) {
*start = doSkipIntervalProcess(pRuntimeEnv, &win, &blockInfo, pTableQueryInfo); *start = doSkipIntervalProcess(pRuntimeEnv, &win, &blockInfo, pTableQueryInfo);
return true; return true;
} }
// current window does not ended in current data block, try next data block
getNextTimeWindow(pQuery, &tw);
/* /*
* If the next time window still starts from current data block, * If the next time window still starts from current data block,
* load the primary timestamp column first, and then find the start position for the next queried time window. * load the primary timestamp column first, and then find the start position for the next queried time window.
...@@ -4584,13 +4576,12 @@ static bool skipTimeInterval(SQueryRuntimeEnv *pRuntimeEnv, TSKEY* start) { ...@@ -4584,13 +4576,12 @@ static bool skipTimeInterval(SQueryRuntimeEnv *pRuntimeEnv, TSKEY* start) {
* TODO: Optimize for this cases. All data blocks are not needed to be loaded, only if the first actually required * TODO: Optimize for this cases. All data blocks are not needed to be loaded, only if the first actually required
* time window resides in current data block. * time window resides in current data block.
*/ */
if ((tw.skey <= blockInfo.window.ekey && QUERY_IS_ASC_QUERY(pQuery)) || if ((tw.skey <= blockInfo.window.ekey && ascQuery) || (tw.ekey >= blockInfo.window.skey && !ascQuery)) {
(tw.ekey >= blockInfo.window.skey && !QUERY_IS_ASC_QUERY(pQuery))) {
SArray * pDataBlock = tsdbRetrieveDataBlock(pRuntimeEnv->pQueryHandle, NULL); SArray *pDataBlock = tsdbRetrieveDataBlock(pRuntimeEnv->pQueryHandle, NULL);
SColumnInfoData *pColInfoData = taosArrayGet(pDataBlock, 0); SColumnInfoData *pColInfoData = taosArrayGet(pDataBlock, 0);
if ((win.ekey > blockInfo.window.ekey && QUERY_IS_ASC_QUERY(pQuery)) || if ((win.ekey > blockInfo.window.ekey && ascQuery) || (win.ekey < blockInfo.window.skey && !ascQuery)) {
(win.ekey < blockInfo.window.skey && !QUERY_IS_ASC_QUERY(pQuery))) {
pQuery->limit.offset -= 1; pQuery->limit.offset -= 1;
} }
...@@ -5767,7 +5758,7 @@ static void tableIntervalProcess(SQInfo *pQInfo, STableQueryInfo* pTableInfo) { ...@@ -5767,7 +5758,7 @@ static void tableIntervalProcess(SQInfo *pQInfo, STableQueryInfo* pTableInfo) {
SQuery *pQuery = pRuntimeEnv->pQuery; SQuery *pQuery = pRuntimeEnv->pQuery;
pQuery->current = pTableInfo; pQuery->current = pTableInfo;
TSKEY newStartKey = TSKEY_INITIAL_VAL; TSKEY newStartKey = QUERY_IS_ASC_QUERY(pQuery)? INT64_MIN:INT64_MAX;
// skip blocks without load the actual data block from file if no filter condition present // skip blocks without load the actual data block from file if no filter condition present
if (!pRuntimeEnv->groupbyNormalCol) { if (!pRuntimeEnv->groupbyNormalCol) {
......
...@@ -244,3 +244,70 @@ if $data00 != -2.000000000 then ...@@ -244,3 +244,70 @@ if $data00 != -2.000000000 then
print expect -2.000000000, actual: $data00 print expect -2.000000000, actual: $data00
return -1 return -1
endi endi
sql create table tm1 (ts timestamp, k int);
sql insert into tm1 values('2020-10-30 18:11:56.680', -1000);
sql insert into tm1 values('2020-11-19 18:11:45.773', NULL);
sql insert into tm1 values('2020-12-09 18:11:17.098', NULL);
sql insert into tm1 values('2020-12-20 18:11:49.412', 1);
sql insert into tm1 values('2020-12-23 18:11:50.412', 2);
sql insert into tm1 values('2020-12-28 18:11:52.412', 3);
print =====================> td-2610
sql select twa(k)from tm1 where ts>='2020-11-19 18:11:45.773' and ts<='2020-12-9 18:11:17.098'
if $rows != 0 then
return -1
endi
print =====================> td-2609
sql select apercentile(k, 50) from tm1 where ts>='2020-10-30 18:11:56.680' and ts<='2020-12-09 18:11:17.098'
if $rows != 1 then
return -1
endi
if $data00 != -1000.000000000 then
return -1
endi
system sh/exec.sh -n dnode1 -s stop -x SIGINT
sleep 1000
system sh/exec.sh -n dnode1 -s start
print ================== server restart completed
sql connect
sleep 500
sql use m_func_db0
print =====================> td-2583
sql select min(k) from tm1 where ts>='2020-11-19 18:11:45.773' and ts<='2020-12-20 18:11:49.412'
if $rows != 1 then
return -1
endi
if $data00 != 1 then
print expect 1, actual: $data00
return -1
endi
print =====================> td-2601
sql select count(*) from tm1 where ts<='2020-6-1 00:00:00' and ts>='2020-1-1 00:00:00' interval(1n) fill(NULL)
if $rows != 0 then
return -1
endi
print =====================> td-2615
sql select last(ts) from tm1 interval(17a) limit 776 offset 3
if $rows != 3 then
return -1
endi
sql select last(ts) from tm1 interval(17a) limit 1000 offset 4
if $rows != 2 then
return -1
endi
sql select last(ts) from tm1 interval(17a) order by ts desc limit 1000 offset 0
if $rows != 6 then
return -1
endi
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册