Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
慢慢CG
TDengine
提交
7cf7f8e9
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看板
未验证
提交
7cf7f8e9
编写于
6月 28, 2021
作者:
H
Haojun Liao
提交者:
GitHub
6月 28, 2021
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #6639 from taosdata/feature/TD-4825
[TD-4825]<feature> order by col after group-by
上级
a18259d6
b33916be
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
173 addition
and
9 deletion
+173
-9
src/client/src/tscSQLParser.c
src/client/src/tscSQLParser.c
+34
-6
src/query/src/qExecutor.c
src/query/src/qExecutor.c
+66
-2
src/util/inc/tarray.h
src/util/inc/tarray.h
+13
-0
src/util/src/tarray.c
src/util/src/tarray.c
+60
-1
未找到文件。
src/client/src/tscSQLParser.c
浏览文件 @
7cf7f8e9
...
...
@@ -5102,7 +5102,7 @@ static void setDefaultOrderInfo(SQueryInfo* pQueryInfo) {
int32_t
validateOrderbyNode
(
SSqlCmd
*
pCmd
,
SQueryInfo
*
pQueryInfo
,
SSqlNode
*
pSqlNode
,
SSchema
*
pSchema
)
{
const
char
*
msg0
=
"only support order by primary timestamp"
;
const
char
*
msg1
=
"invalid column name"
;
const
char
*
msg2
=
"order by primary timestamp
or first tag
in groupby clause allowed"
;
const
char
*
msg2
=
"order by primary timestamp
, first tag or groupby column
in groupby clause allowed"
;
const
char
*
msg3
=
"invalid column in order by clause, only primary timestamp or first tag in groupby clause allowed"
;
setDefaultOrderInfo
(
pQueryInfo
);
...
...
@@ -5155,6 +5155,7 @@ int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSq
bool
orderByTags
=
false
;
bool
orderByTS
=
false
;
bool
orderByGroupbyCol
=
false
;
if
(
index
.
columnIndex
>=
tscGetNumOfColumns
(
pTableMetaInfo
->
pTableMeta
))
{
int32_t
relTagIndex
=
index
.
columnIndex
-
tscGetNumOfColumns
(
pTableMetaInfo
->
pTableMeta
);
...
...
@@ -5174,11 +5175,18 @@ int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSq
if
(
PRIMARYKEY_TIMESTAMP_COL_INDEX
==
index
.
columnIndex
)
{
orderByTS
=
true
;
}
if
(
!
(
orderByTags
||
orderByTS
)
&&
!
isTopBottomQuery
(
pQueryInfo
))
{
SArray
*
columnInfo
=
pQueryInfo
->
groupbyExpr
.
columnInfo
;
if
(
columnInfo
!=
NULL
&&
taosArrayGetSize
(
columnInfo
)
>
0
)
{
SColIndex
*
pColIndex
=
taosArrayGet
(
columnInfo
,
0
);
if
(
PRIMARYKEY_TIMESTAMP_COL_INDEX
!=
index
.
columnIndex
&&
pColIndex
->
colIndex
==
index
.
columnIndex
)
{
orderByGroupbyCol
=
true
;
}
}
if
(
!
(
orderByTags
||
orderByTS
||
orderByGroupbyCol
)
&&
!
isTopBottomQuery
(
pQueryInfo
))
{
return
invalidOperationMsg
(
tscGetErrorMsgPayload
(
pCmd
),
msg3
);
}
else
{
// order by top/bottom result value column is not supported in case of interval query.
assert
(
!
(
orderByTags
&&
orderByTS
));
assert
(
!
(
orderByTags
&&
orderByTS
&&
orderByGroupbyCol
));
}
size_t
s
=
taosArrayGetSize
(
pSortorder
);
...
...
@@ -5188,6 +5196,11 @@ int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSq
tVariantListItem
*
p1
=
taosArrayGet
(
pSqlNode
->
pSortOrder
,
0
);
pQueryInfo
->
groupbyExpr
.
orderType
=
p1
->
sortOrder
;
}
else
if
(
orderByGroupbyCol
)
{
tVariantListItem
*
p1
=
taosArrayGet
(
pSqlNode
->
pSortOrder
,
0
);
pQueryInfo
->
groupbyExpr
.
orderType
=
p1
->
sortOrder
;
pQueryInfo
->
order
.
orderColId
=
pSchema
[
index
.
columnIndex
].
colId
;
}
else
if
(
isTopBottomQuery
(
pQueryInfo
))
{
/* order of top/bottom query in interval is not valid */
SExprInfo
*
pExpr
=
tscExprGet
(
pQueryInfo
,
0
);
...
...
@@ -5220,6 +5233,9 @@ int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSq
if
(
orderByTags
)
{
pQueryInfo
->
groupbyExpr
.
orderIndex
=
index
.
columnIndex
-
tscGetNumOfColumns
(
pTableMetaInfo
->
pTableMeta
);
pQueryInfo
->
groupbyExpr
.
orderType
=
pItem
->
sortOrder
;
}
else
if
(
orderByGroupbyCol
){
pQueryInfo
->
order
.
order
=
pItem
->
sortOrder
;
pQueryInfo
->
order
.
orderColId
=
index
.
columnIndex
;
}
else
{
pQueryInfo
->
order
.
order
=
pItem
->
sortOrder
;
pQueryInfo
->
order
.
orderColId
=
PRIMARYKEY_TIMESTAMP_COL_INDEX
;
...
...
@@ -5245,9 +5261,20 @@ int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSq
if
(
getColumnIndexByName
(
pCmd
,
&
columnName
,
pQueryInfo
,
&
index
)
!=
TSDB_CODE_SUCCESS
)
{
return
invalidOperationMsg
(
tscGetErrorMsgPayload
(
pCmd
),
msg1
);
}
if
(
index
.
columnIndex
!=
PRIMARYKEY_TIMESTAMP_COL_INDEX
&&
!
isTopBottomQuery
(
pQueryInfo
))
{
return
invalidOperationMsg
(
tscGetErrorMsgPayload
(
pCmd
),
msg2
);
bool
validOrder
=
false
;
SArray
*
columnInfo
=
pQueryInfo
->
groupbyExpr
.
columnInfo
;
if
(
columnInfo
!=
NULL
&&
taosArrayGetSize
(
columnInfo
)
>
0
)
{
SColIndex
*
pColIndex
=
taosArrayGet
(
columnInfo
,
0
);
validOrder
=
(
pColIndex
->
colIndex
==
index
.
columnIndex
);
}
if
(
!
validOrder
)
{
return
invalidOperationMsg
(
tscGetErrorMsgPayload
(
pCmd
),
msg2
);
}
tVariantListItem
*
p1
=
taosArrayGet
(
pSqlNode
->
pSortOrder
,
0
);
pQueryInfo
->
groupbyExpr
.
orderIndex
=
pSchema
[
index
.
columnIndex
].
colId
;
pQueryInfo
->
groupbyExpr
.
orderType
=
p1
->
sortOrder
;
}
if
(
isTopBottomQuery
(
pQueryInfo
))
{
...
...
@@ -5268,6 +5295,7 @@ int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSq
tVariantListItem
*
pItem
=
taosArrayGet
(
pSqlNode
->
pSortOrder
,
0
);
pQueryInfo
->
order
.
order
=
pItem
->
sortOrder
;
pQueryInfo
->
order
.
orderColId
=
pSchema
[
index
.
columnIndex
].
colId
;
}
return
TSDB_CODE_SUCCESS
;
...
...
src/query/src/qExecutor.c
浏览文件 @
7cf7f8e9
...
...
@@ -16,6 +16,7 @@
#include "qFill.h"
#include "taosmsg.h"
#include "tglobal.h"
#include "talgo.h"
#include "exception.h"
#include "hash.h"
...
...
@@ -26,6 +27,7 @@
#include "queryLog.h"
#include "tlosertree.h"
#include "ttype.h"
#include "tcompare.h"
#include "tscompression.h"
#define IS_MASTER_SCAN(runtime) ((runtime)->scanFlag == MASTER_SCAN)
...
...
@@ -207,7 +209,66 @@ static void doSetTableGroupOutputBuf(SQueryRuntimeEnv* pRuntimeEnv, SResultRowIn
SQLFunctionCtx
*
pCtx
,
int32_t
*
rowCellInfoOffset
,
int32_t
numOfOutput
,
int32_t
groupIndex
);
// setup the output buffer for each operator
SArray
*
getOrderCheckColumns
(
SQueryAttr
*
pQuery
);
typedef
struct
SRowCompSupporter
{
SQueryRuntimeEnv
*
pRuntimeEnv
;
int16_t
dataOffset
;
__compar_fn_t
comFunc
;
}
SRowCompSupporter
;
static
int
compareRowData
(
const
void
*
a
,
const
void
*
b
,
const
void
*
userData
)
{
const
SResultRow
*
pRow1
=
(
const
SResultRow
*
)
a
;
const
SResultRow
*
pRow2
=
(
const
SResultRow
*
)
b
;
SRowCompSupporter
*
supporter
=
(
SRowCompSupporter
*
)
userData
;
SQueryRuntimeEnv
*
pRuntimeEnv
=
supporter
->
pRuntimeEnv
;
tFilePage
*
page1
=
getResBufPage
(
pRuntimeEnv
->
pResultBuf
,
pRow1
->
pageId
);
tFilePage
*
page2
=
getResBufPage
(
pRuntimeEnv
->
pResultBuf
,
pRow2
->
pageId
);
int16_t
offset
=
supporter
->
dataOffset
;
char
*
in1
=
getPosInResultPage
(
pRuntimeEnv
->
pQueryAttr
,
page1
,
pRow1
->
offset
,
offset
);
char
*
in2
=
getPosInResultPage
(
pRuntimeEnv
->
pQueryAttr
,
page2
,
pRow2
->
offset
,
offset
);
return
(
in1
!=
NULL
&&
in2
!=
NULL
)
?
supporter
->
comFunc
(
in1
,
in2
)
:
0
;
}
static
void
sortGroupResByOrderList
(
SGroupResInfo
*
pGroupResInfo
,
SQueryRuntimeEnv
*
pRuntimeEnv
,
SSDataBlock
*
pDataBlock
)
{
SArray
*
columnOrderList
=
getOrderCheckColumns
(
pRuntimeEnv
->
pQueryAttr
);
if
(
taosArrayGetSize
(
columnOrderList
)
<=
0
)
{
return
;
}
int32_t
orderId
=
pRuntimeEnv
->
pQueryAttr
->
order
.
orderColId
;
if
(
orderId
<=
0
)
{
return
;
}
bool
found
=
false
;
int16_t
dataOffset
=
0
;
//SColIndex *index = taosArrayGet(columnOrderList, 0);
for
(
int32_t
j
=
0
;
j
<
pDataBlock
->
info
.
numOfCols
;
++
j
)
{
SColumnInfoData
*
pColInfoData
=
(
SColumnInfoData
*
)
taosArrayGet
(
pDataBlock
->
pDataBlock
,
j
);
if
(
orderId
==
j
)
{
found
=
true
;
break
;
}
dataOffset
+=
pColInfoData
->
info
.
bytes
;
}
if
(
found
==
false
)
{
return
;
}
int16_t
type
=
pRuntimeEnv
->
pQueryAttr
->
pExpr1
[
orderId
].
base
.
resType
;
SRowCompSupporter
support
=
{.
pRuntimeEnv
=
pRuntimeEnv
,
.
dataOffset
=
dataOffset
,
.
comFunc
=
getComparFunc
(
type
,
0
)};
taosArraySortPWithExt
(
pGroupResInfo
->
pRows
,
compareRowData
,
&
support
);
return
;
}
//setup the output buffer for each operator
SSDataBlock
*
createOutputBuf
(
SExprInfo
*
pExpr
,
int32_t
numOfOutput
,
int32_t
numOfRows
)
{
const
static
int32_t
minSize
=
8
;
...
...
@@ -5588,8 +5649,11 @@ static SSDataBlock* hashGroupbyAggregate(void* param, bool* newgroup) {
}
initGroupResInfo
(
&
pRuntimeEnv
->
groupResInfo
,
&
pInfo
->
binfo
.
resultRowInfo
);
if
(
!
pRuntimeEnv
->
pQueryAttr
->
stableQuery
)
{
sortGroupResByOrderList
(
&
pRuntimeEnv
->
groupResInfo
,
pRuntimeEnv
,
pInfo
->
binfo
.
pRes
);
}
toSSDataBlock
(
&
pRuntimeEnv
->
groupResInfo
,
pRuntimeEnv
,
pInfo
->
binfo
.
pRes
);
if
(
pInfo
->
binfo
.
pRes
->
info
.
rows
==
0
||
!
hasRemainDataInCurrentGroup
(
&
pRuntimeEnv
->
groupResInfo
))
{
pOperator
->
status
=
OP_EXEC_DONE
;
}
...
...
src/util/inc/tarray.h
浏览文件 @
7cf7f8e9
...
...
@@ -197,8 +197,21 @@ void* taosArraySearch(const SArray* pArray, const void* key, __compar_fn_t compa
*/
char
*
taosArraySearchString
(
const
SArray
*
pArray
,
const
char
*
key
,
__compar_fn_t
comparFn
,
int
flags
);
/**
* sort the pointer data in the array
* @param pArray
* @param compar
* @param param
* @return
*/
void
taosArraySortPWithExt
(
SArray
*
pArray
,
__ext_compar_fn_t
fn
,
const
void
*
param
);
#ifdef __cplusplus
}
#endif
#endif // TDENGINE_TAOSARRAY_H
src/util/src/tarray.c
浏览文件 @
7cf7f8e9
...
...
@@ -15,6 +15,7 @@
#include "os.h"
#include "tarray.h"
#include "talgo.h"
void
*
taosArrayInit
(
size_t
size
,
size_t
elemSize
)
{
assert
(
elemSize
>
0
);
...
...
@@ -249,4 +250,62 @@ char* taosArraySearchString(const SArray* pArray, const char* key, __compar_fn_t
return
NULL
;
}
return
*
(
char
**
)
p
;
}
\ No newline at end of file
}
static
int
taosArrayPartition
(
SArray
*
pArray
,
int
i
,
int
j
,
__ext_compar_fn_t
fn
,
const
void
*
userData
)
{
void
*
key
=
taosArrayGetP
(
pArray
,
i
);
while
(
i
<
j
)
{
while
(
i
<
j
&&
fn
(
taosArrayGetP
(
pArray
,
j
),
key
,
userData
)
>=
0
)
{
j
--
;
}
if
(
i
<
j
)
{
void
*
a
=
taosArrayGetP
(
pArray
,
j
);
taosArraySet
(
pArray
,
i
,
&
a
);
}
while
(
i
<
j
&&
fn
(
taosArrayGetP
(
pArray
,
i
),
key
,
userData
)
<=
0
)
{
i
++
;}
if
(
i
<
j
)
{
void
*
a
=
taosArrayGetP
(
pArray
,
i
);
taosArraySet
(
pArray
,
j
,
&
a
);
}
}
taosArraySet
(
pArray
,
i
,
&
key
);
return
i
;
}
static
void
taosArrayQuicksortHelper
(
SArray
*
pArray
,
int
low
,
int
high
,
__ext_compar_fn_t
fn
,
const
void
*
param
)
{
if
(
low
<
high
)
{
int
idx
=
taosArrayPartition
(
pArray
,
low
,
high
,
fn
,
param
);
taosArrayQuicksortHelper
(
pArray
,
low
,
idx
-
1
,
fn
,
param
);
taosArrayQuicksortHelper
(
pArray
,
idx
+
1
,
high
,
fn
,
param
);
}
}
static
void
taosArrayQuickSort
(
SArray
*
pArray
,
__ext_compar_fn_t
fn
,
const
void
*
param
)
{
if
(
pArray
->
size
<=
1
)
{
return
;
}
taosArrayQuicksortHelper
(
pArray
,
0
,
(
int
)(
taosArrayGetSize
(
pArray
)
-
1
),
fn
,
param
);
}
static
void
taosArrayInsertSort
(
SArray
*
pArray
,
__ext_compar_fn_t
fn
,
const
void
*
param
)
{
if
(
pArray
->
size
<=
1
)
{
return
;
}
for
(
int
i
=
1
;
i
<=
pArray
->
size
-
1
;
++
i
)
{
for
(
int
j
=
i
;
j
>
0
;
--
j
)
{
if
(
fn
(
taosArrayGetP
(
pArray
,
j
),
taosArrayGetP
(
pArray
,
j
-
1
),
param
)
==
-
1
)
{
void
*
a
=
taosArrayGetP
(
pArray
,
j
);
void
*
b
=
taosArrayGetP
(
pArray
,
j
-
1
);
taosArraySet
(
pArray
,
j
-
1
,
&
a
);
taosArraySet
(
pArray
,
j
,
&
b
);
}
else
{
break
;
}
}
}
return
;
}
// order array<type *>
void
taosArraySortPWithExt
(
SArray
*
pArray
,
__ext_compar_fn_t
fn
,
const
void
*
param
)
{
taosArrayGetSize
(
pArray
)
>
8
?
taosArrayQuickSort
(
pArray
,
fn
,
param
)
:
taosArrayInsertSort
(
pArray
,
fn
,
param
);
}
//TODO(yihaoDeng) add order array<type>
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录