Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
taosdata
TDengine
提交
b1aa263c
TDengine
项目概览
taosdata
/
TDengine
12 个月 前同步成功
通知
1180
Star
22014
Fork
4786
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
1
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
TDengine
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
1
Issue
1
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
b1aa263c
编写于
5月 01, 2022
作者:
X
Xiaoyu Wang
提交者:
GitHub
5月 01, 2022
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #12080 from taosdata/feature/3.0_wxy
sql command 'select max(c1), c2 from t'
上级
7cecc341
7cdedc8b
变更
12
隐藏空白更改
内联
并排
Showing
12 changed file
with
282 addition
and
119 deletion
+282
-119
include/libs/function/functionMgt.h
include/libs/function/functionMgt.h
+4
-0
source/libs/function/inc/functionMgtInt.h
source/libs/function/inc/functionMgtInt.h
+1
-0
source/libs/function/src/builtins.c
source/libs/function/src/builtins.c
+17
-2
source/libs/function/src/functionMgt.c
source/libs/function/src/functionMgt.c
+2
-0
source/libs/parser/src/parTranslater.c
source/libs/parser/src/parTranslater.c
+154
-85
source/libs/parser/test/mockCatalogService.cpp
source/libs/parser/test/mockCatalogService.cpp
+0
-1
source/libs/parser/test/parSelectTest.cpp
source/libs/parser/test/parSelectTest.cpp
+50
-19
source/libs/planner/test/planGroupByTest.cpp
source/libs/planner/test/planGroupByTest.cpp
+26
-11
source/libs/planner/test/planIntervalTest.cpp
source/libs/planner/test/planIntervalTest.cpp
+9
-0
source/libs/planner/test/planSessionTest.cpp
source/libs/planner/test/planSessionTest.cpp
+9
-0
source/libs/planner/test/planStateTest.cpp
source/libs/planner/test/planStateTest.cpp
+9
-0
tests/system-test/2-query/distinct.py
tests/system-test/2-query/distinct.py
+1
-1
未找到文件。
include/libs/function/functionMgt.h
浏览文件 @
b1aa263c
...
...
@@ -113,6 +113,9 @@ typedef enum EFunctionType {
FUNCTION_TYPE_WENDTS
,
FUNCTION_TYPE_WDURATION
,
// internal function
FUNCTION_TYPE_SELECT_VALUE
,
// user defined funcion
FUNCTION_TYPE_UDF
=
10000
}
EFunctionType
;
...
...
@@ -141,6 +144,7 @@ bool fmIsScalarFunc(int32_t funcId);
bool
fmIsNonstandardSQLFunc
(
int32_t
funcId
);
bool
fmIsStringFunc
(
int32_t
funcId
);
bool
fmIsDatetimeFunc
(
int32_t
funcId
);
bool
fmIsSelectFunc
(
int32_t
funcId
);
bool
fmIsTimelineFunc
(
int32_t
funcId
);
bool
fmIsTimeorderFunc
(
int32_t
funcId
);
bool
fmIsPseudoColumnFunc
(
int32_t
funcId
);
...
...
source/libs/function/inc/functionMgtInt.h
浏览文件 @
b1aa263c
...
...
@@ -39,6 +39,7 @@ extern "C" {
#define FUNC_MGT_DYNAMIC_SCAN_OPTIMIZED FUNC_MGT_FUNC_CLASSIFICATION_MASK(10)
#define FUNC_MGT_MULTI_RES_FUNC FUNC_MGT_FUNC_CLASSIFICATION_MASK(11)
#define FUNC_MGT_SCAN_PC_FUNC FUNC_MGT_FUNC_CLASSIFICATION_MASK(12)
#define FUNC_MGT_SELECT_FUNC FUNC_MGT_FUNC_CLASSIFICATION_MASK(13)
#define FUNC_MGT_TEST_MASK(val, mask) (((val) & (mask)) != 0)
...
...
source/libs/function/src/builtins.c
浏览文件 @
b1aa263c
...
...
@@ -438,6 +438,11 @@ static int32_t translateToJson(SFunctionNode* pFunc, char* pErrBuf, int32_t len)
return
TSDB_CODE_SUCCESS
;
}
static
int32_t
translateSelectValue
(
SFunctionNode
*
pFunc
,
char
*
pErrBuf
,
int32_t
len
)
{
pFunc
->
node
.
resType
=
((
SExprNode
*
)
nodesListGetNode
(
pFunc
->
pParameterList
,
0
))
->
resType
;
return
TSDB_CODE_SUCCESS
;
}
// clang-format off
const
SBuiltinFuncDefinition
funcMgtBuiltins
[]
=
{
{
...
...
@@ -465,7 +470,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
{
.
name
=
"min"
,
.
type
=
FUNCTION_TYPE_MIN
,
.
classification
=
FUNC_MGT_AGG_FUNC
|
FUNC_MGT_SPECIAL_DATA_REQUIRED
,
.
classification
=
FUNC_MGT_AGG_FUNC
|
FUNC_MGT_SPECIAL_DATA_REQUIRED
|
FUNC_MGT_SELECT_FUNC
,
.
translateFunc
=
translateInOutNum
,
.
dataRequiredFunc
=
statisDataRequired
,
.
getEnvFunc
=
getMinmaxFuncEnv
,
...
...
@@ -476,7 +481,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
{
.
name
=
"max"
,
.
type
=
FUNCTION_TYPE_MAX
,
.
classification
=
FUNC_MGT_AGG_FUNC
|
FUNC_MGT_SPECIAL_DATA_REQUIRED
,
.
classification
=
FUNC_MGT_AGG_FUNC
|
FUNC_MGT_SPECIAL_DATA_REQUIRED
|
FUNC_MGT_SELECT_FUNC
,
.
translateFunc
=
translateInOutNum
,
.
dataRequiredFunc
=
statisDataRequired
,
.
getEnvFunc
=
getMinmaxFuncEnv
,
...
...
@@ -974,6 +979,16 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
.
initFunc
=
NULL
,
.
sprocessFunc
=
toJsonFunction
,
.
finalizeFunc
=
NULL
},
{
.
name
=
"_select_value"
,
.
type
=
FUNCTION_TYPE_SELECT_VALUE
,
.
classification
=
FUNC_MGT_AGG_FUNC
|
FUNC_MGT_SELECT_FUNC
,
.
translateFunc
=
translateSelectValue
,
.
getEnvFunc
=
NULL
,
.
initFunc
=
NULL
,
.
sprocessFunc
=
NULL
,
.
finalizeFunc
=
NULL
}
};
// clang-format on
...
...
source/libs/function/src/functionMgt.c
浏览文件 @
b1aa263c
...
...
@@ -145,6 +145,8 @@ bool fmIsAggFunc(int32_t funcId) { return isSpecificClassifyFunc(funcId, FUNC_MG
bool
fmIsScalarFunc
(
int32_t
funcId
)
{
return
isSpecificClassifyFunc
(
funcId
,
FUNC_MGT_SCALAR_FUNC
);
}
bool
fmIsSelectFunc
(
int32_t
funcId
)
{
return
isSpecificClassifyFunc
(
funcId
,
FUNC_MGT_SELECT_FUNC
);
}
bool
fmIsTimelineFunc
(
int32_t
funcId
)
{
return
isSpecificClassifyFunc
(
funcId
,
FUNC_MGT_TIMELINE_FUNC
);
}
bool
fmIsPseudoColumnFunc
(
int32_t
funcId
)
{
return
isSpecificClassifyFunc
(
funcId
,
FUNC_MGT_PSEUDO_COLUMN_FUNC
);
}
...
...
source/libs/parser/src/parTranslater.c
浏览文件 @
b1aa263c
...
...
@@ -256,6 +256,26 @@ static void destroyTranslateContext(STranslateContext* pCxt) {
taosHashCleanup
(
pCxt
->
pTables
);
}
static
bool
isAliasColumn
(
const
SNode
*
pNode
)
{
return
(
QUERY_NODE_COLUMN
==
nodeType
(
pNode
)
&&
(
'\0'
==
((
SColumnNode
*
)
pNode
)
->
tableAlias
[
0
]));
}
static
bool
isAggFunc
(
const
SNode
*
pNode
)
{
return
(
QUERY_NODE_FUNCTION
==
nodeType
(
pNode
)
&&
fmIsAggFunc
(((
SFunctionNode
*
)
pNode
)
->
funcId
));
}
static
bool
isSelectFunc
(
const
SNode
*
pNode
)
{
return
(
QUERY_NODE_FUNCTION
==
nodeType
(
pNode
)
&&
fmIsSelectFunc
(((
SFunctionNode
*
)
pNode
)
->
funcId
));
}
static
bool
isTimelineFunc
(
const
SNode
*
pNode
)
{
return
(
QUERY_NODE_FUNCTION
==
nodeType
(
pNode
)
&&
fmIsTimelineFunc
(((
SFunctionNode
*
)
pNode
)
->
funcId
));
}
static
bool
isDistinctOrderBy
(
STranslateContext
*
pCxt
)
{
return
(
SQL_CLAUSE_ORDER_BY
==
pCxt
->
currClause
&&
pCxt
->
pCurrStmt
->
isDistinct
);
}
static
bool
belongTable
(
const
char
*
currentDb
,
const
SColumnNode
*
pCol
,
const
STableNode
*
pTable
)
{
int
cmp
=
0
;
if
(
'\0'
!=
pCol
->
dbName
[
0
])
{
...
...
@@ -617,13 +637,45 @@ static EDealRes translateOperator(STranslateContext* pCxt, SOperatorNode* pOp) {
}
static
EDealRes
haveAggFunction
(
SNode
*
pNode
,
void
*
pContext
)
{
if
(
QUERY_NODE_FUNCTION
==
nodeType
(
pNode
)
&&
fmIsAggFunc
(((
SFunctionNode
*
)
pNode
)
->
funcId
))
{
if
(
isAggFunc
(
pNode
))
{
*
((
bool
*
)
pContext
)
=
true
;
return
DEAL_RES_END
;
}
return
DEAL_RES_CONTINUE
;
}
static
int32_t
findTable
(
STranslateContext
*
pCxt
,
const
char
*
pTableAlias
,
STableNode
**
pOutput
)
{
SArray
*
pTables
=
taosArrayGetP
(
pCxt
->
pNsLevel
,
pCxt
->
currLevel
);
size_t
nums
=
taosArrayGetSize
(
pTables
);
for
(
size_t
i
=
0
;
i
<
nums
;
++
i
)
{
STableNode
*
pTable
=
taosArrayGetP
(
pTables
,
i
);
if
(
NULL
==
pTableAlias
||
0
==
strcmp
(
pTable
->
tableAlias
,
pTableAlias
))
{
*
pOutput
=
pTable
;
return
TSDB_CODE_SUCCESS
;
}
}
return
generateSyntaxErrMsg
(
&
pCxt
->
msgBuf
,
TSDB_CODE_PAR_TABLE_NOT_EXIST
,
pTableAlias
);
}
static
bool
isCountStar
(
SFunctionNode
*
pFunc
)
{
if
(
FUNCTION_TYPE_COUNT
!=
pFunc
->
funcType
||
1
!=
LIST_LENGTH
(
pFunc
->
pParameterList
))
{
return
false
;
}
SNode
*
pPara
=
nodesListGetNode
(
pFunc
->
pParameterList
,
0
);
return
(
QUERY_NODE_COLUMN
==
nodeType
(
pPara
)
&&
0
==
strcmp
(((
SColumnNode
*
)
pPara
)
->
colName
,
"*"
));
}
// count(*) is rewritten as count(ts) for scannning optimization
static
int32_t
rewriteCountStar
(
STranslateContext
*
pCxt
,
SFunctionNode
*
pCount
)
{
SColumnNode
*
pCol
=
nodesListGetNode
(
pCount
->
pParameterList
,
0
);
STableNode
*
pTable
=
NULL
;
int32_t
code
=
findTable
(
pCxt
,
(
'\0'
==
pCol
->
tableAlias
[
0
]
?
NULL
:
pCol
->
tableAlias
),
&
pTable
);
if
(
TSDB_CODE_SUCCESS
==
code
&&
QUERY_NODE_REAL_TABLE
==
nodeType
(
pTable
))
{
setColumnInfoBySchema
((
SRealTableNode
*
)
pTable
,
((
SRealTableNode
*
)
pTable
)
->
pMeta
->
schema
,
false
,
pCol
);
}
return
code
;
}
static
EDealRes
translateFunction
(
STranslateContext
*
pCxt
,
SFunctionNode
*
pFunc
)
{
SFmGetFuncInfoParam
param
=
{.
pCtg
=
pCxt
->
pParseCxt
->
pCatalog
,
.
pRpc
=
pCxt
->
pParseCxt
->
pTransporter
,
...
...
@@ -631,10 +683,7 @@ static EDealRes translateFunction(STranslateContext* pCxt, SFunctionNode* pFunc)
.
pErrBuf
=
pCxt
->
msgBuf
.
buf
,
.
errBufLen
=
pCxt
->
msgBuf
.
len
};
pCxt
->
errCode
=
fmGetFuncInfo
(
&
param
,
pFunc
);
if
(
TSDB_CODE_SUCCESS
!=
pCxt
->
errCode
)
{
return
DEAL_RES_ERROR
;
}
if
(
fmIsAggFunc
(
pFunc
->
funcId
))
{
if
(
TSDB_CODE_SUCCESS
==
pCxt
->
errCode
&&
fmIsAggFunc
(
pFunc
->
funcId
))
{
if
(
beforeHaving
(
pCxt
->
currClause
))
{
return
generateDealNodeErrMsg
(
pCxt
,
TSDB_CODE_PAR_ILLEGAL_USE_AGG_FUNCTION
);
}
...
...
@@ -643,11 +692,14 @@ static EDealRes translateFunction(STranslateContext* pCxt, SFunctionNode* pFunc)
if
(
haveAggFunc
)
{
return
generateDealNodeErrMsg
(
pCxt
,
TSDB_CODE_PAR_AGG_FUNC_NESTING
);
}
pCxt
->
pCurrStmt
->
hasAggFuncs
=
true
;
pCxt
->
pCurrStmt
->
isTimeOrderQuery
=
false
;
if
(
isCountStar
(
pFunc
))
{
pCxt
->
errCode
=
rewriteCountStar
(
pCxt
,
pFunc
);
}
}
return
DEAL_RES_CONTINUE
;
return
TSDB_CODE_SUCCESS
==
pCxt
->
errCode
?
DEAL_RES_CONTINUE
:
DEAL_RES_ERROR
;
}
static
EDealRes
translateExprSubquery
(
STranslateContext
*
pCxt
,
SNode
*
pNode
)
{
...
...
@@ -691,12 +743,6 @@ static int32_t translateExprList(STranslateContext* pCxt, SNodeList* pList) {
return
pCxt
->
errCode
;
}
static
bool
isAliasColumn
(
SColumnNode
*
pCol
)
{
return
(
'\0'
==
pCol
->
tableAlias
[
0
]);
}
static
bool
isDistinctOrderBy
(
STranslateContext
*
pCxt
)
{
return
(
SQL_CLAUSE_ORDER_BY
==
pCxt
->
currClause
&&
pCxt
->
pCurrStmt
->
isDistinct
);
}
static
SNodeList
*
getGroupByList
(
STranslateContext
*
pCxt
)
{
if
(
isDistinctOrderBy
(
pCxt
))
{
return
pCxt
->
pCurrStmt
->
pProjectionList
;
...
...
@@ -718,31 +764,71 @@ static int32_t getGroupByErrorCode(STranslateContext* pCxt) {
return
TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION
;
}
static
EDealRes
doCheckExprForGroupBy
(
SNode
*
pNode
,
void
*
pContext
)
{
STranslateContext
*
pCxt
=
(
STranslateContext
*
)
pContext
;
if
(
!
nodesIsExprNode
(
pNode
)
||
(
QUERY_NODE_COLUMN
==
nodeType
(
pNode
)
&&
isAliasColumn
((
SColumnNode
*
)
pNode
)))
{
typedef
struct
SCheckExprForGroupByCxt
{
STranslateContext
*
pTranslateCxt
;
int32_t
selectFuncNum
;
bool
hasSelectValFunc
;
}
SCheckExprForGroupByCxt
;
static
EDealRes
rewriteColToSelectValFunc
(
STranslateContext
*
pCxt
,
bool
*
pHasSelectValFunc
,
SNode
**
pNode
)
{
SFunctionNode
*
pFunc
=
nodesMakeNode
(
QUERY_NODE_FUNCTION
);
if
(
NULL
==
pFunc
)
{
pCxt
->
errCode
=
TSDB_CODE_OUT_OF_MEMORY
;
return
DEAL_RES_ERROR
;
}
strcpy
(
pFunc
->
functionName
,
"_select_value"
);
pCxt
->
errCode
=
nodesListMakeAppend
(
&
pFunc
->
pParameterList
,
*
pNode
);
if
(
TSDB_CODE_SUCCESS
==
pCxt
->
errCode
)
{
translateFunction
(
pCxt
,
pFunc
);
}
if
(
TSDB_CODE_SUCCESS
==
pCxt
->
errCode
)
{
*
pNode
=
(
SNode
*
)
pFunc
;
if
(
NULL
!=
pHasSelectValFunc
)
{
*
pHasSelectValFunc
=
true
;
}
}
else
{
nodesDestroyNode
(
pFunc
);
}
return
TSDB_CODE_SUCCESS
==
pCxt
->
errCode
?
DEAL_RES_IGNORE_CHILD
:
DEAL_RES_ERROR
;
}
static
EDealRes
doCheckExprForGroupBy
(
SNode
**
pNode
,
void
*
pContext
)
{
SCheckExprForGroupByCxt
*
pCxt
=
(
SCheckExprForGroupByCxt
*
)
pContext
;
if
(
!
nodesIsExprNode
(
*
pNode
)
||
isAliasColumn
(
*
pNode
))
{
return
DEAL_RES_CONTINUE
;
}
if
(
QUERY_NODE_FUNCTION
==
nodeType
(
pNode
)
&&
fmIsAggFunc
(((
SFunctionNode
*
)
pNode
)
->
funcId
)
&&
!
isDistinctOrderBy
(
pCxt
))
{
pCxt
->
selectFuncNum
+=
isSelectFunc
(
*
pNode
)
?
1
:
0
;
if
(
pCxt
->
selectFuncNum
>
1
&&
pCxt
->
hasSelectValFunc
)
{
return
generateDealNodeErrMsg
(
pCxt
->
pTranslateCxt
,
getGroupByErrorCode
(
pCxt
->
pTranslateCxt
));
}
if
(
isAggFunc
(
*
pNode
)
&&
!
isDistinctOrderBy
(
pCxt
->
pTranslateCxt
))
{
return
DEAL_RES_IGNORE_CHILD
;
}
SNode
*
pGroupNode
;
FOREACH
(
pGroupNode
,
getGroupByList
(
pCxt
))
{
if
(
nodesEqualNode
(
getGroupByNode
(
pGroupNode
),
pNode
))
{
FOREACH
(
pGroupNode
,
getGroupByList
(
pCxt
->
pTranslateCxt
))
{
if
(
nodesEqualNode
(
getGroupByNode
(
pGroupNode
),
*
pNode
))
{
return
DEAL_RES_IGNORE_CHILD
;
}
}
if
(
QUERY_NODE_COLUMN
==
nodeType
(
pNode
)
||
(
QUERY_NODE_FUNCTION
==
nodeType
(
pNode
)
&&
fmIsAggFunc
(((
SFunctionNode
*
)
pNode
)
->
funcId
)
&&
isDistinctOrderBy
(
pCxt
)))
{
return
generateDealNodeErrMsg
(
pCxt
,
getGroupByErrorCode
(
pCxt
));
if
(
QUERY_NODE_COLUMN
==
nodeType
(
*
pNode
))
{
if
(
pCxt
->
selectFuncNum
>
1
)
{
return
generateDealNodeErrMsg
(
pCxt
->
pTranslateCxt
,
getGroupByErrorCode
(
pCxt
->
pTranslateCxt
));
}
else
{
return
rewriteColToSelectValFunc
(
pCxt
->
pTranslateCxt
,
&
pCxt
->
hasSelectValFunc
,
pNode
);
}
}
if
(
isAggFunc
(
*
pNode
)
&&
isDistinctOrderBy
(
pCxt
->
pTranslateCxt
))
{
return
generateDealNodeErrMsg
(
pCxt
->
pTranslateCxt
,
getGroupByErrorCode
(
pCxt
->
pTranslateCxt
));
}
return
DEAL_RES_CONTINUE
;
}
static
int32_t
checkExprForGroupBy
(
STranslateContext
*
pCxt
,
SNode
*
pNode
)
{
nodesWalkExpr
(
pNode
,
doCheckExprForGroupBy
,
pCxt
);
static
int32_t
checkExprForGroupBy
(
STranslateContext
*
pCxt
,
SNode
**
pNode
)
{
SCheckExprForGroupByCxt
cxt
=
{.
pTranslateCxt
=
pCxt
,
.
selectFuncNum
=
0
,
.
hasSelectValFunc
=
false
};
nodesRewriteExpr
(
pNode
,
doCheckExprForGroupBy
,
&
cxt
);
if
(
cxt
.
selectFuncNum
!=
1
&&
cxt
.
hasSelectValFunc
)
{
return
generateSyntaxErrMsg
(
&
pCxt
->
msgBuf
,
getGroupByErrorCode
(
pCxt
));
}
return
pCxt
->
errCode
;
}
...
...
@@ -750,7 +836,29 @@ static int32_t checkExprListForGroupBy(STranslateContext* pCxt, SNodeList* pList
if
(
NULL
==
getGroupByList
(
pCxt
))
{
return
TSDB_CODE_SUCCESS
;
}
nodesWalkExprs
(
pList
,
doCheckExprForGroupBy
,
pCxt
);
SCheckExprForGroupByCxt
cxt
=
{.
pTranslateCxt
=
pCxt
,
.
selectFuncNum
=
0
,
.
hasSelectValFunc
=
false
};
nodesRewriteExprs
(
pList
,
doCheckExprForGroupBy
,
&
cxt
);
if
(
cxt
.
selectFuncNum
!=
1
&&
cxt
.
hasSelectValFunc
)
{
return
generateSyntaxErrMsg
(
&
pCxt
->
msgBuf
,
getGroupByErrorCode
(
pCxt
));
}
return
pCxt
->
errCode
;
}
static
EDealRes
rewriteColsToSelectValFuncImpl
(
SNode
**
pNode
,
void
*
pContext
)
{
if
(
isAggFunc
(
*
pNode
))
{
return
DEAL_RES_IGNORE_CHILD
;
}
if
(
QUERY_NODE_COLUMN
==
nodeType
(
*
pNode
))
{
return
rewriteColToSelectValFunc
((
STranslateContext
*
)
pContext
,
NULL
,
pNode
);
}
return
DEAL_RES_CONTINUE
;
}
static
int32_t
rewriteColsToSelectValFunc
(
STranslateContext
*
pCxt
,
SSelectStmt
*
pSelect
)
{
nodesRewriteExprs
(
pSelect
->
pProjectionList
,
rewriteColsToSelectValFuncImpl
,
pCxt
);
if
(
TSDB_CODE_SUCCESS
==
pCxt
->
errCode
&&
!
pSelect
->
isDistinct
)
{
nodesRewriteExprs
(
pSelect
->
pOrderByList
,
rewriteColsToSelectValFuncImpl
,
pCxt
);
}
return
pCxt
->
errCode
;
}
...
...
@@ -758,11 +866,13 @@ typedef struct CheckAggColCoexistCxt {
STranslateContext
*
pTranslateCxt
;
bool
existAggFunc
;
bool
existCol
;
int32_t
selectFuncNum
;
}
CheckAggColCoexistCxt
;
static
EDealRes
doCheckAggColCoexist
(
SNode
*
pNode
,
void
*
pContext
)
{
CheckAggColCoexistCxt
*
pCxt
=
(
CheckAggColCoexistCxt
*
)
pContext
;
if
(
QUERY_NODE_FUNCTION
==
nodeType
(
pNode
)
&&
fmIsAggFunc
(((
SFunctionNode
*
)
pNode
)
->
funcId
))
{
pCxt
->
selectFuncNum
+=
isSelectFunc
(
pNode
)
?
1
:
0
;
if
(
isAggFunc
(
pNode
))
{
pCxt
->
existAggFunc
=
true
;
return
DEAL_RES_IGNORE_CHILD
;
}
...
...
@@ -781,7 +891,9 @@ static int32_t checkAggColCoexist(STranslateContext* pCxt, SSelectStmt* pSelect)
if
(
!
pSelect
->
isDistinct
)
{
nodesWalkExprs
(
pSelect
->
pOrderByList
,
doCheckAggColCoexist
,
&
cxt
);
}
if
((
cxt
.
existAggFunc
||
NULL
!=
pSelect
->
pWindow
)
&&
cxt
.
existCol
)
{
if
(
1
==
cxt
.
selectFuncNum
)
{
return
rewriteColsToSelectValFunc
(
pCxt
,
pSelect
);
}
else
if
((
cxt
.
selectFuncNum
>
1
||
cxt
.
existAggFunc
||
NULL
!=
pSelect
->
pWindow
)
&&
cxt
.
existCol
)
{
return
generateSyntaxErrMsg
(
&
pCxt
->
msgBuf
,
TSDB_CODE_PAR_NOT_SINGLE_GROUP
);
}
return
TSDB_CODE_SUCCESS
;
...
...
@@ -990,19 +1102,6 @@ static SNode* createMultiResFunc(SFunctionNode* pSrcFunc, SExprNode* pExpr) {
return
(
SNode
*
)
pFunc
;
}
static
int32_t
findTable
(
STranslateContext
*
pCxt
,
const
char
*
pTableAlias
,
STableNode
**
pOutput
)
{
SArray
*
pTables
=
taosArrayGetP
(
pCxt
->
pNsLevel
,
pCxt
->
currLevel
);
size_t
nums
=
taosArrayGetSize
(
pTables
);
for
(
size_t
i
=
0
;
i
<
nums
;
++
i
)
{
STableNode
*
pTable
=
taosArrayGetP
(
pTables
,
i
);
if
(
NULL
==
pTableAlias
||
0
==
strcmp
(
pTable
->
tableAlias
,
pTableAlias
))
{
*
pOutput
=
pTable
;
return
TSDB_CODE_SUCCESS
;
}
}
return
generateSyntaxErrMsg
(
&
pCxt
->
msgBuf
,
TSDB_CODE_PAR_TABLE_NOT_EXIST
,
pTableAlias
);
}
static
int32_t
createTableAllCols
(
STranslateContext
*
pCxt
,
SColumnNode
*
pCol
,
SNodeList
**
pOutput
)
{
STableNode
*
pTable
=
NULL
;
int32_t
code
=
findTable
(
pCxt
,
pCol
->
tableAlias
,
&
pTable
);
...
...
@@ -1228,7 +1327,7 @@ static int32_t translateHaving(STranslateContext* pCxt, SSelectStmt* pSelect) {
pCxt
->
currClause
=
SQL_CLAUSE_HAVING
;
int32_t
code
=
translateExpr
(
pCxt
,
pSelect
->
pHaving
);
if
(
TSDB_CODE_SUCCESS
==
code
)
{
code
=
checkExprForGroupBy
(
pCxt
,
pSelect
->
pHaving
);
code
=
checkExprForGroupBy
(
pCxt
,
&
pSelect
->
pHaving
);
}
return
code
;
}
...
...
@@ -1511,25 +1610,6 @@ static int32_t checkLimit(STranslateContext* pCxt, SSelectStmt* pSelect) {
return
TSDB_CODE_SUCCESS
;
}
static
bool
isCountStar
(
SFunctionNode
*
pFunc
)
{
if
(
1
!=
LIST_LENGTH
(
pFunc
->
pParameterList
))
{
return
false
;
}
SNode
*
pPara
=
nodesListGetNode
(
pFunc
->
pParameterList
,
0
);
return
(
QUERY_NODE_COLUMN
==
nodeType
(
pPara
)
&&
0
==
strcmp
(((
SColumnNode
*
)
pPara
)
->
colName
,
"*"
));
}
// count(*) is rewritten as count(ts) for scannning optimization
static
int32_t
rewriteCountStar
(
STranslateContext
*
pCxt
,
SFunctionNode
*
pCount
)
{
SColumnNode
*
pCol
=
nodesListGetNode
(
pCount
->
pParameterList
,
0
);
STableNode
*
pTable
=
NULL
;
int32_t
code
=
findTable
(
pCxt
,
(
'\0'
==
pCol
->
tableAlias
[
0
]
?
NULL
:
pCol
->
tableAlias
),
&
pTable
);
if
(
TSDB_CODE_SUCCESS
==
code
&&
QUERY_NODE_REAL_TABLE
==
nodeType
(
pTable
))
{
setColumnInfoBySchema
((
SRealTableNode
*
)
pTable
,
((
SRealTableNode
*
)
pTable
)
->
pMeta
->
schema
,
false
,
pCol
);
}
return
code
;
}
static
int32_t
createPrimaryKeyColByTable
(
STranslateContext
*
pCxt
,
STableNode
*
pTable
,
SNode
**
pPrimaryKey
)
{
SColumnNode
*
pCol
=
nodesMakeNode
(
QUERY_NODE_COLUMN
);
if
(
NULL
==
pCol
)
{
...
...
@@ -1553,33 +1633,22 @@ static int32_t createPrimaryKeyCol(STranslateContext* pCxt, SNode** pPrimaryKey)
return
code
;
}
static
int32_t
rewriteTimelineFunc
(
STranslateContext
*
pCxt
,
SFunctionNode
*
pFunc
)
{
SNode
*
pPrimaryKey
=
NULL
;
int32_t
code
=
createPrimaryKeyCol
(
pCxt
,
&
pPrimaryKey
);
if
(
TSDB_CODE_SUCCESS
==
code
)
{
code
=
nodesListMakeStrictAppend
(
&
pFunc
->
pParameterList
,
pPrimaryKey
);
}
return
code
;
}
EDealRes
rewriteFuncForSelectImpl
(
SNode
*
pNode
,
void
*
pContext
)
{
if
(
QUERY_NODE_FUNCTION
==
nodeType
(
pNode
))
{
STranslateContext
*
pCxt
=
pContext
;
SFunctionNode
*
pFunc
=
(
SFunctionNode
*
)
pNode
;
if
(
isCountStar
(
pFunc
))
{
pCxt
->
errCode
=
rewriteCountStar
(
pCxt
,
pFunc
);
}
else
if
(
fmIsTimelineFunc
(
pFunc
->
funcId
))
{
pCxt
->
errCode
=
rewriteTimelineFunc
(
pCxt
,
pFunc
);
}
if
(
TSDB_CODE_SUCCESS
!=
pCxt
->
errCode
)
{
return
DEAL_RES_ERROR
;
static
EDealRes
rewriteTimelineFuncImpl
(
SNode
*
pNode
,
void
*
pContext
)
{
STranslateContext
*
pCxt
=
pContext
;
if
(
isTimelineFunc
(
pNode
))
{
SFunctionNode
*
pFunc
=
(
SFunctionNode
*
)
pNode
;
SNode
*
pPrimaryKey
=
NULL
;
pCxt
->
errCode
=
createPrimaryKeyCol
(
pCxt
,
&
pPrimaryKey
);
if
(
TSDB_CODE_SUCCESS
==
pCxt
->
errCode
)
{
pCxt
->
errCode
=
nodesListMakeStrictAppend
(
&
pFunc
->
pParameterList
,
pPrimaryKey
);
}
return
TSDB_CODE_SUCCESS
==
pCxt
->
errCode
?
DEAL_RES_IGNORE_CHILD
:
DEAL_RES_ERROR
;
}
return
DEAL_RES_CONTINUE
;
}
static
int32_t
rewrite
FuncForSelect
(
STranslateContext
*
pCxt
,
SSelectStmt
*
pSelect
)
{
nodesWalkSelectStmt
(
pSelect
,
SQL_CLAUSE_FROM
,
rewrite
FuncForSelect
Impl
,
pCxt
);
static
int32_t
rewrite
TimelineFunc
(
STranslateContext
*
pCxt
,
SSelectStmt
*
pSelect
)
{
nodesWalkSelectStmt
(
pSelect
,
SQL_CLAUSE_FROM
,
rewrite
TimelineFunc
Impl
,
pCxt
);
return
pCxt
->
errCode
;
}
...
...
@@ -1614,7 +1683,7 @@ static int32_t translateSelect(STranslateContext* pCxt, SSelectStmt* pSelect) {
code
=
checkLimit
(
pCxt
,
pSelect
);
}
if
(
TSDB_CODE_SUCCESS
==
code
)
{
code
=
rewrite
FuncForSelect
(
pCxt
,
pSelect
);
code
=
rewrite
TimelineFunc
(
pCxt
,
pSelect
);
}
return
code
;
}
...
...
source/libs/parser/test/mockCatalogService.cpp
浏览文件 @
b1aa263c
...
...
@@ -103,7 +103,6 @@ class MockCatalogServiceImpl {
const
char
*
tname
=
tNameGetTableName
(
pTableName
);
int32_t
code
=
copyTableSchemaMeta
(
db
,
tname
,
&
table
);
if
(
TSDB_CODE_SUCCESS
!=
code
)
{
std
::
cout
<<
"db : "
<<
db
<<
", table :"
<<
tname
<<
std
::
endl
;
return
code
;
}
*
pTableMeta
=
table
.
release
();
...
...
source/libs/parser/test/parSelectTest.cpp
浏览文件 @
b1aa263c
...
...
@@ -67,49 +67,72 @@ TEST_F(ParserSelectTest, condition) {
TEST_F
(
ParserSelectTest
,
pseudoColumn
)
{
useDb
(
"root"
,
"test"
);
run
(
"SELECT _
wstartts, _wendts
, COUNT(*) FROM t1 INTERVAL(10s)"
);
run
(
"SELECT _
WSTARTTS, _WENDTS
, COUNT(*) FROM t1 INTERVAL(10s)"
);
}
TEST_F
(
ParserSelectTest
,
multiResFunc
)
{
useDb
(
"root"
,
"test"
);
run
(
"SELECT
last(*), first(*), last_row
(*) FROM t1"
);
run
(
"SELECT
LAST(*), FIRST(*), LAST_ROW
(*) FROM t1"
);
run
(
"SELECT
last(c1, c2), first(t1.*), last_row
(c3) FROM t1"
);
run
(
"SELECT
LAST(c1, c2), FIRST(t1.*), LAST_ROW
(c3) FROM t1"
);
run
(
"SELECT
last(t2.*), first(t1.c1, t2.*), last_row
(t1.*, t2.*) FROM st1s1 t1, st1s2 t2 WHERE t1.ts = t2.ts"
);
run
(
"SELECT
LAST(t2.*), FIRST(t1.c1, t2.*), LAST_ROW
(t1.*, t2.*) FROM st1s1 t1, st1s2 t2 WHERE t1.ts = t2.ts"
);
}
TEST_F
(
ParserSelectTest
,
timelineFunc
)
{
useDb
(
"root"
,
"test"
);
run
(
"SELECT
last(*), first
(*) FROM t1"
);
run
(
"SELECT
LAST(*), FIRST
(*) FROM t1"
);
run
(
"SELECT
last(*), first(*) FROM t1 group by c
1"
);
run
(
"SELECT
FIRST(ts), FIRST(c1), FIRST(c2), FIRST(c3) FROM t
1"
);
run
(
"SELECT last(*), first(*) FROM t1 INTERVAL(10s)"
);
run
(
"SELECT LAST(*), FIRST(*) FROM t1 GROUP BY c1"
);
run
(
"SELECT LAST(*), FIRST(*) FROM t1 INTERVAL(10s)"
);
run
(
"SELECT diff(c1) FROM t1"
);
}
TEST_F
(
ParserSelectTest
,
selectFunc
)
{
useDb
(
"root"
,
"test"
);
// select function
run
(
"SELECT MAX(c1), MIN(c1) FROM t1"
);
// select function for GROUP BY clause
run
(
"SELECT MAX(c1), MIN(c1) FROM t1 GROUP BY c1"
);
// select function for INTERVAL clause
run
(
"SELECT MAX(c1), MIN(c1) FROM t1 INTERVAL(10s)"
);
// select function along with the columns of select row
run
(
"SELECT MAX(c1), c2 FROM t1"
);
run
(
"SELECT MAX(c1), t1.* FROM t1"
);
// select function along with the columns of select row, and with GROUP BY clause
run
(
"SELECT MAX(c1), c2 FROM t1 GROUP BY c3"
);
run
(
"SELECT MAX(c1), t1.* FROM t1 GROUP BY c3"
);
// select function along with the columns of select row, and with window clause
run
(
"SELECT MAX(c1), c2 FROM t1 INTERVAL(10s)"
);
run
(
"SELECT MAX(c1), c2 FROM t1 SESSION(ts, 10s)"
);
run
(
"SELECT MAX(c1), c2 FROM t1 STATE_WINDOW(c3)"
);
}
TEST_F
(
ParserSelectTest
,
clause
)
{
useDb
(
"root"
,
"test"
);
//
group by
clause
//
GROUP BY
clause
run
(
"SELECT COUNT(*) cnt FROM t1 WHERE c1 > 0"
);
run
(
"SELECT COUNT(*), c2 cnt FROM t1 WHERE c1 > 0
group by
c2"
);
run
(
"SELECT COUNT(*), c2 cnt FROM t1 WHERE c1 > 0
GROUP BY
c2"
);
run
(
"SELECT COUNT(*) cnt FROM t1 WHERE c1 > 0
group by
c2 having COUNT(c1) > 10"
);
run
(
"SELECT COUNT(*) cnt FROM t1 WHERE c1 > 0
GROUP BY
c2 having COUNT(c1) > 10"
);
run
(
"SELECT COUNT(*), c1, c2 + 10, c1 + c2 cnt FROM t1 WHERE c1 > 0
group by
c2, c1"
);
run
(
"SELECT COUNT(*), c1, c2 + 10, c1 + c2 cnt FROM t1 WHERE c1 > 0
GROUP BY
c2, c1"
);
run
(
"SELECT COUNT(*), c1 + 10, c2 cnt FROM t1 WHERE c1 > 0
group by
c1 + 10, c2"
);
run
(
"SELECT COUNT(*), c1 + 10, c2 cnt FROM t1 WHERE c1 > 0
GROUP BY
c1 + 10, c2"
);
// order by clause
run
(
"SELECT COUNT(*) cnt FROM t1 WHERE c1 > 0
group by
c2 order by cnt"
);
run
(
"SELECT COUNT(*) cnt FROM t1 WHERE c1 > 0
GROUP BY
c2 order by cnt"
);
run
(
"SELECT COUNT(*) cnt FROM t1 WHERE c1 > 0
group by
c2 order by 1"
);
run
(
"SELECT COUNT(*) cnt FROM t1 WHERE c1 > 0
GROUP BY
c2 order by 1"
);
// distinct clause
// run("SELECT distinct c1, c2 FROM t1 WHERE c1 > 0 order by c1");
...
...
@@ -118,7 +141,7 @@ TEST_F(ParserSelectTest, clause) {
// run("SELECT distinct c1 + 10 cc1, c2 cc2 FROM t1 WHERE c1 > 0 order by cc1, c2");
// run("SELECT distinct COUNT(c2) FROM t1 WHERE c1 > 0
group by
c1 order by COUNT(c2)");
// run("SELECT distinct COUNT(c2) FROM t1 WHERE c1 > 0
GROUP BY
c1 order by COUNT(c2)");
}
// INTERVAL(interval_val [, interval_offset]) [SLIDING (sliding_val)] [FILL(fill_mod_and_val)]
...
...
@@ -137,6 +160,14 @@ TEST_F(ParserSelectTest, interval) {
"INTERVAL(10s) FILL(NONE)"
);
}
TEST_F
(
ParserSelectTest
,
intervalSemanticCheck
)
{
useDb
(
"root"
,
"test"
);
run
(
"SELECT c1 FROM t1 INTERVAL(10s)"
,
TSDB_CODE_PAR_NOT_SINGLE_GROUP
,
PARSER_STAGE_TRANSLATE
);
run
(
"SELECT DISTINCT c1, c2 FROM t1 WHERE c1 > 3 INTERVAL(1d) FILL(NEXT)"
,
TSDB_CODE_PAR_INVALID_FILL_TIME_RANGE
,
PARSER_STAGE_TRANSLATE
);
}
TEST_F
(
ParserSelectTest
,
semanticError
)
{
useDb
(
"root"
,
"test"
);
...
...
@@ -164,7 +195,7 @@ TEST_F(ParserSelectTest, semanticError) {
run
(
"SELECT c2 FROM t1 WHERE COUNT(*) > 0"
,
TSDB_CODE_PAR_ILLEGAL_USE_AGG_FUNCTION
,
PARSER_STAGE_TRANSLATE
);
run
(
"SELECT c2 FROM t1
group by
COUNT(*)"
,
TSDB_CODE_PAR_ILLEGAL_USE_AGG_FUNCTION
,
PARSER_STAGE_TRANSLATE
);
run
(
"SELECT c2 FROM t1
GROUP BY
COUNT(*)"
,
TSDB_CODE_PAR_ILLEGAL_USE_AGG_FUNCTION
,
PARSER_STAGE_TRANSLATE
);
// TSDB_CODE_PAR_WRONG_NUMBER_OF_SELECT
run
(
"SELECT c2 FROM t1 order by 0"
,
TSDB_CODE_PAR_WRONG_NUMBER_OF_SELECT
,
PARSER_STAGE_TRANSLATE
);
...
...
@@ -174,13 +205,13 @@ TEST_F(ParserSelectTest, semanticError) {
// TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION
run
(
"SELECT COUNT(*) cnt FROM t1 having c1 > 0"
,
TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION
,
PARSER_STAGE_TRANSLATE
);
run
(
"SELECT COUNT(*) cnt FROM t1
group by
c2 having c1 > 0"
,
TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION
,
run
(
"SELECT COUNT(*) cnt FROM t1
GROUP BY
c2 having c1 > 0"
,
TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION
,
PARSER_STAGE_TRANSLATE
);
run
(
"SELECT COUNT(*), c1 cnt FROM t1
group by
c2 having c2 > 0"
,
TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION
,
run
(
"SELECT COUNT(*), c1 cnt FROM t1
GROUP BY
c2 having c2 > 0"
,
TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION
,
PARSER_STAGE_TRANSLATE
);
run
(
"SELECT COUNT(*) cnt FROM t1
group by
c2 having c2 > 0 order by c1"
,
TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION
,
run
(
"SELECT COUNT(*) cnt FROM t1
GROUP BY
c2 having c2 > 0 order by c1"
,
TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION
,
PARSER_STAGE_TRANSLATE
);
// TSDB_CODE_PAR_NOT_SINGLE_GROUP
...
...
source/libs/planner/test/planGroupByTest.cpp
浏览文件 @
b1aa263c
...
...
@@ -23,30 +23,45 @@ class PlanGroupByTest : public PlannerTestBase {};
TEST_F
(
PlanGroupByTest
,
basic
)
{
useDb
(
"root"
,
"test"
);
run
(
"
select count(*) from
t1"
);
run
(
"
SELECT COUNT(*) FROM
t1"
);
run
(
"
select c1, max(c3), min(c3), count(*) from t1 group by
c1"
);
run
(
"
SELECT c1, MAX(c3), MIN(c3), COUNT(*) FROM t1 GROUP BY
c1"
);
run
(
"
select c1 + c3, c1 + count(*) from t1 where c2 = 'abc' group by
c1, c3"
);
run
(
"
SELECT c1 + c3, c1 + COUNT(*) FROM t1 WHERE c2 = 'abc' GROUP BY
c1, c3"
);
run
(
"
select c1 + c3, sum(c4 * c5) from t1 where concat(c2, 'wwww') = 'abcwww' group by
c1 + c3"
);
run
(
"
SELECT c1 + c3, SUM(c4 * c5) FROM t1 WHERE CONCAT(c2, 'wwww') = 'abcwww' GROUP BY
c1 + c3"
);
run
(
"
select sum(ceil(c1)) from t1 group by ceil
(c1)"
);
run
(
"
SELECT SUM(CEIL(c1)) FROM t1 GROUP BY CEIL
(c1)"
);
}
TEST_F
(
PlanGroupByTest
,
withOrderBy
)
{
useDb
(
"root"
,
"test"
);
//
order by
aggfunc
run
(
"
select count(*), sum(c1) from t1 order by sum
(c1)"
);
//
order by
alias of aggfunc
// run("
select count(*), sum(c1) a from t1 order by
a");
//
ORDER BY
aggfunc
run
(
"
SELECT COUNT(*), SUM(c1) FROM t1 ORDER BY SUM
(c1)"
);
//
ORDER BY
alias of aggfunc
// run("
SELECT COUNT(*), SUM(c1) a FROM t1 ORDER BY
a");
}
TEST_F
(
PlanGroupByTest
,
aggFunc
)
{
useDb
(
"root"
,
"test"
);
run
(
"
select last(*), first(*) from
t1"
);
run
(
"
SELECT LAST(*), FIRST(*) FROM
t1"
);
run
(
"select last(*), first(*) from t1 group by c1"
);
run
(
"SELECT LAST(*), FIRST(*) FROM t1 GROUP BY c1"
);
}
TEST_F
(
PlanGroupByTest
,
selectFunc
)
{
useDb
(
"root"
,
"test"
);
// select function
run
(
"SELECT MAX(c1), MIN(c1) FROM t1"
);
// select function for GROUP BY clause
run
(
"SELECT MAX(c1), MIN(c1) FROM t1 GROUP BY c1"
);
// select function along with the columns of select row
run
(
"SELECT MAX(c1), c2 FROM t1"
);
run
(
"SELECT MAX(c1), t1.* FROM t1"
);
// select function along with the columns of select row, and with GROUP BY clause
run
(
"SELECT MAX(c1), c2 FROM t1 GROUP BY c3"
);
run
(
"SELECT MAX(c1), t1.* FROM t1 GROUP BY c3"
);
}
source/libs/planner/test/planIntervalTest.cpp
浏览文件 @
b1aa263c
...
...
@@ -42,3 +42,12 @@ TEST_F(PlanIntervalTest, fill) {
"WHERE ts > TIMESTAMP '2022-04-01 00:00:00' and ts < TIMESTAMP '2022-04-30 23:59:59' "
"INTERVAL(10s) FILL(VALUE, 10, 20)"
);
}
TEST_F
(
PlanIntervalTest
,
selectFunc
)
{
useDb
(
"root"
,
"test"
);
// select function for INTERVAL clause
run
(
"SELECT MAX(c1), MIN(c1) FROM t1 INTERVAL(10s)"
);
// select function along with the columns of select row, and with INTERVAL clause
run
(
"SELECT MAX(c1), c2 FROM t1 INTERVAL(10s)"
);
}
\ No newline at end of file
source/libs/planner/test/planSessionTest.cpp
浏览文件 @
b1aa263c
...
...
@@ -25,3 +25,12 @@ TEST_F(PlanSessionTest, basic) {
run
(
"select count(*) from t1 session(ts, 10s)"
);
}
TEST_F
(
PlanSessionTest
,
selectFunc
)
{
useDb
(
"root"
,
"test"
);
// select function for SESSION clause
run
(
"SELECT MAX(c1), MIN(c1) FROM t1 SESSION(ts, 10s)"
);
// select function along with the columns of select row, and with SESSION clause
run
(
"SELECT MAX(c1), c2 FROM t1 SESSION(ts, 10s)"
);
}
source/libs/planner/test/planStateTest.cpp
浏览文件 @
b1aa263c
...
...
@@ -31,3 +31,12 @@ TEST_F(PlanStateTest, stateExpr) {
run
(
"select count(*) from t1 state_window(c1 + 10)"
);
}
TEST_F
(
PlanStateTest
,
selectFunc
)
{
useDb
(
"root"
,
"test"
);
// select function for STATE_WINDOW clause
run
(
"SELECT MAX(c1), MIN(c1) FROM t1 STATE_WINDOW(c3)"
);
// select function along with the columns of select row, and with STATE_WINDOW clause
run
(
"SELECT MAX(c1), c2 FROM t1 STATE_WINDOW(c3)"
);
}
tests/system-test/2-query/distinct.py
浏览文件 @
b1aa263c
...
...
@@ -101,7 +101,7 @@ class TDTestCase:
# tdSql.error("select distinct c1, ts from stb1 group by c2")
tdSql
.
error
(
"select distinct c1, ts from t1 group by c2"
)
# tdSql.error("select distinct c1, max(c2) from stb1 ")
tdSql
.
error
(
"select distinct c1, max(c2) from t1 "
)
#
tdSql.error("select distinct c1, max(c2) from t1 ")
# tdSql.error("select max(c2), distinct c1 from stb1 ")
tdSql
.
error
(
"select max(c2), distinct c1 from t1 "
)
# tdSql.error("select distinct c1, c2 from stb1 where c1 > 3 group by t0")
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录