Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
慢慢CG
TDengine
提交
5a7e631c
T
TDengine
项目概览
慢慢CG
/
TDengine
与 Fork 源项目一致
Fork自
taosdata / TDengine
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
T
TDengine
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
5a7e631c
编写于
12月 30, 2020
作者:
H
Haojun Liao
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
[TD-2615]<fix>: fix limit offset query caused crash.
上级
050e41b8
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
89 addition
and
31 deletion
+89
-31
src/client/src/tscFunctionImpl.c
src/client/src/tscFunctionImpl.c
+4
-4
src/query/src/qExecutor.c
src/query/src/qExecutor.c
+18
-27
tests/script/general/parser/function.sim
tests/script/general/parser/function.sim
+67
-0
未找到文件。
src/client/src/tscFunctionImpl.c
浏览文件 @
5a7e631c
...
@@ -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
;
...
...
src/query/src/qExecutor.c
浏览文件 @
5a7e631c
...
@@ -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
)
{
...
...
tests/script/general/parser/function.sim
浏览文件 @
5a7e631c
...
@@ -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.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录