Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
taosdata
TDengine
提交
984e037e
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看板
提交
984e037e
编写于
3月 03, 2021
作者:
D
dapan1121
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
support having
上级
d65b541b
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
369 addition
and
234 deletion
+369
-234
src/client/inc/tsclient.h
src/client/inc/tsclient.h
+10
-7
src/client/src/tscLocalMerge.c
src/client/src/tscLocalMerge.c
+20
-0
src/client/src/tscSQLParser.c
src/client/src/tscSQLParser.c
+266
-214
src/client/src/tscUtil.c
src/client/src/tscUtil.c
+19
-13
src/query/inc/qSqlparser.h
src/query/inc/qSqlparser.h
+2
-0
src/query/src/qParserImpl.c
src/query/src/qParserImpl.c
+52
-0
未找到文件。
src/client/inc/tsclient.h
浏览文件 @
984e037e
...
...
@@ -116,13 +116,6 @@ typedef struct SColumnIndex {
int16_t
columnIndex
;
}
SColumnIndex
;
typedef
struct
SInternalField
{
TAOS_FIELD
field
;
bool
visible
;
SExprInfo
*
pArithExprInfo
;
SSqlExpr
*
pSqlExpr
;
SColumn
*
pFieldFilters
;
}
SInternalField
;
typedef
struct
SFieldInfo
{
int16_t
numOfOutput
;
// number of column in result
...
...
@@ -136,6 +129,15 @@ typedef struct SColumn {
SColumnFilterInfo
*
filterInfo
;
}
SColumn
;
typedef
struct
SInternalField
{
TAOS_FIELD
field
;
bool
visible
;
SExprInfo
*
pArithExprInfo
;
SSqlExpr
*
pSqlExpr
;
tSQLExpr
*
pExpr
;
//used for having parse
SColumn
*
pFieldFilters
;
//having filter info
}
SInternalField
;
typedef
struct
SCond
{
uint64_t
uid
;
int32_t
len
;
// length of tag query condition data
...
...
@@ -228,6 +230,7 @@ typedef struct SQueryInfo {
int32_t
round
;
// 0/1/....
int32_t
bufLen
;
char
*
buf
;
int32_t
havingFieldNum
;
}
SQueryInfo
;
typedef
struct
{
...
...
src/client/src/tscLocalMerge.c
浏览文件 @
984e037e
...
...
@@ -1229,6 +1229,24 @@ static bool saveGroupResultInfo(SSqlObj *pSql) {
return
false
;
}
int32_t
doHavingFilter
(
SQueryInfo
*
pQueryInfo
)
{
if
(
pQueryInfo
->
havingFieldNum
<=
0
)
{
return
TSDB_CODE_SUCCESS
;
}
size_t
numOfOutput
=
tscNumOfFields
(
pQueryInfo
);
for
(
int32_t
i
=
0
;
i
<
numOfOutput
;
++
i
)
{
SColumn
*
pFieldFilters
=
tscFieldInfoGetInternalField
(
&
pQueryInfo
->
fieldsInfo
,
i
)
->
pFieldFilters
;
if
(
pFieldFilters
!=
NULL
)
{
continue
;
}
}
return
TSDB_CODE_SUCCESS
;
}
/**
*
* @param pSql
...
...
@@ -1269,6 +1287,8 @@ bool genFinalResults(SSqlObj *pSql, SLocalMerger *pLocalMerge, bool noMoreCurren
doArithmeticCalculate
(
pQueryInfo
,
pResBuf
,
pModel
->
rowSize
,
pLocalMerge
->
finalModel
->
rowSize
);
}
doHavingFilter
(
pQueryInfo
);
// no interval query, no fill operation
if
(
pQueryInfo
->
interval
.
interval
==
0
||
pQueryInfo
->
fillType
==
TSDB_FILL_NONE
)
{
genFinalResWithoutFill
(
pRes
,
pLocalMerge
,
pQueryInfo
);
...
...
src/client/src/tscSQLParser.c
浏览文件 @
984e037e
...
...
@@ -3097,213 +3097,6 @@ int32_t parseGroupbyClause(SQueryInfo* pQueryInfo, SArray* pList, SSqlCmd* pCmd)
return
TSDB_CODE_SUCCESS
;
}
static
int32_t
handleExprInHavingClause
(
SSqlCmd
*
pCmd
,
SQueryInfo
*
pQueryInfo
,
SColumnIndex
*
pIndex
,
tSQLExpr
*
pExpr
,
int32_t
sqlOptr
)
{
STableMetaInfo
*
pTableMetaInfo
=
tscGetMetaInfo
(
pQueryInfo
,
pIndex
->
tableIndex
);
STableMeta
*
pTableMeta
=
pTableMetaInfo
->
pTableMeta
;
SSchema
*
pSchema
=
tscGetTableColumnSchema
(
pTableMeta
,
pIndex
->
columnIndex
);
const
char
*
msg1
=
"non binary column not support like operator"
;
const
char
*
msg2
=
"binary column not support this operator"
;
const
char
*
msg3
=
"bool column not support this operator"
;
SColumn
*
pColumn
=
tscColumnListInsert
(
pQueryInfo
->
colList
,
pIndex
);
SColumnFilterInfo
*
pColFilter
=
NULL
;
/*
* in case of TK_AND filter condition, we first find the corresponding column and build the query condition together
* the already existed condition.
*/
if
(
sqlOptr
==
TK_AND
)
{
// this is a new filter condition on this column
if
(
pColumn
->
numOfFilters
==
0
)
{
pColFilter
=
addColumnFilterInfo
(
pColumn
);
}
else
{
// update the existed column filter information, find the filter info here
pColFilter
=
&
pColumn
->
filterInfo
[
0
];
}
if
(
pColFilter
==
NULL
)
{
return
TSDB_CODE_TSC_OUT_OF_MEMORY
;
}
}
else
if
(
sqlOptr
==
TK_OR
)
{
// TODO fixme: failed to invalid the filter expression: "col1 = 1 OR col2 = 2"
pColFilter
=
addColumnFilterInfo
(
pColumn
);
if
(
pColFilter
==
NULL
)
{
return
TSDB_CODE_TSC_OUT_OF_MEMORY
;
}
}
else
{
// error;
return
TSDB_CODE_TSC_INVALID_SQL
;
}
pColFilter
->
filterstr
=
((
pSchema
->
type
==
TSDB_DATA_TYPE_BINARY
||
pSchema
->
type
==
TSDB_DATA_TYPE_NCHAR
)
?
1
:
0
);
if
(
pColFilter
->
filterstr
)
{
if
(
pExpr
->
nSQLOptr
!=
TK_EQ
&&
pExpr
->
nSQLOptr
!=
TK_NE
&&
pExpr
->
nSQLOptr
!=
TK_ISNULL
&&
pExpr
->
nSQLOptr
!=
TK_NOTNULL
&&
pExpr
->
nSQLOptr
!=
TK_LIKE
)
{
return
invalidSqlErrMsg
(
tscGetErrorMsgPayload
(
pCmd
),
msg2
);
}
}
else
{
if
(
pExpr
->
nSQLOptr
==
TK_LIKE
)
{
return
invalidSqlErrMsg
(
tscGetErrorMsgPayload
(
pCmd
),
msg1
);
}
if
(
pSchema
->
type
==
TSDB_DATA_TYPE_BOOL
)
{
if
(
pExpr
->
nSQLOptr
!=
TK_EQ
&&
pExpr
->
nSQLOptr
!=
TK_NE
)
{
return
invalidSqlErrMsg
(
tscGetErrorMsgPayload
(
pCmd
),
msg3
);
}
}
}
pColumn
->
colIndex
=
*
pIndex
;
return
doExtractColumnFilterInfo
(
pCmd
,
pQueryInfo
,
pColFilter
,
pIndex
,
pExpr
);
}
int32_t
getHavingExpr
(
SSqlCmd
*
pCmd
,
SQueryInfo
*
pQueryInfo
,
tSQLExpr
**
pExpr
,
int32_t
parentOptr
)
{
if
(
pExpr
==
NULL
||
(
*
pExpr
)
==
NULL
)
{
return
TSDB_CODE_SUCCESS
;
}
const
char
*
msg1
=
"invalid having clause"
;
tSQLExpr
*
pLeft
=
(
*
pExpr
)
->
pLeft
;
tSQLExpr
*
pRight
=
(
*
pExpr
)
->
pRight
;
if
((
*
pExpr
)
->
nSQLOptr
==
TK_AND
||
(
*
pExpr
)
->
nSQLOptr
==
TK_OR
)
{
int32_t
ret
=
getHavingExpr
(
pCmd
,
pQueryInfo
,
&
(
*
pExpr
)
->
pLeft
,
(
*
pExpr
)
->
nSQLOptr
);
if
(
ret
!=
TSDB_CODE_SUCCESS
)
{
return
ret
;
}
return
getHavingExpr
(
pCmd
,
pQueryInfo
,
&
(
*
pExpr
)
->
pRight
,
(
*
pExpr
)
->
nSQLOptr
);
}
if
((
pLeft
->
nSQLOptr
>=
TK_COUNT
&&
pLeft
->
nSQLOptr
<=
TK_AVG_IRATE
)
&&
(
pRight
->
nSQLOptr
>=
TK_COUNT
&&
pRight
->
nSQLOptr
<=
TK_AVG_IRATE
))
{
return
invalidSqlErrMsg
(
tscGetErrorMsgPayload
(
pCmd
),
msg1
);
}
if
(
pLeft
->
nSQLOptr
>=
TK_BOOL
&&
pLeft
->
nSQLOptr
<=
TK_BINARY
&&
pRight
->
nSQLOptr
>=
TK_BOOL
&&
pRight
->
nSQLOptr
<=
TK_BINARY
)
{
return
invalidSqlErrMsg
(
tscGetErrorMsgPayload
(
pCmd
),
msg1
);
}
exchangeExpr
(
*
pExpr
);
pLeft
=
(
*
pExpr
)
->
pLeft
;
pRight
=
(
*
pExpr
)
->
pRight
;
if
(
!
(
pLeft
->
nSQLOptr
>=
TK_COUNT
&&
pLeft
->
nSQLOptr
<=
TK_AVG_IRATE
))
{
return
invalidSqlErrMsg
(
tscGetErrorMsgPayload
(
pCmd
),
msg1
);
}
if
(
!
(
pRight
->
nSQLOptr
>=
TK_BOOL
&&
pRight
->
nSQLOptr
<=
TK_BINARY
))
{
return
invalidSqlErrMsg
(
tscGetErrorMsgPayload
(
pCmd
),
msg1
);
}
if
((
*
pExpr
)
->
nSQLOptr
>=
TK_BITAND
)
{
return
invalidSqlErrMsg
(
tscGetErrorMsgPayload
(
pCmd
),
msg1
);
}
if
(
pLeft
->
pParam
==
NULL
||
pLeft
->
pParam
->
nExpr
<
1
)
{
return
invalidSqlErrMsg
(
tscGetErrorMsgPayload
(
pCmd
),
msg1
);
}
for
(
int32_t
i
=
0
;
i
<
pLeft
->
pParam
->
nExpr
;
i
++
)
{
tSqlExprItem
*
pParamElem
=
&
(
pLeft
->
pParam
->
a
[
i
]);
if
(
pParamElem
->
pNode
->
nSQLOptr
!=
TK_ALL
&&
pParamElem
->
pNode
->
nSQLOptr
!=
TK_ID
)
{
return
invalidSqlErrMsg
(
tscGetErrorMsgPayload
(
pCmd
),
msg1
);
}
SColumnIndex
index
=
COLUMN_INDEX_INITIALIZER
;
if
((
getColumnIndexByName
(
pCmd
,
&
pParamElem
->
pNode
->
colInfo
,
pQueryInfo
,
&
index
)
!=
TSDB_CODE_SUCCESS
))
{
return
invalidSqlErrMsg
(
tscGetErrorMsgPayload
(
pCmd
),
msg1
);
}
STableMetaInfo
*
pTableMetaInfo
=
tscGetMetaInfo
(
pQueryInfo
,
index
.
tableIndex
);
STableMeta
*
pTableMeta
=
pTableMetaInfo
->
pTableMeta
;
if
(
index
.
columnIndex
<=
0
||
index
.
columnIndex
>=
tscGetNumOfColumns
(
pTableMeta
))
{
return
invalidSqlErrMsg
(
tscGetErrorMsgPayload
(
pCmd
),
msg1
);
}
}
tSqlExprItem
item
=
{.
pNode
=
pLeft
,
.
aliasName
=
NULL
,
.
distinct
=
false
};
int32_t
outputIndex
=
(
int32_t
)
tscSqlExprNumOfExprs
(
pQueryInfo
);
// ADD TRUE FOR TEST
if
(
addExprAndResultField
(
pCmd
,
pQueryInfo
,
outputIndex
,
&
item
,
true
)
!=
TSDB_CODE_SUCCESS
)
{
return
TSDB_CODE_TSC_INVALID_SQL
;
}
int32_t
slot
=
tscNumOfFields
(
pQueryInfo
)
-
1
;
SInternalField
*
pInfo
=
tscFieldInfoGetInternalField
(
&
pQueryInfo
->
fieldsInfo
,
slot
);
if
(
pInfo
->
pFieldFilters
==
NULL
)
{
SColumn
*
pFieldFilters
=
calloc
(
1
,
sizeof
(
SColumn
));
if
(
pFieldFilters
==
NULL
)
{
return
TSDB_CODE_TSC_OUT_OF_MEMORY
;
}
pInfo
->
pFieldFilters
=
pFieldFilters
;
}
return
handleExprInHavingClause
(
pCmd
,
pQueryInfo
,
pInfo
->
pFieldFilters
,
pExpr
,
parentOptr
);
}
int32_t
parseHavingClause
(
SQueryInfo
*
pQueryInfo
,
tSQLExpr
**
pExpr
,
SSqlCmd
*
pCmd
)
{
const
char
*
msg1
=
"having only works with group by"
;
//const char* msg2 = "invalid column name in having clause";
//const char* msg3 = "columns from one table allowed as having columns";
//const char* msg4 = "no tag allowed in having clause";
const
char
*
msg5
=
"invalid expression in having clause"
;
/*
const char* msg1 = "too many columns in group by clause";
const char* msg4 = "join query does not support group by";
const char* msg7 = "not support group by expression";
const char* msg8 = "not allowed column type for group by";
const char* msg9 = "tags not allowed for table query";
*/
// todo : handle two tables situation
//STableMetaInfo* pTableMetaInfo = NULL;
if
(
pExpr
==
NULL
||
(
*
pExpr
)
==
NULL
)
{
return
TSDB_CODE_SUCCESS
;
}
if
(
pQueryInfo
->
groupbyExpr
.
numOfGroupCols
<=
0
)
{
return
invalidSqlErrMsg
(
tscGetErrorMsgPayload
(
pCmd
),
msg1
);
}
if
((
*
pExpr
)
->
pLeft
==
NULL
||
(
*
pExpr
)
->
pRight
==
NULL
)
{
return
invalidSqlErrMsg
(
tscGetErrorMsgPayload
(
pCmd
),
msg5
);
}
if
(
pQueryInfo
->
colList
==
NULL
)
{
pQueryInfo
->
colList
=
taosArrayInit
(
4
,
POINTER_BYTES
);
}
int32_t
ret
=
0
;
if
((
ret
=
getHavingExpr
(
pCmd
,
pQueryInfo
,
pExpr
,
TK_AND
))
!=
TSDB_CODE_SUCCESS
)
{
return
ret
;
}
return
TSDB_CODE_SUCCESS
;
}
static
SColumnFilterInfo
*
addColumnFilterInfo
(
SColumn
*
pColumn
)
{
if
(
pColumn
==
NULL
)
{
...
...
@@ -3328,15 +3121,11 @@ static SColumnFilterInfo* addColumnFilterInfo(SColumn* pColumn) {
}
static
int32_t
doExtractColumnFilterInfo
(
SSqlCmd
*
pCmd
,
SQueryInfo
*
pQueryInfo
,
SColumnFilterInfo
*
pColumnFilter
,
SColumnIndex
*
columnIndex
,
tSQLExpr
*
pExpr
)
{
int16_t
colType
,
tSQLExpr
*
pExpr
)
{
const
char
*
msg
=
"not supported filter condition"
;
tSQLExpr
*
pRight
=
pExpr
->
pRight
;
STableMetaInfo
*
pTableMetaInfo
=
tscGetMetaInfo
(
pQueryInfo
,
columnIndex
->
tableIndex
);
SSchema
*
pSchema
=
tscGetTableColumnSchema
(
pTableMetaInfo
->
pTableMeta
,
columnIndex
->
columnIndex
);
int16_t
colType
=
pSchema
->
type
;
if
(
colType
>=
TSDB_DATA_TYPE_TINYINT
&&
colType
<=
TSDB_DATA_TYPE_BIGINT
)
{
colType
=
TSDB_DATA_TYPE_BIGINT
;
}
else
if
(
colType
==
TSDB_DATA_TYPE_FLOAT
||
colType
==
TSDB_DATA_TYPE_DOUBLE
)
{
...
...
@@ -3649,7 +3438,10 @@ static int32_t extractColumnFilterInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SC
}
pColumn
->
colIndex
=
*
pIndex
;
return
doExtractColumnFilterInfo
(
pCmd
,
pQueryInfo
,
pColFilter
,
pIndex
,
pExpr
);
int16_t
colType
=
pSchema
->
type
;
return
doExtractColumnFilterInfo
(
pCmd
,
pQueryInfo
,
pColFilter
,
colType
,
pExpr
);
}
static
void
relToString
(
tSQLExpr
*
pExpr
,
char
**
str
)
{
...
...
@@ -6901,6 +6693,259 @@ static int32_t checkQueryRangeForFill(SSqlCmd* pCmd, SQueryInfo* pQueryInfo) {
return
TSDB_CODE_SUCCESS
;
}
int32_t
tscInsertExprFields
(
SSqlCmd
*
pCmd
,
SQueryInfo
*
pQueryInfo
,
tSQLExpr
*
pExpr
,
SInternalField
**
interField
)
{
tSqlExprItem
item
=
{.
pNode
=
pExpr
,
.
aliasName
=
NULL
,
.
distinct
=
false
};
int32_t
outputIndex
=
(
int32_t
)
tscSqlExprNumOfExprs
(
pQueryInfo
);
// ADD TRUE FOR TEST
if
(
addExprAndResultField
(
pCmd
,
pQueryInfo
,
outputIndex
,
&
item
,
true
)
!=
TSDB_CODE_SUCCESS
)
{
return
TSDB_CODE_TSC_INVALID_SQL
;
}
++
pQueryInfo
->
havingFieldNum
;
int32_t
slot
=
tscNumOfFields
(
pQueryInfo
)
-
1
;
SInternalField
*
pInfo
=
tscFieldInfoGetInternalField
(
&
pQueryInfo
->
fieldsInfo
,
slot
);
pInfo
->
visible
=
false
;
pInfo
->
pExpr
=
pExpr
;
if
(
pInfo
->
pFieldFilters
==
NULL
)
{
SColumn
*
pFieldFilters
=
calloc
(
1
,
sizeof
(
SColumn
));
if
(
pFieldFilters
==
NULL
)
{
return
TSDB_CODE_TSC_OUT_OF_MEMORY
;
}
pInfo
->
pFieldFilters
=
pFieldFilters
;
}
*
interField
=
pInfo
;
return
TSDB_CODE_SUCCESS
;
}
int32_t
tscGetExprFilters
(
SSqlCmd
*
pCmd
,
SQueryInfo
*
pQueryInfo
,
tSQLExpr
*
pExpr
,
SInternalField
**
pField
)
{
SInternalField
*
pInfo
=
NULL
;
for
(
int32_t
i
=
pQueryInfo
->
havingFieldNum
-
1
;
i
>=
0
;
--
i
)
{
pInfo
=
tscFieldInfoGetInternalField
(
&
pQueryInfo
->
fieldsInfo
,
i
);
if
(
0
==
tSqlExprCompare
(
pInfo
->
pExpr
,
pExpr
))
{
*
pField
=
pInfo
;
return
TSDB_CODE_SUCCESS
;
}
}
int32_t
ret
=
tscInsertExprFields
(
pCmd
,
pQueryInfo
,
pExpr
,
&
pInfo
);
if
(
ret
)
{
return
ret
;
}
*
pField
=
pInfo
;
return
TSDB_CODE_SUCCESS
;
}
static
int32_t
handleExprInHavingClause
(
SSqlCmd
*
pCmd
,
SQueryInfo
*
pQueryInfo
,
tSQLExpr
*
pExpr
,
int32_t
sqlOptr
)
{
const
char
*
msg1
=
"non binary column not support like operator"
;
const
char
*
msg2
=
"invalid operator for binary column in having clause"
;
const
char
*
msg3
=
"invalid operator for bool column in having clause"
;
SColumn
*
pColumn
=
NULL
;
SColumnFilterInfo
*
pColFilter
=
NULL
;
SInternalField
*
pInfo
=
NULL
;
/*
* in case of TK_AND filter condition, we first find the corresponding column and build the query condition together
* the already existed condition.
*/
if
(
sqlOptr
==
TK_AND
)
{
int32_t
ret
=
tscGetExprFilters
(
pCmd
,
pQueryInfo
,
pExpr
->
pLeft
,
&
pInfo
);
if
(
ret
)
{
return
ret
;
}
pColumn
=
pInfo
->
pFieldFilters
;
// this is a new filter condition on this column
if
(
pColumn
->
numOfFilters
==
0
)
{
pColFilter
=
addColumnFilterInfo
(
pColumn
);
}
else
{
// update the existed column filter information, find the filter info here
pColFilter
=
&
pColumn
->
filterInfo
[
0
];
}
if
(
pColFilter
==
NULL
)
{
return
TSDB_CODE_TSC_OUT_OF_MEMORY
;
}
}
else
if
(
sqlOptr
==
TK_OR
)
{
int32_t
ret
=
tscInsertExprFields
(
pCmd
,
pQueryInfo
,
pExpr
->
pLeft
,
&
pInfo
);
if
(
ret
)
{
return
ret
;
}
// TODO fixme: failed to invalid the filter expression: "col1 = 1 OR col2 = 2"
pColFilter
=
addColumnFilterInfo
(
pColumn
);
if
(
pColFilter
==
NULL
)
{
return
TSDB_CODE_TSC_OUT_OF_MEMORY
;
}
}
else
{
// error;
return
TSDB_CODE_TSC_INVALID_SQL
;
}
pColFilter
->
filterstr
=
((
pInfo
->
field
.
type
==
TSDB_DATA_TYPE_BINARY
||
pInfo
->
field
.
type
==
TSDB_DATA_TYPE_NCHAR
)
?
1
:
0
);
if
(
pColFilter
->
filterstr
)
{
if
(
pExpr
->
nSQLOptr
!=
TK_EQ
&&
pExpr
->
nSQLOptr
!=
TK_NE
&&
pExpr
->
nSQLOptr
!=
TK_ISNULL
&&
pExpr
->
nSQLOptr
!=
TK_NOTNULL
&&
pExpr
->
nSQLOptr
!=
TK_LIKE
)
{
return
invalidSqlErrMsg
(
tscGetErrorMsgPayload
(
pCmd
),
msg2
);
}
}
else
{
if
(
pExpr
->
nSQLOptr
==
TK_LIKE
)
{
return
invalidSqlErrMsg
(
tscGetErrorMsgPayload
(
pCmd
),
msg1
);
}
if
(
pInfo
->
field
.
type
==
TSDB_DATA_TYPE_BOOL
)
{
if
(
pExpr
->
nSQLOptr
!=
TK_EQ
&&
pExpr
->
nSQLOptr
!=
TK_NE
)
{
return
invalidSqlErrMsg
(
tscGetErrorMsgPayload
(
pCmd
),
msg3
);
}
}
}
return
doExtractColumnFilterInfo
(
pCmd
,
pQueryInfo
,
pColFilter
,
pInfo
->
field
.
type
,
pExpr
);
}
int32_t
getHavingExpr
(
SSqlCmd
*
pCmd
,
SQueryInfo
*
pQueryInfo
,
tSQLExpr
*
pExpr
,
int32_t
parentOptr
)
{
if
(
pExpr
==
NULL
)
{
return
TSDB_CODE_SUCCESS
;
}
const
char
*
msg1
=
"invalid having clause"
;
tSQLExpr
*
pLeft
=
pExpr
->
pLeft
;
tSQLExpr
*
pRight
=
pExpr
->
pRight
;
if
(
pExpr
->
nSQLOptr
==
TK_AND
||
pExpr
->
nSQLOptr
==
TK_OR
)
{
int32_t
ret
=
getHavingExpr
(
pCmd
,
pQueryInfo
,
pExpr
->
pLeft
,
pExpr
->
nSQLOptr
);
if
(
ret
!=
TSDB_CODE_SUCCESS
)
{
return
ret
;
}
return
getHavingExpr
(
pCmd
,
pQueryInfo
,
pExpr
->
pRight
,
pExpr
->
nSQLOptr
);
}
if
((
pLeft
->
nSQLOptr
>=
TK_COUNT
&&
pLeft
->
nSQLOptr
<=
TK_AVG_IRATE
)
&&
(
pRight
->
nSQLOptr
>=
TK_COUNT
&&
pRight
->
nSQLOptr
<=
TK_AVG_IRATE
))
{
return
invalidSqlErrMsg
(
tscGetErrorMsgPayload
(
pCmd
),
msg1
);
}
if
(
pLeft
->
nSQLOptr
>=
TK_BOOL
&&
pLeft
->
nSQLOptr
<=
TK_BINARY
&&
pRight
->
nSQLOptr
>=
TK_BOOL
&&
pRight
->
nSQLOptr
<=
TK_BINARY
)
{
return
invalidSqlErrMsg
(
tscGetErrorMsgPayload
(
pCmd
),
msg1
);
}
exchangeExpr
(
pExpr
);
pLeft
=
pExpr
->
pLeft
;
pRight
=
pExpr
->
pRight
;
if
(
!
(
pLeft
->
nSQLOptr
>=
TK_COUNT
&&
pLeft
->
nSQLOptr
<=
TK_AVG_IRATE
))
{
return
invalidSqlErrMsg
(
tscGetErrorMsgPayload
(
pCmd
),
msg1
);
}
if
(
!
(
pRight
->
nSQLOptr
>=
TK_BOOL
&&
pRight
->
nSQLOptr
<=
TK_BINARY
))
{
return
invalidSqlErrMsg
(
tscGetErrorMsgPayload
(
pCmd
),
msg1
);
}
if
(
pExpr
->
nSQLOptr
>=
TK_BITAND
)
{
return
invalidSqlErrMsg
(
tscGetErrorMsgPayload
(
pCmd
),
msg1
);
}
if
(
pLeft
->
pParam
==
NULL
||
pLeft
->
pParam
->
nExpr
<
1
)
{
return
invalidSqlErrMsg
(
tscGetErrorMsgPayload
(
pCmd
),
msg1
);
}
for
(
int32_t
i
=
0
;
i
<
pLeft
->
pParam
->
nExpr
;
i
++
)
{
tSqlExprItem
*
pParamElem
=
&
(
pLeft
->
pParam
->
a
[
i
]);
if
(
pParamElem
->
pNode
->
nSQLOptr
!=
TK_ALL
&&
pParamElem
->
pNode
->
nSQLOptr
!=
TK_ID
)
{
return
invalidSqlErrMsg
(
tscGetErrorMsgPayload
(
pCmd
),
msg1
);
}
SColumnIndex
index
=
COLUMN_INDEX_INITIALIZER
;
if
((
getColumnIndexByName
(
pCmd
,
&
pParamElem
->
pNode
->
colInfo
,
pQueryInfo
,
&
index
)
!=
TSDB_CODE_SUCCESS
))
{
return
invalidSqlErrMsg
(
tscGetErrorMsgPayload
(
pCmd
),
msg1
);
}
STableMetaInfo
*
pTableMetaInfo
=
tscGetMetaInfo
(
pQueryInfo
,
index
.
tableIndex
);
STableMeta
*
pTableMeta
=
pTableMetaInfo
->
pTableMeta
;
if
(
index
.
columnIndex
<=
0
||
index
.
columnIndex
>=
tscGetNumOfColumns
(
pTableMeta
))
{
return
invalidSqlErrMsg
(
tscGetErrorMsgPayload
(
pCmd
),
msg1
);
}
}
return
handleExprInHavingClause
(
pCmd
,
pQueryInfo
,
pExpr
,
parentOptr
);
}
int32_t
parseHavingClause
(
SQueryInfo
*
pQueryInfo
,
tSQLExpr
*
pExpr
,
SSqlCmd
*
pCmd
)
{
const
char
*
msg1
=
"having only works with group by"
;
//const char* msg2 = "invalid column name in having clause";
//const char* msg3 = "columns from one table allowed as having columns";
//const char* msg4 = "no tag allowed in having clause";
const
char
*
msg5
=
"invalid expression in having clause"
;
/*
const char* msg1 = "too many columns in group by clause";
const char* msg4 = "join query does not support group by";
const char* msg7 = "not support group by expression";
const char* msg8 = "not allowed column type for group by";
const char* msg9 = "tags not allowed for table query";
*/
// todo : handle two tables situation
//STableMetaInfo* pTableMetaInfo = NULL;
if
(
pExpr
==
NULL
)
{
return
TSDB_CODE_SUCCESS
;
}
if
(
pQueryInfo
->
groupbyExpr
.
numOfGroupCols
<=
0
)
{
return
invalidSqlErrMsg
(
tscGetErrorMsgPayload
(
pCmd
),
msg1
);
}
if
(
pExpr
->
pLeft
==
NULL
||
pExpr
->
pRight
==
NULL
)
{
return
invalidSqlErrMsg
(
tscGetErrorMsgPayload
(
pCmd
),
msg5
);
}
if
(
pQueryInfo
->
colList
==
NULL
)
{
pQueryInfo
->
colList
=
taosArrayInit
(
4
,
POINTER_BYTES
);
}
int32_t
ret
=
0
;
if
((
ret
=
getHavingExpr
(
pCmd
,
pQueryInfo
,
pExpr
,
TK_AND
))
!=
TSDB_CODE_SUCCESS
)
{
return
ret
;
}
return
TSDB_CODE_SUCCESS
;
}
int32_t
doCheckForQuery
(
SSqlObj
*
pSql
,
SQuerySQL
*
pQuerySql
,
int32_t
index
)
{
assert
(
pQuerySql
!=
NULL
&&
(
pQuerySql
->
from
==
NULL
||
taosArrayGetSize
(
pQuerySql
->
from
)
>
0
));
...
...
@@ -7028,7 +7073,7 @@ int32_t doCheckForQuery(SSqlObj* pSql, SQuerySQL* pQuerySql, int32_t index) {
}
// parse the having clause in the first place
if
(
parseHavingClause
(
pQueryInfo
,
&
pQuerySql
->
pHaving
,
pCmd
)
!=
TSDB_CODE_SUCCESS
)
{
if
(
parseHavingClause
(
pQueryInfo
,
pQuerySql
->
pHaving
,
pCmd
)
!=
TSDB_CODE_SUCCESS
)
{
return
TSDB_CODE_TSC_INVALID_SQL
;
}
...
...
@@ -7261,3 +7306,10 @@ bool hasNormalColumnFilter(SQueryInfo* pQueryInfo) {
return
false
;
}
src/client/src/tscUtil.c
浏览文件 @
984e037e
...
...
@@ -956,6 +956,7 @@ SInternalField* tscFieldInfoAppend(SFieldInfo* pFieldInfo, TAOS_FIELD* pField) {
.
pSqlExpr
=
NULL
,
.
pArithExprInfo
=
NULL
,
.
visible
=
true
,
.
pFieldFilters
=
NULL
,
};
info
.
field
=
*
pField
;
...
...
@@ -968,6 +969,7 @@ SInternalField* tscFieldInfoInsert(SFieldInfo* pFieldInfo, int32_t index, TAOS_F
.
pSqlExpr
=
NULL
,
.
pArithExprInfo
=
NULL
,
.
visible
=
true
,
.
pFieldFilters
=
NULL
,
};
info
.
field
=
*
field
;
...
...
@@ -1041,6 +1043,22 @@ int32_t tscGetResRowLength(SArray* pExprList) {
return
size
;
}
static
void
destroyFilterInfo
(
SColumnFilterInfo
*
pFilterInfo
,
int32_t
numOfFilters
)
{
for
(
int32_t
i
=
0
;
i
<
numOfFilters
;
++
i
)
{
if
(
pFilterInfo
[
i
].
filterstr
)
{
tfree
(
pFilterInfo
[
i
].
pz
);
}
}
tfree
(
pFilterInfo
);
}
static
void
tscColumnDestroy
(
SColumn
*
pCol
)
{
destroyFilterInfo
(
pCol
->
filterInfo
,
pCol
->
numOfFilters
);
free
(
pCol
);
}
void
tscFieldInfoClear
(
SFieldInfo
*
pFieldInfo
)
{
if
(
pFieldInfo
==
NULL
)
{
return
;
...
...
@@ -1298,15 +1316,7 @@ SColumn* tscColumnListInsert(SArray* pColumnList, SColumnIndex* pColIndex) {
return
taosArrayGetP
(
pColumnList
,
i
);
}
static
void
destroyFilterInfo
(
SColumnFilterInfo
*
pFilterInfo
,
int32_t
numOfFilters
)
{
for
(
int32_t
i
=
0
;
i
<
numOfFilters
;
++
i
)
{
if
(
pFilterInfo
[
i
].
filterstr
)
{
tfree
(
pFilterInfo
[
i
].
pz
);
}
}
tfree
(
pFilterInfo
);
}
SColumn
*
tscColumnClone
(
const
SColumn
*
src
)
{
assert
(
src
!=
NULL
);
...
...
@@ -1323,10 +1333,6 @@ SColumn* tscColumnClone(const SColumn* src) {
return
dst
;
}
static
void
tscColumnDestroy
(
SColumn
*
pCol
)
{
destroyFilterInfo
(
pCol
->
filterInfo
,
pCol
->
numOfFilters
);
free
(
pCol
);
}
void
tscColumnListCopy
(
SArray
*
dst
,
const
SArray
*
src
,
int16_t
tableIndex
)
{
assert
(
src
!=
NULL
&&
dst
!=
NULL
);
...
...
src/query/inc/qSqlparser.h
浏览文件 @
984e037e
...
...
@@ -233,6 +233,8 @@ SArray *tVariantListAppendToken(SArray *pList, SStrToken *pAliasToken, uint8_t s
tSQLExpr
*
tSqlExprCreate
(
tSQLExpr
*
pLeft
,
tSQLExpr
*
pRight
,
int32_t
optrType
);
int32_t
tSqlExprCompare
(
tSQLExpr
*
left
,
tSQLExpr
*
right
);
tSQLExpr
*
tSqlExprClone
(
tSQLExpr
*
pSrc
);
void
tSqlExprDestroy
(
tSQLExpr
*
pExpr
);
...
...
src/query/src/qParserImpl.c
浏览文件 @
984e037e
...
...
@@ -290,6 +290,58 @@ tSQLExpr *tSqlExprCreate(tSQLExpr *pLeft, tSQLExpr *pRight, int32_t optrType) {
}
static
FORCE_INLINE
int32_t
tStrTokenCompare
(
SStrToken
*
left
,
SStrToken
*
right
)
{
return
(
left
->
type
==
right
->
type
&&
left
->
n
==
right
->
n
&&
strncasecmp
(
left
->
z
,
right
->
z
,
left
->
n
)
==
0
)
?
0
:
1
;
}
int32_t
tSqlExprCompare
(
tSQLExpr
*
left
,
tSQLExpr
*
right
)
{
if
(
left
->
nSQLOptr
!=
right
->
nSQLOptr
)
{
return
1
;
}
if
((
left
->
pLeft
&&
right
->
pLeft
==
NULL
)
||
(
left
->
pLeft
==
NULL
&&
right
->
pLeft
)
||
(
left
->
pRight
&&
right
->
pRight
==
NULL
)
||
(
left
->
pRight
==
NULL
&&
right
->
pRight
)
||
(
left
->
pParam
&&
right
->
pParam
==
NULL
)
||
(
left
->
pParam
==
NULL
&&
right
->
pParam
))
{
return
1
;
}
if
(
tVariantCompare
(
&
left
->
val
,
&
right
->
val
))
{
return
1
;
}
if
(
tStrTokenCompare
(
&
left
->
colInfo
,
&
right
->
colInfo
))
{
return
1
;
}
if
(
left
->
pParam
&&
left
->
pParam
->
nExpr
!=
right
->
pParam
->
nExpr
)
{
return
1
;
}
for
(
int32_t
i
=
0
;
i
<
right
->
pParam
->
nExpr
;
i
++
)
{
tSQLExpr
*
pSubLeft
=
left
->
pParam
->
a
[
i
].
pNode
;
tSQLExpr
*
pSubRight
=
right
->
pParam
->
a
[
i
].
pNode
;
if
(
tSqlExprCompare
(
pSubLeft
,
pSubRight
))
{
return
1
;
}
}
if
(
left
->
pLeft
&&
tSqlExprCompare
(
left
->
pLeft
,
right
->
pLeft
))
{
return
1
;
}
if
(
left
->
pRight
&&
tSqlExprCompare
(
left
->
pRight
,
right
->
pRight
))
{
return
1
;
}
return
0
;
}
tSQLExpr
*
tSqlExprClone
(
tSQLExpr
*
pSrc
)
{
tSQLExpr
*
pExpr
=
calloc
(
1
,
sizeof
(
tSQLExpr
));
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录