Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
taosdata
TDengine
提交
d3fcbb25
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看板
未验证
提交
d3fcbb25
编写于
4月 26, 2020
作者:
S
slguan
提交者:
GitHub
4月 26, 2020
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #1717 from taosdata/feature/query
Feature/query
上级
e4ad2117
bb8b91f2
变更
17
展开全部
隐藏空白更改
内联
并排
Showing
17 changed file
with
278 addition
and
361 deletion
+278
-361
src/client/inc/tsclient.h
src/client/inc/tsclient.h
+1
-1
src/client/src/tscFunctionImpl.c
src/client/src/tscFunctionImpl.c
+9
-13
src/client/src/tscProfile.c
src/client/src/tscProfile.c
+6
-5
src/client/src/tscSQLParser.c
src/client/src/tscSQLParser.c
+71
-61
src/client/src/tscServer.c
src/client/src/tscServer.c
+1
-26
src/client/src/tscSql.c
src/client/src/tscSql.c
+22
-23
src/client/src/tscSubquery.c
src/client/src/tscSubquery.c
+2
-2
src/client/src/tscSystem.c
src/client/src/tscSystem.c
+1
-6
src/client/src/tscUtil.c
src/client/src/tscUtil.c
+2
-3
src/inc/taosmsg.h
src/inc/taosmsg.h
+9
-25
src/query/inc/qast.h
src/query/inc/qast.h
+4
-3
src/query/inc/tsqlfunction.h
src/query/inc/tsqlfunction.h
+2
-2
src/query/inc/tvariant.h
src/query/inc/tvariant.h
+1
-1
src/query/src/qast.c
src/query/src/qast.c
+9
-24
src/query/src/queryExecutor.c
src/query/src/queryExecutor.c
+131
-157
src/query/src/tvariant.c
src/query/src/tvariant.c
+5
-5
src/query/tests/astTest.cpp
src/query/tests/astTest.cpp
+2
-4
未找到文件。
src/client/inc/tsclient.h
浏览文件 @
d3fcbb25
...
...
@@ -78,7 +78,7 @@ typedef struct STableMetaInfo {
*/
int32_t
vgroupIndex
;
char
name
[
TSDB_TABLE_ID_LEN
];
// (super) table name
SArray
*
tagColList
;
// involved tag columns
SArray
*
tagColList
;
//
SArray<SColumn*>,
involved tag columns
}
STableMetaInfo
;
/* the structure for sql function in select clause */
...
...
src/client/src/tscFunctionImpl.c
浏览文件 @
d3fcbb25
...
...
@@ -3294,29 +3294,26 @@ static void diff_function_f(SQLFunctionCtx *pCtx, int32_t index) {
}
}
char
*
arithmetic_callback_function
(
void
*
param
,
char
*
name
,
int32_t
colId
)
{
char
*
getArithColumnData
(
void
*
param
,
const
char
*
name
,
int32_t
colId
)
{
SArithmeticSupport
*
pSupport
=
(
SArithmeticSupport
*
)
param
;
SArithExprInfo
*
pExpr
=
pSupport
->
pArithExpr
;
int32_t
colIndex
=
-
1
;
for
(
int32_t
i
=
0
;
i
<
pExpr
->
binExprInfo
.
numOfCols
;
++
i
)
{
if
(
colId
==
pExpr
->
binExprInfo
.
pReqColumns
[
i
].
colId
)
{
colIndex
=
pExpr
->
binExprInfo
.
pReqColumns
[
i
].
colIndex
;
int32_t
index
=
-
1
;
for
(
int32_t
i
=
0
;
i
<
pSupport
->
numOfCols
;
++
i
)
{
if
(
colId
==
pSupport
->
colList
[
i
].
colId
)
{
index
=
i
;
break
;
}
}
assert
(
colI
ndex
>=
0
&&
colId
>=
0
);
return
pSupport
->
data
[
colIndex
]
+
pSupport
->
offset
*
pSupport
->
elemSize
[
colIndex
]
;
assert
(
i
ndex
>=
0
&&
colId
>=
0
);
return
pSupport
->
data
[
index
]
+
pSupport
->
offset
*
pSupport
->
colList
[
index
].
bytes
;
}
static
void
arithmetic_function
(
SQLFunctionCtx
*
pCtx
)
{
GET_RES_INFO
(
pCtx
)
->
numOfRes
+=
pCtx
->
size
;
SArithmeticSupport
*
sas
=
(
SArithmeticSupport
*
)
pCtx
->
param
[
1
].
pz
;
tSQLBinaryExprCalcTraverse
(
sas
->
pArithExpr
->
binExprInfo
.
pBinExpr
,
pCtx
->
size
,
pCtx
->
aOutputBuf
,
sas
,
pCtx
->
order
,
arithmetic_callback_function
);
tExprTreeCalcTraverse
(
sas
->
pArithExpr
->
pExpr
,
pCtx
->
size
,
pCtx
->
aOutputBuf
,
sas
,
pCtx
->
order
,
getArithColumnData
);
pCtx
->
aOutputBuf
+=
pCtx
->
outputBytes
*
pCtx
->
size
;
pCtx
->
param
[
1
].
pz
=
NULL
;
...
...
@@ -3327,8 +3324,7 @@ static void arithmetic_function_f(SQLFunctionCtx *pCtx, int32_t index) {
SArithmeticSupport
*
sas
=
(
SArithmeticSupport
*
)
pCtx
->
param
[
1
].
pz
;
sas
->
offset
=
index
;
tSQLBinaryExprCalcTraverse
(
sas
->
pArithExpr
->
binExprInfo
.
pBinExpr
,
1
,
pCtx
->
aOutputBuf
,
sas
,
pCtx
->
order
,
arithmetic_callback_function
);
tExprTreeCalcTraverse
(
sas
->
pArithExpr
->
pExpr
,
1
,
pCtx
->
aOutputBuf
,
sas
,
pCtx
->
order
,
getArithColumnData
);
pCtx
->
aOutputBuf
+=
pCtx
->
outputBytes
;
}
...
...
src/client/src/tscProfile.c
浏览文件 @
d3fcbb25
...
...
@@ -209,15 +209,15 @@ void tscKillStream(STscObj *pObj, uint32_t killId) {
}
char
*
tscBuildQueryStreamDesc
(
char
*
pMsg
,
STscObj
*
pObj
)
{
SQqueryList
*
pQList
=
(
SQqueryList
*
)
pMsg
;
char
*
pMax
=
pMsg
+
TSDB_PAYLOAD_SIZE
-
256
;
SQ
ueryDesc
*
pQdesc
=
pQList
->
qdesc
;
SQ
queryList
*
pQList
=
(
SQqueryList
*
)
pMsg
;
pQList
->
numOfQueries
=
0
;
SQueryDesc
*
pQdesc
=
(
SQueryDesc
*
)(
pMsg
+
sizeof
(
SQqueryList
));
// We extract the lock to tscBuildHeartBeatMsg function.
/* pthread_mutex_lock (&pObj->mutex); */
pMsg
+=
sizeof
(
SQqueryList
);
SSqlObj
*
pSql
=
pObj
->
sqlList
;
while
(
pSql
)
{
...
...
@@ -244,8 +244,9 @@ char *tscBuildQueryStreamDesc(char *pMsg, STscObj *pObj) {
}
SStreamList
*
pSList
=
(
SStreamList
*
)
pMsg
;
SStreamDesc
*
pSdesc
=
pSList
->
sdesc
;
pSList
->
numOfStreams
=
0
;
SStreamDesc
*
pSdesc
=
(
SStreamDesc
*
)
(
pMsg
+
sizeof
(
SStreamList
));
pMsg
+=
sizeof
(
SStreamList
);
SSqlStream
*
pStream
=
pObj
->
streamList
;
...
...
src/client/src/tscSQLParser.c
浏览文件 @
d3fcbb25
...
...
@@ -101,7 +101,7 @@ static void updateTagColumnIndex(SQueryInfo* pQueryInfo, int32_t tableIndex);
static
int32_t
parseLimitClause
(
SQueryInfo
*
pQueryInfo
,
int32_t
index
,
SQuerySQL
*
pQuerySql
,
SSqlObj
*
pSql
);
static
int32_t
parseCreateDBOptions
(
SSqlCmd
*
pCmd
,
SCreateDBInfo
*
pCreateDbSql
);
static
int32_t
getColumnIndexByName
(
SSQLToken
*
pToken
,
SQueryInfo
*
pQueryInfo
,
SColumnIndex
*
pIndex
);
static
int32_t
getColumnIndexByName
(
const
SSQLToken
*
pToken
,
SQueryInfo
*
pQueryInfo
,
SColumnIndex
*
pIndex
);
static
int32_t
getTableIndexByName
(
SSQLToken
*
pToken
,
SQueryInfo
*
pQueryInfo
,
SColumnIndex
*
pIndex
);
static
int32_t
optrToString
(
tSQLExpr
*
pExpr
,
char
**
exprString
);
...
...
@@ -116,7 +116,7 @@ static int32_t doCheckForCreateTable(SSqlObj* pSql, int32_t subClauseIndex, SSql
static
int32_t
doCheckForCreateFromStable
(
SSqlObj
*
pSql
,
SSqlInfo
*
pInfo
);
static
int32_t
doCheckForStream
(
SSqlObj
*
pSql
,
SSqlInfo
*
pInfo
);
static
int32_t
doCheckForQuery
(
SSqlObj
*
pSql
,
SQuerySQL
*
pQuerySql
,
int32_t
index
);
static
int32_t
exprTreeFromSqlExpr
(
tExprNode
**
pExpr
,
tSQLExpr
*
pSqlExpr
,
SArray
*
pExprInfo
,
SQueryInfo
*
pQueryInfo
,
SArray
*
pCols
);
static
int32_t
exprTreeFromSqlExpr
(
tExprNode
**
pExpr
,
const
tSQLExpr
*
pSqlExpr
,
SArray
*
pExprInfo
,
SQueryInfo
*
pQueryInfo
,
SArray
*
pCols
);
/*
* Used during parsing query sql. Since the query sql usually small in length, error position
...
...
@@ -1171,13 +1171,32 @@ int32_t parseSelectClause(SSqlCmd* pCmd, int32_t clauseIndex, tSQLExprList* pSel
SColumnIndex
index
=
{.
tableIndex
=
tableIndex
};
SSqlExpr
*
pExpr
=
tscSqlExprAppend
(
pQueryInfo
,
TSDB_FUNC_ARITHM
,
&
index
,
TSDB_DATA_TYPE_DOUBLE
,
sizeof
(
double
),
sizeof
(
double
),
false
);
addExprParams
(
pExpr
,
arithmeticExprStr
,
TSDB_DATA_TYPE_BINARY
,
strlen
(
arithmeticExprStr
),
index
.
tableIndex
);
/* todo alias name should use the original sql string */
char
*
name
=
(
pItem
->
aliasName
!=
NULL
)
?
pItem
->
aliasName
:
arithmeticExprStr
;
strncpy
(
pExpr
->
aliasName
,
name
,
TSDB_COL_NAME_LEN
);
tExprNode
*
pNode
=
NULL
;
SArray
*
colList
=
taosArrayInit
(
10
,
sizeof
(
SColIndex
));
int32_t
ret
=
exprTreeFromSqlExpr
(
&
pNode
,
pItem
->
pNode
,
pQueryInfo
->
exprsInfo
,
pQueryInfo
,
colList
);
if
(
ret
!=
TSDB_CODE_SUCCESS
)
{
tExprTreeDestroy
(
&
pNode
,
NULL
);
return
invalidSqlErrMsg
(
pQueryInfo
->
msg
,
"invalid arithmetic expression in select clause"
);
}
SBuffer
buf
=
exprTreeToBinary
(
pNode
);
size_t
len
=
tbufTell
(
&
buf
);
char
*
c
=
tbufGetData
(
&
buf
,
true
);
// set the serialized binary string as the parameter of arithmetic expression
addExprParams
(
pExpr
,
c
,
TSDB_DATA_TYPE_BINARY
,
len
,
index
.
tableIndex
);
insertResultField
(
pQueryInfo
,
i
,
&
columnList
,
sizeof
(
double
),
TSDB_DATA_TYPE_DOUBLE
,
pExpr
->
aliasName
,
pExpr
);
taosArrayDestroy
(
colList
);
tExprTreeDestroy
(
&
pNode
,
NULL
);
}
else
{
columnList
.
num
=
0
;
columnList
.
ids
[
0
]
=
(
SColumnIndex
)
{
0
,
0
};
...
...
@@ -1196,8 +1215,6 @@ int32_t parseSelectClause(SSqlCmd* pCmd, int32_t clauseIndex, tSQLExprList* pSel
pFuncExpr
->
interResBytes
=
sizeof
(
double
);
pFuncExpr
->
type
=
TSDB_DATA_TYPE_DOUBLE
;
SExprInfo
*
pBinExprInfo
=
&
pFuncExpr
->
binExprInfo
;
tExprNode
*
pNode
=
NULL
;
// SArray* colList = taosArrayInit(10, sizeof(SColIndex));
...
...
@@ -1206,26 +1223,26 @@ int32_t parseSelectClause(SSqlCmd* pCmd, int32_t clauseIndex, tSQLExprList* pSel
tExprTreeDestroy
(
&
pNode
,
NULL
);
return
invalidSqlErrMsg
(
pQueryInfo
->
msg
,
"invalid expression in select clause"
);
}
p
BinExprInfo
->
pBin
Expr
=
pNode
;
p
FuncExpr
->
p
Expr
=
pNode
;
assert
(
0
);
// p
Bin
ExprInfo->pReqColumns = pColIndex;
// pExprInfo->pReqColumns = pColIndex;
for
(
int32_t
k
=
0
;
k
<
pBinExprInfo
->
numOfCols
;
++
k
)
{
SColIndex
*
pCol
=
&
pBinExprInfo
->
pReqColumns
[
k
];
size_t
size
=
tscSqlExprNumOfExprs
(
pQueryInfo
);
for
(
int32_t
f
=
0
;
f
<
size
;
++
f
)
{
SSqlExpr
*
pExpr
=
tscSqlExprGet
(
pQueryInfo
,
f
);
if
(
strcmp
(
pExpr
->
aliasName
,
pCol
->
name
)
==
0
)
{
pCol
->
colIndex
=
f
;
break
;
}
}
assert
(
pCol
->
colIndex
>=
0
&&
pCol
->
colIndex
<
size
);
tfree
(
pNode
);
}
// for(int32_t k = 0; k < pFuncExpr
->numOfCols; ++k) {
// SColIndex* pCol = &pFuncExpr->colList
[k];
//
size_t size = tscSqlExprNumOfExprs(pQueryInfo);
//
//
for(int32_t f = 0; f < size; ++f) {
//
SSqlExpr* pExpr = tscSqlExprGet(pQueryInfo, f);
//
if (strcmp(pExpr->aliasName, pCol->name) == 0) {
//
pCol->colIndex = f;
//
break;
//
}
//
}
//
//
assert(pCol->colIndex >= 0 && pCol->colIndex < size);
//
tfree(pNode);
//
}
}
}
}
else
{
...
...
@@ -1317,28 +1334,6 @@ SSqlExpr* doAddProjectCol(SQueryInfo* pQueryInfo, int32_t outputIndex, int32_t c
void
addRequiredTagColumn
(
STableMetaInfo
*
pTableMetaInfo
,
SColumnIndex
*
index
)
{
tscColumnListInsert
(
pTableMetaInfo
->
tagColList
,
index
);
// if (pTableMetaInfo->numOfTags == 0 || pTableMetaInfo->tagColumnIndex[pTableMetaInfo->numOfTags - 1] < tagColIndex) {
// pTableMetaInfo->tagColumnIndex[pTableMetaInfo->numOfTags++] = tagColIndex;
// } else { // find the appropriate position
// for (int32_t i = 0; i < pTableMetaInfo->numOfTags; ++i) {
// if (tagColIndex > pTableMetaInfo->tagColumnIndex[i]) {
// continue;
// } else if (tagColIndex == pTableMetaInfo->tagColumnIndex[i]) {
// break;
// } else {
// memmove(&pTableMetaInfo->tagColumnIndex[i + 1], &pTableMetaInfo->tagColumnIndex[i],
// sizeof(pTableMetaInfo->tagColumnIndex[0]) * (pTableMetaInfo->numOfTags - i));
//
// pTableMetaInfo->tagColumnIndex[i] = tagColIndex;
//
// pTableMetaInfo->numOfTags++;
// break;
// }
// }
// }
// plus one means tbname
// assert(tagColIndex >= -1 && tagColIndex < TSDB_MAX_TAGS && pTableMetaInfo->numOfTags <= TSDB_MAX_TAGS + 1);
}
static
void
addProjectQueryCol
(
SQueryInfo
*
pQueryInfo
,
int32_t
startPos
,
SColumnIndex
*
pIndex
,
tSQLExprItem
*
pItem
)
{
...
...
@@ -2047,7 +2042,7 @@ int32_t getTableIndexByName(SSQLToken* pToken, SQueryInfo* pQueryInfo, SColumnIn
return
TSDB_CODE_SUCCESS
;
}
int32_t
getColumnIndexByName
(
SSQLToken
*
pToken
,
SQueryInfo
*
pQueryInfo
,
SColumnIndex
*
pIndex
)
{
int32_t
getColumnIndexByName
(
const
SSQLToken
*
pToken
,
SQueryInfo
*
pQueryInfo
,
SColumnIndex
*
pIndex
)
{
if
(
pQueryInfo
->
pTableMetaInfo
==
NULL
||
pQueryInfo
->
numOfTables
==
0
)
{
return
TSDB_CODE_INVALID_SQL
;
}
...
...
@@ -3753,13 +3748,24 @@ static int32_t getTagQueryCondExpr(SQueryInfo* pQueryInfo, SCondExpr* pCondExpr,
for
(
int32_t
i
=
0
;
i
<
pQueryInfo
->
numOfTables
;
++
i
)
{
tSQLExpr
*
p1
=
extractExprForSTable
(
pExpr
,
pQueryInfo
,
i
);
tExprNode
*
p
=
NULL
;
ret
=
exprTreeFromSqlExpr
(
&
p
,
p1
,
NULL
,
pQueryInfo
,
NULL
);
SArray
*
colList
=
taosArrayInit
(
10
,
sizeof
(
SColIndex
));
ret
=
exprTreeFromSqlExpr
(
&
p
,
p1
,
NULL
,
pQueryInfo
,
colList
);
SBuffer
buf
=
exprTreeToBinary
(
p
);
int64_t
uid
=
tscGetMetaInfo
(
pQueryInfo
,
i
)
->
pTableMeta
->
uid
;
// add to source column list
STableMetaInfo
*
pTableMetaInfo
=
tscGetMetaInfo
(
pQueryInfo
,
i
);
int64_t
uid
=
pTableMetaInfo
->
pTableMeta
->
uid
;
int32_t
numOfCols
=
tscGetNumOfColumns
(
pTableMetaInfo
->
pTableMeta
);
size_t
num
=
taosArrayGetSize
(
colList
);
for
(
int32_t
j
=
0
;
j
<
num
;
++
j
)
{
SColIndex
*
pIndex
=
taosArrayGet
(
colList
,
j
);
SColumnIndex
index
=
{.
tableIndex
=
i
,
.
columnIndex
=
pIndex
->
colIndex
-
numOfCols
};
addRequiredTagColumn
(
pTableMetaInfo
,
&
index
);
}
tsSetSTableQueryCond
(
&
pQueryInfo
->
tagCond
,
uid
,
&
buf
);
doCompactQueryExpr
(
pExpr
);
tSQLExprDestroy
(
p1
);
...
...
@@ -5871,7 +5877,7 @@ int32_t doCheckForQuery(SSqlObj* pSql, SQuerySQL* pQuerySql, int32_t index) {
return
TSDB_CODE_SUCCESS
;
// Does not build query message here
}
int32_t
exprTreeFromSqlExpr
(
tExprNode
**
pExpr
,
tSQLExpr
*
pSqlExpr
,
SArray
*
pExprInfo
,
SQueryInfo
*
pQueryInfo
,
SArray
*
pCols
)
{
int32_t
exprTreeFromSqlExpr
(
tExprNode
**
pExpr
,
const
tSQLExpr
*
pSqlExpr
,
SArray
*
pExprInfo
,
SQueryInfo
*
pQueryInfo
,
SArray
*
pCols
)
{
tExprNode
*
pLeft
=
NULL
;
tExprNode
*
pRight
=
NULL
;
...
...
@@ -5896,8 +5902,9 @@ int32_t exprTreeFromSqlExpr(tExprNode **pExpr, tSQLExpr* pSqlExpr, SArray* pExpr
(
*
pExpr
)
->
pVal
=
calloc
(
1
,
sizeof
(
tVariant
));
tVariantAssign
((
*
pExpr
)
->
pVal
,
&
pSqlExpr
->
val
);
return
TSDB_CODE_SUCCESS
;
}
else
if
(
pSqlExpr
->
nSQLOptr
>=
TK_COUNT
&&
pSqlExpr
->
nSQLOptr
<=
TK_AVG_IRATE
)
{
// arithmetic expression on the results of aggregation functions
*
pExpr
=
calloc
(
1
,
sizeof
(
tExprNode
));
(
*
pExpr
)
->
nodeType
=
TSQL_NODE_COL
;
(
*
pExpr
)
->
pSchema
=
calloc
(
1
,
sizeof
(
SSchema
));
...
...
@@ -5915,7 +5922,7 @@ int32_t exprTreeFromSqlExpr(tExprNode **pExpr, tSQLExpr* pSqlExpr, SArray* pExpr
break
;
}
}
}
else
if
(
pSqlExpr
->
nSQLOptr
==
TK_ID
)
{
// column name
}
else
if
(
pSqlExpr
->
nSQLOptr
==
TK_ID
)
{
// column name
, normal column arithmetic expression
SColumnIndex
index
=
{
0
};
int32_t
ret
=
getColumnIndexByName
(
&
pSqlExpr
->
colInfo
,
pQueryInfo
,
&
index
);
if
(
ret
!=
TSDB_CODE_SUCCESS
)
{
...
...
@@ -5929,18 +5936,21 @@ int32_t exprTreeFromSqlExpr(tExprNode **pExpr, tSQLExpr* pSqlExpr, SArray* pExpr
STableMeta
*
pTableMeta
=
tscGetMetaInfo
(
pQueryInfo
,
0
)
->
pTableMeta
;
SSchema
*
pSchema
=
tscGetTableColumnSchema
(
pTableMeta
,
index
.
columnIndex
);
*
(
*
pExpr
)
->
pSchema
=
*
pSchema
;
if
(
pCols
!=
NULL
)
{
// record the involved columns
SColIndex
colIndex
=
{
0
};
strncpy
(
colIndex
.
name
,
pSchema
->
name
,
TSDB_COL_NAME_LEN
);
colIndex
.
colId
=
pSchema
->
colId
;
colIndex
.
colIndex
=
index
.
columnIndex
;
taosArrayPush
(
pCols
,
&
colIndex
);
}
return
TSDB_CODE_SUCCESS
;
}
else
{
return
TSDB_CODE_INVALID_SQL
;
}
if
(
pCols
!=
NULL
)
{
// record the involved columns
SColIndex
colIndex
=
{
0
};
strncpy
(
colIndex
.
name
,
pSqlExpr
->
operand
.
z
,
pSqlExpr
->
operand
.
n
);
taosArrayPush
(
pCols
,
&
colIndex
);
}
}
else
{
*
pExpr
=
(
tExprNode
*
)
calloc
(
1
,
sizeof
(
tExprNode
));
(
*
pExpr
)
->
nodeType
=
TSQL_NODE_EXPR
;
...
...
src/client/src/tscServer.c
浏览文件 @
d3fcbb25
...
...
@@ -758,16 +758,10 @@ int tscBuildQueryMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
}
}
bool
hasArithmeticFunction
=
false
;
SSqlFuncMsg
*
pSqlFuncExpr
=
(
SSqlFuncMsg
*
)
pMsg
;
for
(
int32_t
i
=
0
;
i
<
tscSqlExprNumOfExprs
(
pQueryInfo
);
++
i
)
{
SSqlExpr
*
pExpr
=
tscSqlExprGet
(
pQueryInfo
,
i
);
if
(
pExpr
->
functionId
==
TSDB_FUNC_ARITHM
)
{
hasArithmeticFunction
=
true
;
}
if
(
!
tscValidateColumnId
(
pTableMetaInfo
,
pExpr
->
colInfo
.
colId
))
{
/* column id is not valid according to the cached table meta, the table meta is expired */
tscError
(
"%p table schema is not matched with parsed sql"
,
pSql
);
...
...
@@ -788,9 +782,7 @@ int tscBuildQueryMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
if
(
pExpr
->
param
[
j
].
nType
==
TSDB_DATA_TYPE_BINARY
)
{
memcpy
(
pMsg
,
pExpr
->
param
[
j
].
pz
,
pExpr
->
param
[
j
].
nLen
);
// by plus one char to make the string null-terminated
pMsg
+=
pExpr
->
param
[
j
].
nLen
+
1
;
pMsg
+=
pExpr
->
param
[
j
].
nLen
;
}
else
{
pSqlFuncExpr
->
arg
[
j
].
argValue
.
i64
=
htobe64
(
pExpr
->
param
[
j
].
i64Key
);
}
...
...
@@ -799,23 +791,6 @@ int tscBuildQueryMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
pSqlFuncExpr
=
(
SSqlFuncMsg
*
)
pMsg
;
}
int32_t
len
=
0
;
if
(
hasArithmeticFunction
)
{
for
(
int32_t
i
=
0
;
i
<
numOfCols
;
++
i
)
{
SColumn
*
pColBase
=
taosArrayGetP
(
pQueryInfo
->
colList
,
i
);
char
*
name
=
pSchema
[
pColBase
[
i
].
colIndex
.
columnIndex
].
name
;
int32_t
lenx
=
strlen
(
name
);
memcpy
(
pMsg
,
name
,
lenx
);
*
(
pMsg
+
lenx
)
=
','
;
len
+=
(
lenx
+
1
);
// one for comma
pMsg
+=
(
lenx
+
1
);
}
}
pQueryMsg
->
colNameLen
=
htonl
(
len
);
// serialize the table info (sid, uid, tags)
pMsg
=
doSerializeTableInfo
(
pSql
,
htons
(
pQueryMsg
->
head
.
vgId
),
pMsg
);
...
...
src/client/src/tscSql.c
浏览文件 @
d3fcbb25
...
...
@@ -458,20 +458,21 @@ static void transferNcharData(SSqlObj *pSql, int32_t columnIndex, TAOS_FIELD *pF
}
}
static
char
*
getArithemicInputSrc
(
void
*
param
,
char
*
name
,
int32_t
colId
)
{
SArithmeticSupport
*
pSupport
=
(
SArithmeticSupport
*
)
param
;
SArithExprInfo
*
pExpr
=
pSupport
->
pArithExpr
;
int32_t
index
=
-
1
;
for
(
int32_t
i
=
0
;
i
<
pExpr
->
binExprInfo
.
numOfCols
;
++
i
)
{
if
(
strcmp
(
name
,
pExpr
->
binExprInfo
.
pReqColumns
[
i
].
name
)
==
0
)
{
index
=
i
;
break
;
}
}
assert
(
index
>=
0
&&
index
<
pExpr
->
binExprInfo
.
numOfCols
);
return
pSupport
->
data
[
index
]
+
pSupport
->
offset
*
pSupport
->
elemSize
[
index
];
static
char
*
getArithemicInputSrc
(
void
*
param
,
const
char
*
name
,
int32_t
colId
)
{
// SArithmeticSupport *pSupport = (SArithmeticSupport *)param;
// SArithExprInfo * pExpr = pSupport->pArithExpr;
// int32_t index = -1;
// for (int32_t i = 0; i < pExpr->numOfCols; ++i) {
// if (strcmp(name, pExpr->colList[i].name) == 0) {
// index = i;
// break;
// }
// }
//
// assert(index >= 0 && index < pExpr->numOfCols);
// return pSupport->data[index] + pSupport->offset * pSupport->elemSize[index];
return
0
;
}
static
void
**
doSetResultRowData
(
SSqlObj
*
pSql
)
{
...
...
@@ -521,21 +522,21 @@ static void **doSetResultRowData(SSqlObj *pSql) {
sas
->
offset
=
0
;
sas
->
pArithExpr
=
pInfo
->
pArithExprInfo
;
sas
->
numOfCols
=
sas
->
pArithExpr
->
binExprInfo
.
numOfCols
;
// sas->numOfCols = sas->pArithExpr->
numOfCols;
if
(
pRes
->
buffer
[
i
]
==
NULL
)
{
pRes
->
buffer
[
i
]
=
malloc
(
tscFieldInfoGetField
(
&
pQueryInfo
->
fieldsInfo
,
i
)
->
bytes
);
}
for
(
int32_t
k
=
0
;
k
<
sas
->
numOfCols
;
++
k
)
{
int32_t
columnIndex
=
sas
->
pArithExpr
->
binExprInfo
.
pReqColumns
[
k
].
colIndex
;
SSqlExpr
*
pExpr
=
tscSqlExprGet
(
pQueryInfo
,
columnIndex
);
sas
->
elemSize
[
k
]
=
pExpr
->
resBytes
;
sas
->
data
[
k
]
=
(
pRes
->
data
+
pRes
->
numOfRows
*
pExpr
->
offset
)
+
pRes
->
row
*
pExpr
->
resBytes
;
// int32_t columnIndex = sas->pArithExpr->colList
[k].colIndex;
//
SSqlExpr* pExpr = tscSqlExprGet(pQueryInfo, columnIndex);
//
//
sas->elemSize[k] = pExpr->resBytes;
//
sas->data[k] = (pRes->data + pRes->numOfRows* pExpr->offset) + pRes->row*pExpr->resBytes;
}
t
SQLBinaryExprCalcTraverse
(
sas
->
pArithExpr
->
binExprInfo
.
pBin
Expr
,
1
,
pRes
->
buffer
[
i
],
sas
,
TSDB_ORDER_ASC
,
getArithemicInputSrc
);
t
ExprTreeCalcTraverse
(
sas
->
pArithExpr
->
p
Expr
,
1
,
pRes
->
buffer
[
i
],
sas
,
TSDB_ORDER_ASC
,
getArithemicInputSrc
);
pRes
->
tsrow
[
i
]
=
pRes
->
buffer
[
i
];
free
(
sas
);
//todo optimization
...
...
@@ -634,8 +635,6 @@ static UNUSED_FUNC void **tscBuildResFromSubqueries(SSqlObj *pSql) {
}
if
(
success
)
{
// current row of final output has been built, return to app
size_t
numOfExprs
=
tscSqlExprNumOfExprs
(
pQueryInfo
);
for
(
int32_t
i
=
0
;
i
<
numOfExprs
;
++
i
)
{
int32_t
tableIndex
=
pRes
->
pColumnIndex
[
i
].
tableIndex
;
int32_t
columnIndex
=
pRes
->
pColumnIndex
[
i
].
columnIndex
;
...
...
src/client/src/tscSubquery.c
浏览文件 @
d3fcbb25
...
...
@@ -214,8 +214,8 @@ bool needSecondaryQuery(SQueryInfo* pQueryInfo) {
size_t
numOfCols
=
taosArrayGetSize
(
pQueryInfo
->
colList
);
for
(
int32_t
i
=
0
;
i
<
numOfCols
;
++
i
)
{
SColumn
*
pB
ase
=
taosArrayGet
(
pQueryInfo
->
colList
,
i
);
if
(
pB
ase
->
colIndex
.
columnIndex
!=
PRIMARYKEY_TIMESTAMP_COL_INDEX
)
{
SColumn
*
b
ase
=
taosArrayGet
(
pQueryInfo
->
colList
,
i
);
if
(
b
ase
->
colIndex
.
columnIndex
!=
PRIMARYKEY_TIMESTAMP_COL_INDEX
)
{
return
true
;
}
}
...
...
src/client/src/tscSystem.c
浏览文件 @
d3fcbb25
...
...
@@ -17,8 +17,6 @@
#include "taosmsg.h"
#include "tcache.h"
#include "trpc.h"
#include "taosdef.h"
#include "tsocket.h"
#include "tsystem.h"
#include "ttime.h"
#include "ttimer.h"
...
...
@@ -34,7 +32,6 @@
// global, not configurable
void
*
pVnodeConn
;
void
*
tscCacheHandle
;
int
slaveIndex
;
void
*
tscTmr
;
void
*
tscQhandle
;
void
*
tscCheckDiskUsageTmr
;
...
...
@@ -46,7 +43,7 @@ static pthread_once_t tscinit = PTHREAD_ONCE_INIT;
void
taosInitNote
(
int
numOfNoteLines
,
int
maxNotes
,
char
*
lable
);
void
tscUpdateIpSet
(
void
*
ahandle
,
SRpcIpSet
*
pIpSet
);
void
tscCheckDiskUsage
(
void
*
para
,
void
*
unused
)
{
void
tscCheckDiskUsage
(
void
*
UNUSED_PARAM
(
para
),
void
*
UNUSED_PARAM
(
param
)
)
{
taosGetDisk
();
taosTmrReset
(
tscCheckDiskUsage
,
1000
,
NULL
,
tscTmr
,
&
tscCheckDiskUsageTmr
);
}
...
...
@@ -156,7 +153,6 @@ void taos_init_imp() {
}
tscInitMsgsFp
();
slaveIndex
=
rand
();
int
queueSize
=
tsMaxVnodeConnections
+
tsMaxMeterConnections
+
tsMaxMgmtConnections
+
tsMaxMgmtConnections
;
if
(
tscEmbedded
==
0
)
{
...
...
@@ -379,7 +375,6 @@ static int taos_options_imp(TSDB_OPTION option, const char *pStr) {
return
0
;
}
int
taos_options
(
TSDB_OPTION
option
,
const
void
*
arg
,
...)
{
static
int32_t
lock
=
0
;
...
...
src/client/src/tscUtil.c
浏览文件 @
d3fcbb25
...
...
@@ -939,8 +939,7 @@ void tscFieldInfoClear(SFieldInfo* pFieldInfo) {
SFieldSupInfo
*
pInfo
=
taosArrayGet
(
pFieldInfo
->
pSupportInfo
,
i
);
if
(
pInfo
->
pArithExprInfo
!=
NULL
)
{
tExprTreeDestroy
(
&
pInfo
->
pArithExprInfo
->
binExprInfo
.
pBinExpr
,
NULL
);
tfree
(
pInfo
->
pArithExprInfo
->
binExprInfo
.
pReqColumns
);
tExprTreeDestroy
(
&
pInfo
->
pArithExprInfo
->
pExpr
,
NULL
);
}
}
...
...
@@ -1678,7 +1677,7 @@ STableMetaInfo* tscAddTableMetaInfo(SQueryInfo* pQueryInfo, const char* name, ST
}
if
(
pTagCols
==
NULL
)
{
pTableMetaInfo
->
tagColList
=
taosArrayInit
(
4
,
sizeof
(
SColumnIndex
)
);
pTableMetaInfo
->
tagColList
=
taosArrayInit
(
4
,
POINTER_BYTES
);
}
else
{
pTableMetaInfo
->
tagColList
=
taosArrayClone
(
pTagCols
);
}
...
...
src/inc/taosmsg.h
浏览文件 @
d3fcbb25
...
...
@@ -356,17 +356,9 @@ typedef struct {
}
SMDDropVnodeMsg
;
typedef
struct
SColIndex
{
int16_t
colId
;
/*
* colIdx is the index of column in latest schema of table
* it is available in the client side. Also used to determine
* whether current table schema is up-to-date.
*
* colIdxInBuf is used to denote the index of column in pQuery->colList,
* this value is invalid in client side, as well as in cache block of vnode either.
*/
int16_t
colIndex
;
uint16_t
flag
;
// denote if it is a tag or not
int16_t
colId
;
// column id
int16_t
colIndex
;
// column index in colList if it is a normal column or index in tagColList if a tag
uint16_t
flag
;
// denote if it is a tag or a normal column
char
name
[
TSDB_COL_NAME_LEN
];
}
SColIndex
;
...
...
@@ -388,15 +380,9 @@ typedef struct SSqlFuncMsg {
}
arg
[
3
];
}
SSqlFuncMsg
;
typedef
struct
SExprInfo
{
struct
tExprNode
*
pBinExpr
;
/* for binary expression */
int32_t
numOfCols
;
/* binary expression involves the readed number of columns*/
SColIndex
*
pReqColumns
;
/* source column list */
}
SExprInfo
;
typedef
struct
SArithExprInfo
{
SSqlFuncMsg
pB
ase
;
SExprInfo
binExprInfo
;
SSqlFuncMsg
b
ase
;
struct
tExprNode
*
pExpr
;
int16_t
bytes
;
int16_t
type
;
int16_t
interResBytes
;
...
...
@@ -474,8 +460,8 @@ typedef struct {
int16_t
interpoType
;
// interpolate type
uint64_t
defaultVal
;
// default value array list
int32_t
colNameLen
;
int64_t
colNameList
;
//
int32_t colNameLen;
//
int64_t colNameList;
int32_t
tsOffset
;
// offset value in current msg body, NOTE: ts list is compressed
int32_t
tsLen
;
// total length of ts comp block
int32_t
tsNumOfBlocks
;
// ts comp block numbers
...
...
@@ -776,14 +762,14 @@ typedef struct {
}
SMDCfgDnodeMsg
,
SCMCfgDnodeMsg
;
typedef
struct
{
char
sql
[
TSDB_SHOW_SQL_LEN
+
1
];
char
sql
[
TSDB_SHOW_SQL_LEN
];
uint32_t
queryId
;
int64_t
useconds
;
int64_t
stime
;
}
SQueryDesc
;
typedef
struct
{
char
sql
[
TSDB_SHOW_SQL_LEN
+
1
];
char
sql
[
TSDB_SHOW_SQL_LEN
];
uint32_t
streamId
;
int64_t
num
;
// number of computing/cycles
int64_t
useconds
;
...
...
@@ -795,12 +781,10 @@ typedef struct {
typedef
struct
{
int32_t
numOfQueries
;
SQueryDesc
*
qdesc
;
}
SQqueryList
;
typedef
struct
{
int32_t
numOfStreams
;
SStreamDesc
*
sdesc
;
}
SStreamList
;
typedef
struct
{
...
...
src/query/inc/qast.h
浏览文件 @
d3fcbb25
...
...
@@ -82,10 +82,11 @@ void tExprTreeDestroy(tExprNode **pExprs, void (*fp)(void*));
void
tExprTreeTraverse
(
tExprNode
*
pExpr
,
SSkipList
*
pSkipList
,
SArray
*
result
,
SBinaryFilterSupp
*
param
);
void
t
SQLBinaryExpr
CalcTraverse
(
tExprNode
*
pExprs
,
int32_t
numOfRows
,
char
*
pOutput
,
void
*
param
,
int32_t
order
,
char
*
(
*
cb
)(
void
*
,
c
har
*
,
int32_t
));
void
t
ExprTree
CalcTraverse
(
tExprNode
*
pExprs
,
int32_t
numOfRows
,
char
*
pOutput
,
void
*
param
,
int32_t
order
,
char
*
(
*
cb
)(
void
*
,
c
onst
char
*
,
int32_t
));
void
tSQLBinaryExprTrv
(
tExprNode
*
pExprs
,
int32_t
*
val
,
int16_t
*
ids
);
// todo refactor: remove it
void
tSQLBinaryExprTrv
(
tExprNode
*
pExprs
,
SArray
*
res
);
uint8_t
getBinaryExprOptr
(
SSQLToken
*
pToken
);
...
...
src/query/inc/tsqlfunction.h
浏览文件 @
d3fcbb25
...
...
@@ -115,10 +115,10 @@ enum {
typedef
struct
SArithmeticSupport
{
SArithExprInfo
*
pArithExpr
;
int32_t
elemSize
[
TSDB_MAX_COLUMNS
];
int32_t
numOfCols
;
SColumnInfo
*
colList
;
int32_t
offset
;
char
*
data
[
TSDB_MAX_COLUMNS
]
;
char
**
data
;
}
SArithmeticSupport
;
typedef
struct
SQLPreAggVal
{
...
...
src/query/inc/tvariant.h
浏览文件 @
d3fcbb25
...
...
@@ -40,7 +40,7 @@ void tVariantCreate(tVariant *pVar, SSQLToken *token);
void
tVariantCreateFromString
(
tVariant
*
pVar
,
char
*
pz
,
uint32_t
len
,
uint32_t
type
);
void
tVariantCreateFromBinary
(
tVariant
*
pVar
,
c
har
*
pz
,
uint32
_t
len
,
uint32_t
type
);
void
tVariantCreateFromBinary
(
tVariant
*
pVar
,
c
onst
char
*
pz
,
size
_t
len
,
uint32_t
type
);
void
tVariantDestroy
(
tVariant
*
pV
);
...
...
src/query/src/qast.c
浏览文件 @
d3fcbb25
...
...
@@ -620,19 +620,6 @@ static void tQueryIndexColumn(SSkipList* pSkipList, tQueryInfo* pQueryInfo, SArr
}
}
/*
* qsort comparator
* sort the result to ensure meters with the same gid is grouped together
*/
//static int32_t compareByAddr(const void *pLeft, const void *pRight) {
// int64_t p1 = (int64_t) * ((tSkipListNode **)pLeft);
// int64_t p2 = (int64_t) * ((tSkipListNode **)pRight);
//
// DEFAULT_COMP(p1, p2);
//}
// develop_old mgmtSTableQuery for merge & intersect
int32_t
merge
(
SArray
*
pLeft
,
SArray
*
pRight
,
SArray
*
pFinalRes
)
{
// assert(pFinalRes->pRes == 0);
//
...
...
@@ -934,8 +921,8 @@ void tExprTreeTraverse(tExprNode *pExpr, SSkipList *pSkipList, SArray *result, S
}
void
t
SQLBinaryExpr
CalcTraverse
(
tExprNode
*
pExprs
,
int32_t
numOfRows
,
char
*
pOutput
,
void
*
param
,
int32_t
order
,
char
*
(
*
getSourceDataBlock
)(
void
*
,
c
har
*
,
int32_t
))
{
void
t
ExprTree
CalcTraverse
(
tExprNode
*
pExprs
,
int32_t
numOfRows
,
char
*
pOutput
,
void
*
param
,
int32_t
order
,
char
*
(
*
getSourceDataBlock
)(
void
*
,
c
onst
char
*
,
int32_t
))
{
if
(
pExprs
==
NULL
)
{
return
;
}
...
...
@@ -946,13 +933,13 @@ void tSQLBinaryExprCalcTraverse(tExprNode *pExprs, int32_t numOfRows, char *pOut
/* the left output has result from the left child syntax tree */
char
*
pLeftOutput
=
(
char
*
)
malloc
(
sizeof
(
int64_t
)
*
numOfRows
);
if
(
pLeft
->
nodeType
==
TSQL_NODE_EXPR
)
{
t
SQLBinaryExpr
CalcTraverse
(
pLeft
,
numOfRows
,
pLeftOutput
,
param
,
order
,
getSourceDataBlock
);
t
ExprTree
CalcTraverse
(
pLeft
,
numOfRows
,
pLeftOutput
,
param
,
order
,
getSourceDataBlock
);
}
/* the right output has result from the right child syntax tree */
char
*
pRightOutput
=
malloc
(
sizeof
(
int64_t
)
*
numOfRows
);
if
(
pRight
->
nodeType
==
TSQL_NODE_EXPR
)
{
t
SQLBinaryExpr
CalcTraverse
(
pRight
,
numOfRows
,
pRightOutput
,
param
,
order
,
getSourceDataBlock
);
t
ExprTree
CalcTraverse
(
pRight
,
numOfRows
,
pRightOutput
,
param
,
order
,
getSourceDataBlock
);
}
if
(
pLeft
->
nodeType
==
TSQL_NODE_EXPR
)
{
...
...
@@ -1014,7 +1001,7 @@ void tSQLBinaryExprCalcTraverse(tExprNode *pExprs, int32_t numOfRows, char *pOut
free
(
pRightOutput
);
}
void
tSQLBinaryExprTrv
(
tExprNode
*
pExprs
,
int32_t
*
val
,
int16_t
*
id
s
)
{
void
tSQLBinaryExprTrv
(
tExprNode
*
pExprs
,
SArray
*
re
s
)
{
if
(
pExprs
==
NULL
)
{
return
;
}
...
...
@@ -1024,17 +1011,15 @@ void tSQLBinaryExprTrv(tExprNode *pExprs, int32_t *val, int16_t *ids) {
// recursive traverse left child branch
if
(
pLeft
->
nodeType
==
TSQL_NODE_EXPR
)
{
tSQLBinaryExprTrv
(
pLeft
,
val
,
id
s
);
tSQLBinaryExprTrv
(
pLeft
,
re
s
);
}
else
if
(
pLeft
->
nodeType
==
TSQL_NODE_COL
)
{
ids
[
*
val
]
=
pLeft
->
pSchema
->
colId
;
(
*
val
)
+=
1
;
taosArrayPush
(
res
,
&
pLeft
->
pSchema
->
colId
);
}
if
(
pRight
->
nodeType
==
TSQL_NODE_EXPR
)
{
tSQLBinaryExprTrv
(
pRight
,
val
,
id
s
);
tSQLBinaryExprTrv
(
pRight
,
re
s
);
}
else
if
(
pRight
->
nodeType
==
TSQL_NODE_COL
)
{
ids
[
*
val
]
=
pRight
->
pSchema
->
colId
;
(
*
val
)
+=
1
;
taosArrayPush
(
res
,
&
pRight
->
pSchema
->
colId
);
}
}
...
...
src/query/src/queryExecutor.c
浏览文件 @
d3fcbb25
此差异已折叠。
点击以展开。
src/query/src/tvariant.c
浏览文件 @
d3fcbb25
...
...
@@ -72,7 +72,7 @@ void tVariantCreateFromString(tVariant *pVar, char *pz, uint32_t len, uint32_t t
* @param len
* @param type
*/
void
tVariantCreateFromBinary
(
tVariant
*
pVar
,
c
har
*
pz
,
uint32
_t
len
,
uint32_t
type
)
{
void
tVariantCreateFromBinary
(
tVariant
*
pVar
,
c
onst
char
*
pz
,
size
_t
len
,
uint32_t
type
)
{
switch
(
type
)
{
case
TSDB_DATA_TYPE_BOOL
:
case
TSDB_DATA_TYPE_TINYINT
:
{
...
...
@@ -109,10 +109,10 @@ void tVariantCreateFromBinary(tVariant *pVar, char *pz, uint32_t len, uint32_t t
break
;
}
case
TSDB_DATA_TYPE_BINARY
:
{
pVar
->
pz
=
strndup
(
pz
,
len
);
pVar
->
nLen
=
strdequote
(
pVar
->
pz
);
case
TSDB_DATA_TYPE_BINARY
:
{
// todo refactor, extract a method
pVar
->
pz
=
calloc
(
len
,
sizeof
(
char
)
);
memcpy
(
pVar
->
pz
,
pz
,
len
);
pVar
->
nLen
=
len
;
break
;
}
...
...
src/query/tests/astTest.cpp
浏览文件 @
d3fcbb25
...
...
@@ -556,8 +556,7 @@ void exprSerializeTest1() {
ASSERT_TRUE
(
size
>
0
);
char
*
b
=
tbufGetData
(
&
buf
,
false
);
tExprNode
*
p2
=
NULL
;
exprTreeFromBinary
(
b
,
size
,
&
p2
);
tExprNode
*
p2
=
exprTreeFromBinary
(
b
,
size
);
ASSERT_EQ
(
p1
->
nodeType
,
p2
->
nodeType
);
ASSERT_EQ
(
p2
->
_node
.
optr
,
p1
->
_node
.
optr
);
...
...
@@ -593,8 +592,7 @@ void exprSerializeTest2() {
ASSERT_TRUE
(
size
>
0
);
char
*
b
=
tbufGetData
(
&
buf
,
false
);
tExprNode
*
p2
=
NULL
;
exprTreeFromBinary
(
b
,
size
,
&
p2
);
tExprNode
*
p2
=
exprTreeFromBinary
(
b
,
size
);
ASSERT_EQ
(
p1
->
nodeType
,
p2
->
nodeType
);
ASSERT_EQ
(
p2
->
_node
.
optr
,
p1
->
_node
.
optr
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录