Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
taosdata
TDengine
提交
b4ff474e
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看板
提交
b4ff474e
编写于
10月 29, 2021
作者:
L
lichuang
浏览文件
操作
浏览文件
下载
差异文件
Merge branch '3.0' into feature/sync-implementation
上级
5b7261d6
bc82a32b
变更
26
隐藏空白更改
内联
并排
Showing
26 changed file
with
1255 addition
and
820 deletion
+1255
-820
include/common/tvariant.h
include/common/tvariant.h
+2
-2
include/libs/function/function.h
include/libs/function/function.h
+4
-1
include/libs/parser/parser.h
include/libs/parser/parser.h
+2
-1
include/libs/planner/planner.h
include/libs/planner/planner.h
+1
-1
source/common/src/tvariant.c
source/common/src/tvariant.c
+38
-38
source/libs/catalog/src/catalog.c
source/libs/catalog/src/catalog.c
+1
-1
source/libs/function/inc/texpr.h
source/libs/function/inc/texpr.h
+0
-1
source/libs/function/inc/tscalarfunction.h
source/libs/function/inc/tscalarfunction.h
+1
-0
source/libs/function/src/taggfunction.c
source/libs/function/src/taggfunction.c
+78
-78
source/libs/function/src/texpr.c
source/libs/function/src/texpr.c
+9
-9
source/libs/function/src/ttszip.c
source/libs/function/src/ttszip.c
+3
-3
source/libs/parser/inc/queryInfoUtil.h
source/libs/parser/inc/queryInfoUtil.h
+0
-1
source/libs/parser/src/astGenerator.c
source/libs/parser/src/astGenerator.c
+7
-7
source/libs/parser/src/astValidate.c
source/libs/parser/src/astValidate.c
+271
-262
source/libs/parser/src/parser.c
source/libs/parser/src/parser.c
+1
-1
source/libs/parser/src/queryInfoUtil.c
source/libs/parser/src/queryInfoUtil.c
+1
-1
source/libs/parser/test/CMakeLists.txt
source/libs/parser/test/CMakeLists.txt
+1
-1
source/libs/parser/test/parserTests.cpp
source/libs/parser/test/parserTests.cpp
+457
-283
source/libs/parser/test/plannerTest.cpp
source/libs/parser/test/plannerTest.cpp
+130
-0
source/libs/parser/test/tokenizerTest.cpp
source/libs/parser/test/tokenizerTest.cpp
+79
-79
source/libs/planner/CMakeLists.txt
source/libs/planner/CMakeLists.txt
+3
-1
source/libs/planner/inc/plannerUtil.h
source/libs/planner/inc/plannerUtil.h
+29
-0
source/libs/planner/src/planner.c
source/libs/planner/src/planner.c
+25
-49
source/libs/planner/src/plannerUtil.c
source/libs/planner/src/plannerUtil.c
+6
-0
source/libs/planner/test/CMakeLists.txt
source/libs/planner/test/CMakeLists.txt
+18
-0
source/libs/planner/test/plannerTests.cpp
source/libs/planner/test/plannerTests.cpp
+88
-0
未找到文件。
include/common/tvariant.h
浏览文件 @
b4ff474e
...
...
@@ -27,8 +27,8 @@ typedef struct SVariant {
uint32_t
nType
;
int32_t
nLen
;
// only used for string, for number, it is useless
union
{
int64_t
i
64
;
uint64_t
u
64
;
int64_t
i
;
uint64_t
u
;
double
d
;
char
*
pz
;
wchar_t
*
wpz
;
...
...
include/libs/function/function.h
浏览文件 @
b4ff474e
...
...
@@ -186,7 +186,6 @@ typedef struct SResultDataInfo {
int32_t
intermediateBytes
;
}
SResultDataInfo
;
typedef
struct
SMultiFunctionsDesc
{
bool
stableQuery
;
bool
groupbyColumn
;
...
...
@@ -203,6 +202,8 @@ typedef struct SMultiFunctionsDesc {
bool
timewindow
;
bool
topbotQuery
;
bool
interpQuery
;
bool
distinct
;
bool
join
;
}
SMultiFunctionsDesc
;
int32_t
getResultDataInfo
(
int32_t
dataType
,
int32_t
dataBytes
,
int32_t
functionId
,
int32_t
param
,
SResultDataInfo
*
pInfo
,
int16_t
extLength
,
...
...
@@ -222,6 +223,8 @@ const char* qGetFunctionName(int32_t functionId);
void
extractFunctionDesc
(
SArray
*
pFunctionIdList
,
SMultiFunctionsDesc
*
pDesc
);
tExprNode
*
exprdup
(
tExprNode
*
pTree
);
#ifdef __cplusplus
}
#endif
...
...
include/libs/parser/parser.h
浏览文件 @
b4ff474e
...
...
@@ -163,7 +163,6 @@ typedef struct SQueryStmtInfo {
int64_t
vgroupLimit
;
// table limit in case of super table projection query + global order + limit
int32_t
udColumnId
;
// current user-defined constant output field column id, monotonically decreases from TSDB_UD_COLUMN_INDEX
bool
distinct
;
// distinct tag or not
int32_t
bufLen
;
char
*
buf
;
SArray
*
pUdfInfo
;
...
...
@@ -231,6 +230,8 @@ SExprInfo* createExprInfo(STableMetaInfo* pTableMetaInfo, int16_t functionId, SC
int32_t
copyExprInfoList
(
SArray
*
dst
,
const
SArray
*
src
,
uint64_t
uid
,
bool
deepcopy
);
STableMetaInfo
*
getMetaInfo
(
SQueryStmtInfo
*
pQueryInfo
,
int32_t
tableIndex
);
SSchema
*
getOneColumnSchema
(
const
STableMeta
*
pTableMeta
,
int32_t
colIndex
);
int32_t
getNewResColId
();
#ifdef __cplusplus
...
...
include/libs/planner/planner.h
浏览文件 @
b4ff474e
...
...
@@ -56,7 +56,7 @@ int32_t qOptimizeQueryPlan(struct SQueryPlanNode* pQueryNode);
* @param pQueryNode
* @return
*/
int32_t
qCreateQueryPlan
(
const
struct
SQueryStmtInfo
*
pQueryInfo
,
struct
SQueryPlanNode
*
pQueryNode
);
int32_t
qCreateQueryPlan
(
const
struct
SQueryStmtInfo
*
pQueryInfo
,
struct
SQueryPlanNode
*
*
pQueryNode
);
/**
* Convert the query plan to string, in order to display it in the shell.
...
...
source/common/src/tvariant.c
浏览文件 @
b4ff474e
...
...
@@ -82,9 +82,9 @@ void taosVariantCreate(SVariant *pVar, char* z, int32_t n, int32_t type) {
switch
(
type
)
{
case
TSDB_DATA_TYPE_BOOL
:
{
if
(
strncasecmp
(
z
,
"true"
,
4
)
==
0
)
{
pVar
->
i
64
=
TSDB_TRUE
;
pVar
->
i
=
TSDB_TRUE
;
}
else
if
(
strncasecmp
(
z
,
"false"
,
5
)
==
0
)
{
pVar
->
i
64
=
TSDB_FALSE
;
pVar
->
i
=
TSDB_FALSE
;
}
else
{
return
;
}
...
...
@@ -106,7 +106,7 @@ void taosVariantCreate(SVariant *pVar, char* z, int32_t n, int32_t type) {
base
=
2
;
}
ret
=
toInteger
(
z
,
n
,
base
,
&
pVar
->
i
64
,
&
sign
);
ret
=
toInteger
(
z
,
n
,
base
,
&
pVar
->
i
,
&
sign
);
if
(
ret
!=
0
)
{
pVar
->
nType
=
-
1
;
// -1 means error type
return
;
...
...
@@ -127,7 +127,7 @@ void taosVariantCreate(SVariant *pVar, char* z, int32_t n, int32_t type) {
}
case
TSDB_DATA_TYPE_TIMESTAMP
:
{
assert
(
0
);
pVar
->
i
64
=
taosGetTimestamp
(
TSDB_TIME_PRECISION_NANO
);
pVar
->
i
=
taosGetTimestamp
(
TSDB_TIME_PRECISION_NANO
);
break
;
}
...
...
@@ -151,43 +151,43 @@ void taosVariantCreateFromBinary(SVariant *pVar, const char *pz, size_t len, uin
case
TSDB_DATA_TYPE_BOOL
:
case
TSDB_DATA_TYPE_TINYINT
:
{
pVar
->
nLen
=
tDataTypes
[
type
].
bytes
;
pVar
->
i
64
=
GET_INT8_VAL
(
pz
);
pVar
->
i
=
GET_INT8_VAL
(
pz
);
break
;
}
case
TSDB_DATA_TYPE_UTINYINT
:
{
pVar
->
nLen
=
tDataTypes
[
type
].
bytes
;
pVar
->
u
64
=
GET_UINT8_VAL
(
pz
);
pVar
->
u
=
GET_UINT8_VAL
(
pz
);
break
;
}
case
TSDB_DATA_TYPE_SMALLINT
:
{
pVar
->
nLen
=
tDataTypes
[
type
].
bytes
;
pVar
->
i
64
=
GET_INT16_VAL
(
pz
);
pVar
->
i
=
GET_INT16_VAL
(
pz
);
break
;
}
case
TSDB_DATA_TYPE_USMALLINT
:
{
pVar
->
nLen
=
tDataTypes
[
type
].
bytes
;
pVar
->
u
64
=
GET_UINT16_VAL
(
pz
);
pVar
->
u
=
GET_UINT16_VAL
(
pz
);
break
;
}
case
TSDB_DATA_TYPE_INT
:
{
pVar
->
nLen
=
tDataTypes
[
type
].
bytes
;
pVar
->
i
64
=
GET_INT32_VAL
(
pz
);
pVar
->
i
=
GET_INT32_VAL
(
pz
);
break
;
}
case
TSDB_DATA_TYPE_UINT
:
{
pVar
->
nLen
=
tDataTypes
[
type
].
bytes
;
pVar
->
u
64
=
GET_UINT32_VAL
(
pz
);
pVar
->
u
=
GET_UINT32_VAL
(
pz
);
break
;
}
case
TSDB_DATA_TYPE_BIGINT
:
case
TSDB_DATA_TYPE_TIMESTAMP
:
{
pVar
->
nLen
=
tDataTypes
[
type
].
bytes
;
pVar
->
i
64
=
GET_INT64_VAL
(
pz
);
pVar
->
i
=
GET_INT64_VAL
(
pz
);
break
;
}
case
TSDB_DATA_TYPE_UBIGINT
:
{
pVar
->
nLen
=
tDataTypes
[
type
].
bytes
;
pVar
->
u
64
=
GET_UINT64_VAL
(
pz
);
pVar
->
u
=
GET_UINT64_VAL
(
pz
);
break
;
}
case
TSDB_DATA_TYPE_DOUBLE
:
{
...
...
@@ -217,7 +217,7 @@ void taosVariantCreateFromBinary(SVariant *pVar, const char *pz, size_t len, uin
}
default:
pVar
->
i
64
=
GET_INT32_VAL
(
pz
);
pVar
->
i
=
GET_INT32_VAL
(
pz
);
pVar
->
nLen
=
tDataTypes
[
TSDB_DATA_TYPE_INT
].
bytes
;
}
...
...
@@ -271,7 +271,7 @@ void taosVariantAssign(SVariant *pDst, const SVariant *pSrc) {
}
if
(
IS_NUMERIC_TYPE
(
pSrc
->
nType
)
||
(
pSrc
->
nType
==
TSDB_DATA_TYPE_BOOL
))
{
pDst
->
i
64
=
pSrc
->
i64
;
pDst
->
i
=
pSrc
->
i
;
}
else
if
(
pSrc
->
nType
==
TSDB_DATA_TYPE_POINTER_ARRAY
)
{
// this is only for string array
size_t
num
=
taosArrayGetSize
(
pSrc
->
arr
);
pDst
->
arr
=
taosArrayInit
(
num
,
sizeof
(
char
*
));
...
...
@@ -322,16 +322,16 @@ int32_t taosVariantCompare(const SVariant* p1, const SVariant* p2) {
return
p1
->
d
>
p2
->
d
?
1
:-
1
;
}
}
else
if
(
IS_UNSIGNED_NUMERIC_TYPE
(
p1
->
nType
))
{
if
(
p1
->
u
64
==
p2
->
u64
)
{
if
(
p1
->
u
==
p2
->
u
)
{
return
0
;
}
else
{
return
p1
->
u
64
>
p2
->
u64
?
1
:-
1
;
return
p1
->
u
>
p2
->
u
?
1
:-
1
;
}
}
else
{
if
(
p1
->
i
64
==
p2
->
i64
)
{
if
(
p1
->
i
==
p2
->
i
)
{
return
0
;
}
else
{
return
p1
->
i
64
>
p2
->
i64
?
1
:-
1
;
return
p1
->
i
>
p2
->
i
?
1
:-
1
;
}
}
}
...
...
@@ -362,12 +362,12 @@ int32_t taosVariantToString(SVariant *pVar, char *dst) {
case
TSDB_DATA_TYPE_UTINYINT
:
case
TSDB_DATA_TYPE_USMALLINT
:
case
TSDB_DATA_TYPE_UINT
:
return
sprintf
(
dst
,
"%d"
,
(
int32_t
)
pVar
->
i
64
);
return
sprintf
(
dst
,
"%d"
,
(
int32_t
)
pVar
->
i
);
case
TSDB_DATA_TYPE_BIGINT
:
return
sprintf
(
dst
,
"%"
PRId64
,
pVar
->
i
64
);
return
sprintf
(
dst
,
"%"
PRId64
,
pVar
->
i
);
case
TSDB_DATA_TYPE_UBIGINT
:
return
sprintf
(
dst
,
"%"
PRIu64
,
pVar
->
u
64
);
return
sprintf
(
dst
,
"%"
PRIu64
,
pVar
->
u
);
case
TSDB_DATA_TYPE_FLOAT
:
case
TSDB_DATA_TYPE_DOUBLE
:
return
sprintf
(
dst
,
"%.9lf"
,
pVar
->
d
);
...
...
@@ -426,11 +426,11 @@ static int32_t toBinary(SVariant *pVariant, char **pDest, int32_t *pDestSize) {
}
else
{
if
(
IS_SIGNED_NUMERIC_TYPE
(
pVariant
->
nType
))
{
sprintf
(
pBuf
==
NULL
?
*
pDest
:
pBuf
,
"%"
PRId64
,
pVariant
->
i
64
);
sprintf
(
pBuf
==
NULL
?
*
pDest
:
pBuf
,
"%"
PRId64
,
pVariant
->
i
);
}
else
if
(
pVariant
->
nType
==
TSDB_DATA_TYPE_DOUBLE
||
pVariant
->
nType
==
TSDB_DATA_TYPE_FLOAT
)
{
sprintf
(
pBuf
==
NULL
?
*
pDest
:
pBuf
,
"%lf"
,
pVariant
->
d
);
}
else
if
(
pVariant
->
nType
==
TSDB_DATA_TYPE_BOOL
)
{
sprintf
(
pBuf
==
NULL
?
*
pDest
:
pBuf
,
"%s"
,
(
pVariant
->
i
64
==
TSDB_TRUE
)
?
"TRUE"
:
"FALSE"
);
sprintf
(
pBuf
==
NULL
?
*
pDest
:
pBuf
,
"%s"
,
(
pVariant
->
i
==
TSDB_TRUE
)
?
"TRUE"
:
"FALSE"
);
}
else
if
(
pVariant
->
nType
==
0
)
{
// null data
setNull
(
pBuf
==
NULL
?
*
pDest
:
pBuf
,
TSDB_DATA_TYPE_BINARY
,
0
);
}
...
...
@@ -452,16 +452,16 @@ static int32_t toNchar(SVariant *pVariant, char **pDest, int32_t *pDestSize) {
// convert the number to string, than convert it to wchar string.
if
(
IS_SIGNED_NUMERIC_TYPE
(
pVariant
->
nType
))
{
nLen
=
sprintf
(
pDst
,
"%"
PRId64
,
pVariant
->
i
64
);
nLen
=
sprintf
(
pDst
,
"%"
PRId64
,
pVariant
->
i
);
}
else
if
(
IS_UNSIGNED_NUMERIC_TYPE
(
pVariant
->
nType
))
{
nLen
=
sprintf
(
pDst
,
"%"
PRIu64
,
pVariant
->
u
64
);
nLen
=
sprintf
(
pDst
,
"%"
PRIu64
,
pVariant
->
u
);
}
else
if
(
pVariant
->
nType
==
TSDB_DATA_TYPE_DOUBLE
||
pVariant
->
nType
==
TSDB_DATA_TYPE_FLOAT
)
{
nLen
=
sprintf
(
pDst
,
"%lf"
,
pVariant
->
d
);
}
else
if
(
pVariant
->
nType
==
TSDB_DATA_TYPE_BINARY
)
{
pDst
=
pVariant
->
pz
;
nLen
=
pVariant
->
nLen
;
}
else
if
(
pVariant
->
nType
==
TSDB_DATA_TYPE_BOOL
)
{
nLen
=
sprintf
(
pDst
,
"%s"
,
(
pVariant
->
i
64
==
TSDB_TRUE
)
?
"TRUE"
:
"FALSE"
);
nLen
=
sprintf
(
pDst
,
"%s"
,
(
pVariant
->
i
==
TSDB_TRUE
)
?
"TRUE"
:
"FALSE"
);
}
if
(
*
pDest
==
pVariant
->
pz
)
{
...
...
@@ -519,9 +519,9 @@ static FORCE_INLINE int32_t convertToInteger(SVariant *pVariant, int64_t *result
#if 0
errno = 0;
if (IS_SIGNED_NUMERIC_TYPE(pVariant->nType) || (pVariant->nType == TSDB_DATA_TYPE_BOOL)) {
*result = pVariant->i
64
;
*result = pVariant->i;
} else if (IS_UNSIGNED_NUMERIC_TYPE(pVariant->nType)) {
*result = pVariant->u
64
;
*result = pVariant->u;
} else if (IS_FLOAT_TYPE(pVariant->nType)) {
*result = (int64_t) pVariant->d;
} else if (pVariant->nType == TSDB_DATA_TYPE_BINARY) {
...
...
@@ -639,9 +639,9 @@ static FORCE_INLINE int32_t convertToInteger(SVariant *pVariant, int64_t *result
static
int32_t
convertToBool
(
SVariant
*
pVariant
,
int64_t
*
pDest
)
{
if
(
pVariant
->
nType
==
TSDB_DATA_TYPE_BOOL
)
{
*
pDest
=
pVariant
->
i
64
;
// in order to be compatible to null of bool
*
pDest
=
pVariant
->
i
;
// in order to be compatible to null of bool
}
else
if
(
IS_NUMERIC_TYPE
(
pVariant
->
nType
))
{
*
pDest
=
((
pVariant
->
i
64
!=
0
)
?
TSDB_TRUE
:
TSDB_FALSE
);
*
pDest
=
((
pVariant
->
i
!=
0
)
?
TSDB_TRUE
:
TSDB_FALSE
);
}
else
if
(
pVariant
->
nType
==
TSDB_DATA_TYPE_FLOAT
||
pVariant
->
nType
==
TSDB_DATA_TYPE_DOUBLE
)
{
*
pDest
=
((
pVariant
->
d
!=
0
)
?
TSDB_TRUE
:
TSDB_FALSE
);
}
else
if
(
pVariant
->
nType
==
TSDB_DATA_TYPE_BINARY
)
{
...
...
@@ -791,12 +791,12 @@ int32_t tVariantDumpEx(SVariant *pVariant, char *payload, int16_t type, bool inc
*
converted
=
true
;
}
if
(
pVariant
->
i
64
>
FLT_MAX
||
pVariant
->
i64
<
-
FLT_MAX
)
{
SET_EXT_INFO
(
converted
,
pVariant
->
i
64
,
-
FLT_MAX
,
FLT_MAX
,
extInfo
);
if
(
pVariant
->
i
>
FLT_MAX
||
pVariant
->
i
<
-
FLT_MAX
)
{
SET_EXT_INFO
(
converted
,
pVariant
->
i
,
-
FLT_MAX
,
FLT_MAX
,
extInfo
);
return
-
1
;
}
SET_FLOAT_VAL
(
payload
,
pVariant
->
i
64
);
SET_FLOAT_VAL
(
payload
,
pVariant
->
i
);
}
else
if
(
IS_FLOAT_TYPE
(
pVariant
->
nType
))
{
if
(
converted
)
{
*
converted
=
true
;
...
...
@@ -836,7 +836,7 @@ int32_t tVariantDumpEx(SVariant *pVariant, char *payload, int16_t type, bool inc
SET_DOUBLE_VAL
(
payload
,
value
);
}
}
else
if
(
pVariant
->
nType
==
TSDB_DATA_TYPE_BOOL
||
IS_SIGNED_NUMERIC_TYPE
(
pVariant
->
nType
)
||
IS_UNSIGNED_NUMERIC_TYPE
(
pVariant
->
nType
))
{
SET_DOUBLE_VAL
(
payload
,
pVariant
->
i
64
);
SET_DOUBLE_VAL
(
payload
,
pVariant
->
i
);
}
else
if
(
IS_FLOAT_TYPE
(
pVariant
->
nType
))
{
SET_DOUBLE_VAL
(
payload
,
pVariant
->
d
);
}
else
if
(
pVariant
->
nType
==
TSDB_DATA_TYPE_NULL
)
{
...
...
@@ -885,7 +885,7 @@ int32_t tVariantDumpEx(SVariant *pVariant, char *payload, int16_t type, bool inc
if
(
pVariant
->
nType
==
TSDB_DATA_TYPE_NULL
)
{
*
((
int64_t
*
)
payload
)
=
TSDB_DATA_BIGINT_NULL
;
}
else
{
*
((
int64_t
*
)
payload
)
=
pVariant
->
i
64
;
*
((
int64_t
*
)
payload
)
=
pVariant
->
i
;
}
break
;
}
...
...
@@ -951,7 +951,7 @@ int32_t taosVariantTypeSetType(SVariant *pVariant, char type) {
switch
(
type
)
{
case
TSDB_DATA_TYPE_BOOL
:
{
// bool
if
(
convertToBool
(
pVariant
,
&
pVariant
->
i
64
)
<
0
)
{
if
(
convertToBool
(
pVariant
,
&
pVariant
->
i
)
<
0
)
{
return
-
1
;
}
...
...
@@ -962,7 +962,7 @@ int32_t taosVariantTypeSetType(SVariant *pVariant, char type) {
case
TSDB_DATA_TYPE_BIGINT
:
case
TSDB_DATA_TYPE_TINYINT
:
case
TSDB_DATA_TYPE_SMALLINT
:
{
convertToInteger
(
pVariant
,
&
(
pVariant
->
i
64
),
type
,
true
,
true
,
NULL
);
convertToInteger
(
pVariant
,
&
(
pVariant
->
i
),
type
,
true
,
true
,
NULL
);
pVariant
->
nType
=
TSDB_DATA_TYPE_BIGINT
;
break
;
}
...
...
@@ -989,7 +989,7 @@ int32_t taosVariantTypeSetType(SVariant *pVariant, char type) {
free
(
pVariant
->
pz
);
pVariant
->
d
=
v
;
}
else
if
(
pVariant
->
nType
>=
TSDB_DATA_TYPE_BOOL
&&
pVariant
->
nType
<=
TSDB_DATA_TYPE_BIGINT
)
{
double
tmp
=
(
double
)
pVariant
->
i
64
;
double
tmp
=
(
double
)
pVariant
->
i
;
pVariant
->
d
=
tmp
;
}
...
...
source/libs/catalog/src/catalog.c
浏览文件 @
b4ff474e
...
...
@@ -16,7 +16,7 @@
#include "catalogInt.h"
struct
SCatalog
*
getCatalogHandle
(
const
SEpSet
*
pMgmtEps
)
{
return
NULL
;
return
(
struct
SCatalog
*
)
0x1
;
}
int32_t
catalogGetMetaData
(
struct
SCatalog
*
pCatalog
,
const
SMetaReq
*
pMetaReq
,
SMetaData
*
pMetaData
)
{
...
...
source/libs/function/inc/texpr.h
浏览文件 @
b4ff474e
...
...
@@ -62,7 +62,6 @@ typedef struct SExprTraverseSupp {
tExprNode
*
exprTreeFromBinary
(
const
void
*
data
,
size_t
size
);
tExprNode
*
exprTreeFromTableName
(
const
char
*
tbnameCond
);
tExprNode
*
exprdup
(
tExprNode
*
pTree
);
bool
exprTreeApplyFilter
(
tExprNode
*
pExpr
,
const
void
*
pItem
,
SExprTraverseSupp
*
param
);
...
...
source/libs/function/inc/tscalarfunction.h
浏览文件 @
b4ff474e
...
...
@@ -28,6 +28,7 @@ extern struct SScalarFunctionInfo scalarFunc[1];
#define FUNCTION_ROUND 40
#define FUNCTION_MAVG 41
#define FUNCTION_CSUM 42
#define FUNCCTION_CONCAT 43
#ifdef __cplusplus
}
...
...
source/libs/function/src/taggfunction.c
浏览文件 @
b4ff474e
...
...
@@ -61,7 +61,7 @@
for (int32_t _i = 0; _i < (ctx)->tagInfo.numOfTagCols; ++_i) { \
SQLFunctionCtx *__ctx = (ctx)->tagInfo.pTagCtxList[_i]; \
if (__ctx->functionId == FUNCTION_TS_DUMMY) { \
__ctx->tag.i
64
= (ts); \
__ctx->tag.i = (ts); \
__ctx->tag.nType = TSDB_DATA_TYPE_BIGINT; \
} \
aggFunc[FUNCTION_TAG].exec(__ctx); \
...
...
@@ -722,7 +722,7 @@ static int32_t firstFuncRequired(SQLFunctionCtx *pCtx, STimeWindow* w, int32_t c
}
static
int32_t
lastFuncRequired
(
SQLFunctionCtx
*
pCtx
,
STimeWindow
*
w
,
int32_t
colId
)
{
if
(
pCtx
->
order
!=
pCtx
->
param
[
0
].
i
64
)
{
if
(
pCtx
->
order
!=
pCtx
->
param
[
0
].
i
)
{
return
BLK_DATA_NO_NEEDED
;
}
...
...
@@ -754,7 +754,7 @@ static int32_t firstDistFuncRequired(SQLFunctionCtx *pCtx, STimeWindow* w, int32
}
static
int32_t
lastDistFuncRequired
(
SQLFunctionCtx
*
pCtx
,
STimeWindow
*
w
,
int32_t
colId
)
{
if
(
pCtx
->
order
!=
pCtx
->
param
[
0
].
i
64
)
{
if
(
pCtx
->
order
!=
pCtx
->
param
[
0
].
i
)
{
return
BLK_DATA_NO_NEEDED
;
}
...
...
@@ -953,7 +953,7 @@ static void minMax_function(SQLFunctionCtx *pCtx, char *pOutput, int32_t isMin,
for
(
int32_t
i
=
0
;
i
<
(
pCtx
)
->
tagInfo
.
numOfTagCols
;
++
i
)
{
SQLFunctionCtx
*
__ctx
=
pCtx
->
tagInfo
.
pTagCtxList
[
i
];
if
(
__ctx
->
functionId
==
FUNCTION_TS_DUMMY
)
{
__ctx
->
tag
.
i
64
=
key
;
__ctx
->
tag
.
i
=
key
;
__ctx
->
tag
.
nType
=
TSDB_DATA_TYPE_BIGINT
;
}
...
...
@@ -1532,7 +1532,7 @@ static bool first_last_function_setup(SQLFunctionCtx *pCtx, SResultRowCellInfo*
// used to keep the timestamp for comparison
pCtx
->
param
[
1
].
nType
=
0
;
pCtx
->
param
[
1
].
i
64
=
0
;
pCtx
->
param
[
1
].
i
=
0
;
return
true
;
}
...
...
@@ -1628,9 +1628,9 @@ static void first_dist_func_merge(SQLFunctionCtx *pCtx) {
}
// The param[1] is used to keep the initial value of max ts value
if
(
pCtx
->
param
[
1
].
nType
!=
pCtx
->
outputType
||
pCtx
->
param
[
1
].
i
64
>
pInput
->
ts
)
{
if
(
pCtx
->
param
[
1
].
nType
!=
pCtx
->
outputType
||
pCtx
->
param
[
1
].
i
>
pInput
->
ts
)
{
memcpy
(
pCtx
->
pOutput
,
pData
,
pCtx
->
outputBytes
);
pCtx
->
param
[
1
].
i
64
=
pInput
->
ts
;
pCtx
->
param
[
1
].
i
=
pInput
->
ts
;
pCtx
->
param
[
1
].
nType
=
pCtx
->
outputType
;
DO_UPDATE_TAG_COLUMNS
(
pCtx
,
pInput
->
ts
);
...
...
@@ -1649,7 +1649,7 @@ static void first_dist_func_merge(SQLFunctionCtx *pCtx) {
* least one data in this block that is not null.(TODO opt for this case)
*/
static
void
last_function
(
SQLFunctionCtx
*
pCtx
)
{
if
(
pCtx
->
order
!=
pCtx
->
param
[
0
].
i
64
)
{
if
(
pCtx
->
order
!=
pCtx
->
param
[
0
].
i
)
{
return
;
}
...
...
@@ -1723,7 +1723,7 @@ static void last_dist_function(SQLFunctionCtx *pCtx) {
* 1. for scan data is not the required order
* 2. for data blocks that are not loaded, no need to check data
*/
if
(
pCtx
->
order
!=
pCtx
->
param
[
0
].
i
64
)
{
if
(
pCtx
->
order
!=
pCtx
->
param
[
0
].
i
)
{
return
;
}
...
...
@@ -1765,9 +1765,9 @@ static void last_dist_func_merge(SQLFunctionCtx *pCtx) {
* param[1] used to keep the corresponding timestamp to decide if current result is
* the true last result
*/
if
(
pCtx
->
param
[
1
].
nType
!=
pCtx
->
outputType
||
pCtx
->
param
[
1
].
i
64
<
pInput
->
ts
)
{
if
(
pCtx
->
param
[
1
].
nType
!=
pCtx
->
outputType
||
pCtx
->
param
[
1
].
i
<
pInput
->
ts
)
{
memcpy
(
pCtx
->
pOutput
,
pData
,
pCtx
->
outputBytes
);
pCtx
->
param
[
1
].
i
64
=
pInput
->
ts
;
pCtx
->
param
[
1
].
i
=
pInput
->
ts
;
pCtx
->
param
[
1
].
nType
=
pCtx
->
outputType
;
DO_UPDATE_TAG_COLUMNS
(
pCtx
,
pInput
->
ts
);
...
...
@@ -1822,7 +1822,7 @@ static void last_row_finalizer(SQLFunctionCtx *pCtx) {
static
void
valuePairAssign
(
tValuePair
*
dst
,
int16_t
type
,
const
char
*
val
,
int64_t
tsKey
,
char
*
pTags
,
SExtTagsInfo
*
pTagInfo
,
int16_t
stage
)
{
dst
->
v
.
nType
=
type
;
dst
->
v
.
i
64
=
*
(
int64_t
*
)
val
;
dst
->
v
.
i
=
*
(
int64_t
*
)
val
;
dst
->
timestamp
=
tsKey
;
int32_t
size
=
0
;
...
...
@@ -1833,7 +1833,7 @@ static void valuePairAssign(tValuePair *dst, int16_t type, const char *val, int6
SQLFunctionCtx
*
ctx
=
pTagInfo
->
pTagCtxList
[
i
];
if
(
ctx
->
functionId
==
FUNCTION_TS_DUMMY
)
{
ctx
->
tag
.
nType
=
TSDB_DATA_TYPE_BIGINT
;
ctx
->
tag
.
i
64
=
tsKey
;
ctx
->
tag
.
i
=
tsKey
;
}
taosVariantDump
(
&
ctx
->
tag
,
dst
->
pTags
+
size
,
ctx
->
tag
.
nType
,
true
);
...
...
@@ -1856,17 +1856,17 @@ static int32_t topBotComparFn(const void *p1, const void *p2, const void *param)
tValuePair
*
val2
=
*
(
tValuePair
**
)
p2
;
if
(
IS_SIGNED_NUMERIC_TYPE
(
type
))
{
if
(
val1
->
v
.
i
64
==
val2
->
v
.
i64
)
{
if
(
val1
->
v
.
i
==
val2
->
v
.
i
)
{
return
0
;
}
return
(
val1
->
v
.
i
64
>
val2
->
v
.
i64
)
?
1
:
-
1
;
return
(
val1
->
v
.
i
>
val2
->
v
.
i
)
?
1
:
-
1
;
}
else
if
(
IS_UNSIGNED_NUMERIC_TYPE
(
type
))
{
if
(
val1
->
v
.
u
64
==
val2
->
v
.
u64
)
{
if
(
val1
->
v
.
u
==
val2
->
v
.
u
)
{
return
0
;
}
return
(
val1
->
v
.
u
64
>
val2
->
v
.
u64
)
?
1
:
-
1
;
return
(
val1
->
v
.
u
>
val2
->
v
.
u
)
?
1
:
-
1
;
}
if
(
val1
->
v
.
d
==
val2
->
v
.
d
)
{
...
...
@@ -1901,16 +1901,16 @@ static void do_top_function_add(STopBotInfo *pInfo, int32_t maxLen, void *pData,
assert
(
pList
!=
NULL
);
if
(
pInfo
->
num
<
maxLen
)
{
valuePairAssign
(
pList
[
pInfo
->
num
],
type
,
(
const
char
*
)
&
val
.
i
64
,
ts
,
pTags
,
pTagInfo
,
stage
);
valuePairAssign
(
pList
[
pInfo
->
num
],
type
,
(
const
char
*
)
&
val
.
i
,
ts
,
pTags
,
pTagInfo
,
stage
);
taosheapsort
((
void
*
)
pList
,
sizeof
(
tValuePair
**
),
pInfo
->
num
+
1
,
(
const
void
*
)
&
type
,
topBotComparFn
,
(
const
void
*
)
&
pTagInfo
->
tagsLen
,
topBotSwapFn
,
0
);
pInfo
->
num
++
;
}
else
{
if
((
IS_SIGNED_NUMERIC_TYPE
(
type
)
&&
val
.
i
64
>
pList
[
0
]
->
v
.
i64
)
||
(
IS_UNSIGNED_NUMERIC_TYPE
(
type
)
&&
val
.
u
64
>
pList
[
0
]
->
v
.
u64
)
||
if
((
IS_SIGNED_NUMERIC_TYPE
(
type
)
&&
val
.
i
>
pList
[
0
]
->
v
.
i
)
||
(
IS_UNSIGNED_NUMERIC_TYPE
(
type
)
&&
val
.
u
>
pList
[
0
]
->
v
.
u
)
||
(
IS_FLOAT_TYPE
(
type
)
&&
val
.
d
>
pList
[
0
]
->
v
.
d
))
{
valuePairAssign
(
pList
[
0
],
type
,
(
const
char
*
)
&
val
.
i
64
,
ts
,
pTags
,
pTagInfo
,
stage
);
valuePairAssign
(
pList
[
0
],
type
,
(
const
char
*
)
&
val
.
i
,
ts
,
pTags
,
pTagInfo
,
stage
);
taosheapadjust
((
void
*
)
pList
,
sizeof
(
tValuePair
**
),
0
,
maxLen
-
1
,
(
const
void
*
)
&
type
,
topBotComparFn
,
(
const
void
*
)
&
pTagInfo
->
tagsLen
,
topBotSwapFn
,
0
);
}
}
...
...
@@ -1925,16 +1925,16 @@ static void do_bottom_function_add(STopBotInfo *pInfo, int32_t maxLen, void *pDa
assert
(
pList
!=
NULL
);
if
(
pInfo
->
num
<
maxLen
)
{
valuePairAssign
(
pList
[
pInfo
->
num
],
type
,
(
const
char
*
)
&
val
.
i
64
,
ts
,
pTags
,
pTagInfo
,
stage
);
valuePairAssign
(
pList
[
pInfo
->
num
],
type
,
(
const
char
*
)
&
val
.
i
,
ts
,
pTags
,
pTagInfo
,
stage
);
taosheapsort
((
void
*
)
pList
,
sizeof
(
tValuePair
**
),
pInfo
->
num
+
1
,
(
const
void
*
)
&
type
,
topBotComparFn
,
(
const
void
*
)
&
pTagInfo
->
tagsLen
,
topBotSwapFn
,
1
);
pInfo
->
num
++
;
}
else
{
if
((
IS_SIGNED_NUMERIC_TYPE
(
type
)
&&
val
.
i
64
<
pList
[
0
]
->
v
.
i64
)
||
(
IS_UNSIGNED_NUMERIC_TYPE
(
type
)
&&
val
.
u
64
<
pList
[
0
]
->
v
.
u64
)
||
if
((
IS_SIGNED_NUMERIC_TYPE
(
type
)
&&
val
.
i
<
pList
[
0
]
->
v
.
i
)
||
(
IS_UNSIGNED_NUMERIC_TYPE
(
type
)
&&
val
.
u
<
pList
[
0
]
->
v
.
u
)
||
(
IS_FLOAT_TYPE
(
type
)
&&
val
.
d
<
pList
[
0
]
->
v
.
d
))
{
valuePairAssign
(
pList
[
0
],
type
,
(
const
char
*
)
&
val
.
i
64
,
ts
,
pTags
,
pTagInfo
,
stage
);
valuePairAssign
(
pList
[
0
],
type
,
(
const
char
*
)
&
val
.
i
,
ts
,
pTags
,
pTagInfo
,
stage
);
taosheapadjust
((
void
*
)
pList
,
sizeof
(
tValuePair
**
),
0
,
maxLen
-
1
,
(
const
void
*
)
&
type
,
topBotComparFn
,
(
const
void
*
)
&
pTagInfo
->
tagsLen
,
topBotSwapFn
,
1
);
}
}
...
...
@@ -1964,16 +1964,16 @@ static int32_t resDataAscComparFn(const void *pLeft, const void *pRight) {
return
pLeftElem
->
v
.
d
>
pRightElem
->
v
.
d
?
1
:
-
1
;
}
}
else
if
(
IS_SIGNED_NUMERIC_TYPE
(
pLeftElem
->
v
.
nType
)){
if
(
pLeftElem
->
v
.
i
64
==
pRightElem
->
v
.
i64
)
{
if
(
pLeftElem
->
v
.
i
==
pRightElem
->
v
.
i
)
{
return
0
;
}
else
{
return
pLeftElem
->
v
.
i
64
>
pRightElem
->
v
.
i64
?
1
:
-
1
;
return
pLeftElem
->
v
.
i
>
pRightElem
->
v
.
i
?
1
:
-
1
;
}
}
else
{
if
(
pLeftElem
->
v
.
u
64
==
pRightElem
->
v
.
u64
)
{
if
(
pLeftElem
->
v
.
u
==
pRightElem
->
v
.
u
)
{
return
0
;
}
else
{
return
pLeftElem
->
v
.
u
64
>
pRightElem
->
v
.
u64
?
1
:
-
1
;
return
pLeftElem
->
v
.
u
>
pRightElem
->
v
.
u
?
1
:
-
1
;
}
}
}
...
...
@@ -1994,7 +1994,7 @@ static void copyTopBotRes(SQLFunctionCtx *pCtx, int32_t type) {
case
TSDB_DATA_TYPE_INT
:
{
int32_t
*
output
=
(
int32_t
*
)
pCtx
->
pOutput
;
for
(
int32_t
i
=
0
;
i
<
len
;
++
i
,
output
+=
step
)
{
*
output
=
(
int32_t
)
tvp
[
i
]
->
v
.
i
64
;
*
output
=
(
int32_t
)
tvp
[
i
]
->
v
.
i
;
}
break
;
}
...
...
@@ -2002,7 +2002,7 @@ static void copyTopBotRes(SQLFunctionCtx *pCtx, int32_t type) {
case
TSDB_DATA_TYPE_BIGINT
:
{
int64_t
*
output
=
(
int64_t
*
)
pCtx
->
pOutput
;
for
(
int32_t
i
=
0
;
i
<
len
;
++
i
,
output
+=
step
)
{
*
output
=
tvp
[
i
]
->
v
.
i
64
;
*
output
=
tvp
[
i
]
->
v
.
i
;
}
break
;
}
...
...
@@ -2024,7 +2024,7 @@ static void copyTopBotRes(SQLFunctionCtx *pCtx, int32_t type) {
case
TSDB_DATA_TYPE_SMALLINT
:
{
int16_t
*
output
=
(
int16_t
*
)
pCtx
->
pOutput
;
for
(
int32_t
i
=
0
;
i
<
len
;
++
i
,
output
+=
step
)
{
*
output
=
(
int16_t
)
tvp
[
i
]
->
v
.
i
64
;
*
output
=
(
int16_t
)
tvp
[
i
]
->
v
.
i
;
}
break
;
}
...
...
@@ -2032,7 +2032,7 @@ static void copyTopBotRes(SQLFunctionCtx *pCtx, int32_t type) {
case
TSDB_DATA_TYPE_TINYINT
:
{
int8_t
*
output
=
(
int8_t
*
)
pCtx
->
pOutput
;
for
(
int32_t
i
=
0
;
i
<
len
;
++
i
,
output
+=
step
)
{
*
output
=
(
int8_t
)
tvp
[
i
]
->
v
.
i
64
;
*
output
=
(
int8_t
)
tvp
[
i
]
->
v
.
i
;
}
break
;
}
...
...
@@ -2096,11 +2096,11 @@ static STopBotInfo *getTopBotOutputInfo(SQLFunctionCtx *pCtx) {
static
void
buildTopBotStruct
(
STopBotInfo
*
pTopBotInfo
,
SQLFunctionCtx
*
pCtx
)
{
char
*
tmp
=
(
char
*
)
pTopBotInfo
+
sizeof
(
STopBotInfo
);
pTopBotInfo
->
res
=
(
tValuePair
**
)
tmp
;
tmp
+=
POINTER_BYTES
*
pCtx
->
param
[
0
].
i
64
;
tmp
+=
POINTER_BYTES
*
pCtx
->
param
[
0
].
i
;
size_t
size
=
sizeof
(
tValuePair
)
+
pCtx
->
tagInfo
.
tagsLen
;
for
(
int32_t
i
=
0
;
i
<
pCtx
->
param
[
0
].
i
64
;
++
i
)
{
for
(
int32_t
i
=
0
;
i
<
pCtx
->
param
[
0
].
i
;
++
i
)
{
pTopBotInfo
->
res
[
i
]
=
(
tValuePair
*
)
tmp
;
pTopBotInfo
->
res
[
i
]
->
pTags
=
tmp
+
sizeof
(
tValuePair
);
tmp
+=
size
;
...
...
@@ -2116,11 +2116,11 @@ bool topbot_datablock_filter(SQLFunctionCtx *pCtx, const char *minval, const cha
STopBotInfo
*
pTopBotInfo
=
getTopBotOutputInfo
(
pCtx
);
// required number of results are not reached, continue load data block
if
(
pTopBotInfo
->
num
<
pCtx
->
param
[
0
].
i
64
)
{
if
(
pTopBotInfo
->
num
<
pCtx
->
param
[
0
].
i
)
{
return
true
;
}
if
((
void
*
)
pTopBotInfo
->
res
[
0
]
!=
(
void
*
)((
char
*
)
pTopBotInfo
+
sizeof
(
STopBotInfo
)
+
POINTER_BYTES
*
pCtx
->
param
[
0
].
i
64
))
{
if
((
void
*
)
pTopBotInfo
->
res
[
0
]
!=
(
void
*
)((
char
*
)
pTopBotInfo
+
sizeof
(
STopBotInfo
)
+
POINTER_BYTES
*
pCtx
->
param
[
0
].
i
))
{
buildTopBotStruct
(
pTopBotInfo
,
pCtx
);
}
...
...
@@ -2129,13 +2129,13 @@ bool topbot_datablock_filter(SQLFunctionCtx *pCtx, const char *minval, const cha
if
(
pCtx
->
functionId
==
FUNCTION_TOP
)
{
switch
(
pCtx
->
inputType
)
{
case
TSDB_DATA_TYPE_TINYINT
:
return
GET_INT8_VAL
(
maxval
)
>
pRes
[
0
]
->
v
.
i
64
;
return
GET_INT8_VAL
(
maxval
)
>
pRes
[
0
]
->
v
.
i
;
case
TSDB_DATA_TYPE_SMALLINT
:
return
GET_INT16_VAL
(
maxval
)
>
pRes
[
0
]
->
v
.
i
64
;
return
GET_INT16_VAL
(
maxval
)
>
pRes
[
0
]
->
v
.
i
;
case
TSDB_DATA_TYPE_INT
:
return
GET_INT32_VAL
(
maxval
)
>
pRes
[
0
]
->
v
.
i
64
;
return
GET_INT32_VAL
(
maxval
)
>
pRes
[
0
]
->
v
.
i
;
case
TSDB_DATA_TYPE_BIGINT
:
return
GET_INT64_VAL
(
maxval
)
>
pRes
[
0
]
->
v
.
i
64
;
return
GET_INT64_VAL
(
maxval
)
>
pRes
[
0
]
->
v
.
i
;
case
TSDB_DATA_TYPE_FLOAT
:
return
GET_FLOAT_VAL
(
maxval
)
>
pRes
[
0
]
->
v
.
d
;
case
TSDB_DATA_TYPE_DOUBLE
:
...
...
@@ -2146,13 +2146,13 @@ bool topbot_datablock_filter(SQLFunctionCtx *pCtx, const char *minval, const cha
}
else
{
switch
(
pCtx
->
inputType
)
{
case
TSDB_DATA_TYPE_TINYINT
:
return
GET_INT8_VAL
(
minval
)
<
pRes
[
0
]
->
v
.
i
64
;
return
GET_INT8_VAL
(
minval
)
<
pRes
[
0
]
->
v
.
i
;
case
TSDB_DATA_TYPE_SMALLINT
:
return
GET_INT16_VAL
(
minval
)
<
pRes
[
0
]
->
v
.
i
64
;
return
GET_INT16_VAL
(
minval
)
<
pRes
[
0
]
->
v
.
i
;
case
TSDB_DATA_TYPE_INT
:
return
GET_INT32_VAL
(
minval
)
<
pRes
[
0
]
->
v
.
i
64
;
return
GET_INT32_VAL
(
minval
)
<
pRes
[
0
]
->
v
.
i
;
case
TSDB_DATA_TYPE_BIGINT
:
return
GET_INT64_VAL
(
minval
)
<
pRes
[
0
]
->
v
.
i
64
;
return
GET_INT64_VAL
(
minval
)
<
pRes
[
0
]
->
v
.
i
;
case
TSDB_DATA_TYPE_FLOAT
:
return
GET_FLOAT_VAL
(
minval
)
<
pRes
[
0
]
->
v
.
d
;
case
TSDB_DATA_TYPE_DOUBLE
:
...
...
@@ -2179,7 +2179,7 @@ static void top_function(SQLFunctionCtx *pCtx) {
STopBotInfo
*
pRes
=
getTopBotOutputInfo
(
pCtx
);
assert
(
pRes
->
num
>=
0
);
if
((
void
*
)
pRes
->
res
[
0
]
!=
(
void
*
)((
char
*
)
pRes
+
sizeof
(
STopBotInfo
)
+
POINTER_BYTES
*
pCtx
->
param
[
0
].
i
64
))
{
if
((
void
*
)
pRes
->
res
[
0
]
!=
(
void
*
)((
char
*
)
pRes
+
sizeof
(
STopBotInfo
)
+
POINTER_BYTES
*
pCtx
->
param
[
0
].
i
))
{
buildTopBotStruct
(
pRes
,
pCtx
);
}
...
...
@@ -2193,7 +2193,7 @@ static void top_function(SQLFunctionCtx *pCtx) {
// NOTE: Set the default timestamp if it is missing [todo refactor]
TSKEY
ts
=
(
pCtx
->
ptsList
!=
NULL
)
?
GET_TS_DATA
(
pCtx
,
i
)
:
0
;
do_top_function_add
(
pRes
,
(
int32_t
)
pCtx
->
param
[
0
].
i
64
,
data
,
ts
,
pCtx
->
inputType
,
&
pCtx
->
tagInfo
,
NULL
,
0
);
do_top_function_add
(
pRes
,
(
int32_t
)
pCtx
->
param
[
0
].
i
,
data
,
ts
,
pCtx
->
inputType
,
&
pCtx
->
tagInfo
,
NULL
,
0
);
}
if
(
!
pCtx
->
hasNull
)
{
...
...
@@ -2220,7 +2220,7 @@ static void top_func_merge(SQLFunctionCtx *pCtx) {
// the intermediate result is binary, we only use the output data type
for
(
int32_t
i
=
0
;
i
<
pInput
->
num
;
++
i
)
{
int16_t
type
=
(
pCtx
->
outputType
==
TSDB_DATA_TYPE_FLOAT
)
?
TSDB_DATA_TYPE_DOUBLE
:
pCtx
->
outputType
;
do_top_function_add
(
pOutput
,
(
int32_t
)
pCtx
->
param
[
0
].
i
64
,
&
pInput
->
res
[
i
]
->
v
.
i64
,
pInput
->
res
[
i
]
->
timestamp
,
do_top_function_add
(
pOutput
,
(
int32_t
)
pCtx
->
param
[
0
].
i
,
&
pInput
->
res
[
i
]
->
v
.
i
,
pInput
->
res
[
i
]
->
timestamp
,
type
,
&
pCtx
->
tagInfo
,
pInput
->
res
[
i
]
->
pTags
,
pCtx
->
currentStage
);
}
...
...
@@ -2237,7 +2237,7 @@ static void bottom_function(SQLFunctionCtx *pCtx) {
STopBotInfo
*
pRes
=
getTopBotOutputInfo
(
pCtx
);
if
((
void
*
)
pRes
->
res
[
0
]
!=
(
void
*
)((
char
*
)
pRes
+
sizeof
(
STopBotInfo
)
+
POINTER_BYTES
*
pCtx
->
param
[
0
].
i
64
))
{
if
((
void
*
)
pRes
->
res
[
0
]
!=
(
void
*
)((
char
*
)
pRes
+
sizeof
(
STopBotInfo
)
+
POINTER_BYTES
*
pCtx
->
param
[
0
].
i
))
{
buildTopBotStruct
(
pRes
,
pCtx
);
}
...
...
@@ -2250,7 +2250,7 @@ static void bottom_function(SQLFunctionCtx *pCtx) {
notNullElems
++
;
// NOTE: Set the default timestamp if it is missing [todo refactor]
TSKEY
ts
=
(
pCtx
->
ptsList
!=
NULL
)
?
GET_TS_DATA
(
pCtx
,
i
)
:
0
;
do_bottom_function_add
(
pRes
,
(
int32_t
)
pCtx
->
param
[
0
].
i
64
,
data
,
ts
,
pCtx
->
inputType
,
&
pCtx
->
tagInfo
,
NULL
,
0
);
do_bottom_function_add
(
pRes
,
(
int32_t
)
pCtx
->
param
[
0
].
i
,
data
,
ts
,
pCtx
->
inputType
,
&
pCtx
->
tagInfo
,
NULL
,
0
);
}
if
(
!
pCtx
->
hasNull
)
{
...
...
@@ -2277,7 +2277,7 @@ static void bottom_func_merge(SQLFunctionCtx *pCtx) {
// the intermediate result is binary, we only use the output data type
for
(
int32_t
i
=
0
;
i
<
pInput
->
num
;
++
i
)
{
int16_t
type
=
(
pCtx
->
outputType
==
TSDB_DATA_TYPE_FLOAT
)
?
TSDB_DATA_TYPE_DOUBLE
:
pCtx
->
outputType
;
do_bottom_function_add
(
pOutput
,
(
int32_t
)
pCtx
->
param
[
0
].
i
64
,
&
pInput
->
res
[
i
]
->
v
.
i64
,
pInput
->
res
[
i
]
->
timestamp
,
type
,
do_bottom_function_add
(
pOutput
,
(
int32_t
)
pCtx
->
param
[
0
].
i
,
&
pInput
->
res
[
i
]
->
v
.
i
,
pInput
->
res
[
i
]
->
timestamp
,
type
,
&
pCtx
->
tagInfo
,
pInput
->
res
[
i
]
->
pTags
,
pCtx
->
currentStage
);
}
...
...
@@ -2303,11 +2303,11 @@ static void top_bottom_func_finalizer(SQLFunctionCtx *pCtx) {
tValuePair
**
tvp
=
pRes
->
res
;
// user specify the order of output by sort the result according to timestamp
if
(
pCtx
->
param
[
1
].
i
64
==
PRIMARYKEY_TIMESTAMP_COL_ID
)
{
__compar_fn_t
comparator
=
(
pCtx
->
param
[
2
].
i
64
==
TSDB_ORDER_ASC
)
?
resAscComparFn
:
resDescComparFn
;
if
(
pCtx
->
param
[
1
].
i
==
PRIMARYKEY_TIMESTAMP_COL_ID
)
{
__compar_fn_t
comparator
=
(
pCtx
->
param
[
2
].
i
==
TSDB_ORDER_ASC
)
?
resAscComparFn
:
resDescComparFn
;
qsort
(
tvp
,
(
size_t
)
pResInfo
->
numOfRes
,
POINTER_BYTES
,
comparator
);
}
else
/*if (pCtx->param[1].i
64
> PRIMARYKEY_TIMESTAMP_COL_ID)*/
{
__compar_fn_t
comparator
=
(
pCtx
->
param
[
2
].
i
64
==
TSDB_ORDER_ASC
)
?
resDataAscComparFn
:
resDataDescComparFn
;
}
else
/*if (pCtx->param[1].i > PRIMARYKEY_TIMESTAMP_COL_ID)*/
{
__compar_fn_t
comparator
=
(
pCtx
->
param
[
2
].
i
==
TSDB_ORDER_ASC
)
?
resDataAscComparFn
:
resDataDescComparFn
;
qsort
(
tvp
,
(
size_t
)
pResInfo
->
numOfRes
,
POINTER_BYTES
,
comparator
);
}
...
...
@@ -2418,7 +2418,7 @@ static void percentile_function(SQLFunctionCtx *pCtx) {
}
static
void
percentile_finalizer
(
SQLFunctionCtx
*
pCtx
)
{
double
v
=
pCtx
->
param
[
0
].
nType
==
TSDB_DATA_TYPE_INT
?
pCtx
->
param
[
0
].
i
64
:
pCtx
->
param
[
0
].
d
;
double
v
=
pCtx
->
param
[
0
].
nType
==
TSDB_DATA_TYPE_INT
?
pCtx
->
param
[
0
].
i
:
pCtx
->
param
[
0
].
d
;
SResultRowCellInfo
*
pResInfo
=
GET_RES_INFO
(
pCtx
);
SPercentileInfo
*
ppInfo
=
(
SPercentileInfo
*
)
GET_ROWCELL_INTERBUF
(
pResInfo
);
...
...
@@ -2530,7 +2530,7 @@ static void apercentile_func_merge(SQLFunctionCtx *pCtx) {
}
static
void
apercentile_finalizer
(
SQLFunctionCtx
*
pCtx
)
{
double
v
=
(
pCtx
->
param
[
0
].
nType
==
TSDB_DATA_TYPE_INT
)
?
pCtx
->
param
[
0
].
i
64
:
pCtx
->
param
[
0
].
d
;
double
v
=
(
pCtx
->
param
[
0
].
nType
==
TSDB_DATA_TYPE_INT
)
?
pCtx
->
param
[
0
].
i
:
pCtx
->
param
[
0
].
d
;
SResultRowCellInfo
*
pResInfo
=
GET_RES_INFO
(
pCtx
);
SAPercentileInfo
*
pOutput
=
GET_ROWCELL_INTERBUF
(
pResInfo
);
...
...
@@ -2725,7 +2725,7 @@ static void col_project_function(SQLFunctionCtx *pCtx) {
}
// only one row is required.
if
(
pCtx
->
param
[
0
].
i
64
==
1
)
{
if
(
pCtx
->
param
[
0
].
i
==
1
)
{
SET_VAL
(
pCtx
,
pCtx
->
size
,
1
);
}
else
{
INC_INIT_VAL
(
pCtx
,
pCtx
->
size
);
...
...
@@ -2733,7 +2733,7 @@ static void col_project_function(SQLFunctionCtx *pCtx) {
char
*
pData
=
GET_INPUT_DATA_LIST
(
pCtx
);
if
(
pCtx
->
order
==
TSDB_ORDER_ASC
)
{
int32_t
numOfRows
=
(
pCtx
->
param
[
0
].
i
64
==
1
)
?
1
:
pCtx
->
size
;
int32_t
numOfRows
=
(
pCtx
->
param
[
0
].
i
==
1
)
?
1
:
pCtx
->
size
;
memcpy
(
pCtx
->
pOutput
,
pData
,
(
size_t
)
numOfRows
*
pCtx
->
inputBytes
);
}
else
{
for
(
int32_t
i
=
0
;
i
<
pCtx
->
size
;
++
i
)
{
...
...
@@ -2811,9 +2811,9 @@ static bool deriv_function_setup(SQLFunctionCtx *pCtx, SResultRowCellInfo* pResu
// diff function require the value is set to -1
SDerivInfo
*
pDerivInfo
=
GET_ROWCELL_INTERBUF
(
pResultInfo
);
pDerivInfo
->
ignoreNegative
=
pCtx
->
param
[
1
].
i
64
;
pDerivInfo
->
ignoreNegative
=
pCtx
->
param
[
1
].
i
;
pDerivInfo
->
prevTs
=
-
1
;
pDerivInfo
->
tsWindow
=
pCtx
->
param
[
0
].
i
64
;
pDerivInfo
->
tsWindow
=
pCtx
->
param
[
0
].
i
;
pDerivInfo
->
valueSet
=
false
;
return
false
;
}
...
...
@@ -3004,10 +3004,10 @@ static void deriv_function(SQLFunctionCtx *pCtx) {
do { \
if ((ctx)->param[1].nType == INITIAL_VALUE_NOT_ASSIGNED) { \
(ctx)->param[1].nType = (ctx)->inputType; \
*(type *)&(ctx)->param[1].i
64
= *(type *)(d); \
*(type *)&(ctx)->param[1].i = *(type *)(d); \
} else { \
*(type *)(ctx)->pOutput = *(type *)(d) - (*(type *)(&(ctx)->param[1].i
64
)); \
*(type *)(&(ctx)->param[1].i
64
) = *(type *)(d); \
*(type *)(ctx)->pOutput = *(type *)(d) - (*(type *)(&(ctx)->param[1].i)); \
*(type *)(&(ctx)->param[1].i) = *(type *)(d); \
*(int64_t *)(ctx)->ptsOutputBuf = GET_TS_DATA(ctx, index); \
} \
} while (0);
...
...
@@ -3036,13 +3036,13 @@ static void diff_function(SQLFunctionCtx *pCtx) {
}
if
(
pCtx
->
param
[
1
].
nType
!=
INITIAL_VALUE_NOT_ASSIGNED
)
{
// initial value is not set yet
*
pOutput
=
(
int32_t
)(
pData
[
i
]
-
pCtx
->
param
[
1
].
i
64
);
// direct previous may be null
*
pOutput
=
(
int32_t
)(
pData
[
i
]
-
pCtx
->
param
[
1
].
i
);
// direct previous may be null
*
pTimestamp
=
(
tsList
!=
NULL
)
?
tsList
[
i
]
:
0
;
pOutput
+=
1
;
pTimestamp
+=
1
;
}
pCtx
->
param
[
1
].
i
64
=
pData
[
i
];
pCtx
->
param
[
1
].
i
=
pData
[
i
];
pCtx
->
param
[
1
].
nType
=
pCtx
->
inputType
;
notNullElems
++
;
}
...
...
@@ -3058,13 +3058,13 @@ static void diff_function(SQLFunctionCtx *pCtx) {
}
if
(
pCtx
->
param
[
1
].
nType
!=
INITIAL_VALUE_NOT_ASSIGNED
)
{
// initial value is not set yet
*
pOutput
=
pData
[
i
]
-
pCtx
->
param
[
1
].
i
64
;
// direct previous may be null
*
pOutput
=
pData
[
i
]
-
pCtx
->
param
[
1
].
i
;
// direct previous may be null
*
pTimestamp
=
(
tsList
!=
NULL
)
?
tsList
[
i
]
:
0
;
pOutput
+=
1
;
pTimestamp
+=
1
;
}
pCtx
->
param
[
1
].
i
64
=
pData
[
i
];
pCtx
->
param
[
1
].
i
=
pData
[
i
];
pCtx
->
param
[
1
].
nType
=
pCtx
->
inputType
;
notNullElems
++
;
}
...
...
@@ -3124,13 +3124,13 @@ static void diff_function(SQLFunctionCtx *pCtx) {
}
if
(
pCtx
->
param
[
1
].
nType
!=
INITIAL_VALUE_NOT_ASSIGNED
)
{
// initial value is not set yet
*
pOutput
=
(
int16_t
)(
pData
[
i
]
-
pCtx
->
param
[
1
].
i
64
);
// direct previous may be null
*
pOutput
=
(
int16_t
)(
pData
[
i
]
-
pCtx
->
param
[
1
].
i
);
// direct previous may be null
*
pTimestamp
=
(
tsList
!=
NULL
)
?
tsList
[
i
]
:
0
;
pOutput
+=
1
;
pTimestamp
+=
1
;
}
pCtx
->
param
[
1
].
i
64
=
pData
[
i
];
pCtx
->
param
[
1
].
i
=
pData
[
i
];
pCtx
->
param
[
1
].
nType
=
pCtx
->
inputType
;
notNullElems
++
;
}
...
...
@@ -3147,13 +3147,13 @@ static void diff_function(SQLFunctionCtx *pCtx) {
}
if
(
pCtx
->
param
[
1
].
nType
!=
INITIAL_VALUE_NOT_ASSIGNED
)
{
// initial value is not set yet
*
pOutput
=
(
int8_t
)(
pData
[
i
]
-
pCtx
->
param
[
1
].
i
64
);
// direct previous may be null
*
pOutput
=
(
int8_t
)(
pData
[
i
]
-
pCtx
->
param
[
1
].
i
);
// direct previous may be null
*
pTimestamp
=
(
tsList
!=
NULL
)
?
tsList
[
i
]
:
0
;
pOutput
+=
1
;
pTimestamp
+=
1
;
}
pCtx
->
param
[
1
].
i
64
=
pData
[
i
];
pCtx
->
param
[
1
].
i
=
pData
[
i
];
pCtx
->
param
[
1
].
nType
=
pCtx
->
inputType
;
notNullElems
++
;
}
...
...
@@ -3707,7 +3707,7 @@ void twa_function_finalizer(SQLFunctionCtx *pCtx) {
*/
static
void
interp_function_impl
(
SQLFunctionCtx
*
pCtx
)
{
int32_t
type
=
(
int32_t
)
pCtx
->
param
[
2
].
i
64
;
int32_t
type
=
(
int32_t
)
pCtx
->
param
[
2
].
i
;
if
(
type
==
TSDB_FILL_NONE
)
{
return
;
}
...
...
@@ -3891,11 +3891,11 @@ static void ts_comp_function(SQLFunctionCtx *pCtx) {
// primary ts must be existed, so no need to check its existance
if
(
pCtx
->
order
==
TSDB_ORDER_ASC
)
{
tsBufAppend
(
pTSbuf
,
(
int32_t
)
pCtx
->
param
[
0
].
i
64
,
&
pCtx
->
tag
,
input
,
pCtx
->
size
*
TSDB_KEYSIZE
);
tsBufAppend
(
pTSbuf
,
(
int32_t
)
pCtx
->
param
[
0
].
i
,
&
pCtx
->
tag
,
input
,
pCtx
->
size
*
TSDB_KEYSIZE
);
}
else
{
for
(
int32_t
i
=
pCtx
->
size
-
1
;
i
>=
0
;
--
i
)
{
char
*
d
=
GET_INPUT_DATA
(
pCtx
,
i
);
tsBufAppend
(
pTSbuf
,
(
int32_t
)
pCtx
->
param
[
0
].
i
64
,
&
pCtx
->
tag
,
d
,
(
int32_t
)
TSDB_KEYSIZE
);
tsBufAppend
(
pTSbuf
,
(
int32_t
)
pCtx
->
param
[
0
].
i
,
&
pCtx
->
tag
,
d
,
(
int32_t
)
TSDB_KEYSIZE
);
}
}
...
...
@@ -4047,7 +4047,7 @@ static void rate_finalizer(SQLFunctionCtx *pCtx) {
return
;
}
SET_DOUBLE_VAL
((
double
*
)
pCtx
->
pOutput
,
do_calc_rate
(
pRateInfo
,
(
double
)
TSDB_TICK_PER_SECOND
(
pCtx
->
param
[
0
].
i
64
)));
SET_DOUBLE_VAL
((
double
*
)
pCtx
->
pOutput
,
do_calc_rate
(
pRateInfo
,
(
double
)
TSDB_TICK_PER_SECOND
(
pCtx
->
param
[
0
].
i
)));
// cannot set the numOfIteratedElems again since it is set during previous iteration
pResInfo
->
numOfRes
=
1
;
...
...
@@ -4144,7 +4144,7 @@ static void blockInfo_func(SQLFunctionCtx* pCtx) {
int32_t
len
=
*
(
int32_t
*
)
pCtx
->
pInput
;
blockDistInfoFromBinary
((
char
*
)
pCtx
->
pInput
+
sizeof
(
int32_t
),
len
,
pDist
);
pDist
->
rowSize
=
(
uint16_t
)
pCtx
->
param
[
0
].
i
64
;
pDist
->
rowSize
=
(
uint16_t
)
pCtx
->
param
[
0
].
i
;
memcpy
(
pCtx
->
pOutput
,
pCtx
->
pInput
,
sizeof
(
int32_t
)
+
len
);
...
...
@@ -4296,7 +4296,7 @@ void blockinfo_func_finalizer(SQLFunctionCtx* pCtx) {
SResultRowCellInfo
*
pResInfo
=
GET_RES_INFO
(
pCtx
);
STableBlockDist
*
pDist
=
(
STableBlockDist
*
)
GET_ROWCELL_INTERBUF
(
pResInfo
);
pDist
->
rowSize
=
(
uint16_t
)
pCtx
->
param
[
0
].
i
64
;
pDist
->
rowSize
=
(
uint16_t
)
pCtx
->
param
[
0
].
i
;
generateBlockDistResult
(
pDist
,
pCtx
->
pOutput
);
if
(
pDist
->
dataBlockInfos
!=
NULL
)
{
...
...
source/libs/function/src/texpr.c
浏览文件 @
b4ff474e
...
...
@@ -228,7 +228,7 @@ void arithmeticTreeTraverse(tExprNode *pExprs, int32_t numOfRows, char *pOutput,
} else if (pRight->nodeType == TEXPR_VALUE_NODE) { // exprLeft + 12
_arithmetic_operator_fn_t OperatorFn = getArithmeticOperatorFn(pExprs->_node.optr);
OperatorFn(pLeftOutput, numOfRows, TSDB_DATA_TYPE_DOUBLE, &pRight->pVal->i
64
, 1, pRight->pVal->nType, pOutput, TSDB_ORDER_ASC);
OperatorFn(pLeftOutput, numOfRows, TSDB_DATA_TYPE_DOUBLE, &pRight->pVal->i, 1, pRight->pVal->nType, pOutput, TSDB_ORDER_ASC);
}
} else if (pLeft->nodeType == TEXPR_COL_NODE) {
// column data specified on left-hand-side
...
...
@@ -255,16 +255,16 @@ void arithmeticTreeTraverse(tExprNode *pExprs, int32_t numOfRows, char *pOutput,
if (order == TSDB_ORDER_DESC) {
reverseCopy(pdata, pLeftInputData, pLeft->pSchema->type, numOfRows);
OperatorFn(pdata, numOfRows, pLeft->pSchema->type, &pRight->pVal->i
64
, 1, pRight->pVal->nType, pOutput, TSDB_ORDER_ASC);
OperatorFn(pdata, numOfRows, pLeft->pSchema->type, &pRight->pVal->i, 1, pRight->pVal->nType, pOutput, TSDB_ORDER_ASC);
} else {
OperatorFn(pLeftInputData, numOfRows, pLeft->pSchema->type, &pRight->pVal->i
64
, 1, pRight->pVal->nType, pOutput, TSDB_ORDER_ASC);
OperatorFn(pLeftInputData, numOfRows, pLeft->pSchema->type, &pRight->pVal->i, 1, pRight->pVal->nType, pOutput, TSDB_ORDER_ASC);
}
}
} else {
// column data specified on left-hand-side
if (pRight->nodeType == TEXPR_BINARYEXPR_NODE) { // 12 + expr2
_arithmetic_operator_fn_t OperatorFn = getArithmeticOperatorFn(pExprs->_node.optr);
OperatorFn(&pLeft->pVal->i
64
, 1, pLeft->pVal->nType, pRightOutput, numOfRows, TSDB_DATA_TYPE_DOUBLE, pOutput, TSDB_ORDER_ASC);
OperatorFn(&pLeft->pVal->i, 1, pLeft->pVal->nType, pRightOutput, numOfRows, TSDB_DATA_TYPE_DOUBLE, pOutput, TSDB_ORDER_ASC);
} else if (pRight->nodeType == TEXPR_COL_NODE) { // 12 + columnRight
// column data specified on right-hand-side
...
...
@@ -273,14 +273,14 @@ void arithmeticTreeTraverse(tExprNode *pExprs, int32_t numOfRows, char *pOutput,
if (order == TSDB_ORDER_DESC) {
reverseCopy(pdata, pRightInputData, pRight->pSchema->type, numOfRows);
OperatorFn(&pLeft->pVal->i
64
, 1, pLeft->pVal->nType, pdata, numOfRows, pRight->pSchema->type, pOutput, TSDB_ORDER_ASC);
OperatorFn(&pLeft->pVal->i, 1, pLeft->pVal->nType, pdata, numOfRows, pRight->pSchema->type, pOutput, TSDB_ORDER_ASC);
} else {
OperatorFn(&pLeft->pVal->i
64
, 1, pLeft->pVal->nType, pRightInputData, numOfRows, pRight->pSchema->type, pOutput, TSDB_ORDER_ASC);
OperatorFn(&pLeft->pVal->i, 1, pLeft->pVal->nType, pRightInputData, numOfRows, pRight->pSchema->type, pOutput, TSDB_ORDER_ASC);
}
} else if (pRight->nodeType == TEXPR_VALUE_NODE) { // 12 + 12
_arithmetic_operator_fn_t OperatorFn = getArithmeticOperatorFn(pExprs->_node.optr);
OperatorFn(&pLeft->pVal->i
64, 1, pLeft->pVal->nType, &pRight->pVal->i64
, 1, pRight->pVal->nType, pOutput, TSDB_ORDER_ASC);
OperatorFn(&pLeft->pVal->i
, 1, pLeft->pVal->nType, &pRight->pVal->i
, 1, pRight->pVal->nType, pOutput, TSDB_ORDER_ASC);
}
}
...
...
@@ -302,7 +302,7 @@ static void exprTreeToBinaryImpl(SBufferWriter* bw, tExprNode* expr) {
tbufWriteInt32
(
bw
,
pVal
->
nLen
);
tbufWrite
(
bw
,
pVal
->
pz
,
pVal
->
nLen
);
}
else
{
tbufWriteInt64
(
bw
,
pVal
->
i
64
);
tbufWriteInt64
(
bw
,
pVal
->
i
);
}
}
else
if
(
expr
->
nodeType
==
TEXPR_COL_NODE
)
{
...
...
@@ -371,7 +371,7 @@ static tExprNode* exprTreeFromBinaryImpl(SBufferReader* br) {
pVal
->
pz
=
calloc
(
1
,
pVal
->
nLen
+
1
);
tbufReadToBuffer
(
br
,
pVal
->
pz
,
pVal
->
nLen
);
}
else
{
pVal
->
i
64
=
tbufReadInt64
(
br
);
pVal
->
i
=
tbufReadInt64
(
br
);
}
}
else
if
(
pExpr
->
nodeType
==
TEXPR_COL_NODE
)
{
...
...
source/libs/function/src/ttszip.c
浏览文件 @
b4ff474e
...
...
@@ -276,7 +276,7 @@ static void writeDataToDisk(STSBuf* pTSBuf) {
metaLen
+=
(
int32_t
)
fwrite
(
&
tfloat
,
1
,
(
size_t
)
pBlock
->
tag
.
nLen
,
pTSBuf
->
f
);
}
else
if
(
pBlock
->
tag
.
nType
!=
TSDB_DATA_TYPE_NULL
)
{
metaLen
+=
(
int32_t
)
fwrite
(
&
pBlock
->
tag
.
nLen
,
1
,
sizeof
(
pBlock
->
tag
.
nLen
),
pTSBuf
->
f
);
metaLen
+=
(
int32_t
)
fwrite
(
&
pBlock
->
tag
.
i
64
,
1
,
(
size_t
)
pBlock
->
tag
.
nLen
,
pTSBuf
->
f
);
metaLen
+=
(
int32_t
)
fwrite
(
&
pBlock
->
tag
.
i
,
1
,
(
size_t
)
pBlock
->
tag
.
nLen
,
pTSBuf
->
f
);
}
else
{
trueLen
=
0
;
metaLen
+=
(
int32_t
)
fwrite
(
&
trueLen
,
1
,
sizeof
(
pBlock
->
tag
.
nLen
),
pTSBuf
->
f
);
...
...
@@ -364,7 +364,7 @@ STSBlock* readDataFromDisk(STSBuf* pTSBuf, int32_t order, bool decomp) {
pBlock
->
tag
.
d
=
(
double
)
tfloat
;
UNUSED
(
sz
);
}
else
if
(
pBlock
->
tag
.
nType
!=
TSDB_DATA_TYPE_NULL
)
{
//TODO check the return value
sz
=
fread
(
&
pBlock
->
tag
.
i
64
,
(
size_t
)
pBlock
->
tag
.
nLen
,
1
,
pTSBuf
->
f
);
sz
=
fread
(
&
pBlock
->
tag
.
i
,
(
size_t
)
pBlock
->
tag
.
nLen
,
1
,
pTSBuf
->
f
);
UNUSED
(
sz
);
}
...
...
@@ -984,7 +984,7 @@ void tsBufDisplay(STSBuf* pTSBuf) {
while
(
tsBufNextPos
(
pTSBuf
))
{
STSElem
elem
=
tsBufGetElem
(
pTSBuf
);
if
(
elem
.
tag
->
nType
==
TSDB_DATA_TYPE_BIGINT
)
{
printf
(
"%d-%"
PRId64
"-%"
PRId64
"
\n
"
,
elem
.
id
,
elem
.
tag
->
i
64
,
elem
.
ts
);
printf
(
"%d-%"
PRId64
"-%"
PRId64
"
\n
"
,
elem
.
id
,
elem
.
tag
->
i
,
elem
.
ts
);
}
}
...
...
source/libs/parser/inc/queryInfoUtil.h
浏览文件 @
b4ff474e
...
...
@@ -27,7 +27,6 @@ int32_t getNumOfColumns(const STableMeta* pTableMeta);
int32_t
getNumOfTags
(
const
STableMeta
*
pTableMeta
);
SSchema
*
getTableColumnSchema
(
const
STableMeta
*
pTableMeta
);
SSchema
*
getTableTagSchema
(
const
STableMeta
*
pTableMeta
);
SSchema
*
getOneColumnSchema
(
const
STableMeta
*
pTableMeta
,
int32_t
colIndex
);
size_t
getNumOfExprs
(
SQueryStmtInfo
*
pQueryInfo
);
SExprInfo
*
createBinaryExprInfo
(
struct
tExprNode
*
pNode
,
SSchema
*
pResSchema
);
...
...
source/libs/parser/src/astGenerator.c
浏览文件 @
b4ff474e
...
...
@@ -375,25 +375,25 @@ void tSqlExprEvaluate(tSqlExpr* pExpr) {
switch
(
optrType
)
{
case
TK_PLUS
:
{
pExpr
->
value
.
i
64
=
pLeft
->
value
.
i64
+
pRight
->
value
.
i64
;
pExpr
->
value
.
i
=
pLeft
->
value
.
i
+
pRight
->
value
.
i
;
break
;
}
case
TK_MINUS
:
{
pExpr
->
value
.
i
64
=
pLeft
->
value
.
i64
-
pRight
->
value
.
i64
;
pExpr
->
value
.
i
=
pLeft
->
value
.
i
-
pRight
->
value
.
i
;
break
;
}
case
TK_STAR
:
{
pExpr
->
value
.
i
64
=
pLeft
->
value
.
i64
*
pRight
->
value
.
i64
;
pExpr
->
value
.
i
=
pLeft
->
value
.
i
*
pRight
->
value
.
i
;
break
;
}
case
TK_DIVIDE
:
{
pExpr
->
tokenId
=
TK_FLOAT
;
pExpr
->
value
.
nType
=
TSDB_DATA_TYPE_DOUBLE
;
pExpr
->
value
.
d
=
(
double
)
pLeft
->
value
.
i
64
/
pRight
->
value
.
i64
;
pExpr
->
value
.
d
=
(
double
)
pLeft
->
value
.
i
/
pRight
->
value
.
i
;
break
;
}
case
TK_REM
:
{
pExpr
->
value
.
i
64
=
pLeft
->
value
.
i64
%
pRight
->
value
.
i64
;
pExpr
->
value
.
i
=
pLeft
->
value
.
i
%
pRight
->
value
.
i
;
break
;
}
default:
...
...
@@ -411,8 +411,8 @@ void tSqlExprEvaluate(tSqlExpr* pExpr) {
pExpr
->
tokenId
=
TK_FLOAT
;
pExpr
->
type
=
SQL_NODE_VALUE
;
double
left
=
(
pLeft
->
value
.
nType
==
TSDB_DATA_TYPE_DOUBLE
)
?
pLeft
->
value
.
d
:
pLeft
->
value
.
i
64
;
double
right
=
(
pRight
->
value
.
nType
==
TSDB_DATA_TYPE_DOUBLE
)
?
pRight
->
value
.
d
:
pRight
->
value
.
i
64
;
double
left
=
(
pLeft
->
value
.
nType
==
TSDB_DATA_TYPE_DOUBLE
)
?
pLeft
->
value
.
d
:
pLeft
->
value
.
i
;
double
right
=
(
pRight
->
value
.
nType
==
TSDB_DATA_TYPE_DOUBLE
)
?
pRight
->
value
.
d
:
pRight
->
value
.
i
;
switch
(
optrType
)
{
case
TK_PLUS
:
{
...
...
source/libs/parser/src/astValidate.c
浏览文件 @
b4ff474e
...
...
@@ -36,6 +36,8 @@
#define COLUMN_INDEX_INITIALIZER { COLUMN_INDEX_INITIAL_VAL, COLUMN_INDEX_INITIAL_VAL }
static
int32_t
validateSelectNodeList
(
SQueryStmtInfo
*
pQueryInfo
,
SArray
*
pSelNodeList
,
bool
outerQuery
,
SMsgBuf
*
pMsgBuf
);
static
int32_t
extractFunctionParameterInfo
(
SQueryStmtInfo
*
pQueryInfo
,
int32_t
tokenId
,
STableMetaInfo
**
pTableMetaInfo
,
SSchema
*
columnSchema
,
tExprNode
**
pNode
,
SColumnIndex
*
pIndex
,
tSqlExprItem
*
pParamElem
,
SMsgBuf
*
pMsgBuf
);
void
setTokenAndResColumnName
(
tSqlExprItem
*
pItem
,
char
*
resColumnName
,
char
*
rawName
,
int32_t
nameLength
)
{
memset
(
resColumnName
,
0
,
nameLength
);
...
...
@@ -51,19 +53,15 @@ void setTokenAndResColumnName(tSqlExprItem* pItem, char* resColumnName, char* ra
}
}
size_t
tscNumOfExprs
(
SQueryStmtInfo
*
pQueryInfo
)
{
return
taosArrayGetSize
(
pQueryInfo
->
exprList
);
}
static
int32_t
evaluateImpl
(
tSqlExpr
*
pExpr
,
int32_t
tsPrecision
)
{
static
int32_t
evaluateSqlNodeImpl
(
tSqlExpr
*
pExpr
,
int32_t
tsPrecision
)
{
int32_t
code
=
0
;
if
(
pExpr
->
type
==
SQL_NODE_EXPR
)
{
code
=
evaluateImpl
(
pExpr
->
pLeft
,
tsPrecision
);
code
=
evaluate
SqlNode
Impl
(
pExpr
->
pLeft
,
tsPrecision
);
if
(
code
!=
TSDB_CODE_SUCCESS
)
{
return
code
;
}
code
=
evaluateImpl
(
pExpr
->
pRight
,
tsPrecision
);
code
=
evaluate
SqlNode
Impl
(
pExpr
->
pRight
,
tsPrecision
);
if
(
code
!=
TSDB_CODE_SUCCESS
)
{
return
code
;
}
...
...
@@ -84,13 +82,13 @@ static int32_t evaluateImpl(tSqlExpr* pExpr, int32_t tsPrecision) {
}
}
else
if
(
pExpr
->
type
==
SQL_NODE_VALUE
)
{
if
(
pExpr
->
tokenId
==
TK_NOW
)
{
pExpr
->
value
.
i
64
=
taosGetTimestamp
(
tsPrecision
);
pExpr
->
value
.
i
=
taosGetTimestamp
(
tsPrecision
);
pExpr
->
value
.
nType
=
TSDB_DATA_TYPE_BIGINT
;
pExpr
->
tokenId
=
TK_TIMESTAMP
;
}
else
if
(
pExpr
->
tokenId
==
TK_VARIABLE
)
{
char
unit
=
0
;
SToken
*
pToken
=
&
pExpr
->
exprToken
;
int32_t
ret
=
parseAbsoluteDuration
(
pToken
->
z
,
pToken
->
n
,
&
pExpr
->
value
.
i
64
,
&
unit
,
tsPrecision
);
int32_t
ret
=
parseAbsoluteDuration
(
pToken
->
z
,
pToken
->
n
,
&
pExpr
->
value
.
i
,
&
unit
,
tsPrecision
);
if
(
ret
!=
TSDB_CODE_SUCCESS
)
{
return
TSDB_CODE_TSC_SQL_SYNTAX_ERROR
;
}
...
...
@@ -109,28 +107,18 @@ static int32_t evaluateImpl(tSqlExpr* pExpr, int32_t tsPrecision) {
return
TSDB_CODE_SUCCESS
;
// other types of data are handled in the parent level.
}
return
TSDB_CODE_SUCCESS
;
}
typedef
struct
SVgroupTableInfo
{
SVgroupMsg
vgInfo
;
SArray
*
itemList
;
// SArray<STableIdInfo>
}
SVgroupTableInfo
;
void
freeVgroupTableInfo
(
SArray
*
pVgroupTables
)
{
if
(
pVgroupTables
==
NULL
)
{
return
;
}
}
else
if
(
pExpr
->
type
==
SQL_NODE_SQLFUNCTION
)
{
SArray
*
pParam
=
pExpr
->
Expr
.
paramList
;
size_t
num
=
taosArrayGetSize
(
pVgroupTables
);
for
(
size_t
i
=
0
;
i
<
num
;
i
++
)
{
SVgroupTableInfo
*
pInfo
=
taosArrayGet
(
pVgroupTables
,
i
);
taosArrayDestroy
(
pInfo
->
itemList
);
if
(
pParam
!=
NULL
)
{
for
(
int32_t
i
=
0
;
i
<
taosArrayGetSize
(
pParam
);
++
i
)
{
tSqlExprItem
*
pItem
=
taosArrayGet
(
pParam
,
i
);
evaluateSqlNodeImpl
(
pItem
->
pNode
,
tsPrecision
);
}
}
}
taosArrayDestroy
(
pVgroupTables
)
;
return
TSDB_CODE_SUCCESS
;
}
void
destroyFilterInfo
(
SColumnFilterList
*
pFilterList
)
{
...
...
@@ -183,7 +171,7 @@ void clearTableMetaInfo(STableMetaInfo* pTableMetaInfo) {
}
static
STableMeta
*
extractTempTableMetaFromSubquery
(
SQueryStmtInfo
*
pUpstream
)
{
STableMetaInfo
*
pUpstreamTableMetaInfo
/*= getMetaInfo(pUpstream, 0)*/
;
STableMetaInfo
*
pUpstreamTableMetaInfo
=
getMetaInfo
(
pUpstream
,
0
)
;
int32_t
numOfColumns
=
pUpstream
->
fieldsInfo
.
numOfOutput
;
STableMeta
*
meta
=
calloc
(
1
,
sizeof
(
STableMeta
)
+
sizeof
(
SSchema
)
*
numOfColumns
);
...
...
@@ -196,20 +184,14 @@ static STableMeta* extractTempTableMetaFromSubquery(SQueryStmtInfo* pUpstream) {
int32_t
n
=
0
;
for
(
int32_t
i
=
0
;
i
<
numOfColumns
;
++
i
)
{
// SInternalField* pField = tscFieldInfoGetInternalField(&pUpstream->fieldsInfo, i);
// if (!pField->visible) {
// continue;
// }
//
// meta->schema[n].bytes = pField->field.bytes;
// meta->schema[n].type = pField->field.type;
//
// SExprInfo* pExpr = pField->pExpr;
// meta->schema[n].colId = pExpr->base.resColId;
// tstrncpy(meta->schema[n].name, pField->pExpr->base.aliasName, TSDB_COL_NAME_LEN);
// info->rowSize += meta->schema[n].bytes;
//
// n += 1;
SInternalField
*
pField
=
getInternalField
(
&
pUpstream
->
fieldsInfo
,
i
);
if
(
!
pField
->
visible
)
{
continue
;
}
meta
->
schema
[
n
]
=
pField
->
pExpr
->
base
.
resSchema
;
info
->
rowSize
+=
meta
->
schema
[
n
].
bytes
;
n
+=
1
;
}
info
->
numOfColumns
=
n
;
...
...
@@ -501,9 +483,15 @@ int32_t validateGroupbyNode(SQueryStmtInfo* pQueryInfo, SArray* pList, SMsgBuf*
const
char
*
msg4
=
"join query does not support group by"
;
const
char
*
msg5
=
"not allowed column type for group by"
;
const
char
*
msg6
=
"tags not allowed for table query"
;
const
char
*
msg7
=
"no
t support group by expression
"
;
const
char
*
msg7
=
"no
rmal column and tags can not be mixed up in group by clause
"
;
const
char
*
msg8
=
"normal column can only locate at the end of group by clause"
;
SGroupbyExpr
*
pGroupExpr
=
&
(
pQueryInfo
->
groupbyExpr
);
pGroupExpr
->
columnInfo
=
taosArrayInit
(
4
,
sizeof
(
SColIndex
));
if
(
pGroupExpr
->
columnInfo
==
NULL
)
{
return
TSDB_CODE_TSC_OUT_OF_MEMORY
;
}
// todo : handle two tables situation
STableMetaInfo
*
pTableMetaInfo
=
NULL
;
if
(
pList
==
NULL
)
{
...
...
@@ -514,12 +502,6 @@ int32_t validateGroupbyNode(SQueryStmtInfo* pQueryInfo, SArray* pList, SMsgBuf*
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg4
);
}
SGroupbyExpr
*
pGroupExpr
=
&
(
pQueryInfo
->
groupbyExpr
);
pGroupExpr
->
columnInfo
=
taosArrayInit
(
4
,
sizeof
(
SColIndex
));
if
(
pGroupExpr
->
columnInfo
==
NULL
)
{
return
TSDB_CODE_TSC_OUT_OF_MEMORY
;
}
size_t
num
=
taosArrayGetSize
(
pList
);
if
(
num
>
TSDB_MAX_TAGS
)
{
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg1
);
...
...
@@ -528,6 +510,7 @@ int32_t validateGroupbyNode(SQueryStmtInfo* pQueryInfo, SArray* pList, SMsgBuf*
int32_t
numOfGroupbyCols
=
0
;
SSchema
*
pSchema
=
NULL
;
int32_t
tableIndex
=
COLUMN_INDEX_INITIAL_VAL
;
bool
groupbyTag
=
false
;
for
(
int32_t
i
=
0
;
i
<
num
;
++
i
)
{
SListItem
*
pItem
=
taosArrayGet
(
pList
,
i
);
...
...
@@ -561,6 +544,8 @@ int32_t validateGroupbyNode(SQueryStmtInfo* pQueryInfo, SArray* pList, SMsgBuf*
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg6
);
}
groupbyTag
=
true
;
int32_t
relIndex
=
index
.
columnIndex
;
if
(
index
.
columnIndex
!=
TSDB_TBNAME_COLUMN_INDEX
)
{
relIndex
-=
getNumOfColumns
(
pTableMeta
);
...
...
@@ -590,12 +575,12 @@ int32_t validateGroupbyNode(SQueryStmtInfo* pQueryInfo, SArray* pList, SMsgBuf*
}
}
// 1. only one normal column allowed in the group by clause
// 2. the normal column in the group by clause can only located at the end position
if
(
numOfGroupbyCols
>
1
)
{
if
(
numOfGroupbyCols
>
0
&&
groupbyTag
)
{
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg7
);
}
// todo ???
// 1. the normal column in the group by clause can only located at the end position
for
(
int32_t
i
=
0
;
i
<
num
;
++
i
)
{
SColIndex
*
pIndex
=
taosArrayGet
(
pGroupExpr
->
columnInfo
,
i
);
if
(
TSDB_COL_IS_NORMAL_COL
(
pIndex
->
flag
)
&&
i
!=
num
-
1
)
{
...
...
@@ -608,29 +593,30 @@ int32_t validateGroupbyNode(SQueryStmtInfo* pQueryInfo, SArray* pList, SMsgBuf*
return
TSDB_CODE_SUCCESS
;
}
int32_t
filterUnsupportedQueryFunction
(
SQueryStmtInfo
*
pQueryInfo
,
SMsgBuf
*
pMsgBuf
)
{
// todo NOT support yet
const
char
*
msg6
=
"not support stddev/percentile/interp in the outer query yet"
;
const
char
*
msg9
=
"not support 3 level select"
;
int32_t
checkForUnsupportedQuery
(
SQueryStmtInfo
*
pQueryInfo
,
SMsgBuf
*
pMsgBuf
)
{
const
char
*
msg1
=
"not support percentile/interp/block_dist in the outer query yet"
;
for
(
int32_t
i
=
0
;
i
<
tsc
NumOfExprs
(
pQueryInfo
);
++
i
)
{
for
(
int32_t
i
=
0
;
i
<
get
NumOfExprs
(
pQueryInfo
);
++
i
)
{
SExprInfo
*
pExpr
=
getExprInfo
(
pQueryInfo
,
i
);
assert
(
pExpr
->
pExpr
->
nodeType
==
TEXPR_UNARYEXPR_NODE
);
int32_t
f
=
pExpr
->
pExpr
->
_node
.
functionId
;
if
(
f
==
FUNCTION_
STDDEV
||
f
==
FUNCTION_
PERCT
||
f
==
FUNCTION_INTERP
)
{
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg
6
);
int32_t
f
=
getExprFunctionId
(
pExpr
)
;
if
(
f
==
FUNCTION_PERCT
||
f
==
FUNCTION_INTERP
)
{
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg
1
);
}
if
(
f
==
FUNCTION_BLKINFO
&&
taosArrayGetSize
(
pQueryInfo
->
pUpstream
)
>
0
)
{
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg
9
);
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg
1
);
}
#if 0
//todo planner handle this
if (/*(timeWindowQuery || pQueryInfo->stateWindow) &&*/ f == FUNCTION_LAST) {
pExpr->base.numOfParams = 1;
pExpr
->
base
.
param
[
0
].
i
64
=
TSDB_ORDER_ASC
;
pExpr->base.param[0].i = TSDB_ORDER_ASC;
pExpr->base.param[0].nType = TSDB_DATA_TYPE_INT;
}
#endif
}
}
...
...
@@ -644,34 +630,36 @@ static int32_t parseIntervalOffset(SQueryStmtInfo* pQueryInfo, SToken* offsetTok
const
char
*
msg3
=
"cannot use 'year' as offset when interval is 'month'"
;
SToken
*
t
=
offsetToken
;
SInterval
*
pInterval
=
&
pQueryInfo
->
interval
;
if
(
t
->
n
==
0
)
{
p
QueryInfo
->
interval
.
offsetUnit
=
pQueryInfo
->
interval
.
intervalUnit
;
p
QueryInfo
->
interval
.
offset
=
0
;
p
Interval
->
offsetUnit
=
pInterval
->
intervalUnit
;
p
Interval
->
offset
=
0
;
return
TSDB_CODE_SUCCESS
;
}
if
(
parseNatualDuration
(
t
->
z
,
t
->
n
,
&
p
QueryInfo
->
interval
.
offset
,
&
pQueryInfo
->
interval
.
offsetUnit
,
precision
)
!=
TSDB_CODE_SUCCESS
)
{
if
(
parseNatualDuration
(
t
->
z
,
t
->
n
,
&
p
Interval
->
offset
,
&
pInterval
->
offsetUnit
,
precision
)
!=
TSDB_CODE_SUCCESS
)
{
return
TSDB_CODE_TSC_INVALID_OPERATION
;
}
if
(
p
QueryInfo
->
interval
.
offset
<
0
)
{
if
(
p
Interval
->
offset
<
0
)
{
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg1
);
}
if
(
!
TIME_IS_VAR_DURATION
(
p
QueryInfo
->
interval
.
offsetUnit
))
{
if
(
!
TIME_IS_VAR_DURATION
(
p
QueryInfo
->
interval
.
intervalUnit
))
{
if
(
p
QueryInfo
->
interval
.
offset
>
pQueryInfo
->
interval
.
interval
)
{
if
(
!
TIME_IS_VAR_DURATION
(
p
Interval
->
offsetUnit
))
{
if
(
!
TIME_IS_VAR_DURATION
(
p
Interval
->
intervalUnit
))
{
if
(
p
Interval
->
offset
>
pInterval
->
interval
)
{
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg2
);
}
}
}
else
if
(
p
QueryInfo
->
interval
.
offsetUnit
==
pQueryInfo
->
interval
.
intervalUnit
)
{
if
(
p
QueryInfo
->
interval
.
offset
>=
pQueryInfo
->
interval
.
interval
)
{
}
else
if
(
p
Interval
->
offsetUnit
==
pInterval
->
intervalUnit
)
{
if
(
p
Interval
->
offset
>=
pInterval
->
interval
)
{
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg2
);
}
}
else
if
(
p
QueryInfo
->
interval
.
intervalUnit
==
'n'
&&
pQueryInfo
->
interval
.
offsetUnit
==
'y'
)
{
}
else
if
(
p
Interval
->
intervalUnit
==
'n'
&&
pInterval
->
offsetUnit
==
'y'
)
{
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg3
);
}
else
if
(
p
QueryInfo
->
interval
.
intervalUnit
==
'y'
&&
pQueryInfo
->
interval
.
offsetUnit
==
'n'
)
{
if
(
p
QueryInfo
->
interval
.
interval
*
12
<=
pQueryInfo
->
interval
.
offset
)
{
}
else
if
(
p
Interval
->
intervalUnit
==
'y'
&&
pInterval
->
offsetUnit
==
'n'
)
{
if
(
p
Interval
->
interval
*
12
<=
pQueryInfo
->
interval
.
offset
)
{
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg2
);
}
}
else
{
...
...
@@ -777,10 +765,6 @@ int32_t validateIntervalNode(SQueryStmtInfo *pQueryInfo, SSqlNode* pSqlNode, SMs
// if ((pSqlNode->interval.token == TK_EVERY && (!interpQuery)) || (pSqlNode->interval.token == TK_INTERVAL && interpQuery)) {
// return buildInvalidOperationMsg(pMsgBuf, msg4);
// }
// The following part is used to check for the invalid query expression.
// return checkInvalidExprForTimeWindow(pCmd, pQueryInfo);
}
int32_t
validateSessionNode
(
SQueryStmtInfo
*
pQueryInfo
,
SSessionWindowVal
*
pSession
,
int32_t
precision
,
SMsgBuf
*
pMsgBuf
)
{
...
...
@@ -825,8 +809,6 @@ int32_t validateSessionNode(SQueryStmtInfo *pQueryInfo, SSessionWindowVal* pSess
pQueryInfo
->
sessionWindow
.
primaryColId
=
PRIMARYKEY_TIMESTAMP_COL_ID
;
return
TSDB_CODE_SUCCESS
;
// The following part is used to check for the invalid query expression.
// return checkInvalidExprForTimeWindow(pCmd, pQueryInfo);
}
// parse the window_state
...
...
@@ -948,7 +930,6 @@ int32_t validateLimitNode(SQueryStmtInfo *pQueryInfo, SSqlNode* pSqlNode, SMsgBu
static
void
setTsOutputExprInfo
(
SQueryStmtInfo
*
pQueryInfo
,
STableMetaInfo
*
pTableMetaInfo
,
int32_t
outputIndex
,
int32_t
tableIndex
);
int32_t
validateOrderbyNode
(
SQueryStmtInfo
*
pQueryInfo
,
SSqlNode
*
pSqlNode
,
SMsgBuf
*
pMsgBuf
)
{
const
char
*
msg1
=
"invalid column name in orderby clause"
;
const
char
*
msg2
=
"too many order by columns"
;
...
...
@@ -991,11 +972,11 @@ int32_t validateOrderbyNode(SQueryStmtInfo *pQueryInfo, SSqlNode* pSqlNode, SMsg
s
=
*
(
SSchema
*
)
getOneColumnSchema
(
pTableMetaInfo
->
pTableMeta
,
index
.
columnIndex
);
}
else
{
// order by [1|2|3]
if
(
pVar
->
i
64
>
getNumOfExprs
(
pQuery
Info
))
{
if
(
pVar
->
i
>
getNumOfFields
(
&
pQueryInfo
->
fields
Info
))
{
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg4
);
}
SExprInfo
*
pExprInfo
=
getExprInfo
(
pQueryInfo
,
pVar
->
i
64
);
SExprInfo
*
pExprInfo
=
getExprInfo
(
pQueryInfo
,
pVar
->
i
);
s
=
pExprInfo
->
base
.
resSchema
;
}
...
...
@@ -1150,7 +1131,7 @@ int32_t checkForInvalidOrderby(SQueryStmtInfo *pQueryInfo, SSqlNode* pSqlNode, S
// orderby ts query on super table
if (tscOrderedProjectionQueryOnSTable(pQueryInfo, 0)) {
bool found = false;
for (int32_t i = 0; i <
tsc
NumOfExprs(pQueryInfo); ++i) {
for (int32_t i = 0; i <
get
NumOfExprs(pQueryInfo); ++i) {
SExprInfo* pExpr = getExprInfo(pQueryInfo, i);
if (getExprFunctionId(pExpr) == FUNCTION_PRJ && pExpr->base.colInfo.colId == PRIMARYKEY_TIMESTAMP_COL_ID) {
found = true;
...
...
@@ -1266,7 +1247,7 @@ int32_t checkForInvalidOrderby(SQueryStmtInfo *pQueryInfo, SSqlNode* pSqlNode, S
}
#endif
static
int32_t
check
QueryRangeForFill
(
SQueryStmtInfo
*
pQueryInfo
,
SMsgBuf
*
pMsgBuf
)
{
static
int32_t
check
FillQueryRange
(
SQueryStmtInfo
*
pQueryInfo
,
SMsgBuf
*
pMsgBuf
)
{
const
char
*
msg3
=
"start(end) time of time range required or time range too large"
;
if
(
pQueryInfo
->
interval
.
interval
==
0
)
{
...
...
@@ -1305,20 +1286,14 @@ int32_t validateFillNode(SQueryStmtInfo *pQueryInfo, SSqlNode* pSqlNode, SMsgBuf
const
char
*
msg1
=
"value is expected"
;
const
char
*
msg2
=
"invalid fill option"
;
const
char
*
msg3
=
"top/bottom not support fill"
;
const
char
*
msg4
=
"illegal value or data overflow"
;
const
char
*
msg5
=
"fill only available for interval query"
;
const
char
*
msg6
=
"not supported function now"
;
// if ((!isTimeWindowQuery(pQueryInfo)) && (!tscIsPointInterpQuery(pQueryInfo))) {
// return buildInvalidOperationMsg(pMsgBuf, msg5);
// }
/*
* fill options are set at the end position, when all columns are set properly
* the columns may be increased due to group by operation
*/
if
(
check
QueryRangeForFill
(
pQueryInfo
,
pMsgBuf
)
!=
TSDB_CODE_SUCCESS
)
{
if
(
check
FillQueryRange
(
pQueryInfo
,
pMsgBuf
)
!=
TSDB_CODE_SUCCESS
)
{
return
TSDB_CODE_TSC_INVALID_OPERATION
;
}
...
...
@@ -1406,15 +1381,6 @@ int32_t validateFillNode(SQueryStmtInfo *pQueryInfo, SSqlNode* pSqlNode, SMsgBuf
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg2
);
}
// for(int32_t i = 0; i < tscNumOfExprs(pQueryInfo); ++i) {
// SExprInfo* pExpr = getExprInfo(pQueryInfo, i);
//
// int32_t functionId = pExpr->pExpr->_node.functionId;
// if (functionId == FUNCTION_TOP || functionId == FUNCTION_BOTTOM) {
// return buildInvalidOperationMsg(pMsgBuf, msg3);
// }
// }
return
TSDB_CODE_SUCCESS
;
}
...
...
@@ -1437,6 +1403,8 @@ int32_t validateSqlNode(SSqlNode* pSqlNode, SQueryStmtInfo* pQueryInfo, SMsgBuf*
* select server_version();
* select client_version();
* select database();
* select 1+2;
* select now();
*/
if
(
pSqlNode
->
from
==
NULL
)
{
assert
(
pSqlNode
->
fillType
==
NULL
&&
pSqlNode
->
pGroupby
==
NULL
&&
pSqlNode
->
pWhere
==
NULL
&&
...
...
@@ -1458,28 +1426,24 @@ int32_t validateSqlNode(SSqlNode* pSqlNode, SQueryStmtInfo* pQueryInfo, SMsgBuf*
}
}
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
,
pMsgBuf
)
!=
TSDB_CODE_SUCCESS
)
{
return
TSDB_CODE_TSC_INVALID_OPERATION
;
}
if
(
validateSelectNodeList
(
pQueryInfo
,
pSqlNode
->
pSelNodeList
,
true
,
pMsgBuf
)
!=
TSDB_CODE_SUCCESS
)
{
if
(
validateSelectNodeList
(
pQueryInfo
,
pSqlNode
->
pSelNodeList
,
true
,
pMsgBuf
)
!=
TSDB_CODE_SUCCESS
)
{
return
TSDB_CODE_TSC_INVALID_OPERATION
;
}
code
=
filterUnsupportedQueryFunction
(
pQueryInfo
,
pMsgBuf
);
code
=
checkForUnsupportedQuery
(
pQueryInfo
,
pMsgBuf
);
STableMeta
*
pTableMeta
=
getMetaInfo
(
pQueryInfo
,
0
)
->
pTableMeta
;
SSchema
*
pSchema
=
getOneColumnSchema
(
pTableMeta
,
0
);
int32_t
precision
=
pTableMeta
->
tableInfo
.
precision
;
#if 0
if (pSchema->type != TSDB_DATA_TYPE_TIMESTAMP) {
int32_t
numOfExprs
=
(
int32_t
)
tsc
NumOfExprs
(
pQueryInfo
);
int32_t numOfExprs = (int32_t)
get
NumOfExprs(pQueryInfo);
for (int32_t i = 0; i < numOfExprs; ++i) {
SExprInfo* pExpr = getExprInfo(pQueryInfo, i);
...
...
@@ -1490,6 +1454,7 @@ int32_t validateSqlNode(SSqlNode* pSqlNode, SQueryStmtInfo* pQueryInfo, SMsgBuf*
}
}
}
#endif
// validate the query filter condition info
if
(
pSqlNode
->
pWhere
!=
NULL
)
{
...
...
@@ -1536,19 +1501,14 @@ int32_t validateSqlNode(SSqlNode* pSqlNode, SQueryStmtInfo* pQueryInfo, SMsgBuf*
}
}
else
{
pQueryInfo
->
command
=
TSDB_SQL_SELECT
;
size_t
numOfTables
=
taosArrayGetSize
(
pSqlNode
->
from
->
list
);
if
(
numOfTables
>
TSDB_MAX_JOIN_TABLE_NUM
)
{
if
(
taosArrayGetSize
(
pSqlNode
->
from
->
list
)
>
TSDB_MAX_JOIN_TABLE_NUM
)
{
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg2
);
}
STableMetaInfo
*
pTableMetaInfo
=
getMetaInfo
(
pQueryInfo
,
0
);
int32_t
precision
=
pTableMetaInfo
->
pTableMeta
->
tableInfo
.
precision
;
bool
isSTable
=
UTIL_TABLE_IS_SUPER_TABLE
(
pTableMetaInfo
);
pQueryInfo
->
info
.
stableQuery
=
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
);
int32_t
precision
=
pTableMetaInfo
->
pTableMeta
->
tableInfo
.
precision
;
// parse the group by clause in the first place
if
(
validateGroupbyNode
(
pQueryInfo
,
pSqlNode
->
pGroupby
,
pMsgBuf
)
!=
TSDB_CODE_SUCCESS
)
{
...
...
@@ -1566,8 +1526,7 @@ int32_t validateSqlNode(SSqlNode* pSqlNode, SQueryStmtInfo* pQueryInfo, SMsgBuf*
}
}
if
(
validateSelectNodeList
(
pQueryInfo
,
pSqlNode
->
pSelNodeList
,
false
,
pMsgBuf
)
!=
TSDB_CODE_SUCCESS
)
{
if
(
validateSelectNodeList
(
pQueryInfo
,
pSqlNode
->
pSelNodeList
,
false
,
pMsgBuf
)
!=
TSDB_CODE_SUCCESS
)
{
return
TSDB_CODE_TSC_INVALID_OPERATION
;
}
...
...
@@ -1599,10 +1558,6 @@ int32_t validateSqlNode(SSqlNode* pSqlNode, SQueryStmtInfo* pQueryInfo, SMsgBuf*
return
TSDB_CODE_TSC_INVALID_OPERATION
;
}
// if (isTimeWindowQuery(pQueryInfo) && (validateFunctionsInIntervalOrGroupbyQuery(pCmd, pQueryInfo) != TSDB_CODE_SUCCESS)) {
// 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
;
...
...
@@ -1623,27 +1578,96 @@ int32_t validateSqlNode(SSqlNode* pSqlNode, SQueryStmtInfo* pQueryInfo, SMsgBuf*
int32_t
checkForInvalidExpr
(
SQueryStmtInfo
*
pQueryInfo
,
SMsgBuf
*
pMsgBuf
)
{
assert
(
pQueryInfo
!=
NULL
&&
pMsgBuf
!=
NULL
);
return
0
;
}
static
int32_t
distinctCompatibleCheck
(
SQueryStmtInfo
*
pQueryInfo
,
bool
joinQuery
,
SMsgBuf
*
pMsgBuf
)
{
const
char
*
msg1
=
"invalid query expression"
;
const
char
*
msg2
=
"top/bottom query does not support order by value in time window query"
;
const
char
*
msg3
=
"fill only available in time window query"
;
const
char
*
msg4
=
"top/bottom not support fill"
;
const
char
*
msg5
=
"scalar function can not be used in time window query"
;
const
char
*
msg6
=
"not support distinct mixed with join"
;
const
char
*
msg7
=
"not support distinct mixed with groupby"
;
const
char
*
msg8
=
"not support distinct in nest query"
;
const
char
*
msg8
=
"_block_dist not support subquery, only support stable/table"
;
if
(
pQueryInfo
->
info
.
topbotQuery
)
{
// 1. invalid sql:
// select top(col, k) from table_name [interval(1d)|session(ts, 1d)|statewindow(col)] order by k asc
// order by normal column is not supported
int32_t
colId
=
pQueryInfo
->
order
.
orderColId
;
if
(
pQueryInfo
->
info
.
timewindow
&&
colId
!=
PRIMARYKEY_TIMESTAMP_COL_ID
)
{
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg2
);
}
// select top(col, k) from table_name interval(10s) fill(prev)
// not support fill in top/bottom query.
if
(
pQueryInfo
->
fillType
!=
TSDB_FILL_NONE
)
{
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg4
);
}
}
/*
* 2. invalid sql:
* select count(tbname)/count(tag1)/count(tag2) from super_table_name [interval(1d)|session(ts, 1d)|statewindow(col)];
*/
if
(
pQueryInfo
->
info
.
timewindow
)
{
size_t
size
=
getNumOfExprs
(
pQueryInfo
);
for
(
int32_t
i
=
0
;
i
<
size
;
++
i
)
{
SExprInfo
*
pExpr
=
getExprInfo
(
pQueryInfo
,
i
);
int32_t
functionId
=
getExprFunctionId
(
pExpr
);
if
(
functionId
==
FUNCTION_COUNT
&&
TSDB_COL_IS_TAG
(
pExpr
->
base
.
colInfo
.
flag
))
{
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg1
);
}
}
}
/*
* 3. invalid sql:
* select tbname, tags_fields from super_table_name [interval(1s)|session(ts,1s)|statewindow(col)]
*/
if
(
pQueryInfo
->
info
.
onlyTagQuery
&&
pQueryInfo
->
info
.
timewindow
)
{
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg1
);
}
/*
* 4. invalid sql:
* select * from table_name fill(prev|next|null|none)
*/
if
(
!
pQueryInfo
->
info
.
timewindow
&&
!
pQueryInfo
->
info
.
interpQuery
&&
pQueryInfo
->
fillType
!=
TSDB_FILL_NONE
)
{
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg3
);
}
if
(
pQueryInfo
->
distinct
)
{
if
(
joinQuery
)
{
/*
* 5. invalid sql:
* select diff(col)|derivative(col)|* from table_name interval(1s)|session(20s)|statewindow(col)
* projection query not compatible with the time window query
*/
if
(
pQueryInfo
->
info
.
timewindow
&&
pQueryInfo
->
info
.
projectionQuery
)
{
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg5
);
}
/*
* 6. invalid sql:
* distinct + join not supported.
* select distinct a,b from table1, table2 where table1.ts=table2.ts
*
* distinct + group by not supported:
* select distinct count(a) from table_name group by col1;
*/
if
(
pQueryInfo
->
info
.
distinct
)
{
if
(
pQueryInfo
->
info
.
join
)
{
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg6
);
}
if
(
taosArrayGetSize
(
pQueryInfo
->
groupbyExpr
.
columnInfo
)
!=
0
)
{
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg7
);
}
if
(
pQueryInfo
->
pDownstream
!=
NULL
)
{
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg8
);
}
}
/*
* 7. invalid sql:
* nested subquery not support block_dist query
* select block_dist() from (select * from table_name)
*/
}
static
int32_t
resColId
=
5000
;
...
...
@@ -1684,42 +1708,32 @@ void setResultColName(char* name, tSqlExprItem* pItem, SToken* pToken, SToken* f
}
SExprInfo
*
doAddOneExprInfo
(
SQueryStmtInfo
*
pQueryInfo
,
int32_t
outputColIndex
,
int16_t
functionId
,
SColumnIndex
*
pIndex
,
SSchema
*
pColSchema
,
SSchema
*
pResultSchema
,
tExprNode
*
pExprNode
,
int32_t
interSize
,
const
char
*
token
)
{
SSchema
*
pColSchema
,
SSchema
*
pResultSchema
,
tExprNode
*
pExprNode
,
int32_t
interSize
,
const
char
*
token
,
bool
finalResult
)
{
STableMetaInfo
*
pTableMetaInfo
=
getMetaInfo
(
pQueryInfo
,
pIndex
->
tableIndex
);
SExprInfo
*
pExpr
=
createExprInfo
(
pTableMetaInfo
,
functionId
,
pIndex
,
pExprNode
,
pResultSchema
,
interSize
);
addExprInfo
(
pQueryInfo
,
outputColIndex
,
pExpr
);
tstrncpy
(
pExpr
->
base
.
token
,
token
,
sizeof
(
pExpr
->
base
.
token
));
pExpr
->
base
.
colInfo
.
flag
=
pIndex
->
type
;
uint64_t
uid
=
pTableMetaInfo
->
pTableMeta
->
uid
;
SArray
*
p
=
TSDB_COL_IS_TAG
(
pIndex
->
type
)
?
pTableMetaInfo
->
tagColList
:
pQueryInfo
->
colList
;
columnListInsert
(
p
,
pIndex
->
columnIndex
,
pTableMetaInfo
->
pTableMeta
->
uid
,
pColSchema
);
addResColumnInfo
(
pQueryInfo
,
outputColIndex
,
pColSchema
,
pExpr
);
return
pExpr
;
}
columnListInsert
(
p
,
pIndex
->
columnIndex
,
uid
,
pColSchema
);
void
doAddSourceColumnAndResColumn
(
SQueryStmtInfo
*
pQueryInfo
,
SColumnIndex
*
index
,
int32_t
outputIndex
,
SExprInfo
*
pExpr
,
SSchema
*
pColSchema
,
bool
finalResult
)
{
columnListInsert
(
pQueryInfo
->
colList
,
index
->
columnIndex
,
pExpr
->
base
.
uid
,
pColSchema
);
pExpr
->
base
.
colInfo
.
flag
=
pIndex
->
type
;
if
(
TSDB_COL_IS_NORMAL_COL
(
pIndex
->
type
))
{
insertPrimaryTsColumn
(
pQueryInfo
->
colList
,
uid
);
}
if
(
finalResult
)
{
addResColumnInfo
(
pQueryInfo
,
output
Index
,
&
pExpr
->
base
.
res
Schema
,
pExpr
);
addResColumnInfo
(
pQueryInfo
,
output
ColIndex
,
pCol
Schema
,
pExpr
);
}
if
(
TSDB_COL_IS_NORMAL_COL
(
index
->
type
))
{
insertPrimaryTsColumn
(
pQueryInfo
->
colList
,
pExpr
->
base
.
uid
);
}
return
pExpr
;
}
static
int32_t
addOneExprInfo
(
SQueryStmtInfo
*
pQueryInfo
,
tSqlExprItem
*
pItem
,
int32_t
functionId
,
int32_t
outputColIndex
,
SColumnIndex
*
pColIndex
,
tExprNode
*
pNode
,
bool
finalResult
,
SMsgBuf
*
pMsgBuf
)
{
static
int32_t
addOneExprInfo
(
SQueryStmtInfo
*
pQueryInfo
,
tSqlExprItem
*
pItem
,
int32_t
functionId
,
int32_t
outputIndex
,
SSchema
*
pSchema
,
SColumnIndex
*
pColIndex
,
tExprNode
*
pNode
,
bool
finalResult
,
SMsgBuf
*
pMsgBuf
)
{
const
char
*
msg1
=
"not support column types"
;
STableMetaInfo
*
pTableMetaInfo
=
getMetaInfo
(
pQueryInfo
,
pColIndex
->
tableIndex
);
SSchema
*
pSchema
=
getOneColumnSchema
(
pTableMetaInfo
->
pTableMeta
,
pColIndex
->
columnIndex
);
if
(
functionId
==
FUNCTION_SPREAD
)
{
if
(
IS_VAR_DATA_TYPE
(
pSchema
->
type
)
||
pSchema
->
type
==
TSDB_DATA_TYPE_BOOL
)
{
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg1
);
...
...
@@ -1734,7 +1748,7 @@ static int32_t addOneExprInfo(SQueryStmtInfo* pQueryInfo, tSqlExprItem* pItem, i
getResultDataInfo
(
pSchema
->
type
,
pSchema
->
bytes
,
functionId
,
0
,
&
resInfo
,
0
,
false
);
SSchema
resultSchema
=
createSchema
(
resInfo
.
type
,
resInfo
.
bytes
,
getNewResColId
(),
name
);
doAddOneExprInfo
(
pQueryInfo
,
output
ColIndex
,
functionId
,
pColIndex
,
pSchema
,
&
resultSchema
,
pNode
,
resInfo
.
intermediateBytes
,
name
);
doAddOneExprInfo
(
pQueryInfo
,
output
Index
,
functionId
,
pColIndex
,
pSchema
,
&
resultSchema
,
pNode
,
resInfo
.
intermediateBytes
,
name
,
finalResult
);
return
TSDB_CODE_SUCCESS
;
}
...
...
@@ -1776,6 +1790,8 @@ static void setTsOutputExprInfo(SQueryStmtInfo* pQueryInfo, STableMetaInfo* pTab
SSchema
s
=
createSchema
(
TSDB_DATA_TYPE_TIMESTAMP
,
TSDB_KEYSIZE
,
getNewResColId
(),
"ts"
);
SExprInfo
*
pExpr
=
createExprInfo
(
pTableMetaInfo
,
FUNCTION_TS_DUMMY
,
&
indexTS
,
NULL
,
&
s
,
TSDB_KEYSIZE
);
strncpy
(
pExpr
->
base
.
token
,
"ts"
,
tListLen
(
pExpr
->
base
.
token
));
addExprInfo
(
pQueryInfo
,
outputIndex
,
pExpr
);
SSchema
*
pSourceSchema
=
getOneColumnSchema
(
pTableMetaInfo
->
pTableMeta
,
indexTS
.
columnIndex
);
...
...
@@ -1783,37 +1799,45 @@ static void setTsOutputExprInfo(SQueryStmtInfo* pQueryInfo, STableMetaInfo* pTab
addResColumnInfo
(
pQueryInfo
,
outputIndex
,
&
pExpr
->
base
.
resSchema
,
pExpr
);
}
// todo handle count(a+b)
static
int32_t
setColumnIndex
(
SQueryStmtInfo
*
pQueryInfo
,
SArray
*
pParamList
,
SColumnIndex
*
index
,
SMsgBuf
*
pMsgBuf
)
{
const
char
*
msg3
=
"illegal column name"
;
const
char
*
msg4
=
"invalid table name"
;
static
int32_t
setColumnIndex
(
SQueryStmtInfo
*
pQueryInfo
,
SArray
*
pParamList
,
SColumnIndex
*
index
,
SSchema
*
columnSchema
,
tExprNode
**
pNode
,
SMsgBuf
*
pMsgBuf
)
{
const
char
*
msg1
=
"illegal column name"
;
const
char
*
msg2
=
"invalid table name"
;
if
(
pParamList
!=
NULL
)
{
STableMeta
*
pTableMeta
=
getMetaInfo
(
pQueryInfo
,
0
)
->
pTableMeta
;
if
(
pParamList
==
NULL
)
{
// count(*) is equalled to count(primary_timestamp_key)
*
index
=
(
SColumnIndex
)
{
0
,
PRIMARYKEY_TIMESTAMP_COL_ID
,
false
};
*
columnSchema
=
*
(
SSchema
*
)
getOneColumnSchema
(
pTableMeta
,
index
->
columnIndex
);
}
else
{
tSqlExprItem
*
pParamElem
=
taosArrayGet
(
pParamList
,
0
);
SToken
*
pToken
=
&
pParamElem
->
pNode
->
columnName
;
int16_t
tokenId
=
pParamElem
->
pNode
->
tokenId
;
if
((
pToken
->
z
==
NULL
||
pToken
->
n
==
0
)
&&
(
TK_INTEGER
!=
tokenId
))
{
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg3
);
}
// select count(table.*), select count(1), count(2)
if
(
tokenId
==
TK_ALL
||
tokenId
==
TK_INTEGER
)
{
if
(
tokenId
==
TK_ALL
||
tokenId
==
TK_INTEGER
||
tokenId
==
TK_FLOAT
)
{
// check if the table name is valid or not
SToken
tmpToken
=
pParamElem
->
pNode
->
columnName
;
if
(
getTableIndexByName
(
&
tmpToken
,
pQueryInfo
,
index
)
!=
TSDB_CODE_SUCCESS
)
{
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg
4
);
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg
2
);
}
index
->
columnIndex
=
PRIMARYKEY_TIMESTAMP_COL_ID
;
}
else
{
*
index
=
(
SColumnIndex
)
{
0
,
PRIMARYKEY_TIMESTAMP_COL_ID
,
false
};
*
columnSchema
=
*
(
SSchema
*
)
getOneColumnSchema
(
pTableMeta
,
index
->
columnIndex
);
}
else
if
(
pToken
->
z
!=
NULL
&&
pToken
->
n
>
0
)
{
// count the number of table created according to the super table
if
(
getColumnIndexByName
(
pToken
,
pQueryInfo
,
index
,
pMsgBuf
)
!=
TSDB_CODE_SUCCESS
)
{
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg3
);
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg1
);
}
*
columnSchema
=
*
(
SSchema
*
)
getOneColumnSchema
(
pTableMeta
,
index
->
columnIndex
);
}
else
{
STableMetaInfo
*
pTableMetaInfo
=
NULL
;
int32_t
code
=
extractFunctionParameterInfo
(
pQueryInfo
,
tokenId
,
&
pTableMetaInfo
,
columnSchema
,
pNode
,
index
,
pParamElem
,
pMsgBuf
);
if
(
code
!=
TSDB_CODE_SUCCESS
)
{
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg1
);
}
}
}
else
{
// count(*) is equalled to count(primary_timestamp_key)
*
index
=
(
SColumnIndex
)
{
0
,
PRIMARYKEY_TIMESTAMP_COL_ID
,
false
};
}
return
TSDB_CODE_SUCCESS
;
...
...
@@ -1821,10 +1845,12 @@ static int32_t setColumnIndex(SQueryStmtInfo* pQueryInfo, SArray* pParamList, SC
static
int32_t
doAddAllColumnExprInSelectClause
(
SQueryStmtInfo
*
pQueryInfo
,
STableMetaInfo
*
pTableMetaInfo
,
tSqlExprItem
*
pItem
,
int32_t
functionId
,
int32_t
tableIndex
,
int32_t
*
colIndex
,
bool
finalResult
,
SMsgBuf
*
pMsgBuf
)
{
for
(
int32_t
i
=
0
;
i
<
getNumOfColumns
(
pTableMetaInfo
->
pTableMeta
);
++
i
)
{
STableMeta
*
pTableMeta
=
pTableMetaInfo
->
pTableMeta
;
for
(
int32_t
i
=
0
;
i
<
getNumOfColumns
(
pTableMeta
);
++
i
)
{
SColumnIndex
index
=
{.
tableIndex
=
tableIndex
,
.
columnIndex
=
i
,
.
type
=
TSDB_COL_NORMAL
};
if
(
addOneExprInfo
(
pQueryInfo
,
pItem
,
functionId
,
*
colIndex
,
&
index
,
NULL
,
finalResult
,
pMsgBuf
)
!=
0
)
{
SSchema
*
pSchema
=
getOneColumnSchema
(
pTableMeta
,
i
);
if
(
addOneExprInfo
(
pQueryInfo
,
pItem
,
functionId
,
*
colIndex
,
pSchema
,
&
index
,
NULL
,
finalResult
,
pMsgBuf
)
!=
0
)
{
return
TSDB_CODE_TSC_INVALID_OPERATION
;
}
...
...
@@ -1832,9 +1858,6 @@ static int32_t doAddAllColumnExprInSelectClause(SQueryStmtInfo *pQueryInfo, STab
}
}
static
int32_t
extractFunctionParameterInfo
(
SQueryStmtInfo
*
pQueryInfo
,
int32_t
tokenId
,
STableMetaInfo
**
pTableMetaInfo
,
SSchema
*
columnSchema
,
tExprNode
**
pNode
,
SColumnIndex
*
pIndex
,
tSqlExprItem
*
pParamElem
,
SMsgBuf
*
pMsgBuf
);
static
int32_t
doHandleOneParam
(
SQueryStmtInfo
*
pQueryInfo
,
tSqlExprItem
*
pItem
,
tSqlExprItem
*
pParamElem
,
int32_t
functionId
,
int32_t
*
outputIndex
,
bool
finalResult
,
SMsgBuf
*
pMsgBuf
)
{
const
char
*
msg3
=
"illegal column name"
;
...
...
@@ -1858,18 +1881,17 @@ static int32_t doHandleOneParam(SQueryStmtInfo *pQueryInfo, tSqlExprItem* pItem,
SSchema
columnSchema
=
{
0
};
STableMetaInfo
*
pTableMetaInfo
=
{
0
};
extractFunctionParameterInfo
(
pQueryInfo
,
tokenId
,
&
pTableMetaInfo
,
&
columnSchema
,
&
pNode
,
&
index
,
pParamElem
,
pMsgBuf
);
if
(
getColumnIndexByName
(
&
pParamElem
->
pNode
->
columnName
,
pQueryInfo
,
&
index
,
pMsgBuf
)
!=
TSDB_CODE_SUCCESS
)
{
int32_t
code
=
extractFunctionParameterInfo
(
pQueryInfo
,
tokenId
,
&
pTableMetaInfo
,
&
columnSchema
,
&
pNode
,
&
index
,
pParamElem
,
pMsgBuf
);
if
(
code
!=
TSDB_CODE_SUCCESS
)
{
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg3
);
}
// functions can not be applied to tags
if
(
TSDB_COL_IS_TAG
(
index
.
type
))
{
if
(
TSDB_COL_IS_TAG
(
index
.
type
)
&&
(
functionId
==
FUNCTION_INTERP
||
functionId
==
FUNCTION_SPREAD
)
)
{
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg6
);
}
if
(
addOneExprInfo
(
pQueryInfo
,
pItem
,
functionId
,
(
*
outputIndex
)
++
,
&
index
,
pNode
,
finalResult
,
pMsgBuf
)
!=
0
)
{
if
(
addOneExprInfo
(
pQueryInfo
,
pItem
,
functionId
,
(
*
outputIndex
)
++
,
&
columnSchema
,
&
index
,
pNode
,
finalResult
,
pMsgBuf
)
!=
0
)
{
return
TSDB_CODE_TSC_INVALID_OPERATION
;
}
}
...
...
@@ -1882,9 +1904,9 @@ int32_t extractFunctionParameterInfo(SQueryStmtInfo* pQueryInfo, int32_t tokenId
const
char
*
msg1
=
"not support column types"
;
const
char
*
msg2
=
"invalid parameters"
;
const
char
*
msg3
=
"illegal column name"
;
const
char
*
msg
6
=
"functions applied to tags are not allow
ed"
;
const
char
*
msg
13
=
"nested function is not support
ed"
;
const
char
*
msg
4
=
"nested function is not support
ed"
;
const
char
*
msg
5
=
"functions applied to tags are not allow
ed"
;
if
(
tokenId
==
TK_ALL
||
tokenId
==
TK_ID
)
{
// simple parameter
if
((
getColumnIndexByName
(
&
pParamElem
->
pNode
->
columnName
,
pQueryInfo
,
pIndex
,
pMsgBuf
)
!=
TSDB_CODE_SUCCESS
))
{
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg3
);
...
...
@@ -1892,14 +1914,14 @@ int32_t extractFunctionParameterInfo(SQueryStmtInfo* pQueryInfo, int32_t tokenId
// functions can not be applied to tags
if
(
TSDB_COL_IS_TAG
(
pIndex
->
type
))
{
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg
6
);
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg
5
);
}
*
pTableMetaInfo
=
getMetaInfo
(
pQueryInfo
,
pIndex
->
tableIndex
);
// 2. check if sql function can be applied on this column data type
*
columnSchema
=
*
(
SSchema
*
)
getOneColumnSchema
((
*
pTableMetaInfo
)
->
pTableMeta
,
pIndex
->
columnIndex
);
}
else
if
(
tokenId
==
TK_PLUS
||
tokenId
==
TK_MINUS
||
tokenId
==
TK_STAR
||
tokenId
==
TK_REM
||
tokenId
==
TK_CONCAT
)
{
}
else
if
(
tokenId
==
TK_PLUS
||
tokenId
==
TK_MINUS
||
tokenId
==
TK_STAR
||
tokenId
==
TK_REM
||
tokenId
==
TK_
DIVIDE
||
tokenId
==
TK_
CONCAT
)
{
int32_t
arithmeticType
=
NON_ARITHMEIC_EXPR
;
SArray
*
pColumnList
=
taosArrayInit
(
4
,
sizeof
(
SColumnIndex
));
if
(
validateComplexExpr
(
pParamElem
->
pNode
,
pQueryInfo
,
pColumnList
,
&
arithmeticType
,
pMsgBuf
)
!=
TSDB_CODE_SUCCESS
)
{
...
...
@@ -1907,12 +1929,16 @@ int32_t extractFunctionParameterInfo(SQueryStmtInfo* pQueryInfo, int32_t tokenId
}
if
(
arithmeticType
!=
NORMAL_ARITHMETIC
)
{
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg
13
);
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg
4
);
}
*
pTableMetaInfo
=
getMetaInfo
(
pQueryInfo
,
0
);
// todo get the first table meta.
*
columnSchema
=
createSchema
(
TSDB_DATA_TYPE_DOUBLE
,
sizeof
(
double
),
getNewResColId
(),
""
);
SToken
*
pExprToken
=
&
pParamElem
->
pNode
->
exprToken
;
int32_t
len
=
MIN
(
TSDB_COL_NAME_LEN
,
pExprToken
->
n
+
1
);
tstrncpy
(
columnSchema
->
name
,
pExprToken
->
z
,
len
);
SArray
*
colList
=
taosArrayInit
(
10
,
sizeof
(
SColIndex
));
int32_t
ret
=
sqlExprToExprNode
(
pNode
,
pParamElem
->
pNode
,
pQueryInfo
,
colList
,
NULL
,
pMsgBuf
);
if
(
ret
!=
TSDB_CODE_SUCCESS
)
{
...
...
@@ -1978,8 +2004,11 @@ int32_t addExprAndResColumn(SQueryStmtInfo* pQueryInfo, int32_t colIndex, tSqlEx
return
code
;
}
tExprNode
*
pNode
=
NULL
;
SColumnIndex
index
=
COLUMN_INDEX_INITIALIZER
;
code
=
setColumnIndex
(
pQueryInfo
,
pParamList
,
&
index
,
pMsgBuf
);
SSchema
columnSchema
=
{
0
};
code
=
setColumnIndex
(
pQueryInfo
,
pParamList
,
&
index
,
&
columnSchema
,
&
pNode
,
pMsgBuf
);
if
(
code
!=
TSDB_CODE_SUCCESS
)
{
return
code
;
}
...
...
@@ -1990,11 +2019,8 @@ int32_t addExprAndResColumn(SQueryStmtInfo* pQueryInfo, int32_t colIndex, tSqlEx
char
token
[
TSDB_COL_NAME_LEN
]
=
{
0
};
setTokenAndResColumnName
(
pItem
,
s
.
name
,
token
,
sizeof
(
s
.
name
)
-
1
);
STableMeta
*
pTableMeta
=
getMetaInfo
(
pQueryInfo
,
index
.
tableIndex
)
->
pTableMeta
;
int32_t
outputIndex
=
getNumOfFields
(
&
pQueryInfo
->
fieldsInfo
);
SSchema
*
ps
=
getOneColumnSchema
(
pTableMeta
,
index
.
columnIndex
);
doAddOneExprInfo
(
pQueryInfo
,
outputIndex
,
functionId
,
&
index
,
ps
,
&
s
,
NULL
,
size
,
token
);
doAddOneExprInfo
(
pQueryInfo
,
outputIndex
,
functionId
,
&
index
,
&
columnSchema
,
&
s
,
pNode
,
size
,
token
,
finalResult
);
return
TSDB_CODE_SUCCESS
;
}
...
...
@@ -2058,7 +2084,7 @@ int32_t addExprAndResColumn(SQueryStmtInfo* pQueryInfo, int32_t colIndex, tSqlEx
char
token
[
TSDB_COL_NAME_LEN
]
=
{
0
};
setTokenAndResColumnName
(
pItem
,
s
.
name
,
token
,
sizeof
(
s
.
name
)
-
1
);
SExprInfo
*
pExpr
=
doAddOneExprInfo
(
pQueryInfo
,
numOfOutput
,
functionId
,
&
index
,
&
columnSchema
,
&
s
,
pNode
,
resInfo
.
intermediateBytes
,
token
);
SExprInfo
*
pExpr
=
doAddOneExprInfo
(
pQueryInfo
,
numOfOutput
,
functionId
,
&
index
,
&
columnSchema
,
&
s
,
pNode
,
resInfo
.
intermediateBytes
,
token
,
finalResult
);
if
(
functionId
==
FUNCTION_LEASTSQR
)
{
// set the leastsquares parameters
char
val
[
8
]
=
{
0
};
...
...
@@ -2151,13 +2177,17 @@ int32_t addExprAndResColumn(SQueryStmtInfo* pQueryInfo, int32_t colIndex, tSqlEx
}
tSqlExprItem
*
pParamElem
=
taosArrayGet
(
pItem
->
pNode
->
Expr
.
paramList
,
0
);
if
(
pParamElem
->
pNode
->
tokenId
!=
TK_ID
)
{
if
(
pParamElem
->
pNode
->
tokenId
==
TK_ALL
)
{
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg2
);
}
tExprNode
*
pNode
=
NULL
;
int32_t
tokenId
=
pParamElem
->
pNode
->
tokenId
;
SColumnIndex
index
=
COLUMN_INDEX_INITIALIZER
;
if
(
getColumnIndexByName
(
&
pParamElem
->
pNode
->
columnName
,
pQueryInfo
,
&
index
,
pMsgBuf
)
!=
TSDB_CODE_SUCCESS
)
{
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg3
);
SSchema
columnSchema
=
{
0
};
code
=
extractFunctionParameterInfo
(
pQueryInfo
,
tokenId
,
&
pTableMetaInfo
,
&
columnSchema
,
&
pNode
,
&
index
,
pParamElem
,
pMsgBuf
);
if
(
code
!=
TSDB_CODE_SUCCESS
)
{
return
code
;
}
// functions can not be applied to tags
...
...
@@ -2166,10 +2196,9 @@ int32_t addExprAndResColumn(SQueryStmtInfo* pQueryInfo, int32_t colIndex, tSqlEx
}
pTableMetaInfo
=
getMetaInfo
(
pQueryInfo
,
index
.
tableIndex
);
SSchema
*
pSchema
=
getOneColumnSchema
(
pTableMetaInfo
->
pTableMeta
,
index
.
columnIndex
);
// 2. valid the column type
if
(
!
IS_NUMERIC_TYPE
(
pSchema
->
type
))
{
if
(
!
IS_NUMERIC_TYPE
(
columnSchema
.
type
))
{
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg1
);
}
...
...
@@ -2178,50 +2207,42 @@ int32_t addExprAndResColumn(SQueryStmtInfo* pQueryInfo, int32_t colIndex, tSqlEx
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg2
);
}
SVariant
*
pVariant
=
&
pParamElem
[
1
].
pNode
->
value
;
SResultDataInfo
resInfo
=
{
0
};
char
val
[
8
]
=
{
0
};
getResultDataInfo
(
columnSchema
.
type
,
columnSchema
.
bytes
,
functionId
,
0
,
&
resInfo
,
0
,
false
);
if
(
functionId
==
FUNCTION_TOP
||
functionId
==
FUNCTION_BOTTOM
)
{
// set the first column ts for top/bottom query
setTsOutputExprInfo
(
pQueryInfo
,
pTableMetaInfo
,
colIndex
,
index
.
tableIndex
);
colIndex
+=
1
;
// the first column is ts
}
if
(
functionId
==
FUNCTION_PERCT
||
functionId
==
FUNCTION_APERCT
)
{
taosVariantDump
(
pVariant
,
val
,
TSDB_DATA_TYPE_DOUBLE
,
true
);
SSchema
s
=
createSchema
(
resInfo
.
type
,
resInfo
.
bytes
,
getNewResColId
(),
""
);
double
dp
=
GET_DOUBLE_VAL
(
val
);
if
(
dp
<
0
||
dp
>
TOP_BOTTOM_QUERY_LIMIT
)
{
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg5
);
}
char
token
[
TSDB_COL_NAME_LEN
]
=
{
0
};
setTokenAndResColumnName
(
pItem
,
s
.
name
,
token
,
sizeof
(
s
.
name
)
-
1
);
SExprInfo
*
pExpr
=
doAddOneExprInfo
(
pQueryInfo
,
colIndex
,
functionId
,
&
index
,
&
columnSchema
,
&
s
,
pNode
,
resInfo
.
intermediateBytes
,
token
,
finalResult
);
SToken
*
pParamToken
=
&
pParamElem
[
1
].
pNode
->
exprToken
;
pExpr
->
base
.
numOfParams
+=
1
;
getResultDataInfo
(
pSchema
->
type
,
pSchema
->
bytes
,
functionId
,
0
,
&
resInfo
,
0
,
false
);
SVariant
*
pVar
=
&
pExpr
->
base
.
param
[
0
];
if
(
functionId
==
FUNCTION_PERCT
||
functionId
==
FUNCTION_APERCT
)
{
taosVariantCreate
(
pVar
,
pParamToken
->
z
,
pParamToken
->
n
,
TSDB_DATA_TYPE_DOUBLE
);
/*
* sql function transformation
* for dp = 0, it is actually min,
* for dp = 100, it is max,
*/
colIndex
+=
1
;
// the first column is ts
if
(
pVar
->
d
<
0
||
pVar
->
d
>
TOP_BOTTOM_QUERY_LIMIT
)
{
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg5
);
}
}
else
{
taosVariantDump
(
pVariant
,
val
,
TSDB_DATA_TYPE_BIGINT
,
true
);
int64_t
nTop
=
GET_INT32_VAL
(
val
);
if
(
nTop
<=
0
||
nTop
>
100
)
{
// todo use macro
taosVariantCreate
(
pVar
,
pParamToken
->
z
,
pParamToken
->
n
,
TSDB_DATA_TYPE_BIGINT
);
if
(
pVar
->
i
<=
0
||
pVar
->
i
>
100
)
{
// todo use macro
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg12
);
}
// set the first column ts for top/bottom query
setTsOutputExprInfo
(
pQueryInfo
,
pTableMetaInfo
,
colIndex
,
index
.
tableIndex
);
colIndex
+=
1
;
// the first column is ts
}
SSchema
s
=
createSchema
(
resInfo
.
type
,
resInfo
.
bytes
,
getNewResColId
(),
""
);
char
token
[
TSDB_COL_NAME_LEN
]
=
{
0
};
setTokenAndResColumnName
(
pItem
,
s
.
name
,
token
,
sizeof
(
s
.
name
)
-
1
);
SExprInfo
*
pExpr
=
doAddOneExprInfo
(
pQueryInfo
,
colIndex
,
functionId
,
&
index
,
pSchema
,
&
s
,
NULL
,
resInfo
.
intermediateBytes
,
token
);
if
(
functionId
==
FUNCTION_PERCT
||
functionId
==
FUNCTION_APERCT
)
{
addExprInfoParam
(
&
pExpr
->
base
,
val
,
TSDB_DATA_TYPE_DOUBLE
,
sizeof
(
double
));
}
else
{
addExprInfoParam
(
&
pExpr
->
base
,
val
,
TSDB_DATA_TYPE_BIGINT
,
sizeof
(
int64_t
));
}
return
TSDB_CODE_SUCCESS
;
}
...
...
@@ -2288,7 +2309,7 @@ int32_t addExprAndResColumn(SQueryStmtInfo* pQueryInfo, int32_t colIndex, tSqlEx
s
.
colId
=
getNewResColId
();
TSDB_QUERY_SET_TYPE
(
pQueryInfo
->
type
,
TSDB_QUERY_TYPE_TAG_FILTER_QUERY
);
doAddOneExprInfo
(
pQueryInfo
,
0
,
FUNCTION_TID_TAG
,
&
index
,
&
s
,
&
s
,
NULL
,
0
,
s
.
name
);
doAddOneExprInfo
(
pQueryInfo
,
0
,
FUNCTION_TID_TAG
,
&
index
,
&
s
,
&
s
,
NULL
,
0
,
s
.
name
,
true
);
return
TSDB_CODE_SUCCESS
;
}
...
...
@@ -2309,7 +2330,7 @@ int32_t addExprAndResColumn(SQueryStmtInfo* pQueryInfo, int32_t colIndex, tSqlEx
char
token
[
TSDB_COL_NAME_LEN
]
=
{
0
};
setTokenAndResColumnName
(
pItem
,
s
.
name
,
token
,
sizeof
(
s
.
name
)
-
1
);
SExprInfo
*
pExpr
=
doAddOneExprInfo
(
pQueryInfo
,
colIndex
,
functionId
,
&
index
,
&
colSchema
,
&
s
,
NULL
,
resInfo
.
intermediateBytes
,
token
);
SExprInfo
*
pExpr
=
doAddOneExprInfo
(
pQueryInfo
,
colIndex
,
functionId
,
&
index
,
&
colSchema
,
&
s
,
NULL
,
resInfo
.
intermediateBytes
,
token
,
finalResult
);
int64_t
rowSize
=
pTableMetaInfo
->
pTableMeta
->
tableInfo
.
rowSize
;
addExprInfoParam
(
&
pExpr
->
base
,
(
char
*
)
&
rowSize
,
TSDB_DATA_TYPE_BIGINT
,
8
);
...
...
@@ -2351,7 +2372,7 @@ int32_t addExprAndResColumn(SQueryStmtInfo* pQueryInfo, int32_t colIndex, tSqlEx
char
token
[
TSDB_COL_NAME_LEN
]
=
{
0
};
setTokenAndResColumnName
(
pItem
,
s
.
name
,
token
,
sizeof
(
s
.
name
)
-
1
);
doAddOneExprInfo
(
pQueryInfo
,
colIndex
,
functionId
,
&
index
,
colSchema
,
&
s
,
NULL
,
resInfo
.
intermediateBytes
,
token
);
doAddOneExprInfo
(
pQueryInfo
,
colIndex
,
functionId
,
&
index
,
colSchema
,
&
s
,
NULL
,
resInfo
.
intermediateBytes
,
token
,
finalResult
);
return
TSDB_CODE_SUCCESS
;
}
}
...
...
@@ -2377,7 +2398,7 @@ SExprInfo* doAddProjectCol(SQueryStmtInfo* pQueryInfo, int32_t outputColIndex, S
const
char
*
name
=
(
aliasName
==
NULL
)
?
pSchema
->
name
:
aliasName
;
SSchema
s
=
createSchema
(
pSchema
->
type
,
pSchema
->
bytes
,
colId
,
name
);
return
doAddOneExprInfo
(
pQueryInfo
,
outputColIndex
,
functionId
,
&
index
,
pSchema
,
&
s
,
NULL
,
0
,
pSchema
->
name
);
return
doAddOneExprInfo
(
pQueryInfo
,
outputColIndex
,
functionId
,
&
index
,
pSchema
,
&
s
,
NULL
,
0
,
pSchema
->
name
,
true
);
}
static
int32_t
doAddProjectionExprAndResColumn
(
SQueryStmtInfo
*
pQueryInfo
,
SColumnIndex
*
pIndex
,
int32_t
startPos
)
{
...
...
@@ -2440,7 +2461,7 @@ int32_t addProjectionExprAndResColumn(SQueryStmtInfo* pQueryInfo, tSqlExprItem*
return
TSDB_CODE_TSC_INVALID_OPERATION
;
}
int32_t
startPos
=
(
int32_t
)
tsc
NumOfExprs
(
pQueryInfo
);
int32_t
startPos
=
(
int32_t
)
get
NumOfExprs
(
pQueryInfo
);
int32_t
tokenId
=
pItem
->
pNode
->
tokenId
;
if
(
tokenId
==
TK_ALL
)
{
// project on all fields
TSDB_QUERY_SET_TYPE
(
pQueryInfo
->
type
,
TSDB_QUERY_TYPE_PROJECTION_QUERY
);
...
...
@@ -2470,9 +2491,9 @@ int32_t addProjectionExprAndResColumn(SQueryStmtInfo* pQueryInfo, tSqlExprItem*
SColumnIndex
index
=
createConstantColumnIndex
(
&
pQueryInfo
->
udColumnId
);
SSchema
colSchema
=
createConstantColumnSchema
(
&
pItem
->
pNode
->
value
,
&
pItem
->
pNode
->
exprToken
,
pItem
->
aliasName
);
char
rawName
[
TSDB_COL_NAME_LEN
]
=
{
0
};
tstrncpy
(
rawName
,
pItem
->
pNode
->
exprToken
.
z
,
MIN
(
TSDB_COL_NAME_LEN
,
TSDB_COL_NAME_LEN
));
SExprInfo
*
pExpr
=
doAddOneExprInfo
(
pQueryInfo
,
startPos
,
FUNCTION_PRJ
,
&
index
,
&
colSchema
,
&
colSchema
,
NULL
,
0
,
rawNam
e
);
char
token
[
TSDB_COL_NAME_LEN
]
=
{
0
};
tstrncpy
(
token
,
pItem
->
pNode
->
exprToken
.
z
,
MIN
(
TSDB_COL_NAME_LEN
,
TSDB_COL_NAME_LEN
));
SExprInfo
*
pExpr
=
doAddOneExprInfo
(
pQueryInfo
,
startPos
,
FUNCTION_PRJ
,
&
index
,
&
colSchema
,
&
colSchema
,
NULL
,
0
,
token
,
tru
e
);
// NOTE: the first parameter is reserved for the tag column id during join query process.
pExpr
->
base
.
numOfParams
=
2
;
...
...
@@ -2519,7 +2540,7 @@ int32_t addProjectionExprAndResColumn(SQueryStmtInfo* pQueryInfo, tSqlExprItem*
char
rawName
[
TSDB_COL_NAME_LEN
]
=
{
0
};
setTokenAndResColumnName
(
pItem
,
resultSchema
.
name
,
rawName
,
sizeof
(
colSchema
.
name
)
-
1
);
doAddOneExprInfo
(
pQueryInfo
,
startPos
,
functionId
,
&
index
,
&
colSchema
,
&
resultSchema
,
NULL
,
0
,
rawName
);
doAddOneExprInfo
(
pQueryInfo
,
startPos
,
functionId
,
&
index
,
&
colSchema
,
&
resultSchema
,
NULL
,
0
,
rawName
,
true
);
}
else
{
STableMetaInfo
*
pTableMetaInfo
=
getMetaInfo
(
pQueryInfo
,
index
.
tableIndex
);
if
(
TSDB_COL_IS_TAG
(
index
.
type
)
&&
UTIL_TABLE_IS_NORMAL_TABLE
(
pTableMetaInfo
))
{
...
...
@@ -2584,13 +2605,13 @@ static int32_t validateExprLeafNode(tSqlExpr* pExpr, SQueryStmtInfo* pQueryInfo,
return
TSDB_CODE_TSC_INVALID_OPERATION
;
}
int32_t
outputIndex
=
(
int32_t
)
tsc
NumOfExprs
(
pQueryInfo
);
int32_t
outputIndex
=
(
int32_t
)
get
NumOfExprs
(
pQueryInfo
);
if
(
addExprAndResColumn
(
pQueryInfo
,
outputIndex
,
&
item
,
false
,
pMsgBuf
)
!=
TSDB_CODE_SUCCESS
)
{
return
TSDB_CODE_TSC_INVALID_OPERATION
;
}
// It is invalid in case of more than one sqlExpr, such as first(ts, k) - last(ts, k)
int32_t
inc
=
(
int32_t
)
tsc
NumOfExprs
(
pQueryInfo
)
-
outputIndex
;
int32_t
inc
=
(
int32_t
)
get
NumOfExprs
(
pQueryInfo
)
-
outputIndex
;
if
(
inc
>
1
)
{
return
TSDB_CODE_TSC_INVALID_OPERATION
;
}
...
...
@@ -2805,7 +2826,7 @@ int32_t sqlExprToExprNode(tExprNode **pExpr, const tSqlExpr* pSqlExpr, SQuerySt
// check for dividing by 0
if
((
*
pExpr
)
->
_node
.
optr
==
TSDB_BINARY_OP_DIVIDE
)
{
if
(
pRight
->
nodeType
==
TEXPR_VALUE_NODE
)
{
if
(
pRight
->
pVal
->
nType
==
TSDB_DATA_TYPE_INT
&&
pRight
->
pVal
->
i
64
==
0
)
{
if
(
pRight
->
pVal
->
nType
==
TSDB_DATA_TYPE_INT
&&
pRight
->
pVal
->
i
==
0
)
{
return
buildInvalidOperationMsg
(
pMsgBuf
,
"invalid expr (divide by 0)"
);
}
else
if
(
pRight
->
pVal
->
nType
==
TSDB_DATA_TYPE_FLOAT
&&
pRight
->
pVal
->
d
==
0
)
{
return
buildInvalidOperationMsg
(
pMsgBuf
,
"invalid expr (divide by 0)"
);
...
...
@@ -2950,32 +2971,27 @@ int32_t validateSelectNodeList(SQueryStmtInfo* pQueryInfo, SArray* pSelNodeList,
const
char
*
msg1
=
"too many items in selection clause"
;
const
char
*
msg2
=
"functions or others can not be mixed up"
;
const
char
*
msg3
=
"not support query expression"
;
const
char
*
msg4
=
"
not support distinct mixed with proj/agg func
"
;
const
char
*
msg4
=
"
distinct should be in the first place in select clause
"
;
const
char
*
msg5
=
"invalid function name"
;
const
char
*
msg6
=
"_block_dist not support subquery, only support stable/table"
;
// too many result columns not support order by in query
if
(
taosArrayGetSize
(
pSelNodeList
)
>
TSDB_MAX_COLUMNS
)
{
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg1
);
}
if
(
pQueryInfo
->
colList
==
NULL
)
{
pQueryInfo
->
colList
=
taosArrayInit
(
4
,
POINTER_BYTES
);
}
size_t
numOfExpr
=
taosArrayGetSize
(
pSelNodeList
);
for
(
int32_t
i
=
0
;
i
<
numOfExpr
;
++
i
)
{
int32_t
outputIndex
=
(
int32_t
)
tsc
NumOfExprs
(
pQueryInfo
);
int32_t
outputIndex
=
(
int32_t
)
get
NumOfExprs
(
pQueryInfo
);
tSqlExprItem
*
pItem
=
taosArrayGet
(
pSelNodeList
,
i
);
int32_t
type
=
pItem
->
pNode
->
type
;
if
(
pItem
->
distinct
)
{
if
(
i
!=
0
||
type
==
SQL_NODE_SQLFUNCTION
||
type
==
SQL_NODE_EXPR
)
{
if
(
i
!=
0
/* || type == SQL_NODE_SQLFUNCTION || type == SQL_NODE_EXPR*/
)
{
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg4
);
}
pQueryInfo
->
distinct
=
true
;
pQueryInfo
->
info
.
distinct
=
true
;
}
if
(
type
==
SQL_NODE_SQLFUNCTION
)
{
...
...
@@ -3010,39 +3026,32 @@ int32_t validateSelectNodeList(SQueryStmtInfo* pQueryInfo, SArray* pSelNodeList,
}
}
// there is only one user-defined column in the final result field, add the timestamp column.
// size_t numOfSrcCols = taosArrayGetSize(pQueryInfo->colList);
// if ((numOfSrcCols <= 0 || !hasNoneUserDefineExpr(pQueryInfo)) && !tscQueryTags(pQueryInfo) && !tscQueryBlockInfo(pQueryInfo)) {
// addPrimaryTsColIntoResult(pQueryInfo, pCmd);
// }
return
TSDB_CODE_SUCCESS
;
}
int32_t
evaluateSqlNode
(
SSqlNode
*
pNode
,
int32_t
tsPrecision
,
SMsgBuf
*
pMsgBuf
)
{
assert
(
pNode
!=
NULL
&&
pMsgBuf
!=
NULL
&&
pMsgBuf
->
len
>
0
);
if
(
pNode
->
pWhere
==
NULL
)
{
return
TSDB_CODE_SUCCESS
;
}
// Evaluate expression in where clause
int32_t
code
=
evaluateImpl
(
pNode
->
pWhere
,
tsPrecision
);
if
(
code
!=
TSDB_CODE_SUCCESS
)
{
strncpy
(
pMsgBuf
->
buf
,
"invalid time expression in sql"
,
pMsgBuf
->
len
);
return
code
;
if
(
pNode
->
pWhere
!=
NULL
)
{
int32_t
code
=
evaluateSqlNodeImpl
(
pNode
->
pWhere
,
tsPrecision
);
if
(
code
!=
TSDB_CODE_SUCCESS
)
{
strncpy
(
pMsgBuf
->
buf
,
"invalid time expression in sql"
,
pMsgBuf
->
len
);
return
code
;
}
}
// Evaluate the expression in select clause
size_t
size
=
taosArrayGetSize
(
pNode
->
pSelNodeList
);
for
(
int32_t
i
=
0
;
i
<
size
;
++
i
)
{
tSqlExprItem
*
pItem
=
taosArrayGet
(
pNode
->
pSelNodeList
,
i
);
code
=
evaluat
eImpl
(
pItem
->
pNode
,
tsPrecision
);
int32_t
code
=
evaluateSqlNod
eImpl
(
pItem
->
pNode
,
tsPrecision
);
if
(
code
!=
TSDB_CODE_SUCCESS
)
{
return
code
;
}
}
return
code
;
return
TSDB_CODE_SUCCESS
;
}
int32_t
qParserValidateSqlNode
(
struct
SCatalog
*
pCatalog
,
SSqlInfo
*
pInfo
,
SQueryStmtInfo
*
pQueryInfo
,
int64_t
id
,
char
*
msgBuf
,
int32_t
msgBufLen
)
{
...
...
source/libs/parser/src/parser.c
浏览文件 @
b4ff474e
...
...
@@ -177,7 +177,7 @@ int32_t qParserExtractRequestedMetaInfo(const SSqlInfo* pSqlInfo, SMetaReq* pMet
}
// Let's assume that it is an UDF/UDAF, if it is not a built-in function.
if
(
!
qIsBuiltinFunction
(
t
->
z
,
t
->
n
)
)
{
if
(
qIsBuiltinFunction
(
t
->
z
,
t
->
n
)
<
0
)
{
char
*
fname
=
strndup
(
t
->
z
,
t
->
n
);
taosArrayPush
(
pMetaInfo
->
pUdf
,
&
fname
);
}
...
...
source/libs/parser/src/queryInfoUtil.c
浏览文件 @
b4ff474e
...
...
@@ -212,7 +212,7 @@ void assignExprInfo(SExprInfo* dst, const SExprInfo* src) {
}
#endif
//
dst->pExpr = exprdup(src->pExpr);
dst
->
pExpr
=
exprdup
(
src
->
pExpr
);
memset
(
dst
->
base
.
param
,
0
,
sizeof
(
SVariant
)
*
tListLen
(
dst
->
base
.
param
));
for
(
int32_t
j
=
0
;
j
<
src
->
base
.
numOfParams
;
++
j
)
{
taosVariantAssign
(
&
dst
->
base
.
param
[
j
],
&
src
->
base
.
param
[
j
]);
...
...
source/libs/parser/test/CMakeLists.txt
浏览文件 @
b4ff474e
...
...
@@ -8,7 +8,7 @@ AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} SOURCE_LIST)
ADD_EXECUTABLE
(
parserTest
${
SOURCE_LIST
}
)
TARGET_LINK_LIBRARIES
(
parserTest
PUBLIC os util common parser catalog transport gtest function
PUBLIC os util common parser catalog transport gtest function
planner
)
TARGET_INCLUDE_DIRECTORIES
(
...
...
source/libs/parser/test/parserTests.cpp
浏览文件 @
b4ff474e
...
...
@@ -13,7 +13,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <function.h>
#include <gtest/gtest.h>
#include <iostream>
#pragma GCC diagnostic ignored "-Wwrite-strings"
...
...
@@ -124,287 +123,462 @@ TEST(testCase, validateAST_test) {
destroySqlInfo
(
&
info1
);
}
//TEST(testCase, function_Test) {
// SSqlInfo info1 = doGenerateAST("select count(a) from `t.1abc`");
// ASSERT_EQ(info1.valid, true);
//
// char msg[128] = {0};
// SMsgBuf buf;
// buf.len = 128;
// buf.buf = msg;
//
// SSqlNode* pNode = (SSqlNode*) taosArrayGetP(((SArray*)info1.list), 0);
// int32_t code = evaluateSqlNode(pNode, TSDB_TIME_PRECISION_NANO, &buf);
// ASSERT_EQ(code, 0);
//
// SMetaReq req = {0};
// int32_t ret = qParserExtractRequestedMetaInfo(&info1, &req, msg, 128);
// ASSERT_EQ(ret, 0);
// ASSERT_EQ(taosArrayGetSize(req.pTableName), 1);
//
// SQueryStmtInfo* pQueryInfo = createQueryInfo();
// setTableMetaInfo(pQueryInfo, &req);
//
// SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.list, 0);
// ret = validateSqlNode(pSqlNode, pQueryInfo, &buf);
//
// SArray* pExprList = pQueryInfo->exprList;
// ASSERT_EQ(taosArrayGetSize(pExprList), 1);
//
// SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 0);
// ASSERT_EQ(p1->base.uid, 110);
// ASSERT_EQ(p1->base.numOfParams, 0);
// ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_BIGINT);
// ASSERT_STRCASEEQ(p1->base.resSchema.name, "count(a)");
// ASSERT_STRCASEEQ(p1->base.colInfo.name, "t.1abc.a");
// ASSERT_EQ(p1->base.colInfo.colId, 1);
// ASSERT_EQ(p1->base.colInfo.flag, TSDB_COL_NORMAL);
// ASSERT_STRCASEEQ(p1->base.token, "count(a)");
// ASSERT_EQ(p1->base.interBytes, 8);
//
// ASSERT_EQ(taosArrayGetSize(pQueryInfo->colList), 2);
// ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 1);
//
// destroyQueryInfo(pQueryInfo);
// qParserClearupMetaRequestInfo(&req);
// destroySqlInfo(&info1);
//}
//
//TEST(testCase, function_Test2) {
// SSqlInfo info1 = doGenerateAST("select count(a) abc from `t.1abc`");
// ASSERT_EQ(info1.valid, true);
//
// char msg[128] = {0};
// SMsgBuf buf;
// buf.len = 128;
// buf.buf = msg;
//
// SSqlNode* pNode = (SSqlNode*) taosArrayGetP(((SArray*)info1.list), 0);
// int32_t code = evaluateSqlNode(pNode, TSDB_TIME_PRECISION_NANO, &buf);
// ASSERT_EQ(code, 0);
//
// SMetaReq req = {0};
// int32_t ret = qParserExtractRequestedMetaInfo(&info1, &req, msg, 128);
// ASSERT_EQ(ret, 0);
// ASSERT_EQ(taosArrayGetSize(req.pTableName), 1);
//
// SQueryStmtInfo* pQueryInfo = createQueryInfo();
// setTableMetaInfo(pQueryInfo, &req);
//
// SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.list, 0);
// ret = validateSqlNode(pSqlNode, pQueryInfo, &buf);
//
// SArray* pExprList = pQueryInfo->exprList;
// ASSERT_EQ(taosArrayGetSize(pExprList), 1);
//
// SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 0);
// ASSERT_EQ(p1->base.uid, 110);
// ASSERT_EQ(p1->base.numOfParams, 0);
// ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_BIGINT);
// ASSERT_STRCASEEQ(p1->base.resSchema.name, "abc");
// ASSERT_STRCASEEQ(p1->base.colInfo.name, "t.1abc.a");
// ASSERT_EQ(p1->base.colInfo.colId, 1);
// ASSERT_EQ(p1->base.colInfo.flag, TSDB_COL_NORMAL);
// ASSERT_STRCASEEQ(p1->base.token, "count(a)");
// ASSERT_EQ(p1->base.interBytes, 8);
//
// ASSERT_EQ(taosArrayGetSize(pQueryInfo->colList), 2);
// ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 1);
//
// destroyQueryInfo(pQueryInfo);
// qParserClearupMetaRequestInfo(&req);
// destroySqlInfo(&info1);
//}
//
//TEST(testCase, function_Test3) {
// SSqlInfo info1 = doGenerateAST("select first(*) from `t.1abc`");
// ASSERT_EQ(info1.valid, true);
//
// char msg[128] = {0};
// SMsgBuf buf;
// buf.len = 128;
// buf.buf = msg;
//
// SSqlNode* pNode = (SSqlNode*) taosArrayGetP(((SArray*)info1.list), 0);
// int32_t code = evaluateSqlNode(pNode, TSDB_TIME_PRECISION_NANO, &buf);
// ASSERT_EQ(code, 0);
//
// SMetaReq req = {0};
// int32_t ret = qParserExtractRequestedMetaInfo(&info1, &req, msg, 128);
// ASSERT_EQ(ret, 0);
// ASSERT_EQ(taosArrayGetSize(req.pTableName), 1);
//
// SQueryStmtInfo* pQueryInfo = createQueryInfo();
// setTableMetaInfo(pQueryInfo, &req);
//
// SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.list, 0);
// ret = validateSqlNode(pSqlNode, pQueryInfo, &buf);
//
// SArray* pExprList = pQueryInfo->exprList;
// ASSERT_EQ(taosArrayGetSize(pExprList), 4);
//
// SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 0);
// ASSERT_EQ(p1->base.uid, 110);
// ASSERT_EQ(p1->base.numOfParams, 0);
// ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_TIMESTAMP);
// ASSERT_STRCASEEQ(p1->base.resSchema.name, "first(ts)");
TEST
(
testCase
,
function_Test
)
{
SSqlInfo
info1
=
doGenerateAST
(
"select count(a) from `t.1abc`"
);
ASSERT_EQ
(
info1
.
valid
,
true
);
char
msg
[
128
]
=
{
0
};
SMsgBuf
buf
;
buf
.
len
=
128
;
buf
.
buf
=
msg
;
SSqlNode
*
pNode
=
(
SSqlNode
*
)
taosArrayGetP
(((
SArray
*
)
info1
.
list
),
0
);
int32_t
code
=
evaluateSqlNode
(
pNode
,
TSDB_TIME_PRECISION_NANO
,
&
buf
);
ASSERT_EQ
(
code
,
0
);
SMetaReq
req
=
{
0
};
int32_t
ret
=
qParserExtractRequestedMetaInfo
(
&
info1
,
&
req
,
msg
,
128
);
ASSERT_EQ
(
ret
,
0
);
ASSERT_EQ
(
taosArrayGetSize
(
req
.
pTableName
),
1
);
SQueryStmtInfo
*
pQueryInfo
=
createQueryInfo
();
setTableMetaInfo
(
pQueryInfo
,
&
req
);
SSqlNode
*
pSqlNode
=
(
SSqlNode
*
)
taosArrayGetP
(
info1
.
list
,
0
);
ret
=
validateSqlNode
(
pSqlNode
,
pQueryInfo
,
&
buf
);
SArray
*
pExprList
=
pQueryInfo
->
exprList
;
ASSERT_EQ
(
taosArrayGetSize
(
pExprList
),
1
);
SExprInfo
*
p1
=
(
SExprInfo
*
)
taosArrayGetP
(
pExprList
,
0
);
ASSERT_EQ
(
p1
->
base
.
uid
,
110
);
ASSERT_EQ
(
p1
->
base
.
numOfParams
,
0
);
ASSERT_EQ
(
p1
->
base
.
resSchema
.
type
,
TSDB_DATA_TYPE_BIGINT
);
ASSERT_STRCASEEQ
(
p1
->
base
.
resSchema
.
name
,
"count(a)"
);
ASSERT_STRCASEEQ
(
p1
->
base
.
colInfo
.
name
,
"t.1abc.a"
);
ASSERT_EQ
(
p1
->
base
.
colInfo
.
colId
,
1
);
ASSERT_EQ
(
p1
->
base
.
colInfo
.
flag
,
TSDB_COL_NORMAL
);
ASSERT_STRCASEEQ
(
p1
->
base
.
token
,
"count(a)"
);
ASSERT_EQ
(
p1
->
base
.
interBytes
,
8
);
ASSERT_EQ
(
taosArrayGetSize
(
pQueryInfo
->
colList
),
2
);
ASSERT_EQ
(
pQueryInfo
->
fieldsInfo
.
numOfOutput
,
1
);
destroyQueryInfo
(
pQueryInfo
);
qParserClearupMetaRequestInfo
(
&
req
);
destroySqlInfo
(
&
info1
);
}
TEST
(
testCase
,
function_Test2
)
{
SSqlInfo
info1
=
doGenerateAST
(
"select count(a) abc from `t.1abc`"
);
ASSERT_EQ
(
info1
.
valid
,
true
);
char
msg
[
128
]
=
{
0
};
SMsgBuf
buf
;
buf
.
len
=
128
;
buf
.
buf
=
msg
;
SSqlNode
*
pNode
=
(
SSqlNode
*
)
taosArrayGetP
(((
SArray
*
)
info1
.
list
),
0
);
int32_t
code
=
evaluateSqlNode
(
pNode
,
TSDB_TIME_PRECISION_NANO
,
&
buf
);
ASSERT_EQ
(
code
,
0
);
SMetaReq
req
=
{
0
};
int32_t
ret
=
qParserExtractRequestedMetaInfo
(
&
info1
,
&
req
,
msg
,
128
);
ASSERT_EQ
(
ret
,
0
);
ASSERT_EQ
(
taosArrayGetSize
(
req
.
pTableName
),
1
);
SQueryStmtInfo
*
pQueryInfo
=
createQueryInfo
();
setTableMetaInfo
(
pQueryInfo
,
&
req
);
SSqlNode
*
pSqlNode
=
(
SSqlNode
*
)
taosArrayGetP
(
info1
.
list
,
0
);
ret
=
validateSqlNode
(
pSqlNode
,
pQueryInfo
,
&
buf
);
SArray
*
pExprList
=
pQueryInfo
->
exprList
;
ASSERT_EQ
(
taosArrayGetSize
(
pExprList
),
1
);
SExprInfo
*
p1
=
(
SExprInfo
*
)
taosArrayGetP
(
pExprList
,
0
);
ASSERT_EQ
(
p1
->
base
.
uid
,
110
);
ASSERT_EQ
(
p1
->
base
.
numOfParams
,
0
);
ASSERT_EQ
(
p1
->
base
.
resSchema
.
type
,
TSDB_DATA_TYPE_BIGINT
);
ASSERT_STRCASEEQ
(
p1
->
base
.
resSchema
.
name
,
"abc"
);
ASSERT_STRCASEEQ
(
p1
->
base
.
colInfo
.
name
,
"t.1abc.a"
);
ASSERT_EQ
(
p1
->
base
.
colInfo
.
colId
,
1
);
ASSERT_EQ
(
p1
->
base
.
colInfo
.
flag
,
TSDB_COL_NORMAL
);
ASSERT_STRCASEEQ
(
p1
->
base
.
token
,
"count(a)"
);
ASSERT_EQ
(
p1
->
base
.
interBytes
,
8
);
ASSERT_EQ
(
taosArrayGetSize
(
pQueryInfo
->
colList
),
2
);
ASSERT_EQ
(
pQueryInfo
->
fieldsInfo
.
numOfOutput
,
1
);
destroyQueryInfo
(
pQueryInfo
);
qParserClearupMetaRequestInfo
(
&
req
);
destroySqlInfo
(
&
info1
);
}
TEST
(
testCase
,
function_Test3
)
{
SSqlInfo
info1
=
doGenerateAST
(
"select first(*) from `t.1abc`"
);
ASSERT_EQ
(
info1
.
valid
,
true
);
char
msg
[
128
]
=
{
0
};
SMsgBuf
buf
;
buf
.
len
=
128
;
buf
.
buf
=
msg
;
SSqlNode
*
pNode
=
(
SSqlNode
*
)
taosArrayGetP
(((
SArray
*
)
info1
.
list
),
0
);
int32_t
code
=
evaluateSqlNode
(
pNode
,
TSDB_TIME_PRECISION_NANO
,
&
buf
);
ASSERT_EQ
(
code
,
0
);
SMetaReq
req
=
{
0
};
int32_t
ret
=
qParserExtractRequestedMetaInfo
(
&
info1
,
&
req
,
msg
,
128
);
ASSERT_EQ
(
ret
,
0
);
ASSERT_EQ
(
taosArrayGetSize
(
req
.
pTableName
),
1
);
SQueryStmtInfo
*
pQueryInfo
=
createQueryInfo
();
setTableMetaInfo
(
pQueryInfo
,
&
req
);
SSqlNode
*
pSqlNode
=
(
SSqlNode
*
)
taosArrayGetP
(
info1
.
list
,
0
);
ret
=
validateSqlNode
(
pSqlNode
,
pQueryInfo
,
&
buf
);
SArray
*
pExprList
=
pQueryInfo
->
exprList
;
ASSERT_EQ
(
taosArrayGetSize
(
pExprList
),
4
);
SExprInfo
*
p1
=
(
SExprInfo
*
)
taosArrayGetP
(
pExprList
,
0
);
ASSERT_EQ
(
p1
->
base
.
uid
,
110
);
ASSERT_EQ
(
p1
->
base
.
numOfParams
,
0
);
ASSERT_EQ
(
p1
->
base
.
resSchema
.
type
,
TSDB_DATA_TYPE_TIMESTAMP
);
ASSERT_STRCASEEQ
(
p1
->
base
.
resSchema
.
name
,
"first(ts)"
);
ASSERT_STRCASEEQ
(
p1
->
base
.
colInfo
.
name
,
"t.1abc.ts"
);
ASSERT_EQ
(
p1
->
base
.
colInfo
.
colId
,
0
);
ASSERT_EQ
(
p1
->
base
.
colInfo
.
flag
,
TSDB_COL_NORMAL
);
ASSERT_STRCASEEQ
(
p1
->
base
.
token
,
"first(ts)"
);
ASSERT_EQ
(
p1
->
base
.
interBytes
,
24
);
ASSERT_EQ
(
pQueryInfo
->
fieldsInfo
.
numOfOutput
,
4
);
destroyQueryInfo
(
pQueryInfo
);
qParserClearupMetaRequestInfo
(
&
req
);
destroySqlInfo
(
&
info1
);
}
TEST
(
testCase
,
function_Test4
)
{
SSqlInfo
info1
=
doGenerateAST
(
"select _block_dist() as a1 from `t.1abc`"
);
ASSERT_EQ
(
info1
.
valid
,
true
);
char
msg
[
128
]
=
{
0
};
SMsgBuf
buf
;
buf
.
len
=
128
;
buf
.
buf
=
msg
;
SSqlNode
*
pNode
=
(
SSqlNode
*
)
taosArrayGetP
(((
SArray
*
)
info1
.
list
),
0
);
int32_t
code
=
evaluateSqlNode
(
pNode
,
TSDB_TIME_PRECISION_NANO
,
&
buf
);
ASSERT_EQ
(
code
,
0
);
SMetaReq
req
=
{
0
};
int32_t
ret
=
qParserExtractRequestedMetaInfo
(
&
info1
,
&
req
,
msg
,
128
);
ASSERT_EQ
(
ret
,
0
);
ASSERT_EQ
(
taosArrayGetSize
(
req
.
pTableName
),
1
);
SQueryStmtInfo
*
pQueryInfo
=
createQueryInfo
();
setTableMetaInfo
(
pQueryInfo
,
&
req
);
SSqlNode
*
pSqlNode
=
(
SSqlNode
*
)
taosArrayGetP
(
info1
.
list
,
0
);
ret
=
validateSqlNode
(
pSqlNode
,
pQueryInfo
,
&
buf
);
SArray
*
pExprList
=
pQueryInfo
->
exprList
;
ASSERT_EQ
(
taosArrayGetSize
(
pExprList
),
1
);
SExprInfo
*
p1
=
(
SExprInfo
*
)
taosArrayGetP
(
pExprList
,
0
);
ASSERT_EQ
(
p1
->
base
.
uid
,
110
);
ASSERT_EQ
(
p1
->
base
.
numOfParams
,
1
);
ASSERT_EQ
(
p1
->
base
.
resSchema
.
type
,
TSDB_DATA_TYPE_BINARY
);
ASSERT_STRCASEEQ
(
p1
->
base
.
resSchema
.
name
,
"a1"
);
// ASSERT_STRCASEEQ(p1->base.colInfo.name, "t.1abc.ts");
// ASSERT_EQ(p1->base.colInfo.colId, 0);
// ASSERT_EQ(p1->base.colInfo.flag, TSDB_COL_NORMAL);
// ASSERT_STRCASEEQ(p1->base.token, "first(ts)");
// ASSERT_EQ(p1->base.interBytes, 24);
//
// ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 4);
//
// destroyQueryInfo(pQueryInfo);
// qParserClearupMetaRequestInfo(&req);
// destroySqlInfo(&info1);
//}
//
//TEST(testCase, function_Test4) {
// SSqlInfo info1 = doGenerateAST("select _block_dist() as a1 from `t.1abc`");
// ASSERT_EQ(info1.valid, true);
//
// char msg[128] = {0};
// SMsgBuf buf;
// buf.len = 128;
// buf.buf = msg;
//
// SSqlNode* pNode = (SSqlNode*) taosArrayGetP(((SArray*)info1.list), 0);
// int32_t code = evaluateSqlNode(pNode, TSDB_TIME_PRECISION_NANO, &buf);
// ASSERT_EQ(code, 0);
//
// SMetaReq req = {0};
// int32_t ret = qParserExtractRequestedMetaInfo(&info1, &req, msg, 128);
// ASSERT_EQ(ret, 0);
// ASSERT_EQ(taosArrayGetSize(req.pTableName), 1);
//
// SQueryStmtInfo* pQueryInfo = createQueryInfo();
// setTableMetaInfo(pQueryInfo, &req);
//
// SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.list, 0);
// ret = validateSqlNode(pSqlNode, pQueryInfo, &buf);
//
// SArray* pExprList = pQueryInfo->exprList;
// ASSERT_EQ(taosArrayGetSize(pExprList), 1);
//
// SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 0);
// ASSERT_EQ(p1->base.uid, 110);
// ASSERT_EQ(p1->base.numOfParams, 1);
// ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_BINARY);
// ASSERT_STRCASEEQ(p1->base.resSchema.name, "a1");
//// ASSERT_STRCASEEQ(p1->base.colInfo.name, "t.1abc.ts");
//// ASSERT_EQ(p1->base.colInfo.colId, 0);
// ASSERT_EQ(p1->base.colInfo.flag, TSDB_COL_NORMAL);
// ASSERT_STRCASEEQ(p1->base.token, "_block_dist()");
// ASSERT_EQ(p1->base.interBytes, 0);
//
// ASSERT_EQ(taosArrayGetSize(pQueryInfo->colList), 1);
// ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 1);
//
// destroyQueryInfo(pQueryInfo);
// qParserClearupMetaRequestInfo(&req);
// destroySqlInfo(&info1);
//}
//
//TEST(testCase, function_Test5) {
// SSqlInfo info1 = doGenerateAST("select sum(a) + avg(b) as a1 from `t.1abc`");
// ASSERT_EQ(info1.valid, true);
//
// char msg[128] = {0};
// SMsgBuf buf;
// buf.len = 128;
// buf.buf = msg;
//
// SSqlNode* pNode = (SSqlNode*) taosArrayGetP(((SArray*)info1.list), 0);
// int32_t code = evaluateSqlNode(pNode, TSDB_TIME_PRECISION_NANO, &buf);
// ASSERT_EQ(code, 0);
//
// SMetaReq req = {0};
// int32_t ret = qParserExtractRequestedMetaInfo(&info1, &req, msg, 128);
// ASSERT_EQ(ret, 0);
// ASSERT_EQ(taosArrayGetSize(req.pTableName), 1);
//
// SQueryStmtInfo* pQueryInfo = createQueryInfo();
// setTableMetaInfo(pQueryInfo, &req);
//
// SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.list, 0);
// ret = validateSqlNode(pSqlNode, pQueryInfo, &buf);
// ASSERT_EQ(ret, 0);
//
// SArray* pExprList = pQueryInfo->exprList;
// ASSERT_EQ(taosArrayGetSize(pExprList), 3);
//
// SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 0);
// ASSERT_EQ(p1->base.uid, 0);
// ASSERT_EQ(p1->base.numOfParams, 1);
// ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_DOUBLE);
// ASSERT_STRCASEEQ(p1->base.resSchema.name, "a1");
//// ASSERT_STRCASEEQ(p1->base.colInfo.name, "t.1abc.ts");
//// ASSERT_EQ(p1->base.colInfo.colId, 0);
// ASSERT_EQ(p1->base.colInfo.flag, TSDB_COL_NORMAL);
// ASSERT_STRCASEEQ(p1->base.token, "sum(a) + avg(b)");
// ASSERT_EQ(p1->base.interBytes, 0);
//
// ASSERT_EQ(taosArrayGetSize(pQueryInfo->colList), 3);
// ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 1);
//
// destroyQueryInfo(pQueryInfo);
// qParserClearupMetaRequestInfo(&req);
// destroySqlInfo(&info1);
//}
//
//TEST(testCase, function_Test6) {
// SSqlInfo info1 = doGenerateAST("select sum(a+b) as a1, first(b*a) from `t.1abc` interval(10s, 1s)");
// ASSERT_EQ(info1.valid, true);
//
// char msg[128] = {0};
// SMsgBuf buf;
// buf.len = 128;
// buf.buf = msg;
//
// SSqlNode* pNode = (SSqlNode*) taosArrayGetP(((SArray*)info1.list), 0);
// int32_t code = evaluateSqlNode(pNode, TSDB_TIME_PRECISION_NANO, &buf);
// ASSERT_EQ(code, 0);
//
// SMetaReq req = {0};
// int32_t ret = qParserExtractRequestedMetaInfo(&info1, &req, msg, 128);
// ASSERT_EQ(ret, 0);
// ASSERT_EQ(taosArrayGetSize(req.pTableName), 1);
//
// SQueryStmtInfo* pQueryInfo = createQueryInfo();
// setTableMetaInfo(pQueryInfo, &req);
//
// SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.list, 0);
// ret = validateSqlNode(pSqlNode, pQueryInfo, &buf);
// ASSERT_EQ(ret, 0);
//
// SArray* pExprList = pQueryInfo->exprList;
// ASSERT_EQ(taosArrayGetSize(pExprList), 2);
//
// SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 0);
// ASSERT_EQ(p1->base.uid, 110);
// ASSERT_EQ(p1->base.numOfParams, 0);
// ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_DOUBLE);
// ASSERT_STRCASEEQ(p1->base.resSchema.name, "a1");
// ASSERT_EQ(p1->base.colInfo.flag, TSDB_COL_NORMAL);
// ASSERT_STRCASEEQ(p1->base.token, "sum(a+b)");
// ASSERT_EQ(p1->base.interBytes, 16);
// ASSERT_EQ(p1->pExpr->nodeType, TEXPR_UNARYEXPR_NODE);
// ASSERT_EQ(p1->pExpr->_node.functionId, FUNCTION_SUM);
// ASSERT_TRUE(p1->pExpr->_node.pRight == NULL);
//
// tExprNode* pParam = p1->pExpr->_node.pLeft;
//
// ASSERT_EQ(pParam->nodeType, TEXPR_BINARYEXPR_NODE);
// ASSERT_EQ(pParam->_node.optr, TSDB_BINARY_OP_ADD);
// ASSERT_EQ(pParam->_node.pLeft->nodeType, TEXPR_COL_NODE);
// ASSERT_EQ(pParam->_node.pRight->nodeType, TEXPR_COL_NODE);
//
// ASSERT_EQ(taosArrayGetSize(pQueryInfo->colList), 3);
// ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 2);
//
// destroyQueryInfo(pQueryInfo);
// qParserClearupMetaRequestInfo(&req);
// destroySqlInfo(&info1);
//}
\ No newline at end of file
ASSERT_EQ
(
p1
->
base
.
colInfo
.
flag
,
TSDB_COL_NORMAL
);
ASSERT_STRCASEEQ
(
p1
->
base
.
token
,
"_block_dist()"
);
ASSERT_EQ
(
p1
->
base
.
interBytes
,
0
);
ASSERT_EQ
(
taosArrayGetSize
(
pQueryInfo
->
colList
),
1
);
ASSERT_EQ
(
pQueryInfo
->
fieldsInfo
.
numOfOutput
,
1
);
destroyQueryInfo
(
pQueryInfo
);
qParserClearupMetaRequestInfo
(
&
req
);
destroySqlInfo
(
&
info1
);
}
TEST
(
testCase
,
function_Test5
)
{
SSqlInfo
info1
=
doGenerateAST
(
"select sum(a) + avg(b) as a1 from `t.1abc`"
);
ASSERT_EQ
(
info1
.
valid
,
true
);
char
msg
[
128
]
=
{
0
};
SMsgBuf
buf
;
buf
.
len
=
128
;
buf
.
buf
=
msg
;
SSqlNode
*
pNode
=
(
SSqlNode
*
)
taosArrayGetP
(((
SArray
*
)
info1
.
list
),
0
);
int32_t
code
=
evaluateSqlNode
(
pNode
,
TSDB_TIME_PRECISION_NANO
,
&
buf
);
ASSERT_EQ
(
code
,
0
);
SMetaReq
req
=
{
0
};
int32_t
ret
=
qParserExtractRequestedMetaInfo
(
&
info1
,
&
req
,
msg
,
128
);
ASSERT_EQ
(
ret
,
0
);
ASSERT_EQ
(
taosArrayGetSize
(
req
.
pTableName
),
1
);
SQueryStmtInfo
*
pQueryInfo
=
createQueryInfo
();
setTableMetaInfo
(
pQueryInfo
,
&
req
);
SSqlNode
*
pSqlNode
=
(
SSqlNode
*
)
taosArrayGetP
(
info1
.
list
,
0
);
ret
=
validateSqlNode
(
pSqlNode
,
pQueryInfo
,
&
buf
);
ASSERT_EQ
(
ret
,
0
);
SArray
*
pExprList
=
pQueryInfo
->
exprList
;
ASSERT_EQ
(
taosArrayGetSize
(
pExprList
),
3
);
SExprInfo
*
p1
=
(
SExprInfo
*
)
taosArrayGetP
(
pExprList
,
0
);
ASSERT_EQ
(
p1
->
base
.
uid
,
0
);
ASSERT_EQ
(
p1
->
base
.
numOfParams
,
1
);
ASSERT_EQ
(
p1
->
base
.
resSchema
.
type
,
TSDB_DATA_TYPE_DOUBLE
);
ASSERT_STRCASEEQ
(
p1
->
base
.
resSchema
.
name
,
"a1"
);
// ASSERT_STRCASEEQ(p1->base.colInfo.name, "t.1abc.ts");
// ASSERT_EQ(p1->base.colInfo.colId, 0);
ASSERT_EQ
(
p1
->
base
.
colInfo
.
flag
,
TSDB_COL_NORMAL
);
ASSERT_STRCASEEQ
(
p1
->
base
.
token
,
"sum(a) + avg(b)"
);
ASSERT_EQ
(
p1
->
base
.
interBytes
,
0
);
ASSERT_EQ
(
taosArrayGetSize
(
pQueryInfo
->
colList
),
3
);
ASSERT_EQ
(
pQueryInfo
->
fieldsInfo
.
numOfOutput
,
1
);
destroyQueryInfo
(
pQueryInfo
);
qParserClearupMetaRequestInfo
(
&
req
);
destroySqlInfo
(
&
info1
);
}
TEST
(
testCase
,
function_Test6
)
{
SSqlInfo
info1
=
doGenerateAST
(
"select sum(a+b) as a1, first(b*a), count(b+b), count(1), count(42.1) from `t.1abc` interval(10s, 1s)"
);
ASSERT_EQ
(
info1
.
valid
,
true
);
char
msg
[
128
]
=
{
0
};
SMsgBuf
buf
;
buf
.
len
=
128
;
buf
.
buf
=
msg
;
SSqlNode
*
pNode
=
(
SSqlNode
*
)
taosArrayGetP
(((
SArray
*
)
info1
.
list
),
0
);
int32_t
code
=
evaluateSqlNode
(
pNode
,
TSDB_TIME_PRECISION_NANO
,
&
buf
);
ASSERT_EQ
(
code
,
0
);
SMetaReq
req
=
{
0
};
int32_t
ret
=
qParserExtractRequestedMetaInfo
(
&
info1
,
&
req
,
msg
,
128
);
ASSERT_EQ
(
ret
,
0
);
ASSERT_EQ
(
taosArrayGetSize
(
req
.
pTableName
),
1
);
SQueryStmtInfo
*
pQueryInfo
=
createQueryInfo
();
setTableMetaInfo
(
pQueryInfo
,
&
req
);
SSqlNode
*
pSqlNode
=
(
SSqlNode
*
)
taosArrayGetP
(
info1
.
list
,
0
);
ret
=
validateSqlNode
(
pSqlNode
,
pQueryInfo
,
&
buf
);
ASSERT_EQ
(
ret
,
0
);
SArray
*
pExprList
=
pQueryInfo
->
exprList
;
ASSERT_EQ
(
taosArrayGetSize
(
pExprList
),
5
);
SExprInfo
*
p1
=
(
SExprInfo
*
)
taosArrayGetP
(
pExprList
,
0
);
ASSERT_EQ
(
p1
->
base
.
uid
,
110
);
ASSERT_EQ
(
p1
->
base
.
numOfParams
,
0
);
ASSERT_EQ
(
p1
->
base
.
resSchema
.
type
,
TSDB_DATA_TYPE_DOUBLE
);
ASSERT_STRCASEEQ
(
p1
->
base
.
resSchema
.
name
,
"a1"
);
ASSERT_EQ
(
p1
->
base
.
colInfo
.
flag
,
TSDB_COL_NORMAL
);
ASSERT_STRCASEEQ
(
p1
->
base
.
token
,
"sum(a+b)"
);
ASSERT_EQ
(
p1
->
base
.
interBytes
,
16
);
ASSERT_EQ
(
p1
->
pExpr
->
nodeType
,
TEXPR_UNARYEXPR_NODE
);
ASSERT_EQ
(
p1
->
pExpr
->
_node
.
functionId
,
FUNCTION_SUM
);
ASSERT_TRUE
(
p1
->
pExpr
->
_node
.
pRight
==
NULL
);
tExprNode
*
pParam
=
p1
->
pExpr
->
_node
.
pLeft
;
ASSERT_EQ
(
pParam
->
nodeType
,
TEXPR_BINARYEXPR_NODE
);
ASSERT_EQ
(
pParam
->
_node
.
optr
,
TSDB_BINARY_OP_ADD
);
ASSERT_EQ
(
pParam
->
_node
.
pLeft
->
nodeType
,
TEXPR_COL_NODE
);
ASSERT_EQ
(
pParam
->
_node
.
pRight
->
nodeType
,
TEXPR_COL_NODE
);
ASSERT_EQ
(
taosArrayGetSize
(
pQueryInfo
->
colList
),
3
);
ASSERT_EQ
(
pQueryInfo
->
fieldsInfo
.
numOfOutput
,
5
);
SExprInfo
*
p2
=
(
SExprInfo
*
)
taosArrayGetP
(
pExprList
,
1
);
ASSERT_EQ
(
p2
->
base
.
uid
,
110
);
ASSERT_EQ
(
p2
->
base
.
numOfParams
,
0
);
ASSERT_EQ
(
p2
->
base
.
resSchema
.
type
,
TSDB_DATA_TYPE_DOUBLE
);
ASSERT_STRCASEEQ
(
p2
->
base
.
resSchema
.
name
,
"first(b*a)"
);
ASSERT_EQ
(
p2
->
base
.
colInfo
.
flag
,
TSDB_COL_NORMAL
);
ASSERT_STRCASEEQ
(
p2
->
base
.
token
,
"first(b*a)"
);
ASSERT_EQ
(
p2
->
base
.
interBytes
,
24
);
ASSERT_EQ
(
p2
->
pExpr
->
nodeType
,
TEXPR_UNARYEXPR_NODE
);
ASSERT_EQ
(
p2
->
pExpr
->
_node
.
functionId
,
FUNCTION_FIRST
);
ASSERT_TRUE
(
p2
->
pExpr
->
_node
.
pRight
==
NULL
);
destroyQueryInfo
(
pQueryInfo
);
qParserClearupMetaRequestInfo
(
&
req
);
destroySqlInfo
(
&
info1
);
}
TEST
(
testCase
,
function_Test7
)
{
SSqlInfo
info1
=
doGenerateAST
(
"select count(a+b),count(1) from `t.1abc` interval(10s, 1s)"
);
ASSERT_EQ
(
info1
.
valid
,
true
);
char
msg
[
128
]
=
{
0
};
SMsgBuf
buf
;
buf
.
len
=
128
;
buf
.
buf
=
msg
;
SSqlNode
*
pNode
=
(
SSqlNode
*
)
taosArrayGetP
(((
SArray
*
)
info1
.
list
),
0
);
int32_t
code
=
evaluateSqlNode
(
pNode
,
TSDB_TIME_PRECISION_NANO
,
&
buf
);
ASSERT_EQ
(
code
,
0
);
SMetaReq
req
=
{
0
};
int32_t
ret
=
qParserExtractRequestedMetaInfo
(
&
info1
,
&
req
,
msg
,
128
);
ASSERT_EQ
(
ret
,
0
);
ASSERT_EQ
(
taosArrayGetSize
(
req
.
pTableName
),
1
);
SQueryStmtInfo
*
pQueryInfo
=
createQueryInfo
();
setTableMetaInfo
(
pQueryInfo
,
&
req
);
SSqlNode
*
pSqlNode
=
(
SSqlNode
*
)
taosArrayGetP
(
info1
.
list
,
0
);
ret
=
validateSqlNode
(
pSqlNode
,
pQueryInfo
,
&
buf
);
ASSERT_EQ
(
ret
,
0
);
SArray
*
pExprList
=
pQueryInfo
->
exprList
;
ASSERT_EQ
(
taosArrayGetSize
(
pExprList
),
2
);
SExprInfo
*
p1
=
(
SExprInfo
*
)
taosArrayGetP
(
pExprList
,
0
);
ASSERT_EQ
(
p1
->
base
.
uid
,
110
);
ASSERT_EQ
(
p1
->
base
.
numOfParams
,
0
);
ASSERT_EQ
(
p1
->
base
.
resSchema
.
type
,
TSDB_DATA_TYPE_BIGINT
);
ASSERT_STRCASEEQ
(
p1
->
base
.
resSchema
.
name
,
"count(a+b)"
);
ASSERT_EQ
(
p1
->
base
.
colInfo
.
flag
,
TSDB_COL_NORMAL
);
ASSERT_STRCASEEQ
(
p1
->
base
.
token
,
"count(a+b)"
);
ASSERT_EQ
(
p1
->
base
.
interBytes
,
8
);
ASSERT_EQ
(
p1
->
pExpr
->
nodeType
,
TEXPR_UNARYEXPR_NODE
);
ASSERT_EQ
(
p1
->
pExpr
->
_node
.
functionId
,
FUNCTION_COUNT
);
ASSERT_TRUE
(
p1
->
pExpr
->
_node
.
pRight
==
NULL
);
tExprNode
*
pParam
=
p1
->
pExpr
->
_node
.
pLeft
;
ASSERT_EQ
(
pParam
->
nodeType
,
TEXPR_BINARYEXPR_NODE
);
ASSERT_EQ
(
pParam
->
_node
.
optr
,
TSDB_BINARY_OP_ADD
);
ASSERT_EQ
(
pParam
->
_node
.
pLeft
->
nodeType
,
TEXPR_COL_NODE
);
ASSERT_EQ
(
pParam
->
_node
.
pRight
->
nodeType
,
TEXPR_COL_NODE
);
ASSERT_EQ
(
taosArrayGetSize
(
pQueryInfo
->
colList
),
3
);
ASSERT_EQ
(
pQueryInfo
->
fieldsInfo
.
numOfOutput
,
2
);
destroyQueryInfo
(
pQueryInfo
);
qParserClearupMetaRequestInfo
(
&
req
);
destroySqlInfo
(
&
info1
);
}
TEST
(
testCase
,
function_Test8
)
{
SSqlInfo
info1
=
doGenerateAST
(
"select top(a*b / 99, 20) from `t.1abc` interval(10s, 1s)"
);
ASSERT_EQ
(
info1
.
valid
,
true
);
char
msg
[
128
]
=
{
0
};
SMsgBuf
buf
;
buf
.
len
=
128
;
buf
.
buf
=
msg
;
SSqlNode
*
pNode
=
(
SSqlNode
*
)
taosArrayGetP
(((
SArray
*
)
info1
.
list
),
0
);
int32_t
code
=
evaluateSqlNode
(
pNode
,
TSDB_TIME_PRECISION_NANO
,
&
buf
);
ASSERT_EQ
(
code
,
0
);
SMetaReq
req
=
{
0
};
int32_t
ret
=
qParserExtractRequestedMetaInfo
(
&
info1
,
&
req
,
msg
,
128
);
ASSERT_EQ
(
ret
,
0
);
ASSERT_EQ
(
taosArrayGetSize
(
req
.
pTableName
),
1
);
SQueryStmtInfo
*
pQueryInfo
=
createQueryInfo
();
setTableMetaInfo
(
pQueryInfo
,
&
req
);
SSqlNode
*
pSqlNode
=
(
SSqlNode
*
)
taosArrayGetP
(
info1
.
list
,
0
);
ret
=
validateSqlNode
(
pSqlNode
,
pQueryInfo
,
&
buf
);
ASSERT_EQ
(
ret
,
0
);
SArray
*
pExprList
=
pQueryInfo
->
exprList
;
ASSERT_EQ
(
taosArrayGetSize
(
pExprList
),
2
);
SExprInfo
*
p1
=
(
SExprInfo
*
)
taosArrayGetP
(
pExprList
,
1
);
ASSERT_EQ
(
p1
->
base
.
uid
,
110
);
ASSERT_EQ
(
p1
->
base
.
numOfParams
,
1
);
ASSERT_EQ
(
p1
->
base
.
resSchema
.
type
,
TSDB_DATA_TYPE_DOUBLE
);
ASSERT_STRCASEEQ
(
p1
->
base
.
resSchema
.
name
,
"top(a*b / 99, 20)"
);
ASSERT_EQ
(
p1
->
base
.
colInfo
.
flag
,
TSDB_COL_NORMAL
);
ASSERT_STRCASEEQ
(
p1
->
base
.
token
,
"top(a*b / 99, 20)"
);
ASSERT_EQ
(
p1
->
base
.
interBytes
,
16
);
ASSERT_EQ
(
p1
->
pExpr
->
nodeType
,
TEXPR_UNARYEXPR_NODE
);
ASSERT_EQ
(
p1
->
pExpr
->
_node
.
functionId
,
FUNCTION_TOP
);
ASSERT_TRUE
(
p1
->
pExpr
->
_node
.
pRight
==
NULL
);
tExprNode
*
pParam
=
p1
->
pExpr
->
_node
.
pLeft
;
ASSERT_EQ
(
pParam
->
nodeType
,
TEXPR_BINARYEXPR_NODE
);
ASSERT_EQ
(
pParam
->
_node
.
optr
,
TSDB_BINARY_OP_DIVIDE
);
ASSERT_EQ
(
pParam
->
_node
.
pLeft
->
nodeType
,
TEXPR_BINARYEXPR_NODE
);
ASSERT_EQ
(
pParam
->
_node
.
pRight
->
nodeType
,
TEXPR_VALUE_NODE
);
ASSERT_EQ
(
taosArrayGetSize
(
pQueryInfo
->
colList
),
3
);
ASSERT_EQ
(
pQueryInfo
->
fieldsInfo
.
numOfOutput
,
2
);
destroyQueryInfo
(
pQueryInfo
);
qParserClearupMetaRequestInfo
(
&
req
);
destroySqlInfo
(
&
info1
);
}
TEST
(
testCase
,
invalid_sql_Test
)
{
char
msg
[
128
]
=
{
0
};
SMsgBuf
buf
;
buf
.
len
=
128
;
buf
.
buf
=
msg
;
SSqlInfo
info1
=
doGenerateAST
(
"select count(k) from `t.1abc` interval(10s, 1s)"
);
ASSERT_EQ
(
info1
.
valid
,
true
);
SSqlNode
*
pNode
=
(
SSqlNode
*
)
taosArrayGetP
(((
SArray
*
)
info1
.
list
),
0
);
int32_t
code
=
evaluateSqlNode
(
pNode
,
TSDB_TIME_PRECISION_NANO
,
&
buf
);
ASSERT_EQ
(
code
,
0
);
SMetaReq
req
=
{
0
};
int32_t
ret
=
qParserExtractRequestedMetaInfo
(
&
info1
,
&
req
,
msg
,
128
);
ASSERT_EQ
(
ret
,
0
);
ASSERT_EQ
(
taosArrayGetSize
(
req
.
pTableName
),
1
);
SQueryStmtInfo
*
pQueryInfo
=
createQueryInfo
();
setTableMetaInfo
(
pQueryInfo
,
&
req
);
SSqlNode
*
pSqlNode
=
(
SSqlNode
*
)
taosArrayGetP
(
info1
.
list
,
0
);
ret
=
validateSqlNode
(
pSqlNode
,
pQueryInfo
,
&
buf
);
ASSERT_NE
(
ret
,
0
);
destroyQueryInfo
(
pQueryInfo
);
qParserClearupMetaRequestInfo
(
&
req
);
destroySqlInfo
(
&
info1
);
//===============================================================================================================
info1
=
doGenerateAST
(
"select top(a*b, ABC) from `t.1abc` interval(10s, 1s)"
);
ASSERT_EQ
(
info1
.
valid
,
true
);
pNode
=
(
SSqlNode
*
)
taosArrayGetP
(((
SArray
*
)
info1
.
list
),
0
);
code
=
evaluateSqlNode
(
pNode
,
TSDB_TIME_PRECISION_NANO
,
&
buf
);
ASSERT_EQ
(
code
,
0
);
ret
=
qParserExtractRequestedMetaInfo
(
&
info1
,
&
req
,
msg
,
128
);
ASSERT_EQ
(
ret
,
0
);
ASSERT_EQ
(
taosArrayGetSize
(
req
.
pTableName
),
1
);
pQueryInfo
=
createQueryInfo
();
setTableMetaInfo
(
pQueryInfo
,
&
req
);
pSqlNode
=
(
SSqlNode
*
)
taosArrayGetP
(
info1
.
list
,
0
);
ret
=
validateSqlNode
(
pSqlNode
,
pQueryInfo
,
&
buf
);
ASSERT_NE
(
ret
,
0
);
destroyQueryInfo
(
pQueryInfo
);
qParserClearupMetaRequestInfo
(
&
req
);
destroySqlInfo
(
&
info1
);
}
\ No newline at end of file
source/libs/parser/test/plannerTest.cpp
0 → 100644
浏览文件 @
b4ff474e
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <gtest/gtest.h>
#include <iostream>
#pragma GCC diagnostic ignored "-Wwrite-strings"
#pragma GCC diagnostic ignored "-Wunused-function"
#pragma GCC diagnostic ignored "-Wunused-variable"
#pragma GCC diagnostic ignored "-Wsign-compare"
#include "os.h"
#include "astGenerator.h"
#include "parserInt.h"
#include "taos.h"
#include "tdef.h"
#include "tvariant.h"
#include "planner.h"
namespace
{
void
setSchema
(
SSchema
*
p
,
int32_t
type
,
int32_t
bytes
,
const
char
*
name
,
int32_t
colId
)
{
p
->
colId
=
colId
;
p
->
bytes
=
bytes
;
p
->
type
=
type
;
strcpy
(
p
->
name
,
name
);
}
void
setTableMetaInfo
(
SQueryStmtInfo
*
pQueryInfo
,
SMetaReq
*
req
)
{
pQueryInfo
->
numOfTables
=
1
;
pQueryInfo
->
pTableMetaInfo
=
(
STableMetaInfo
**
)
calloc
(
1
,
POINTER_BYTES
);
STableMetaInfo
*
pTableMetaInfo
=
(
STableMetaInfo
*
)
calloc
(
1
,
sizeof
(
STableMetaInfo
));
pQueryInfo
->
pTableMetaInfo
[
0
]
=
pTableMetaInfo
;
SName
*
name
=
(
SName
*
)
taosArrayGet
(
req
->
pTableName
,
0
);
memcpy
(
&
pTableMetaInfo
->
name
,
taosArrayGet
(
req
->
pTableName
,
0
),
sizeof
(
SName
));
pTableMetaInfo
->
pTableMeta
=
(
STableMeta
*
)
calloc
(
1
,
sizeof
(
STableMeta
)
+
4
*
sizeof
(
SSchema
));
strcpy
(
pTableMetaInfo
->
aliasName
,
name
->
tname
);
STableMeta
*
pTableMeta
=
pTableMetaInfo
->
pTableMeta
;
pTableMeta
->
tableType
=
TSDB_NORMAL_TABLE
;
pTableMeta
->
tableInfo
.
numOfColumns
=
4
;
pTableMeta
->
tableInfo
.
rowSize
=
28
;
pTableMeta
->
uid
=
110
;
pTableMetaInfo
->
tagColList
=
(
SArray
*
)
taosArrayInit
(
4
,
POINTER_BYTES
);
SSchema
*
pSchema
=
pTableMetaInfo
->
pTableMeta
->
schema
;
setSchema
(
&
pSchema
[
0
],
TSDB_DATA_TYPE_TIMESTAMP
,
8
,
"ts"
,
0
);
setSchema
(
&
pSchema
[
1
],
TSDB_DATA_TYPE_INT
,
4
,
"a"
,
1
);
setSchema
(
&
pSchema
[
2
],
TSDB_DATA_TYPE_DOUBLE
,
8
,
"b"
,
2
);
setSchema
(
&
pSchema
[
3
],
TSDB_DATA_TYPE_DOUBLE
,
8
,
"col"
,
3
);
}
}
TEST
(
testCase
,
planner_test
)
{
SSqlInfo
info1
=
doGenerateAST
(
"select top(a*b / 99, 20) from `t.1abc` interval(10s, 1s)"
);
ASSERT_EQ
(
info1
.
valid
,
true
);
char
msg
[
128
]
=
{
0
};
SMsgBuf
buf
;
buf
.
len
=
128
;
buf
.
buf
=
msg
;
SSqlNode
*
pNode
=
(
SSqlNode
*
)
taosArrayGetP
(((
SArray
*
)
info1
.
list
),
0
);
int32_t
code
=
evaluateSqlNode
(
pNode
,
TSDB_TIME_PRECISION_NANO
,
&
buf
);
ASSERT_EQ
(
code
,
0
);
SMetaReq
req
=
{
0
};
int32_t
ret
=
qParserExtractRequestedMetaInfo
(
&
info1
,
&
req
,
msg
,
128
);
ASSERT_EQ
(
ret
,
0
);
ASSERT_EQ
(
taosArrayGetSize
(
req
.
pTableName
),
1
);
SQueryStmtInfo
*
pQueryInfo
=
createQueryInfo
();
setTableMetaInfo
(
pQueryInfo
,
&
req
);
SSqlNode
*
pSqlNode
=
(
SSqlNode
*
)
taosArrayGetP
(
info1
.
list
,
0
);
ret
=
validateSqlNode
(
pSqlNode
,
pQueryInfo
,
&
buf
);
ASSERT_EQ
(
ret
,
0
);
SArray
*
pExprList
=
pQueryInfo
->
exprList
;
ASSERT_EQ
(
taosArrayGetSize
(
pExprList
),
2
);
SExprInfo
*
p1
=
(
SExprInfo
*
)
taosArrayGetP
(
pExprList
,
1
);
ASSERT_EQ
(
p1
->
base
.
uid
,
110
);
ASSERT_EQ
(
p1
->
base
.
numOfParams
,
1
);
ASSERT_EQ
(
p1
->
base
.
resSchema
.
type
,
TSDB_DATA_TYPE_DOUBLE
);
ASSERT_STRCASEEQ
(
p1
->
base
.
resSchema
.
name
,
"top(a*b / 99, 20)"
);
ASSERT_EQ
(
p1
->
base
.
colInfo
.
flag
,
TSDB_COL_NORMAL
);
ASSERT_STRCASEEQ
(
p1
->
base
.
token
,
"top(a*b / 99, 20)"
);
ASSERT_EQ
(
p1
->
base
.
interBytes
,
16
);
ASSERT_EQ
(
p1
->
pExpr
->
nodeType
,
TEXPR_UNARYEXPR_NODE
);
ASSERT_EQ
(
p1
->
pExpr
->
_node
.
functionId
,
FUNCTION_TOP
);
ASSERT_TRUE
(
p1
->
pExpr
->
_node
.
pRight
==
NULL
);
tExprNode
*
pParam
=
p1
->
pExpr
->
_node
.
pLeft
;
ASSERT_EQ
(
pParam
->
nodeType
,
TEXPR_BINARYEXPR_NODE
);
ASSERT_EQ
(
pParam
->
_node
.
optr
,
TSDB_BINARY_OP_DIVIDE
);
ASSERT_EQ
(
pParam
->
_node
.
pLeft
->
nodeType
,
TEXPR_BINARYEXPR_NODE
);
ASSERT_EQ
(
pParam
->
_node
.
pRight
->
nodeType
,
TEXPR_VALUE_NODE
);
ASSERT_EQ
(
taosArrayGetSize
(
pQueryInfo
->
colList
),
3
);
ASSERT_EQ
(
pQueryInfo
->
fieldsInfo
.
numOfOutput
,
2
);
struct
SQueryPlanNode
*
n
=
nullptr
;
code
=
qCreateQueryPlan
(
pQueryInfo
,
&
n
);
char
*
str
=
NULL
;
qQueryPlanToString
(
n
,
&
str
);
printf
(
"%s
\n
"
,
str
);
destroyQueryInfo
(
pQueryInfo
);
qParserClearupMetaRequestInfo
(
&
req
);
destroySqlInfo
(
&
info1
);
}
\ No newline at end of file
source/libs/parser/test/tokenizerTest.cpp
浏览文件 @
b4ff474e
...
...
@@ -37,22 +37,22 @@ SToken createToken(char* s) {
}
// namespace
static
void
_init_tvariant_bool
(
SVariant
*
t
)
{
t
->
i
64
=
TSDB_FALSE
;
t
->
i
=
TSDB_FALSE
;
t
->
nType
=
TSDB_DATA_TYPE_BOOL
;
}
static
void
_init_tvariant_tinyint
(
SVariant
*
t
)
{
t
->
i
64
=
-
27
;
t
->
i
=
-
27
;
t
->
nType
=
TSDB_DATA_TYPE_TINYINT
;
}
static
void
_init_tvariant_int
(
SVariant
*
t
)
{
t
->
i
64
=
-
23997659
;
t
->
i
=
-
23997659
;
t
->
nType
=
TSDB_DATA_TYPE_INT
;
}
static
void
_init_tvariant_bigint
(
SVariant
*
t
)
{
t
->
i
64
=
-
3333333333333
;
t
->
i
=
-
3333333333333
;
t
->
nType
=
TSDB_DATA_TYPE_BIGINT
;
}
...
...
@@ -359,19 +359,19 @@ TEST(testCase, tvariant_convert) {
_init_tvariant_bool(&t);
EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_BOOL), 0);
EXPECT_EQ(t.i
64
, 0);
EXPECT_EQ(t.i, 0);
_init_tvariant_bool(&t);
EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_TINYINT), 0);
EXPECT_EQ(t.i
64
, 0);
EXPECT_EQ(t.i, 0);
_init_tvariant_bool(&t);
EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_SMALLINT), 0);
EXPECT_EQ(t.i
64
, 0);
EXPECT_EQ(t.i, 0);
_init_tvariant_bool(&t);
EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_BIGINT), 0);
EXPECT_EQ(t.i
64
, 0);
EXPECT_EQ(t.i, 0);
_init_tvariant_bool(&t);
EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_FLOAT), 0);
...
...
@@ -394,23 +394,23 @@ TEST(testCase, tvariant_convert) {
// 2. tinyint to other data types
_init_tvariant_tinyint(&t);
EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_BOOL), 0);
EXPECT_EQ(t.i
64
, 1);
EXPECT_EQ(t.i, 1);
_init_tvariant_tinyint(&t);
EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_TINYINT), 0);
EXPECT_EQ(t.i
64
, -27);
EXPECT_EQ(t.i, -27);
_init_tvariant_tinyint(&t);
EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_SMALLINT), 0);
EXPECT_EQ(t.i
64
, -27);
EXPECT_EQ(t.i, -27);
_init_tvariant_tinyint(&t);
EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_INT), 0);
EXPECT_EQ(t.i
64
, -27);
EXPECT_EQ(t.i, -27);
_init_tvariant_tinyint(&t);
EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_BIGINT), 0);
EXPECT_EQ(t.i
64
, -27);
EXPECT_EQ(t.i, -27);
_init_tvariant_tinyint(&t);
EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_FLOAT), 0);
...
...
@@ -434,7 +434,7 @@ TEST(testCase, tvariant_convert) {
// types//////////////////////////////////////////////////////////////////
_init_tvariant_int(&t);
EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_BOOL), 0);
EXPECT_EQ(t.i
64
, 1);
EXPECT_EQ(t.i, 1);
_init_tvariant_int(&t);
EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_TINYINT), 0);
...
...
@@ -444,11 +444,11 @@ TEST(testCase, tvariant_convert) {
_init_tvariant_int(&t);
EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_INT), 0);
EXPECT_EQ(t.i
64
, -23997659);
EXPECT_EQ(t.i, -23997659);
_init_tvariant_int(&t);
EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_BIGINT), 0);
EXPECT_EQ(t.i
64
, -23997659);
EXPECT_EQ(t.i, -23997659);
_init_tvariant_int(&t);
EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_FLOAT), 0);
...
...
@@ -472,7 +472,7 @@ TEST(testCase, tvariant_convert) {
// type//////////////////////////////////////////////////////////////////////////////
_init_tvariant_bigint(&t);
EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_BOOL), 0);
EXPECT_EQ(t.i
64
, 1);
EXPECT_EQ(t.i, 1);
_init_tvariant_bigint(&t);
EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_TINYINT), 0);
...
...
@@ -485,7 +485,7 @@ TEST(testCase, tvariant_convert) {
_init_tvariant_bigint(&t);
EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_BIGINT), 0);
EXPECT_EQ(t.i
64
, -3333333333333);
EXPECT_EQ(t.i, -3333333333333);
_init_tvariant_bigint(&t);
EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_FLOAT), 0);
...
...
@@ -509,11 +509,11 @@ TEST(testCase, tvariant_convert) {
// types////////////////////////////////////////////////////////////////////////
_init_tvariant_float(&t);
EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_BOOL), 0);
EXPECT_EQ(t.i
64
, 1);
EXPECT_EQ(t.i, 1);
_init_tvariant_float(&t);
EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_BIGINT), 0);
EXPECT_EQ(t.i
64
, -8991212199);
EXPECT_EQ(t.i, -8991212199);
_init_tvariant_float(&t);
EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_FLOAT), 0);
...
...
@@ -539,14 +539,14 @@ TEST(testCase, tvariant_convert) {
t.nLen = strlen(t.pz);
t.nType = TSDB_DATA_TYPE_BINARY;
EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_BOOL), 0);
EXPECT_EQ(t.i
64
, 1);
EXPECT_EQ(t.i, 1);
_init_tvariant_binary(&t);
EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_BOOL), -1);
_init_tvariant_binary(&t);
EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_BIGINT), 0);
EXPECT_EQ(t.i
64
, 200000);
EXPECT_EQ(t.i, 200000);
_init_tvariant_binary(&t);
EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_FLOAT), 0);
...
...
@@ -572,14 +572,14 @@ TEST(testCase, tvariant_convert) {
t.nLen = wcslen(t.wpz);
t.nType = TSDB_DATA_TYPE_NCHAR;
EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_BOOL), 0);
EXPECT_EQ(t.i
64
, 0);
EXPECT_EQ(t.i, 0);
_init_tvariant_nchar(&t);
EXPECT_LE(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_BOOL), 0);
_init_tvariant_nchar(&t);
EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_BIGINT), 0);
EXPECT_EQ(t.i
64
, -2000000);
EXPECT_EQ(t.i, -2000000);
_init_tvariant_nchar(&t);
EXPECT_EQ(taosVariantTypeSetType(&t, TSDB_DATA_TYPE_FLOAT), 0);
...
...
@@ -667,59 +667,59 @@ TEST(testCase, isValidNumber_test) {
EXPECT_EQ
(
tGetNumericStringType
(
&
t1
),
TK_FLOAT
);
}
//
TEST(testCase, generateAST_test) {
//
SSqlInfo info = doGenerateAST("select * from t1 where ts < now");
//
ASSERT_EQ(info.valid, true);
//
//
SSqlInfo info1 = doGenerateAST("select * from `t.1abc` where ts<now+2h and col < 20+99");
//
ASSERT_EQ(info1.valid, true);
//
//
char msg[128] = {0};
//
//
SMsgBuf msgBuf = {0};
//
msgBuf.buf = msg;
//
msgBuf.len = 128;
//
//
SSqlNode* pNode = (SSqlNode*) taosArrayGetP(((SArray*)info1.list), 0);
//
int32_t code = evaluateSqlNode(pNode, TSDB_TIME_PRECISION_NANO, &msgBuf);
//
ASSERT_EQ(code, 0);
//
//
SSqlInfo info2 = doGenerateAST("select * from abc where ts<now+2");
//
SSqlNode* pNode2 = (SSqlNode*) taosArrayGetP(((SArray*)info2.list), 0);
//
code = evaluateSqlNode(pNode2, TSDB_TIME_PRECISION_MILLI, &msgBuf);
//
ASSERT_NE(code, 0);
//
//
destroySqlInfo(&info);
//
destroySqlInfo(&info1);
//
destroySqlInfo(&info2);
//
}
//
//
TEST(testCase, evaluateAST_test) {
//
SSqlInfo info1 = doGenerateAST("select a, b+22 from `t.1abc` where ts<now+2h and `col` < 20 + 99");
//
ASSERT_EQ(info1.valid, true);
//
//
char msg[128] = {0};
//
SMsgBuf msgBuf = {0};
//
msgBuf.buf = msg;
//
msgBuf.len = 128;
//
//
SSqlNode* pNode = (SSqlNode*) taosArrayGetP(((SArray*)info1.list), 0);
//
int32_t code = evaluateSqlNode(pNode, TSDB_TIME_PRECISION_NANO, &msgBuf);
//
ASSERT_EQ(code, 0);
//
destroySqlInfo(&info1);
//
}
//
//
TEST(testCase, extractMeta_test) {
//
SSqlInfo info1 = doGenerateAST("select a, b+22 from `t.1abc` where ts<now+2h and `col` < 20 + 99");
//
ASSERT_EQ(info1.valid, true);
//
//
char msg[128] = {0};
//
SMetaReq req = {0};
//
int32_t ret = qParserExtractRequestedMetaInfo(&info1, &req, msg, 128);
//
ASSERT_EQ(ret, 0);
//
ASSERT_EQ(taosArrayGetSize(req.pTableName), 1);
//
//
qParserClearupMetaRequestInfo(&req);
//
destroySqlInfo(&info1);
//
}
TEST
(
testCase
,
generateAST_test
)
{
SSqlInfo
info
=
doGenerateAST
(
"select * from t1 where ts < now"
);
ASSERT_EQ
(
info
.
valid
,
true
);
SSqlInfo
info1
=
doGenerateAST
(
"select * from `t.1abc` where ts<now+2h and col < 20+99"
);
ASSERT_EQ
(
info1
.
valid
,
true
);
char
msg
[
128
]
=
{
0
};
SMsgBuf
msgBuf
=
{
0
};
msgBuf
.
buf
=
msg
;
msgBuf
.
len
=
128
;
SSqlNode
*
pNode
=
(
SSqlNode
*
)
taosArrayGetP
(((
SArray
*
)
info1
.
list
),
0
);
int32_t
code
=
evaluateSqlNode
(
pNode
,
TSDB_TIME_PRECISION_NANO
,
&
msgBuf
);
ASSERT_EQ
(
code
,
0
);
SSqlInfo
info2
=
doGenerateAST
(
"select * from abc where ts<now+2"
);
SSqlNode
*
pNode2
=
(
SSqlNode
*
)
taosArrayGetP
(((
SArray
*
)
info2
.
list
),
0
);
code
=
evaluateSqlNode
(
pNode2
,
TSDB_TIME_PRECISION_MILLI
,
&
msgBuf
);
ASSERT_NE
(
code
,
0
);
destroySqlInfo
(
&
info
);
destroySqlInfo
(
&
info1
);
destroySqlInfo
(
&
info2
);
}
TEST
(
testCase
,
evaluateAST_test
)
{
SSqlInfo
info1
=
doGenerateAST
(
"select a, b+22 from `t.1abc` where ts<now+2h and `col` < 20 + 99"
);
ASSERT_EQ
(
info1
.
valid
,
true
);
char
msg
[
128
]
=
{
0
};
SMsgBuf
msgBuf
=
{
0
};
msgBuf
.
buf
=
msg
;
msgBuf
.
len
=
128
;
SSqlNode
*
pNode
=
(
SSqlNode
*
)
taosArrayGetP
(((
SArray
*
)
info1
.
list
),
0
);
int32_t
code
=
evaluateSqlNode
(
pNode
,
TSDB_TIME_PRECISION_NANO
,
&
msgBuf
);
ASSERT_EQ
(
code
,
0
);
destroySqlInfo
(
&
info1
);
}
TEST
(
testCase
,
extractMeta_test
)
{
SSqlInfo
info1
=
doGenerateAST
(
"select a, b+22 from `t.1abc` where ts<now+2h and `col` < 20 + 99"
);
ASSERT_EQ
(
info1
.
valid
,
true
);
char
msg
[
128
]
=
{
0
};
SMetaReq
req
=
{
0
};
int32_t
ret
=
qParserExtractRequestedMetaInfo
(
&
info1
,
&
req
,
msg
,
128
);
ASSERT_EQ
(
ret
,
0
);
ASSERT_EQ
(
taosArrayGetSize
(
req
.
pTableName
),
1
);
qParserClearupMetaRequestInfo
(
&
req
);
destroySqlInfo
(
&
info1
);
}
source/libs/planner/CMakeLists.txt
浏览文件 @
b4ff474e
...
...
@@ -9,4 +9,6 @@ target_include_directories(
target_link_libraries
(
planner
PRIVATE os util common catalog parser transport function
)
\ No newline at end of file
)
ADD_SUBDIRECTORY
(
test
)
\ No newline at end of file
source/libs/planner/inc/plannerUtil.h
0 → 100644
浏览文件 @
b4ff474e
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TDENGINE_PLANNERUTIL_H
#define TDENGINE_PLANNERUTIL_H
#ifdef __cplusplus
extern
"C"
{
#endif
#include "parser.h"
#ifdef __cplusplus
extern
"C"
{
#endif
#endif // TDENGINE_PLANNERUTIL_H
source/libs/planner/src/planner.c
浏览文件 @
b4ff474e
...
...
@@ -46,23 +46,20 @@ typedef struct SJoinCond {
static
SArray
*
createQueryPlanImpl
(
SQueryStmtInfo
*
pQueryInfo
);
static
void
doDestroyQueryNode
(
SQueryPlanNode
*
pQueryNode
);
int32_t
qOptimizeQueryPlan
(
struct
SQueryPlanNode
*
pQueryNode
)
{
int32_t
qOptimizeQueryPlan
(
struct
SQueryPlanNode
*
pQueryNode
)
{
return
0
;
}
int32_t
qCreateQueryPlan
(
const
struct
SQueryStmtInfo
*
pQueryInfo
,
struct
SQueryPlanNode
*
pQueryNode
)
{
int32_t
qCreateQueryPlan
(
const
struct
SQueryStmtInfo
*
pQueryInfo
,
struct
SQueryPlanNode
*
*
pQueryNode
)
{
SArray
*
upstream
=
createQueryPlanImpl
((
struct
SQueryStmtInfo
*
)
pQueryInfo
);
assert
(
taosArrayGetSize
(
upstream
)
==
1
);
/*SQueryPlanNode* p = */
taosArrayGetP
(
upstream
,
0
);
*
pQueryNode
=
taosArrayGetP
(
upstream
,
0
);
taosArrayDestroy
(
upstream
);
return
TSDB_CODE_SUCCESS
;
}
int32_t
qQueryPlanToString
(
struct
SQueryPlanNode
*
pQueryNode
,
char
**
str
)
{
return
0
;
}
int32_t
qQueryPlanToSql
(
struct
SQueryPlanNode
*
pQueryNode
,
char
**
sql
)
{
return
0
;
}
...
...
@@ -108,10 +105,10 @@ static SQueryPlanNode* createQueryNode(int32_t type, const char* name, SQueryPla
}
pNode
->
numOfOutput
=
numOfOutput
;
pNode
->
pExpr
=
calloc
(
numOfOutput
,
sizeof
(
SExprInfo
));
pNode
->
pExpr
=
taosArrayInit
(
numOfOutput
,
POINTER_BYTES
);
for
(
int32_t
i
=
0
;
i
<
numOfOutput
;
++
i
)
{
SExprInfo
*
pExprInfo
=
taosArrayGet
(
pNode
->
pExpr
,
i
);
assignExprInfo
(
pExprInfo
,
pExpr
[
i
]);
taosArrayPush
(
pNode
->
pExpr
,
&
pExpr
[
i
]);
}
pNode
->
pPrevNodes
=
taosArrayInit
(
4
,
POINTER_BYTES
);
...
...
@@ -167,7 +164,7 @@ static SQueryPlanNode* doAddTableColumnNode(SQueryStmtInfo* pQueryInfo, STableMe
int32_t
num
=
(
int32_t
)
taosArrayGetSize
(
pExprs
);
SQueryPlanNode
*
pNode
=
createQueryNode
(
QNODE_TAGSCAN
,
"TableTagScan"
,
NULL
,
0
,
pExprs
->
pData
,
num
,
info
,
NULL
);
if
(
pQueryInfo
->
distinct
)
{
if
(
pQueryInfo
->
info
.
distinct
)
{
pNode
=
createQueryNode
(
QNODE_DISTINCT
,
"Distinct"
,
&
pNode
,
1
,
pExprs
->
pData
,
num
,
info
,
NULL
);
}
...
...
@@ -184,22 +181,21 @@ static SQueryPlanNode* doAddTableColumnNode(SQueryStmtInfo* pQueryInfo, STableMe
// table source column projection, generate the projection expr
int32_t
numOfCols
=
(
int32_t
)
taosArrayGetSize
(
tableCols
);
SExprInfo
**
pExpr
=
calloc
(
numOfCols
,
POINTER_BYTES
);
SSchema
*
pSchema
=
pTableMetaInfo
->
pTableMeta
->
schema
;
STableMetaInfo
*
pTableMetaInfo1
=
getMetaInfo
(
pQueryInfo
,
0
);
SSchema
resultSchema
=
*
pSchema
;
resultSchema
.
colId
=
getNewResColId
();
for
(
int32_t
i
=
0
;
i
<
numOfCols
;
++
i
)
{
SColumn
*
pCol
=
taosArrayGetP
(
tableCols
,
i
);
SColumnIndex
index
=
{.
tableIndex
=
0
,
.
columnIndex
=
pCol
->
columnIndex
};
SSchema
*
pSchema
=
getOneColumnSchema
(
pTableMetaInfo
->
pTableMeta
,
i
);
SSchema
resultSchema
=
*
pSchema
;
SExprInfo
*
p
=
createExprInfo
(
pTableMetaInfo1
,
FUNCTION_PRJ
,
&
index
,
NULL
,
&
resultSchema
,
0
);
pExpr
[
i
]
=
p
;
}
pNode
=
createQueryNode
(
QNODE_PROJECT
,
"Projection"
,
&
pNode
,
1
,
pExpr
,
numOfCols
,
info
,
NULL
);
// dropAllExprInfo(pExpr);
tfree
(
pExpr
);
}
...
...
@@ -254,7 +250,7 @@ static SQueryPlanNode* doCreateQueryPlanForOneTableImpl(SQueryStmtInfo* pQueryIn
static
SQueryPlanNode
*
doCreateQueryPlanForOneTable
(
SQueryStmtInfo
*
pQueryInfo
,
STableMetaInfo
*
pTableMetaInfo
,
SArray
*
pExprs
,
SArray
*
tableCols
)
{
char
name
[
TSDB_TABLE_FNAME_LEN
]
=
{
0
};
t
NameExtractFullName
(
&
pTableMetaInfo
->
name
,
name
);
t
strncpy
(
name
,
pTableMetaInfo
->
name
.
tname
,
TSDB_TABLE_FNAME_LEN
);
SQueryTableInfo
info
=
{.
tableName
=
strdup
(
name
),
.
uid
=
pTableMetaInfo
->
pTableMeta
->
uid
,};
...
...
@@ -357,12 +353,6 @@ static void doDestroyQueryNode(SQueryPlanNode* pQueryNode) {
tfree
(
pQueryNode
);
}
bool
hasAliasName
(
SExprInfo
*
pExpr
)
{
assert
(
pExpr
!=
NULL
);
return
true
;
// return strncmp(pExpr->base.token, pExpr->base., tListLen(pExpr->base.aliasName)) != 0;
}
static
int32_t
doPrintPlan
(
char
*
buf
,
SQueryPlanNode
*
pQueryNode
,
int32_t
level
,
int32_t
totalLen
)
{
if
(
level
>
0
)
{
sprintf
(
buf
+
totalLen
,
"%*c"
,
level
,
' '
);
...
...
@@ -412,13 +402,7 @@ static int32_t doPrintPlan(char* buf, SQueryPlanNode* pQueryNode, int32_t level,
SExprInfo
*
pExprInfo
=
taosArrayGetP
(
pQueryNode
->
pExpr
,
i
);
SSqlExpr
*
pExpr
=
&
pExprInfo
->
base
;
// if (hasAliasName(&pQueryNode->pExpr[i])) {
len1
=
sprintf
(
buf
+
len
,
"[%s #%s]"
,
pExpr
->
token
,
pExpr
->
resSchema
.
name
);
// } else {
// len1 = sprintf(buf + len,"[%s]", pExpr->token);
// }
len
+=
len1
;
len
+=
sprintf
(
buf
+
len
,
"%s [%s #%d]"
,
pExpr
->
token
,
pExpr
->
resSchema
.
name
,
pExpr
->
resSchema
.
colId
);
if
(
i
<
pQueryNode
->
numOfOutput
-
1
)
{
len1
=
sprintf
(
buf
+
len
,
", "
);
len
+=
len1
;
...
...
@@ -435,13 +419,7 @@ static int32_t doPrintPlan(char* buf, SQueryPlanNode* pQueryNode, int32_t level,
SExprInfo
*
pExprInfo
=
taosArrayGetP
(
pQueryNode
->
pExpr
,
i
);
SSqlExpr
*
pExpr
=
&
pExprInfo
->
base
;
if
(
hasAliasName
(
pExprInfo
))
{
len1
=
sprintf
(
buf
+
len
,
"[%s #%s]"
,
pExpr
->
token
,
pExpr
->
resSchema
.
name
);
}
else
{
len1
=
sprintf
(
buf
+
len
,
"[%s]"
,
pExpr
->
token
);
}
len
+=
len1
;
len
+=
sprintf
(
buf
+
len
,
"%s [%s #%d]"
,
pExpr
->
token
,
pExpr
->
resSchema
.
name
,
pExpr
->
resSchema
.
colId
);
if
(
i
<
pQueryNode
->
numOfOutput
-
1
)
{
len1
=
sprintf
(
buf
+
len
,
", "
);
len
+=
len1
;
...
...
@@ -452,9 +430,11 @@ static int32_t doPrintPlan(char* buf, SQueryPlanNode* pQueryNode, int32_t level,
len
+=
len1
;
SInterval
*
pInterval
=
pQueryNode
->
pExtInfo
;
len1
=
sprintf
(
buf
+
len
,
"interval:%"
PRId64
"(%s), sliding:%"
PRId64
"(%s), offset:%"
PRId64
"
\n
"
,
// todo dynamic return the time precision
len1
=
sprintf
(
buf
+
len
,
"interval:%"
PRId64
"(%s), sliding:%"
PRId64
"(%s), offset:%"
PRId64
"(%s)
\n
"
,
pInterval
->
interval
,
TSDB_TIME_PRECISION_MILLI_STR
,
pInterval
->
sliding
,
TSDB_TIME_PRECISION_MILLI_STR
,
pInterval
->
offset
);
pInterval
->
offset
,
TSDB_TIME_PRECISION_MILLI_STR
);
len
+=
len1
;
break
;
...
...
@@ -465,12 +445,7 @@ static int32_t doPrintPlan(char* buf, SQueryPlanNode* pQueryNode, int32_t level,
SExprInfo
*
pExprInfo
=
taosArrayGetP
(
pQueryNode
->
pExpr
,
i
);
SSqlExpr
*
pExpr
=
&
pExprInfo
->
base
;
if
(
hasAliasName
(
pExprInfo
))
{
len1
=
sprintf
(
buf
+
len
,
"[%s #%s]"
,
pExpr
->
token
,
pExpr
->
resSchema
.
name
);
}
else
{
len1
=
sprintf
(
buf
+
len
,
"[%s]"
,
pExpr
->
token
);
}
len1
=
sprintf
(
buf
+
len
,
"%s [%s #%d]"
,
pExpr
->
token
,
pExpr
->
resSchema
.
name
,
pExpr
->
resSchema
.
colId
);
len
+=
len1
;
if
(
i
<
pQueryNode
->
numOfOutput
-
1
)
{
...
...
@@ -568,14 +543,15 @@ int32_t queryPlanToStringImpl(char* buf, SQueryPlanNode* pQueryNode, int32_t lev
return
len
;
}
char
*
queryPlanToString
(
SQueryPlanNode
*
pQueryNode
)
{
int32_t
qQueryPlanToString
(
struct
SQueryPlanNode
*
pQueryNode
,
char
**
str
)
{
assert
(
pQueryNode
);
char
*
buf
=
calloc
(
1
,
4096
);
*
str
=
calloc
(
1
,
4096
);
int32_t
len
=
sprintf
(
buf
,
"===== logic plan =====
\n
"
);
queryPlanToStringImpl
(
buf
,
pQueryNode
,
0
,
len
);
return
buf
;
int32_t
len
=
sprintf
(
*
str
,
"===== logic plan =====
\n
"
);
queryPlanToStringImpl
(
*
str
,
pQueryNode
,
0
,
len
);
return
TSDB_CODE_SUCCESS
;
}
SQueryPlanNode
*
queryPlanFromString
()
{
...
...
source/libs/planner/src/plannerUtil.c
0 → 100644
浏览文件 @
b4ff474e
#include "tvariant.h"
#include "plannerUtil.h"
source/libs/planner/test/CMakeLists.txt
0 → 100644
浏览文件 @
b4ff474e
MESSAGE
(
STATUS
"build planner unit test"
)
# GoogleTest requires at least C++11
SET
(
CMAKE_CXX_STANDARD 11
)
AUX_SOURCE_DIRECTORY
(
${
CMAKE_CURRENT_SOURCE_DIR
}
SOURCE_LIST
)
ADD_EXECUTABLE
(
plannerTest
${
SOURCE_LIST
}
)
TARGET_LINK_LIBRARIES
(
plannerTest
PUBLIC os util common planner parser catalog transport gtest function
)
TARGET_INCLUDE_DIRECTORIES
(
plannerTest
PUBLIC
"
${
CMAKE_SOURCE_DIR
}
/include/libs/planner/"
PRIVATE
"
${
CMAKE_SOURCE_DIR
}
/source/libs/planner/inc"
)
source/libs/planner/test/plannerTests.cpp
浏览文件 @
b4ff474e
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <gtest/gtest.h>
#include <iostream>
#include "os.h"
#include "taos.h"
#include "parser.h"
#pragma GCC diagnostic ignored "-Wwrite-strings"
#pragma GCC diagnostic ignored "-Wunused-function"
#pragma GCC diagnostic ignored "-Wunused-variable"
#pragma GCC diagnostic ignored "-Wsign-compare"
int
main
(
int
argc
,
char
**
argv
)
{
testing
::
InitGoogleTest
(
&
argc
,
argv
);
return
RUN_ALL_TESTS
();
}
TEST
(
testCase
,
planner_test
)
{
char
msg
[
128
]
=
{
0
};
const
char
*
sql
=
"select top(a*b / 99, 20) from `t.1abc` interval(10s, 1s)"
;
SQueryStmtInfo
*
pQueryInfo
=
nullptr
;
// int32_t code = qParseQuerySql(sql, strlen(sql), &pQueryInfo, 0, msg, sizeof(msg));
// ASSERT_EQ(code, 0);
// SSqlNode* pNode = (SSqlNode*)taosArrayGetP(((SArray*)info1.list), 0);
// int32_t code = evaluateSqlNode(pNode, TSDB_TIME_PRECISION_NANO, &buf);
// ASSERT_EQ(code, 0);
//
// SMetaReq req = {0};
// int32_t ret = qParserExtractRequestedMetaInfo(&info1, &req, msg, 128);
// ASSERT_EQ(ret, 0);
// ASSERT_EQ(taosArrayGetSize(req.pTableName), 1);
//
// SQueryStmtInfo* pQueryInfo = createQueryInfo();
// setTableMetaInfo(pQueryInfo, &req);
//
// SSqlNode* pSqlNode = (SSqlNode*)taosArrayGetP(info1.list, 0);
// ret = validateSqlNode(pSqlNode, pQueryInfo, &buf);
// ASSERT_EQ(ret, 0);
//
// SArray* pExprList = pQueryInfo->exprList;
// ASSERT_EQ(taosArrayGetSize(pExprList), 2);
//
// SExprInfo* p1 = (SExprInfo*)taosArrayGetP(pExprList, 1);
// ASSERT_EQ(p1->base.uid, 110);
// ASSERT_EQ(p1->base.numOfParams, 1);
// ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_DOUBLE);
// ASSERT_STRCASEEQ(p1->base.resSchema.name, "top(a*b / 99, 20)");
// ASSERT_EQ(p1->base.colInfo.flag, TSDB_COL_NORMAL);
// ASSERT_STRCASEEQ(p1->base.token, "top(a*b / 99, 20)");
// ASSERT_EQ(p1->base.interBytes, 16);
//
// ASSERT_EQ(p1->pExpr->nodeType, TEXPR_UNARYEXPR_NODE);
// ASSERT_EQ(p1->pExpr->_node.functionId, FUNCTION_TOP);
// ASSERT_TRUE(p1->pExpr->_node.pRight == NULL);
//
// tExprNode* pParam = p1->pExpr->_node.pLeft;
//
// ASSERT_EQ(pParam->nodeType, TEXPR_BINARYEXPR_NODE);
// ASSERT_EQ(pParam->_node.optr, TSDB_BINARY_OP_DIVIDE);
// ASSERT_EQ(pParam->_node.pLeft->nodeType, TEXPR_BINARYEXPR_NODE);
// ASSERT_EQ(pParam->_node.pRight->nodeType, TEXPR_VALUE_NODE);
//
// ASSERT_EQ(taosArrayGetSize(pQueryInfo->colList), 3);
// ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 2);
//
// destroyQueryInfo(pQueryInfo);
// qParserClearupMetaRequestInfo(&req);
// destroySqlInfo(&info1);
}
\ No newline at end of file
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录