Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
taosdata
TDengine
提交
c3881e1a
T
TDengine
项目概览
taosdata
/
TDengine
1 年多 前同步成功
通知
1185
Star
22016
Fork
4786
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
1
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
T
TDengine
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
1
Issue
1
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
c3881e1a
编写于
10月 13, 2021
作者:
H
Haojun Liao
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
[td-10564] refactor query statement parse procedure.
上级
0fcbd2f5
变更
1
显示空白变更内容
内联
并排
Showing
1 changed file
with
349 addition
and
1 deletion
+349
-1
source/libs/parser/src/astValidate.c
source/libs/parser/src/astValidate.c
+349
-1
未找到文件。
source/libs/parser/src/astValidate.c
浏览文件 @
c3881e1a
...
...
@@ -76,6 +76,336 @@ static int32_t evaluateImpl(tSqlExpr* pExpr, int32_t tsPrecision) {
return
TSDB_CODE_SUCCESS
;
}
int32_t
validateSqlNode
(
SSqlNode
*
pSqlNode
,
SQueryStmtInfo
*
pQueryInfo
,
char
*
msg
,
int32_t
msgBufLen
)
{
assert
(
pSqlNode
!=
NULL
&&
(
pSqlNode
->
from
==
NULL
||
taosArrayGetSize
(
pSqlNode
->
from
->
list
)
>
0
));
const
char
*
msg1
=
"point interpolation query needs timestamp"
;
const
char
*
msg2
=
"too many tables in from clause"
;
const
char
*
msg3
=
"start(end) time of query range required or time range too large"
;
const
char
*
msg4
=
"interval query not supported, since the result of sub query not include valid timestamp column"
;
const
char
*
msg5
=
"only tag query not compatible with normal column filter"
;
const
char
*
msg6
=
"not support stddev/percentile/interp in the outer query yet"
;
const
char
*
msg7
=
"derivative/twa/irate requires timestamp column exists in subquery"
;
const
char
*
msg8
=
"condition missing for join query"
;
const
char
*
msg9
=
"not support 3 level select"
;
int32_t
code
=
TSDB_CODE_SUCCESS
;
STableMetaInfo
*
pTableMetaInfo
=
tscGetMetaInfo
(
pQueryInfo
,
0
);
if
(
pTableMetaInfo
==
NULL
)
{
pTableMetaInfo
=
tscAddEmptyMetaInfo
(
pQueryInfo
);
}
/*
* handle the sql expression without from subclause
* select server_status();
* select server_version();
* select client_version();
* select database();
*/
if
(
pSqlNode
->
from
==
NULL
)
{
assert
(
pSqlNode
->
fillType
==
NULL
&&
pSqlNode
->
pGroupby
==
NULL
&&
pSqlNode
->
pWhere
==
NULL
&&
pSqlNode
->
pSortOrder
==
NULL
);
return
doLocalQueryProcess
(
pCmd
,
pQueryInfo
,
pSqlNode
);
}
if
(
pSqlNode
->
from
->
type
==
SQL_NODE_FROM_SUBQUERY
)
{
clearAllTableMetaInfo
(
pQueryInfo
,
false
,
pSql
->
self
);
pQueryInfo
->
numOfTables
=
0
;
// parse the subquery in the first place
int32_t
numOfSub
=
(
int32_t
)
taosArrayGetSize
(
pSqlNode
->
from
->
list
);
for
(
int32_t
i
=
0
;
i
<
numOfSub
;
++
i
)
{
// check if there is 3 level select
SRelElementPair
*
subInfo
=
taosArrayGet
(
pSqlNode
->
from
->
list
,
i
);
SSqlNode
*
p
=
taosArrayGetP
(
subInfo
->
pSubquery
,
0
);
if
(
p
->
from
->
type
==
SQL_NODE_FROM_SUBQUERY
)
{
return
parserSetInvalidOperatorMsg
(
msg
,
msgBufLen
,
msg9
);
}
code
=
doValidateSubquery
(
pSqlNode
,
i
,
pSql
,
pQueryInfo
,
tscGetErrorMsgPayload
(
pCmd
));
if
(
code
!=
TSDB_CODE_SUCCESS
)
{
return
code
;
}
}
int32_t
timeWindowQuery
=
(
TPARSER_HAS_TOKEN
(
pSqlNode
->
interval
.
interval
)
||
TPARSER_HAS_TOKEN
(
pSqlNode
->
sessionVal
.
gap
));
TSDB_QUERY_SET_TYPE
(
pQueryInfo
->
type
,
TSDB_QUERY_TYPE_TABLE_QUERY
);
// parse the group by clause in the first place
if
(
validateGroupbyNode
(
pQueryInfo
,
pSqlNode
->
pGroupby
,
pCmd
)
!=
TSDB_CODE_SUCCESS
)
{
return
TSDB_CODE_TSC_INVALID_OPERATION
;
}
if
(
validateSelectNodeList
(
pCmd
,
pQueryInfo
,
pSqlNode
->
pSelNodeList
,
false
,
timeWindowQuery
,
true
)
!=
TSDB_CODE_SUCCESS
)
{
return
TSDB_CODE_TSC_INVALID_OPERATION
;
}
// todo NOT support yet
for
(
int32_t
i
=
0
;
i
<
tscNumOfExprs
(
pQueryInfo
);
++
i
)
{
SExprInfo
*
pExpr
=
tscExprGet
(
pQueryInfo
,
i
);
int32_t
f
=
pExpr
->
base
.
functionId
;
if
(
f
==
TSDB_FUNC_STDDEV
||
f
==
TSDB_FUNC_PERCT
||
f
==
TSDB_FUNC_INTERP
)
{
return
parserSetInvalidOperatorMsg
(
msg
,
msgBufLen
,
msg6
);
}
if
((
timeWindowQuery
||
pQueryInfo
->
stateWindow
)
&&
f
==
TSDB_FUNC_LAST
)
{
pExpr
->
base
.
numOfParams
=
1
;
pExpr
->
base
.
param
[
0
].
i64
=
TSDB_ORDER_ASC
;
pExpr
->
base
.
param
[
0
].
nType
=
TSDB_DATA_TYPE_INT
;
}
}
STableMeta
*
pTableMeta
=
tscGetMetaInfo
(
pQueryInfo
,
0
)
->
pTableMeta
;
SSchema
*
pSchema
=
tscGetTableColumnSchema
(
pTableMeta
,
0
);
if
(
pSchema
->
type
!=
TSDB_DATA_TYPE_TIMESTAMP
)
{
int32_t
numOfExprs
=
(
int32_t
)
tscNumOfExprs
(
pQueryInfo
);
for
(
int32_t
i
=
0
;
i
<
numOfExprs
;
++
i
)
{
SExprInfo
*
pExpr
=
tscExprGet
(
pQueryInfo
,
i
);
int32_t
f
=
pExpr
->
base
.
functionId
;
if
(
f
==
TSDB_FUNC_DERIVATIVE
||
f
==
TSDB_FUNC_TWA
||
f
==
TSDB_FUNC_IRATE
)
{
return
parserSetInvalidOperatorMsg
(
msg
,
msgBufLen
,
msg7
);
}
}
}
// validate the query filter condition info
if
(
pSqlNode
->
pWhere
!=
NULL
)
{
if
(
validateWhereNode
(
pQueryInfo
,
&
pSqlNode
->
pWhere
,
pSql
)
!=
TSDB_CODE_SUCCESS
)
{
return
TSDB_CODE_TSC_INVALID_OPERATION
;
}
}
else
{
if
(
pQueryInfo
->
numOfTables
>
1
)
{
return
parserSetInvalidOperatorMsg
(
msg
,
msgBufLen
,
msg8
);
}
}
// validate the interval info
if
(
validateIntervalNode
(
pSql
,
pQueryInfo
,
pSqlNode
)
!=
TSDB_CODE_SUCCESS
)
{
return
TSDB_CODE_TSC_INVALID_OPERATION
;
}
else
{
if
(
validateSessionNode
(
pCmd
,
pQueryInfo
,
pSqlNode
)
!=
TSDB_CODE_SUCCESS
)
{
return
TSDB_CODE_TSC_INVALID_OPERATION
;
}
// parse the window_state
if
(
validateStateWindowNode
(
pCmd
,
pQueryInfo
,
pSqlNode
,
false
)
!=
TSDB_CODE_SUCCESS
)
{
return
TSDB_CODE_TSC_INVALID_OPERATION
;
}
if
(
isTimeWindowQuery
(
pQueryInfo
))
{
// check if the first column of the nest query result is timestamp column
SColumn
*
pCol
=
taosArrayGetP
(
pQueryInfo
->
colList
,
0
);
if
(
pCol
->
info
.
type
!=
TSDB_DATA_TYPE_TIMESTAMP
)
{
return
parserSetInvalidOperatorMsg
(
msg
,
msgBufLen
,
msg4
);
}
if
(
validateFunctionsInIntervalOrGroupbyQuery
(
pCmd
,
pQueryInfo
)
!=
TSDB_CODE_SUCCESS
)
{
return
TSDB_CODE_TSC_INVALID_OPERATION
;
}
}
}
// disable group result mixed up if interval/session window query exists.
if
(
isTimeWindowQuery
(
pQueryInfo
))
{
size_t
num
=
taosArrayGetSize
(
pQueryInfo
->
pUpstream
);
for
(
int32_t
i
=
0
;
i
<
num
;
++
i
)
{
SQueryInfo
*
pUp
=
taosArrayGetP
(
pQueryInfo
->
pUpstream
,
i
);
pUp
->
multigroupResult
=
false
;
}
}
// parse the having clause in the first place
int32_t
joinQuery
=
(
pSqlNode
->
from
!=
NULL
&&
taosArrayGetSize
(
pSqlNode
->
from
->
list
)
>
1
);
if
(
validateHavingClause
(
pQueryInfo
,
pSqlNode
->
pHaving
,
pCmd
,
pSqlNode
->
pSelNodeList
,
joinQuery
,
timeWindowQuery
)
!=
TSDB_CODE_SUCCESS
)
{
return
TSDB_CODE_TSC_INVALID_OPERATION
;
}
if
((
code
=
validateLimitNode
(
pCmd
,
pQueryInfo
,
pSqlNode
,
pSql
))
!=
TSDB_CODE_SUCCESS
)
{
return
code
;
}
// set order by info
if
(
validateOrderbyNode
(
pCmd
,
pQueryInfo
,
pSqlNode
,
tscGetTableSchema
(
pTableMeta
))
!=
TSDB_CODE_SUCCESS
)
{
return
TSDB_CODE_TSC_INVALID_OPERATION
;
}
if
((
code
=
doFunctionsCompatibleCheck
(
pCmd
,
pQueryInfo
,
tscGetErrorMsgPayload
(
pCmd
)))
!=
TSDB_CODE_SUCCESS
)
{
return
code
;
}
// updateFunctionInterBuf(pQueryInfo, false);
updateLastScanOrderIfNeeded
(
pQueryInfo
);
if
((
code
=
validateFillNode
(
pCmd
,
pQueryInfo
,
pSqlNode
))
!=
TSDB_CODE_SUCCESS
)
{
return
code
;
}
}
else
{
pQueryInfo
->
command
=
TSDB_SQL_SELECT
;
size_t
numOfTables
=
taosArrayGetSize
(
pSqlNode
->
from
->
list
);
if
(
numOfTables
>
TSDB_MAX_JOIN_TABLE_NUM
)
{
return
parserSetInvalidOperatorMsg
(
msg
,
msgBufLen
,
msg2
);
}
// set all query tables, which are maybe more than one.
code
=
doLoadAllTableMeta
(
pSql
,
pQueryInfo
,
pSqlNode
,
(
int32_t
)
numOfTables
);
if
(
code
!=
TSDB_CODE_SUCCESS
)
{
return
code
;
}
bool
isSTable
=
UTIL_TABLE_IS_SUPER_TABLE
(
pTableMetaInfo
);
int32_t
type
=
isSTable
?
TSDB_QUERY_TYPE_STABLE_QUERY
:
TSDB_QUERY_TYPE_TABLE_QUERY
;
TSDB_QUERY_SET_TYPE
(
pQueryInfo
->
type
,
type
);
// parse the group by clause in the first place
if
(
validateGroupbyNode
(
pQueryInfo
,
pSqlNode
->
pGroupby
,
pCmd
)
!=
TSDB_CODE_SUCCESS
)
{
return
TSDB_CODE_TSC_INVALID_OPERATION
;
}
pQueryInfo
->
onlyHasTagCond
=
true
;
// set where info
if
(
pSqlNode
->
pWhere
!=
NULL
)
{
if
(
validateWhereNode
(
pQueryInfo
,
&
pSqlNode
->
pWhere
,
pSql
)
!=
TSDB_CODE_SUCCESS
)
{
return
TSDB_CODE_TSC_INVALID_OPERATION
;
}
pSqlNode
->
pWhere
=
NULL
;
}
else
{
if
(
taosArrayGetSize
(
pSqlNode
->
from
->
list
)
>
1
)
{
// Cross join not allowed yet
return
parserSetInvalidOperatorMsg
(
msg
,
msgBufLen
,
"cross join not supported yet"
);
}
}
int32_t
joinQuery
=
(
pSqlNode
->
from
!=
NULL
&&
taosArrayGetSize
(
pSqlNode
->
from
->
list
)
>
1
);
int32_t
timeWindowQuery
=
(
TPARSER_HAS_TOKEN
(
pSqlNode
->
interval
.
interval
)
||
TPARSER_HAS_TOKEN
(
pSqlNode
->
sessionVal
.
gap
));
if
(
validateSelectNodeList
(
pCmd
,
pQueryInfo
,
pSqlNode
->
pSelNodeList
,
joinQuery
,
timeWindowQuery
,
false
)
!=
TSDB_CODE_SUCCESS
)
{
return
TSDB_CODE_TSC_INVALID_OPERATION
;
}
if
(
isSTable
&&
tscQueryTags
(
pQueryInfo
)
&&
pQueryInfo
->
distinct
&&
!
pQueryInfo
->
onlyHasTagCond
)
{
return
TSDB_CODE_TSC_INVALID_OPERATION
;
}
// parse the window_state
if
(
validateStateWindowNode
(
pCmd
,
pQueryInfo
,
pSqlNode
,
isSTable
)
!=
TSDB_CODE_SUCCESS
)
{
return
TSDB_CODE_TSC_INVALID_OPERATION
;
}
// set order by info
if
(
validateOrderbyNode
(
pCmd
,
pQueryInfo
,
pSqlNode
,
tscGetTableSchema
(
pTableMetaInfo
->
pTableMeta
))
!=
TSDB_CODE_SUCCESS
)
{
return
TSDB_CODE_TSC_INVALID_OPERATION
;
}
// set interval value
if
(
validateIntervalNode
(
pSql
,
pQueryInfo
,
pSqlNode
)
!=
TSDB_CODE_SUCCESS
)
{
return
TSDB_CODE_TSC_INVALID_OPERATION
;
}
if
(
tscQueryTags
(
pQueryInfo
))
{
SExprInfo
*
pExpr1
=
tscExprGet
(
pQueryInfo
,
0
);
if
(
pExpr1
->
base
.
functionId
!=
TSDB_FUNC_TID_TAG
)
{
if
((
pQueryInfo
->
colCond
&&
taosArrayGetSize
(
pQueryInfo
->
colCond
)
>
0
)
||
IS_TSWINDOW_SPECIFIED
(
pQueryInfo
->
window
))
{
return
parserSetInvalidOperatorMsg
(
msg
,
msgBufLen
,
msg5
);
}
}
}
// parse the having clause in the first place
if
(
validateHavingClause
(
pQueryInfo
,
pSqlNode
->
pHaving
,
pCmd
,
pSqlNode
->
pSelNodeList
,
joinQuery
,
timeWindowQuery
)
!=
TSDB_CODE_SUCCESS
)
{
return
TSDB_CODE_TSC_INVALID_OPERATION
;
}
/*
* transfer sql functions that need secondary merge into another format
* in dealing with super table queries such as: count/first/last
*/
if
(
validateSessionNode
(
pCmd
,
pQueryInfo
,
pSqlNode
)
!=
TSDB_CODE_SUCCESS
)
{
return
TSDB_CODE_TSC_INVALID_OPERATION
;
}
if
(
isTimeWindowQuery
(
pQueryInfo
)
&&
(
validateFunctionsInIntervalOrGroupbyQuery
(
pCmd
,
pQueryInfo
)
!=
TSDB_CODE_SUCCESS
))
{
return
TSDB_CODE_TSC_INVALID_OPERATION
;
}
if
(
isSTable
)
{
tscTansformFuncForSTableQuery
(
pQueryInfo
);
if
(
hasUnsupportFunctionsForSTableQuery
(
pCmd
,
pQueryInfo
))
{
return
TSDB_CODE_TSC_INVALID_OPERATION
;
}
}
// no result due to invalid query time range
if
(
pQueryInfo
->
window
.
skey
>
pQueryInfo
->
window
.
ekey
)
{
pQueryInfo
->
command
=
TSDB_SQL_RETRIEVE_EMPTY_RESULT
;
return
TSDB_CODE_SUCCESS
;
}
if
(
!
hasTimestampForPointInterpQuery
(
pQueryInfo
))
{
return
parserSetInvalidOperatorMsg
(
msg
,
msgBufLen
,
msg1
);
}
// in case of join query, time range is required.
if
(
QUERY_IS_JOIN_QUERY
(
pQueryInfo
->
type
))
{
uint64_t
timeRange
=
(
uint64_t
)
pQueryInfo
->
window
.
ekey
-
pQueryInfo
->
window
.
skey
;
if
(
timeRange
==
0
&&
pQueryInfo
->
window
.
skey
==
0
)
{
return
parserSetInvalidOperatorMsg
(
msg
,
msgBufLen
,
msg3
);
}
}
if
((
code
=
validateLimitNode
(
pCmd
,
pQueryInfo
,
pSqlNode
,
pSql
))
!=
TSDB_CODE_SUCCESS
)
{
return
code
;
}
if
((
code
=
doFunctionsCompatibleCheck
(
pCmd
,
pQueryInfo
,
tscGetErrorMsgPayload
(
pCmd
)))
!=
TSDB_CODE_SUCCESS
)
{
return
code
;
}
updateLastScanOrderIfNeeded
(
pQueryInfo
);
tscFieldInfoUpdateOffset
(
pQueryInfo
);
// updateFunctionInterBuf(pQueryInfo, isSTable);
if
((
code
=
validateFillNode
(
pCmd
,
pQueryInfo
,
pSqlNode
))
!=
TSDB_CODE_SUCCESS
)
{
return
code
;
}
}
{
// set the query info
pQueryInfo
->
projectionQuery
=
tscIsProjectionQuery
(
pQueryInfo
);
pQueryInfo
->
hasFilter
=
tscHasColumnFilter
(
pQueryInfo
);
pQueryInfo
->
simpleAgg
=
isSimpleAggregateRv
(
pQueryInfo
);
pQueryInfo
->
onlyTagQuery
=
onlyTagPrjFunction
(
pQueryInfo
);
pQueryInfo
->
groupbyColumn
=
tscGroupbyColumn
(
pQueryInfo
);
pQueryInfo
->
arithmeticOnAgg
=
tsIsArithmeticQueryOnAggResult
(
pQueryInfo
);
pQueryInfo
->
orderProjectQuery
=
tscOrderedProjectionQueryOnSTable
(
pQueryInfo
,
0
);
SExprInfo
**
p
=
NULL
;
int32_t
numOfExpr
=
0
;
pTableMetaInfo
=
tscGetMetaInfo
(
pQueryInfo
,
0
);
code
=
createProjectionExpr
(
pQueryInfo
,
pTableMetaInfo
,
&
p
,
&
numOfExpr
);
if
(
pQueryInfo
->
exprList1
==
NULL
)
{
pQueryInfo
->
exprList1
=
taosArrayInit
(
4
,
POINTER_BYTES
);
}
taosArrayAddBatch
(
pQueryInfo
->
exprList1
,
(
void
*
)
p
,
numOfExpr
);
tfree
(
p
);
}
return
TSDB_CODE_SUCCESS
;
// Does not build query message here
}
int32_t
evaluateSqlNode
(
SSqlNode
*
pNode
,
int32_t
tsPrecision
,
char
*
msg
,
int32_t
msgBufLen
)
{
assert
(
pNode
!=
NULL
&&
msg
!=
NULL
&&
msgBufLen
>
0
);
if
(
pNode
->
pWhere
==
NULL
)
{
...
...
@@ -534,15 +864,33 @@ int32_t qParserValidateSqlNode(struct SCatalog* pCatalog, SSqlInfo* pInfo, SQuer
#endif
SMetaReq
req
=
{
0
};
SMetaData
data
=
{
0
};
// TODO: check if the qnode info has been cached already
req
.
qNodeEpset
=
true
;
code
=
qParserExtractRequestedMetaInfo
(
pInfo
,
&
req
,
msgBuf
,
msgBufLen
);
if
(
code
!=
TSDB_CODE_SUCCESS
)
{
return
code
;
}
// load the meta data from catalog
code
=
catalogGetMetaData
(
pCatalog
,
&
req
,
&
data
);
if
(
code
!=
TSDB_CODE_SUCCESS
)
{
return
code
;
}
// evaluate the sqlnode
STableMeta
*
pTableMeta
=
(
STableMeta
*
)
taosArrayGetP
(
data
.
pTableMeta
,
0
);
assert
(
pTableMeta
!=
NULL
);
size_t
len
=
taosArrayGetSize
(
pInfo
->
list
);
for
(
int32_t
i
=
0
;
i
<
len
;
++
i
)
{
SSqlNode
*
p
=
taosArrayGetP
(
pInfo
->
list
,
i
);
code
=
evaluateSqlNode
(
p
,
pTableMeta
->
tableInfo
.
precision
,
msgBuf
,
msgBufLen
);
if
(
code
!=
TSDB_CODE_SUCCESS
)
{
return
code
;
}
}
// convert the sqlnode into queryinfo
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录