提交 e4bda74d 编写于 作者: D dapan1121

Merge branch 'feature/qnode' of github.com:taosdata/TDengine into feature/qnode

...@@ -1090,6 +1090,10 @@ static FORCE_INLINE void* tDeserializeSMVSubscribeReq(void* buf, SMVSubscribeReq ...@@ -1090,6 +1090,10 @@ static FORCE_INLINE void* tDeserializeSMVSubscribeReq(void* buf, SMVSubscribeReq
return buf; return buf;
} }
typedef struct SMqTmrMsg {
int32_t reserved;
} SMqTmrMsg;
typedef struct { typedef struct {
int64_t status; int64_t status;
} SMVSubscribeRsp; } SMVSubscribeRsp;
...@@ -1517,20 +1521,19 @@ typedef struct SMqSetCVgReq { ...@@ -1517,20 +1521,19 @@ typedef struct SMqSetCVgReq {
int32_t vgId; int32_t vgId;
int64_t consumerId; int64_t consumerId;
char topicName[TSDB_TOPIC_FNAME_LEN]; char topicName[TSDB_TOPIC_FNAME_LEN];
char cGroup[TSDB_CONSUMER_GROUP_LEN]; char cgroup[TSDB_CONSUMER_GROUP_LEN];
char* sql; char* sql;
char* logicalPlan; char* logicalPlan;
char* physicalPlan; char* physicalPlan;
SArray* tasks; // SArray<SSubQueryMsg> SArray* tasks; // SArray<SSubQueryMsg>
} SMqSetCVgReq; } SMqSetCVgReq;
static FORCE_INLINE int32_t tEncodeSMqSetCVgReq(void** buf, const SMqSetCVgReq* pReq) { static FORCE_INLINE int32_t tEncodeSMqSetCVgReq(void** buf, const SMqSetCVgReq* pReq) {
int32_t tlen = 0; int32_t tlen = 0;
tlen += taosEncodeFixedI32(buf, pReq->vgId); tlen += taosEncodeFixedI32(buf, pReq->vgId);
tlen += taosEncodeFixedI64(buf, pReq->consumerId); tlen += taosEncodeFixedI64(buf, pReq->consumerId);
tlen += taosEncodeString(buf, pReq->topicName); tlen += taosEncodeString(buf, pReq->topicName);
tlen += taosEncodeString(buf, pReq->cGroup); tlen += taosEncodeString(buf, pReq->cgroup);
tlen += taosEncodeString(buf, pReq->sql); tlen += taosEncodeString(buf, pReq->sql);
tlen += taosEncodeString(buf, pReq->logicalPlan); tlen += taosEncodeString(buf, pReq->logicalPlan);
tlen += taosEncodeString(buf, pReq->physicalPlan); tlen += taosEncodeString(buf, pReq->physicalPlan);
...@@ -1541,7 +1544,7 @@ static FORCE_INLINE void* tDecodeSMqSetCVgReq(void* buf, SMqSetCVgReq* pReq) { ...@@ -1541,7 +1544,7 @@ static FORCE_INLINE void* tDecodeSMqSetCVgReq(void* buf, SMqSetCVgReq* pReq) {
buf = taosDecodeFixedI32(buf, &pReq->vgId); buf = taosDecodeFixedI32(buf, &pReq->vgId);
buf = taosDecodeFixedI64(buf, &pReq->consumerId); buf = taosDecodeFixedI64(buf, &pReq->consumerId);
buf = taosDecodeStringTo(buf, pReq->topicName); buf = taosDecodeStringTo(buf, pReq->topicName);
buf = taosDecodeStringTo(buf, pReq->cGroup); buf = taosDecodeStringTo(buf, pReq->cgroup);
buf = taosDecodeString(buf, &pReq->sql); buf = taosDecodeString(buf, &pReq->sql);
buf = taosDecodeString(buf, &pReq->logicalPlan); buf = taosDecodeString(buf, &pReq->logicalPlan);
buf = taosDecodeString(buf, &pReq->physicalPlan); buf = taosDecodeString(buf, &pReq->physicalPlan);
...@@ -1549,6 +1552,39 @@ static FORCE_INLINE void* tDecodeSMqSetCVgReq(void* buf, SMqSetCVgReq* pReq) { ...@@ -1549,6 +1552,39 @@ static FORCE_INLINE void* tDecodeSMqSetCVgReq(void* buf, SMqSetCVgReq* pReq) {
return buf; return buf;
} }
typedef struct SMqSetCVgRsp {
int32_t vgId;
int64_t consumerId;
char topicName[TSDB_TOPIC_FNAME_LEN];
char cGroup[TSDB_CONSUMER_GROUP_LEN];
} SMqSetCVgRsp;
typedef struct SMqCVConsumeReq {
int64_t reqId;
int64_t offset;
int64_t consumerId;
int64_t blockingTime;
char topicName[TSDB_TOPIC_FNAME_LEN];
char cgroup[TSDB_CONSUMER_GROUP_LEN];
} SMqCVConsumeReq;
typedef struct SMqConsumeRspBlock {
int32_t bodyLen;
char topicName[TSDB_TOPIC_FNAME_LEN];
char body[];
} SMqConsumeRspBlock;
typedef struct SMqCVConsumeRsp {
int64_t reqId;
int64_t clientId;
int64_t committedOffset;
int64_t receiveOffset;
int64_t rspOffset;
int32_t skipLogNum;
int32_t bodyLen;
char topicName[TSDB_TOPIC_FNAME_LEN];
SMqConsumeRspBlock blocks[];
} SMqCvConsumeRsp;
#ifdef __cplusplus #ifdef __cplusplus
} }
......
...@@ -140,6 +140,7 @@ enum { ...@@ -140,6 +140,7 @@ enum {
TD_DEF_MSG_TYPE(TDMT_MND_ALTER_TOPIC, "mnode-alter-topic", NULL, NULL) TD_DEF_MSG_TYPE(TDMT_MND_ALTER_TOPIC, "mnode-alter-topic", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_MND_DROP_TOPIC, "mnode-drop-topic", NULL, NULL) TD_DEF_MSG_TYPE(TDMT_MND_DROP_TOPIC, "mnode-drop-topic", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_MND_SUBSCRIBE, "mnode-subscribe", SCMSubscribeReq, SCMSubscribeRsp) TD_DEF_MSG_TYPE(TDMT_MND_SUBSCRIBE, "mnode-subscribe", SCMSubscribeReq, SCMSubscribeRsp)
TD_DEF_MSG_TYPE(TDMT_MND_MQ_TIMER, "mnode-timer", SMqTmrMsg, SMqTmrMsg)
// Requests handled by VNODE // Requests handled by VNODE
TD_NEW_MSG_SEG(TDMT_VND_MSG) TD_NEW_MSG_SEG(TDMT_VND_MSG)
...@@ -159,7 +160,7 @@ enum { ...@@ -159,7 +160,7 @@ enum {
TD_DEF_MSG_TYPE(TDMT_VND_MQ_QUERY, "vnode-mq-query", NULL, NULL) TD_DEF_MSG_TYPE(TDMT_VND_MQ_QUERY, "vnode-mq-query", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_VND_MQ_CONNECT, "vnode-mq-connect", NULL, NULL) TD_DEF_MSG_TYPE(TDMT_VND_MQ_CONNECT, "vnode-mq-connect", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_VND_MQ_DISCONNECT, "vnode-mq-disconnect", NULL, NULL) TD_DEF_MSG_TYPE(TDMT_VND_MQ_DISCONNECT, "vnode-mq-disconnect", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_VND_MQ_SET_CONN, "vnode-mq-set-conn", NULL, NULL) TD_DEF_MSG_TYPE(TDMT_VND_MQ_SET_CONN, "vnode-mq-set-conn", SMqSetCVgReq, SMqSetCVgRsp)
TD_DEF_MSG_TYPE(TDMT_VND_MQ_SET_CUR, "vnode-mq-set-cur", NULL, NULL) TD_DEF_MSG_TYPE(TDMT_VND_MQ_SET_CUR, "vnode-mq-set-cur", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_VND_RES_READY, "vnode-res-ready", NULL, NULL) TD_DEF_MSG_TYPE(TDMT_VND_RES_READY, "vnode-res-ready", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_VND_TASKS_STATUS, "vnode-tasks-status", NULL, NULL) TD_DEF_MSG_TYPE(TDMT_VND_TASKS_STATUS, "vnode-tasks-status", NULL, NULL)
...@@ -173,6 +174,7 @@ enum { ...@@ -173,6 +174,7 @@ enum {
TD_DEF_MSG_TYPE(TDMT_VND_QUERY_CONTINUE, "vnode-query-continue", NULL, NULL) TD_DEF_MSG_TYPE(TDMT_VND_QUERY_CONTINUE, "vnode-query-continue", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_VND_SUBSCRIBE, "vnode-subscribe", SMVSubscribeReq, SMVSubscribeRsp) TD_DEF_MSG_TYPE(TDMT_VND_SUBSCRIBE, "vnode-subscribe", SMVSubscribeReq, SMVSubscribeRsp)
TD_DEF_MSG_TYPE(TDMT_VND_CONSUME, "vnode-consume", SMqCVConsumeReq, SMqCVConsumeRsp)
// Requests handled by QNODE // Requests handled by QNODE
......
...@@ -80,6 +80,13 @@ extern "C" { ...@@ -80,6 +80,13 @@ extern "C" {
#define FUNCTION_COV 38 #define FUNCTION_COV 38
typedef struct SResultRowEntryInfo {
int8_t hasResult; // result generated, not NULL value
bool initialized; // output buffer has been initialized
bool complete; // query has completed
uint32_t numOfRes; // num of output result in current buffer
} SResultRowEntryInfo;
// determine the real data need to calculated the result // determine the real data need to calculated the result
enum { enum {
BLK_DATA_NO_NEEDED = 0x0, BLK_DATA_NO_NEEDED = 0x0,
...@@ -127,6 +134,8 @@ typedef struct SFunctionFpSet { ...@@ -127,6 +134,8 @@ typedef struct SFunctionFpSet {
void (*combine)(struct SQLFunctionCtx *pCtx); void (*combine)(struct SQLFunctionCtx *pCtx);
} SFunctionFpSet; } SFunctionFpSet;
extern SFunctionFpSet fpSet[1];
// sql function runtime context // sql function runtime context
typedef struct SQLFunctionCtx { typedef struct SQLFunctionCtx {
int32_t size; // number of rows int32_t size; // number of rows
...@@ -156,6 +165,7 @@ typedef struct SQLFunctionCtx { ...@@ -156,6 +165,7 @@ typedef struct SQLFunctionCtx {
SPoint1 start; SPoint1 start;
SPoint1 end; SPoint1 end;
int32_t columnIndex;
SFunctionFpSet* fpSet; SFunctionFpSet* fpSet;
} SQLFunctionCtx; } SQLFunctionCtx;
......
/*
* 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 _TD_FUNCTION_MGT_H_
#define _TD_FUNCTION_MGT_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "nodes.h"
struct SQLFunctionCtx;
struct SResultRowEntryInfo;
struct STimeWindow;
typedef struct SFuncExecEnv {
int32_t calcMemSize;
} SFuncExecEnv;
typedef void* FuncMgtHandle;
typedef bool (*FExecGetEnv)(SFunctionNode* pFunc, SFuncExecEnv* pEnv);
typedef bool (*FExecInit)(struct SQLFunctionCtx *pCtx, struct SResultRowEntryInfo* pResultCellInfo);
typedef void (*FExecProcess)(struct SQLFunctionCtx *pCtx);
typedef void (*FExecFinalize)(struct SQLFunctionCtx *pCtx);
typedef struct SFuncExecFuncs {
FExecGetEnv getEnv;
FExecInit init;
FExecProcess process;
FExecFinalize finalize;
} SFuncExecFuncs;
int32_t fmFuncMgtInit();
int32_t fmGetHandle(FuncMgtHandle* pHandle);
int32_t fmGetFuncId(FuncMgtHandle handle, const char* name);
int32_t fmGetFuncResultType(FuncMgtHandle handle, SFunctionNode* pFunc);
bool fmIsAggFunc(int32_t funcId);
bool fmIsStringFunc(int32_t funcId);
bool fmIsTimestampFunc(int32_t funcId);
bool fmIsTimelineFunc(int32_t funcId);
bool fmIsTimeorderFunc(int32_t funcId);
bool fmIsNonstandardSQLFunc(int32_t funcId);
int32_t fmFuncScanType(int32_t funcId);
int32_t fmGetFuncExecFuncs(FuncMgtHandle handle, int32_t funcId, SFuncExecFuncs* pFpSet);
#ifdef __cplusplus
}
#endif
#endif // _TD_FUNCTION_MGT_H_
...@@ -91,6 +91,7 @@ SSchema *getOneColumnSchema(const STableMeta* pTableMeta, int32_t colIndex); ...@@ -91,6 +91,7 @@ SSchema *getOneColumnSchema(const STableMeta* pTableMeta, int32_t colIndex);
int32_t getNewResColId(); int32_t getNewResColId();
void addIntoSourceParam(SSourceParam* pSourceParam, tExprNode* pNode, SColumn* pColumn); void addIntoSourceParam(SSourceParam* pSourceParam, tExprNode* pNode, SColumn* pColumn);
SExprInfo* createBinaryExprInfo(struct tExprNode* pNode, SSchema* pResSchema);
#ifdef __cplusplus #ifdef __cplusplus
} }
......
...@@ -80,8 +80,8 @@ typedef enum { TAOS_WAL_NOLOG = 0, TAOS_WAL_WRITE = 1, TAOS_WAL_FSYNC = 2 } EWal ...@@ -80,8 +80,8 @@ typedef enum { TAOS_WAL_NOLOG = 0, TAOS_WAL_WRITE = 1, TAOS_WAL_FSYNC = 2 } EWal
typedef struct SWalReadHead { typedef struct SWalReadHead {
int8_t headVer; int8_t headVer;
uint8_t msgType; int16_t msgType;
int8_t reserved[2]; int8_t reserved;
int32_t len; int32_t len;
int64_t ingestTs; // not implemented int64_t ingestTs; // not implemented
int64_t version; int64_t version;
......
/*
* 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 _TD_NODES_H_
#define _TD_NODES_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "tarray.h"
#include "tdef.h"
typedef enum ENodeType {
QUERY_NODE_COLUMN = 1,
QUERY_NODE_VALUE,
QUERY_NODE_OPERATOR,
QUERY_NODE_LOGIC_CONDITION,
QUERY_NODE_IS_NULL_CONDITION,
QUERY_NODE_FUNCTION,
QUERY_NODE_REAL_TABLE,
QUERY_NODE_TEMP_TABLE,
QUERY_NODE_JOIN_TABLE,
QUERY_NODE_GROUPING_SET,
QUERY_NODE_ORDER_BY_EXPR,
QUERY_NODE_STATE_WINDOW,
QUERY_NODE_SESSION_WINDOW,
QUERY_NODE_INTERVAL_WINDOW,
QUERY_NODE_SET_OPERATOR,
QUERY_NODE_SELECT_STMT
} ENodeType;
/**
* The first field of a node of any type is guaranteed to be the ENodeType.
* Hence the type of any node can be gotten by casting it to SNode.
*/
typedef struct SNode {
ENodeType type;
} SNode;
#define nodeType(nodeptr) (((const SNode*)(nodeptr))->type)
typedef struct SDataType {
uint8_t type;
uint8_t precision;
uint8_t scale;
int32_t bytes;
} SDataType;
typedef struct SExprNode {
ENodeType nodeType;
SDataType resType;
char aliasName[TSDB_COL_NAME_LEN];
} SExprNode;
typedef enum EColumnType {
COLUMN_TYPE_COLUMN = 1,
COLUMN_TYPE_TAG
} EColumnType;
typedef struct SColumnNode {
SExprNode node; // QUERY_NODE_COLUMN
int16_t colId;
EColumnType colType; // column or tag
char dbName[TSDB_DB_NAME_LEN];
char tableName[TSDB_TABLE_NAME_LEN];
char colName[TSDB_COL_NAME_LEN];
} SColumnNode;
typedef struct SValueNode {
SExprNode type; // QUERY_NODE_VALUE
char* literal;
} SValueNode;
typedef enum EOperatorType {
// arithmetic operator
OP_TYPE_ADD = 1,
OP_TYPE_SUB,
OP_TYPE_MULTI,
OP_TYPE_DIV,
OP_TYPE_MOD,
// comparison operator
OP_TYPE_GREATER_THAN,
OP_TYPE_GREATER_EQUAL,
OP_TYPE_LOWER_THAN,
OP_TYPE_LOWER_EQUAL,
OP_TYPE_EQUAL,
OP_TYPE_NOT_EQUAL,
OP_TYPE_IN,
OP_TYPE_NOT_IN,
OP_TYPE_LIKE,
OP_TYPE_NOT_LIKE,
OP_TYPE_MATCH,
OP_TYPE_NMATCH,
// json operator
OP_TYPE_JSON_GET_VALUE,
OP_TYPE_JSON_CONTAINS
} EOperatorType;
typedef struct SOperatorNode {
SExprNode type; // QUERY_NODE_OPERATOR
EOperatorType opType;
SNode* pLeft;
SNode* pRight;
} SOperatorNode;
typedef enum ELogicConditionType {
LOGIC_COND_TYPE_AND,
LOGIC_COND_TYPE_OR,
LOGIC_COND_TYPE_NOT,
} ELogicConditionType;
typedef struct SLogicConditionNode {
ENodeType type; // QUERY_NODE_LOGIC_CONDITION
ELogicConditionType condType;
SArray* pParameterList;
} SLogicConditionNode;
typedef struct SIsNullCondNode {
ENodeType type; // QUERY_NODE_IS_NULL_CONDITION
SNode* pExpr;
bool isNot;
} SIsNullCondNode;
typedef struct SFunctionNode {
SExprNode type; // QUERY_NODE_FUNCTION
char functionName[TSDB_FUNC_NAME_LEN];
int32_t funcId;
SArray* pParameterList; // SNode
} SFunctionNode;
typedef struct STableNode {
ENodeType type;
char tableName[TSDB_TABLE_NAME_LEN];
char tableAliasName[TSDB_COL_NAME_LEN];
} STableNode;
typedef struct SRealTableNode {
STableNode type; // QUERY_NODE_REAL_TABLE
char dbName[TSDB_DB_NAME_LEN];
} SRealTableNode;
typedef struct STempTableNode {
STableNode type; // QUERY_NODE_TEMP_TABLE
SNode* pSubquery;
} STempTableNode;
typedef enum EJoinType {
JOIN_TYPE_INNER = 1
} EJoinType;
typedef struct SJoinTableNode {
STableNode type; // QUERY_NODE_JOIN_TABLE
EJoinType joinType;
SNode* pLeft;
SNode* pRight;
SNode* pOnCond;
} SJoinTableNode;
typedef enum EGroupingSetType {
GP_TYPE_NORMAL = 1
} EGroupingSetType;
typedef struct SGroupingSetNode {
ENodeType type; // QUERY_NODE_GROUPING_SET
EGroupingSetType groupingSetType;
SArray* pParameterList;
} SGroupingSetNode;
typedef enum EOrder {
ORDER_ASC = 1,
ORDER_DESC
} EOrder;
typedef enum ENullOrder {
NULL_ORDER_FIRST = 1,
NULL_ORDER_LAST
} ENullOrder;
typedef struct SOrderByExprNode {
ENodeType type; // QUERY_NODE_ORDER_BY_EXPR
SNode* pExpr;
EOrder order;
ENullOrder nullOrder;
} SOrderByExprNode;
typedef struct SLimitInfo {
uint64_t limit;
uint64_t offset;
} SLimitInfo;
typedef struct SStateWindowNode {
ENodeType type; // QUERY_NODE_STATE_WINDOW
SNode* pCol;
} SStateWindowNode;
typedef struct SSessionWindowNode {
ENodeType type; // QUERY_NODE_SESSION_WINDOW
int64_t gap; // gap between two session window(in microseconds)
SNode* pCol;
} SSessionWindowNode;
typedef struct SIntervalWindowNode {
ENodeType type; // QUERY_NODE_INTERVAL_WINDOW
int64_t interval;
int64_t sliding;
int64_t offset;
} SIntervalWindowNode;
typedef struct SSelectStmt {
ENodeType type; // QUERY_NODE_SELECT_STMT
bool isDistinct;
SArray* pProjectionList; // SNode
SNode* pFromTable;
SNode* pWhereCond;
SArray* pPartitionByList; // SNode
SNode* pWindowClause;
SArray* pGroupByList; // SGroupingSetNode
SArray* pOrderByList; // SOrderByExprNode
SLimitInfo limit;
SLimitInfo slimit;
} SSelectStmt;
typedef enum ESetOperatorType {
SET_OP_TYPE_UNION_ALL = 1
} ESetOperatorType;
typedef struct SSetOperator {
ENodeType type; // QUERY_NODE_SET_OPERATOR
ESetOperatorType opType;
SNode* pLeft;
SNode* pRight;
} SSetOperator;
typedef bool (*FQueryNodeWalker)(SNode* pNode, void* pContext);
bool nodeArrayWalker(SArray* pArray, FQueryNodeWalker walker, void* pContext);
bool nodeTreeWalker(SNode* pNode, FQueryNodeWalker walker, void* pContext);
bool stmtWalker(SNode* pNode, FQueryNodeWalker walker, void* pContext);
bool nodeEqual(const SNode* a, const SNode* b);
void cloneNode(const SNode* pNode);
int32_t nodeToString(const SNode* pNode, char** pStr, int32_t* pLen);
int32_t stringToNode(const char* pStr, SNode** pNode);
bool isTimeorderQuery(const SNode* pQuery);
bool isTimelineQuery(const SNode* pQuery);
#ifdef __cplusplus
}
#endif
#endif /*_TD_NODES_H_*/
...@@ -3,4 +3,5 @@ add_subdirectory(util) ...@@ -3,4 +3,5 @@ add_subdirectory(util)
add_subdirectory(common) add_subdirectory(common)
add_subdirectory(libs) add_subdirectory(libs)
add_subdirectory(client) add_subdirectory(client)
add_subdirectory(dnode) add_subdirectory(dnode)
\ No newline at end of file add_subdirectory(nodes)
\ No newline at end of file
...@@ -259,7 +259,7 @@ int32_t scheduleQuery(SRequestObj* pRequest, SQueryDag* pDag) { ...@@ -259,7 +259,7 @@ int32_t scheduleQuery(SRequestObj* pRequest, SQueryDag* pDag) {
SArray *execNode = taosArrayInit(4, sizeof(SQueryNodeAddr)); SArray *execNode = taosArrayInit(4, sizeof(SQueryNodeAddr));
SQueryNodeAddr addr = {.numOfEps = 1, .inUse = 0, .nodeId = 2}; SQueryNodeAddr addr = {.numOfEps = 1, .inUse = 0, .nodeId = 2};
addr.epAddr[0].port = 6030; addr.epAddr[0].port = 7100;
strcpy(addr.epAddr[0].fqdn, "localhost"); strcpy(addr.epAddr[0].fqdn, "localhost");
taosArrayPush(execNode, &addr); taosArrayPush(execNode, &addr);
...@@ -728,6 +728,7 @@ void* doFetchRow(SRequestObj* pRequest) { ...@@ -728,6 +728,7 @@ void* doFetchRow(SRequestObj* pRequest) {
goto _return; goto _return;
} else if (pRequest->type == TDMT_MND_SHOW) { } else if (pRequest->type == TDMT_MND_SHOW) {
pRequest->type = TDMT_MND_SHOW_RETRIEVE; pRequest->type = TDMT_MND_SHOW_RETRIEVE;
epSet = getEpSet_s(&pRequest->pTscObj->pAppInfo->mgmtEp);
} else if (pRequest->type == TDMT_VND_SHOW_TABLES) { } else if (pRequest->type == TDMT_VND_SHOW_TABLES) {
pRequest->type = TDMT_VND_SHOW_TABLES_FETCH; pRequest->type = TDMT_VND_SHOW_TABLES_FETCH;
SShowReqInfo* pShowReqInfo = &pRequest->body.showInfo; SShowReqInfo* pShowReqInfo = &pRequest->body.showInfo;
...@@ -772,6 +773,8 @@ void* doFetchRow(SRequestObj* pRequest) { ...@@ -772,6 +773,8 @@ void* doFetchRow(SRequestObj* pRequest) {
tsem_wait(&pRequest->body.rspSem); tsem_wait(&pRequest->body.rspSem);
pRequest->type = TDMT_VND_SHOW_TABLES_FETCH; pRequest->type = TDMT_VND_SHOW_TABLES_FETCH;
} else if (pRequest->type == TDMT_MND_SHOW_RETRIEVE && pResultInfo->pData != NULL) {
return NULL;
} }
SMsgSendInfo* body = buildMsgInfoImpl(pRequest); SMsgSendInfo* body = buildMsgInfoImpl(pRequest);
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include <taoserror.h> #include <taoserror.h>
#include <tglobal.h>
#include <iostream> #include <iostream>
#pragma GCC diagnostic ignored "-Wwrite-strings" #pragma GCC diagnostic ignored "-Wwrite-strings"
...@@ -46,17 +47,19 @@ int main(int argc, char** argv) { ...@@ -46,17 +47,19 @@ int main(int argc, char** argv) {
return RUN_ALL_TESTS(); return RUN_ALL_TESTS();
} }
TEST(testCase, driverInit_Test) { taos_init(); } TEST(testCase, driverInit_Test) {
taosInitGlobalCfg();
TEST(testCase, connect_Test) { // taos_init();
TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0);
if (pConn == NULL) {
printf("failed to connect to server, reason:%s\n", taos_errstr(NULL));
}
sleep(3);
taos_close(pConn);
} }
//TEST(testCase, connect_Test) {
// TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0);
// if (pConn == NULL) {
// printf("failed to connect to server, reason:%s\n", taos_errstr(NULL));
// }
// taos_close(pConn);
//}
//
//TEST(testCase, create_user_Test) { //TEST(testCase, create_user_Test) {
// TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0); // TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0);
// assert(pConn != NULL); // assert(pConn != NULL);
...@@ -149,27 +152,27 @@ TEST(testCase, connect_Test) { ...@@ -149,27 +152,27 @@ TEST(testCase, connect_Test) {
//} //}
// //
//TEST(testCase, create_db_Test) { //TEST(testCase, create_db_Test) {
//TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0); // TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0);
//assert(pConn != NULL); // assert(pConn != NULL);
//
//TAOS_RES* pRes = taos_query(pConn, "create database abc1 vgroups 2"); // TAOS_RES* pRes = taos_query(pConn, "create database abc1 vgroups 2");
//if (taos_errno(pRes) != 0) { // if (taos_errno(pRes) != 0) {
//printf("error in create db, reason:%s\n", taos_errstr(pRes)); // printf("error in create db, reason:%s\n", taos_errstr(pRes));
//} // }
//
//TAOS_FIELD* pFields = taos_fetch_fields(pRes); // TAOS_FIELD* pFields = taos_fetch_fields(pRes);
//ASSERT_TRUE(pFields == NULL); // ASSERT_TRUE(pFields == NULL);
//
//int32_t numOfFields = taos_num_fields(pRes); // int32_t numOfFields = taos_num_fields(pRes);
//ASSERT_EQ(numOfFields, 0); // ASSERT_EQ(numOfFields, 0);
//
//taos_free_result(pRes); // taos_free_result(pRes);
//
//pRes = taos_query(pConn, "create database abc1 vgroups 4"); // pRes = taos_query(pConn, "create database abc1 vgroups 4");
//if (taos_errno(pRes) != 0) { // if (taos_errno(pRes) != 0) {
//printf("error in create db, reason:%s\n", taos_errstr(pRes)); // printf("error in create db, reason:%s\n", taos_errstr(pRes));
//} // }
//taos_close(pConn); // taos_close(pConn);
//} //}
// //
//TEST(testCase, create_dnode_Test) { //TEST(testCase, create_dnode_Test) {
...@@ -254,7 +257,7 @@ TEST(testCase, connect_Test) { ...@@ -254,7 +257,7 @@ TEST(testCase, connect_Test) {
// taos_free_result(pRes); // taos_free_result(pRes);
// taos_close(pConn); // taos_close(pConn);
//} //}
//
//TEST(testCase, create_stable_Test) { //TEST(testCase, create_stable_Test) {
// TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0); // TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0);
// assert(pConn != NULL); // assert(pConn != NULL);
...@@ -275,17 +278,14 @@ TEST(testCase, connect_Test) { ...@@ -275,17 +278,14 @@ TEST(testCase, connect_Test) {
// //
// int32_t numOfFields = taos_num_fields(pRes); // int32_t numOfFields = taos_num_fields(pRes);
// ASSERT_EQ(numOfFields, 0); // ASSERT_EQ(numOfFields, 0);
//
// taos_free_result(pRes); // taos_free_result(pRes);
// taos_close(pConn);
//}
// //
// pRes = taos_query(pConn, "create stable if not exists abc1.`123_$^)` (ts timestamp, `abc` int) tags(a int)"); // pRes = taos_query(pConn, "create stable if not exists abc1.`123_$^)` (ts timestamp, `abc` int) tags(a int)");
// if (taos_errno(pRes) != 0) { // if (taos_errno(pRes) != 0) {
// printf("failed to create super table 123_$^), reason:%s\n", taos_errstr(pRes)); // printf("failed to create super table 123_$^), reason:%s\n", taos_errstr(pRes));
// } // }
// //
// TAOS_RES* pRes = taos_query(pConn, "use abc1"); // pRes = taos_query(pConn, "use abc1");
// taos_free_result(pRes); // taos_free_result(pRes);
// pRes = taos_query(pConn, "drop stable `123_$^)`"); // pRes = taos_query(pConn, "drop stable `123_$^)`");
// if (taos_errno(pRes) != 0) { // if (taos_errno(pRes) != 0) {
...@@ -294,7 +294,7 @@ TEST(testCase, connect_Test) { ...@@ -294,7 +294,7 @@ TEST(testCase, connect_Test) {
// //
// taos_close(pConn); // taos_close(pConn);
//} //}
//
//TEST(testCase, create_table_Test) { //TEST(testCase, create_table_Test) {
// TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0); // TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0);
// assert(pConn != NULL); // assert(pConn != NULL);
...@@ -313,7 +313,7 @@ TEST(testCase, connect_Test) { ...@@ -313,7 +313,7 @@ TEST(testCase, connect_Test) {
// taos_free_result(pRes); // taos_free_result(pRes);
// taos_close(pConn); // taos_close(pConn);
//} //}
//
//TEST(testCase, create_ctable_Test) { //TEST(testCase, create_ctable_Test) {
// TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0); // TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0);
// assert(pConn != NULL); // assert(pConn != NULL);
...@@ -324,6 +324,12 @@ TEST(testCase, connect_Test) { ...@@ -324,6 +324,12 @@ TEST(testCase, connect_Test) {
// } // }
// taos_free_result(pRes); // taos_free_result(pRes);
// //
// pRes = taos_query(pConn, "create stable if not exists st1 (ts timestamp, k int ) tags(a int)");
// if (taos_errno(pRes) != 0) {
// printf("failed to create stable, reason:%s\n", taos_errstr(pRes));
// }
// taos_free_result(pRes);
//
// pRes = taos_query(pConn, "create table tm0 using st1 tags(1)"); // pRes = taos_query(pConn, "create table tm0 using st1 tags(1)");
// if (taos_errno(pRes) != 0) { // if (taos_errno(pRes) != 0) {
// printf("failed to create child table tm0, reason:%s\n", taos_errstr(pRes)); // printf("failed to create child table tm0, reason:%s\n", taos_errstr(pRes));
...@@ -332,17 +338,11 @@ TEST(testCase, connect_Test) { ...@@ -332,17 +338,11 @@ TEST(testCase, connect_Test) {
// taos_free_result(pRes); // taos_free_result(pRes);
// taos_close(pConn); // taos_close(pConn);
//} //}
//
//TEST(testCase, show_stable_Test) { //TEST(testCase, show_stable_Test) {
// TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0); // TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0);
// assert(pConn != nullptr); // assert(pConn != nullptr);
// //
//// TAOS_RES* pRes = taos_query(pConn, "use abc1");
//// if (taos_errno(pRes) != 0) {
//// printf("failed to use db, reason:%s\n", taos_errstr(pRes));
//// }
//// taos_free_result(pRes);
//
// TAOS_RES* pRes = taos_query(pConn, "show abc1.stables"); // TAOS_RES* pRes = taos_query(pConn, "show abc1.stables");
// if (taos_errno(pRes) != 0) { // if (taos_errno(pRes) != 0) {
// printf("failed to show stables, reason:%s\n", taos_errstr(pRes)); // printf("failed to show stables, reason:%s\n", taos_errstr(pRes));
...@@ -456,24 +456,28 @@ TEST(testCase, connect_Test) { ...@@ -456,24 +456,28 @@ TEST(testCase, connect_Test) {
// TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0); // TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0);
// assert(pConn != NULL); // assert(pConn != NULL);
// //
// TAOS_RES* pRes = taos_query(pConn, "use abc1"); // TAOS_RES* pRes = taos_query(pConn, "show tables");
// taos_free_result(pRes); // if (taos_errno(pRes) != 0) {
// printf("failed to show tables, reason:%s\n", taos_errstr(pRes));
// taos_free_result(pRes);
// }
// //
// pRes = taos_query(pConn, "show tables"); // pRes = taos_query(pConn, "show abc1.tables");
// if (taos_errno(pRes) != 0) { // if (taos_errno(pRes) != 0) {
// printf("failed to show vgroups, reason:%s\n", taos_errstr(pRes)); // printf("failed to show tables, reason:%s\n", taos_errstr(pRes));
// taos_free_result(pRes); // taos_free_result(pRes);
// ASSERT_TRUE(false);
// } // }
// //
// TAOS_ROW pRow = NULL; // TAOS_ROW pRow = NULL;
// TAOS_FIELD* pFields = taos_fetch_fields(pRes); // TAOS_FIELD* pFields = taos_fetch_fields(pRes);
// int32_t numOfFields = taos_num_fields(pRes); // int32_t numOfFields = taos_num_fields(pRes);
// //
// int32_t count = 0;
// char str[512] = {0}; // char str[512] = {0};
//
// while ((pRow = taos_fetch_row(pRes)) != NULL) { // while ((pRow = taos_fetch_row(pRes)) != NULL) {
// int32_t code = taos_print_row(str, pRow, pFields, numOfFields); // int32_t code = taos_print_row(str, pRow, pFields, numOfFields);
// printf("%s\n", str); // printf("%d: %s\n", ++count, str);
// } // }
// //
// taos_free_result(pRes); // taos_free_result(pRes);
...@@ -521,30 +525,30 @@ TEST(testCase, connect_Test) { ...@@ -521,30 +525,30 @@ TEST(testCase, connect_Test) {
// taosHashCleanup(phash); // taosHashCleanup(phash);
//} //}
// //
TEST(testCase, create_topic_Test) { //TEST(testCase, create_topic_Test) {
TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0); // TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0);
assert(pConn != NULL); // assert(pConn != NULL);
//
TAOS_RES* pRes = taos_query(pConn, "use abc1"); // TAOS_RES* pRes = taos_query(pConn, "use abc1");
if (taos_errno(pRes) != 0) { // if (taos_errno(pRes) != 0) {
printf("error in use db, reason:%s\n", taos_errstr(pRes)); // printf("error in use db, reason:%s\n", taos_errstr(pRes));
} // }
taos_free_result(pRes); // taos_free_result(pRes);
//
TAOS_FIELD* pFields = taos_fetch_fields(pRes); // TAOS_FIELD* pFields = taos_fetch_fields(pRes);
ASSERT_TRUE(pFields == nullptr); // ASSERT_TRUE(pFields == nullptr);
//
int32_t numOfFields = taos_num_fields(pRes); // int32_t numOfFields = taos_num_fields(pRes);
ASSERT_EQ(numOfFields, 0); // ASSERT_EQ(numOfFields, 0);
//
taos_free_result(pRes); // taos_free_result(pRes);
//
char* sql = "select * from tu"; // char* sql = "select * from tu";
pRes = taos_create_topic(pConn, "test_topic_1", sql, strlen(sql)); // pRes = taos_create_topic(pConn, "test_topic_1", sql, strlen(sql));
taos_free_result(pRes); // taos_free_result(pRes);
taos_close(pConn); // taos_close(pConn);
} //}
//
//TEST(testCase, insert_test) { //TEST(testCase, insert_test) {
// TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0); // TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0);
// ASSERT_NE(pConn, nullptr); // ASSERT_NE(pConn, nullptr);
...@@ -562,7 +566,7 @@ TEST(testCase, create_topic_Test) { ...@@ -562,7 +566,7 @@ TEST(testCase, create_topic_Test) {
// taos_free_result(pRes); // taos_free_result(pRes);
// taos_close(pConn); // taos_close(pConn);
//} //}
//
//TEST(testCase, projection_query_tables) { //TEST(testCase, projection_query_tables) {
// TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0); // TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0);
// ASSERT_NE(pConn, nullptr); // ASSERT_NE(pConn, nullptr);
...@@ -613,7 +617,7 @@ TEST(testCase, create_topic_Test) { ...@@ -613,7 +617,7 @@ TEST(testCase, create_topic_Test) {
// taos_free_result(pRes); // taos_free_result(pRes);
// taos_close(pConn); // taos_close(pConn);
//} //}
//
//TEST(testCase, projection_query_stables) { //TEST(testCase, projection_query_stables) {
// TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0); // TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0);
// ASSERT_NE(pConn, nullptr); // ASSERT_NE(pConn, nullptr);
...@@ -641,3 +645,31 @@ TEST(testCase, create_topic_Test) { ...@@ -641,3 +645,31 @@ TEST(testCase, create_topic_Test) {
// taos_free_result(pRes); // taos_free_result(pRes);
// taos_close(pConn); // taos_close(pConn);
//} //}
TEST(testCase, agg_query_tables) {
TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0);
ASSERT_NE(pConn, nullptr);
TAOS_RES* pRes = taos_query(pConn, "use abc1");
taos_free_result(pRes);
pRes = taos_query(pConn, "select count(*) from tu");
if (taos_errno(pRes) != 0) {
printf("failed to select from table, reason:%s\n", taos_errstr(pRes));
taos_free_result(pRes);
ASSERT_TRUE(false);
}
TAOS_ROW pRow = NULL;
TAOS_FIELD* pFields = taos_fetch_fields(pRes);
int32_t numOfFields = taos_num_fields(pRes);
char str[512] = {0};
while ((pRow = taos_fetch_row(pRes)) != NULL) {
int32_t code = taos_print_row(str, pRow, pFields, numOfFields);
printf("%s\n", str);
}
taos_free_result(pRes);
taos_close(pConn);
}
\ No newline at end of file
...@@ -100,7 +100,7 @@ static void dndInitMsgFp(STransMgmt *pMgmt) { ...@@ -100,7 +100,7 @@ static void dndInitMsgFp(STransMgmt *pMgmt) {
pMgmt->msgFp[TMSG_INDEX(TDMT_MND_VGROUP_LIST)] = dndProcessMnodeReadMsg; pMgmt->msgFp[TMSG_INDEX(TDMT_MND_VGROUP_LIST)] = dndProcessMnodeReadMsg;
pMgmt->msgFp[TMSG_INDEX(TDMT_MND_KILL_QUERY)] = dndProcessMnodeWriteMsg; pMgmt->msgFp[TMSG_INDEX(TDMT_MND_KILL_QUERY)] = dndProcessMnodeWriteMsg;
pMgmt->msgFp[TMSG_INDEX(TDMT_MND_KILL_CONN)] = dndProcessMnodeWriteMsg; pMgmt->msgFp[TMSG_INDEX(TDMT_MND_KILL_CONN)] = dndProcessMnodeWriteMsg;
pMgmt->msgFp[TMSG_INDEX(TDMT_MND_HEARTBEAT)] = dndProcessMnodeReadMsg; pMgmt->msgFp[TMSG_INDEX(TDMT_MND_HEARTBEAT)] = dndProcessMnodeWriteMsg;
pMgmt->msgFp[TMSG_INDEX(TDMT_MND_SHOW)] = dndProcessMnodeReadMsg; pMgmt->msgFp[TMSG_INDEX(TDMT_MND_SHOW)] = dndProcessMnodeReadMsg;
pMgmt->msgFp[TMSG_INDEX(TDMT_MND_SHOW_RETRIEVE)] = dndProcessMnodeReadMsg; pMgmt->msgFp[TMSG_INDEX(TDMT_MND_SHOW_RETRIEVE)] = dndProcessMnodeReadMsg;
pMgmt->msgFp[TMSG_INDEX(TDMT_MND_STATUS)] = dndProcessMnodeReadMsg; pMgmt->msgFp[TMSG_INDEX(TDMT_MND_STATUS)] = dndProcessMnodeReadMsg;
......
...@@ -230,7 +230,7 @@ typedef struct { ...@@ -230,7 +230,7 @@ typedef struct {
char acct[TSDB_USER_LEN]; char acct[TSDB_USER_LEN];
int64_t createdTime; int64_t createdTime;
int64_t updateTime; int64_t updateTime;
int64_t uid; uint64_t uid;
int32_t cfgVersion; int32_t cfgVersion;
int32_t vgVersion; int32_t vgVersion;
int8_t hashMethod; // default is 1 int8_t hashMethod; // default is 1
...@@ -354,6 +354,7 @@ typedef struct SMqSubscribeObj { ...@@ -354,6 +354,7 @@ typedef struct SMqSubscribeObj {
char key[TSDB_SUBSCRIBE_KEY_LEN]; char key[TSDB_SUBSCRIBE_KEY_LEN];
int32_t epoch; int32_t epoch;
//TODO: replace with priority queue //TODO: replace with priority queue
int32_t nextConsumerIdx;
SArray* availConsumer; // SArray<int64_t> (consumerId) SArray* availConsumer; // SArray<int64_t> (consumerId)
SArray* assigned; // SArray<SMqConsumerEp> SArray* assigned; // SArray<SMqConsumerEp>
SArray* unassignedConsumer; // SArray<SMqConsumerEp> SArray* unassignedConsumer; // SArray<SMqConsumerEp>
......
...@@ -80,6 +80,7 @@ typedef struct SMnode { ...@@ -80,6 +80,7 @@ typedef struct SMnode {
SReplica replicas[TSDB_MAX_REPLICA]; SReplica replicas[TSDB_MAX_REPLICA];
tmr_h timer; tmr_h timer;
tmr_h transTimer; tmr_h transTimer;
tmr_h mqTimer;
char *path; char *path;
SMnodeCfg cfg; SMnodeCfg cfg;
int64_t checkTime; int64_t checkTime;
......
...@@ -839,14 +839,12 @@ static int32_t mndRetrieveStb(SMnodeMsg *pReq, SShowObj *pShow, char *data, int3 ...@@ -839,14 +839,12 @@ static int32_t mndRetrieveStb(SMnodeMsg *pReq, SShowObj *pShow, char *data, int3
SStbObj *pStb = NULL; SStbObj *pStb = NULL;
int32_t cols = 0; int32_t cols = 0;
char *pWrite; char *pWrite;
char prefix[64] = {0}; char prefix[TSDB_DB_FNAME_LEN] = {0};
SDbObj *pDb = mndAcquireDb(pMnode, pShow->db); SDbObj *pDb = mndAcquireDb(pMnode, pShow->db);
if (pDb == NULL) { if (pDb == NULL) return 0;
return TSDB_CODE_MND_INVALID_DB;
}
tstrncpy(prefix, pShow->db, 64); tstrncpy(prefix, pShow->db, TSDB_DB_FNAME_LEN);
strcat(prefix, TS_PATH_DELIMITER); strcat(prefix, TS_PATH_DELIMITER);
int32_t prefixLen = (int32_t)strlen(prefix); int32_t prefixLen = (int32_t)strlen(prefix);
...@@ -855,6 +853,10 @@ static int32_t mndRetrieveStb(SMnodeMsg *pReq, SShowObj *pShow, char *data, int3 ...@@ -855,6 +853,10 @@ static int32_t mndRetrieveStb(SMnodeMsg *pReq, SShowObj *pShow, char *data, int3
if (pShow->pIter == NULL) break; if (pShow->pIter == NULL) break;
if (pStb->dbUid != pDb->uid) { if (pStb->dbUid != pDb->uid) {
if (strncmp(pStb->db, pDb->name, tListLen(pStb->db)) == 0) {
mError("Inconsistent table data, name:%s, db:%s, dbUid:%"PRIu64, pStb->name, pDb->name, pDb->uid);
}
sdbRelease(pSdb, pStb); sdbRelease(pSdb, pStb);
continue; continue;
} }
......
...@@ -13,13 +13,13 @@ ...@@ -13,13 +13,13 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "mndSubscribe.h"
#include "mndConsumer.h" #include "mndConsumer.h"
#include "mndDb.h" #include "mndDb.h"
#include "mndDnode.h" #include "mndDnode.h"
#include "mndMnode.h" #include "mndMnode.h"
#include "mndShow.h" #include "mndShow.h"
#include "mndStb.h" #include "mndStb.h"
#include "mndSubscribe.h"
#include "mndTopic.h" #include "mndTopic.h"
#include "mndTrans.h" #include "mndTrans.h"
#include "mndUser.h" #include "mndUser.h"
...@@ -40,6 +40,10 @@ static int32_t mndProcessSubscribeReq(SMnodeMsg *pMsg); ...@@ -40,6 +40,10 @@ static int32_t mndProcessSubscribeReq(SMnodeMsg *pMsg);
static int32_t mndProcessSubscribeRsp(SMnodeMsg *pMsg); static int32_t mndProcessSubscribeRsp(SMnodeMsg *pMsg);
static int32_t mndProcessSubscribeInternalReq(SMnodeMsg *pMsg); static int32_t mndProcessSubscribeInternalReq(SMnodeMsg *pMsg);
static int32_t mndProcessSubscribeInternalRsp(SMnodeMsg *pMsg); static int32_t mndProcessSubscribeInternalRsp(SMnodeMsg *pMsg);
static int32_t mndProcessMqTimerMsg(SMnodeMsg *pMsg);
static int mndBuildMqSetConsumerVgReq(SMnode *pMnode, STrans *pTrans, SMqConsumerObj *pConsumer,
SMqConsumerTopic *pConsumerTopic, SMqTopicObj *pTopic);
int32_t mndInitSubscribe(SMnode *pMnode) { int32_t mndInitSubscribe(SMnode *pMnode) {
SSdbTable table = {.sdbType = SDB_SUBSCRIBE, SSdbTable table = {.sdbType = SDB_SUBSCRIBE,
...@@ -51,12 +55,91 @@ int32_t mndInitSubscribe(SMnode *pMnode) { ...@@ -51,12 +55,91 @@ int32_t mndInitSubscribe(SMnode *pMnode) {
.deleteFp = (SdbDeleteFp)mndSubActionDelete}; .deleteFp = (SdbDeleteFp)mndSubActionDelete};
mndSetMsgHandle(pMnode, TDMT_MND_SUBSCRIBE, mndProcessSubscribeReq); mndSetMsgHandle(pMnode, TDMT_MND_SUBSCRIBE, mndProcessSubscribeReq);
/*mndSetMsgHandle(pMnode, TDMT_MND_SUBSCRIBE_RSP, mndProcessSubscribeRsp);*/
/*mndSetMsgHandle(pMnode, TDMT_VND_SUBSCRIBE, mndProcessSubscribeInternalReq);*/
mndSetMsgHandle(pMnode, TDMT_VND_SUBSCRIBE_RSP, mndProcessSubscribeInternalRsp); mndSetMsgHandle(pMnode, TDMT_VND_SUBSCRIBE_RSP, mndProcessSubscribeInternalRsp);
mndSetMsgHandle(pMnode, TDMT_MND_MQ_TIMER, mndProcessMqTimerMsg);
return sdbSetTable(pMnode->pSdb, table); return sdbSetTable(pMnode->pSdb, table);
} }
static int32_t mndSplitSubscribeKey(char *key, char **topic, char **cgroup) {
int i = 0;
while (key[i] != ':') {
i++;
}
key[i] = 0;
*topic = strdup(key);
key[i] = ':';
*cgroup = strdup(&key[i + 1]);
return 0;
}
static int32_t mndProcessMqTimerMsg(SMnodeMsg *pMsg) {
SMnode *pMnode = pMsg->pMnode;
SSdb *pSdb = pMnode->pSdb;
SMqSubscribeObj *pSub = NULL;
void *pIter = sdbFetch(pSdb, SDB_SUBSCRIBE, NULL, (void **)&pSub);
int sz;
while (pIter != NULL) {
if ((sz = taosArrayGetSize(pSub->unassignedVg)) > 0) {
char *topic = NULL;
char *cgroup = NULL;
mndSplitSubscribeKey(pSub->key, &topic, &cgroup);
SMqTopicObj *pTopic = mndAcquireTopic(pMnode, topic);
// create trans
STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, &pMsg->rpcMsg);
for (int i = 0; i < sz; i++) {
int64_t consumerId = *(int64_t *)taosArrayGet(pSub->availConsumer, pSub->nextConsumerIdx);
SMqConsumerEp *pCEp = taosArrayPop(pSub->unassignedVg);
pCEp->consumerId = consumerId;
taosArrayPush(pSub->assigned, pCEp);
pSub->nextConsumerIdx = (pSub->nextConsumerIdx + 1) % taosArrayGetSize(pSub->availConsumer);
// build msg
SMqSetCVgReq req = {
.vgId = pCEp->vgId,
.consumerId = consumerId,
};
strcpy(req.cgroup, cgroup);
strcpy(req.topicName, topic);
strcpy(req.sql, pTopic->sql);
strcpy(req.logicalPlan, pTopic->logicalPlan);
strcpy(req.physicalPlan, pTopic->physicalPlan);
int32_t tlen = tEncodeSMqSetCVgReq(NULL, &req);
void *reqStr = malloc(tlen);
if (reqStr == NULL) {
terrno = TSDB_CODE_OUT_OF_MEMORY;
return -1;
}
void *abuf = reqStr;
tEncodeSMqSetCVgReq(abuf, &req);
// persist msg
STransAction action = {0};
action.epSet = pCEp->epset;
action.pCont = reqStr;
action.contLen = tlen;
action.msgType = TDMT_VND_MQ_SET_CONN;
mndTransAppendRedoAction(pTrans, &action);
// persist raw
SSdbRaw *pRaw = mndSubActionEncode(pSub);
mndTransAppendRedolog(pTrans, pRaw);
tfree(topic);
tfree(cgroup);
}
if (mndTransPrepare(pMnode, pTrans) != 0) {
mError("trans:%d, failed to prepare since %s", pTrans->id, terrstr());
}
mndReleaseTopic(pMnode, pTopic);
mndTransDrop(pTrans);
}
pIter = sdbFetch(pSdb, SDB_SUBSCRIBE, NULL, (void **)&pSub);
}
return 0;
}
static int mndInitUnassignedVg(SMnode *pMnode, SMqTopicObj *pTopic, SArray *unassignedVg) { static int mndInitUnassignedVg(SMnode *pMnode, SMqTopicObj *pTopic, SArray *unassignedVg) {
SMqConsumerEp CEp; SMqConsumerEp CEp;
CEp.lastConsumerHbTs = CEp.lastVgHbTs = -1; CEp.lastConsumerHbTs = CEp.lastVgHbTs = -1;
...@@ -76,7 +159,7 @@ static int mndInitUnassignedVg(SMnode *pMnode, SMqTopicObj *pTopic, SArray *unas ...@@ -76,7 +159,7 @@ static int mndInitUnassignedVg(SMnode *pMnode, SMqTopicObj *pTopic, SArray *unas
} }
static int mndBuildMqSetConsumerVgReq(SMnode *pMnode, STrans *pTrans, SMqConsumerObj *pConsumer, static int mndBuildMqSetConsumerVgReq(SMnode *pMnode, STrans *pTrans, SMqConsumerObj *pConsumer,
SMqConsumerTopic *pConsumerTopic) { SMqConsumerTopic *pConsumerTopic, SMqTopicObj *pTopic) {
int32_t sz = taosArrayGetSize(pConsumerTopic->pVgInfo); int32_t sz = taosArrayGetSize(pConsumerTopic->pVgInfo);
for (int32_t i = 0; i < sz; i++) { for (int32_t i = 0; i < sz; i++) {
int32_t vgId = *(int32_t *)taosArrayGet(pConsumerTopic->pVgInfo, i); int32_t vgId = *(int32_t *)taosArrayGet(pConsumerTopic->pVgInfo, i);
...@@ -85,8 +168,11 @@ static int mndBuildMqSetConsumerVgReq(SMnode *pMnode, STrans *pTrans, SMqConsume ...@@ -85,8 +168,11 @@ static int mndBuildMqSetConsumerVgReq(SMnode *pMnode, STrans *pTrans, SMqConsume
.vgId = vgId, .vgId = vgId,
.consumerId = pConsumer->consumerId, .consumerId = pConsumer->consumerId,
}; };
strcpy(req.cGroup, pConsumer->cgroup); strcpy(req.cgroup, pConsumer->cgroup);
strcpy(req.topicName, pConsumerTopic->name); strcpy(req.topicName, pTopic->name);
strcpy(req.sql, pTopic->sql);
strcpy(req.logicalPlan, pTopic->logicalPlan);
strcpy(req.physicalPlan, pTopic->physicalPlan);
int32_t tlen = tEncodeSMqSetCVgReq(NULL, &req); int32_t tlen = tEncodeSMqSetCVgReq(NULL, &req);
void *reqStr = malloc(tlen); void *reqStr = malloc(tlen);
if (reqStr == NULL) { if (reqStr == NULL) {
...@@ -94,7 +180,7 @@ static int mndBuildMqSetConsumerVgReq(SMnode *pMnode, STrans *pTrans, SMqConsume ...@@ -94,7 +180,7 @@ static int mndBuildMqSetConsumerVgReq(SMnode *pMnode, STrans *pTrans, SMqConsume
return -1; return -1;
} }
void *abuf = reqStr; void *abuf = reqStr;
tEncodeSMqSetCVgReq(abuf, &req); tEncodeSMqSetCVgReq(&abuf, &req);
STransAction action = {0}; STransAction action = {0};
action.epSet = mndGetVgroupEpset(pMnode, pVgObj); action.epSet = mndGetVgroupEpset(pMnode, pVgObj);
...@@ -278,20 +364,20 @@ static int32_t mndProcessSubscribeReq(SMnodeMsg *pMsg) { ...@@ -278,20 +364,20 @@ static int32_t mndProcessSubscribeReq(SMnodeMsg *pMsg) {
int i = 0, j = 0; int i = 0, j = 0;
while (i < newTopicNum || j < oldTopicNum) { while (i < newTopicNum || j < oldTopicNum) {
char* newTopicName = NULL; char *newTopicName = NULL;
char* oldTopicName = NULL; char *oldTopicName = NULL;
if (i >= newTopicNum) { if (i >= newTopicNum) {
// encode unset topic msg to all vnodes related to that topic // encode unset topic msg to all vnodes related to that topic
oldTopicName = ((SMqConsumerTopic*)taosArrayGet(oldSub, j))->name; oldTopicName = ((SMqConsumerTopic *)taosArrayGet(oldSub, j))->name;
j++; j++;
} else if (j >= oldTopicNum) { } else if (j >= oldTopicNum) {
newTopicName = taosArrayGet(newSub, i); newTopicName = taosArrayGet(newSub, i);
i++; i++;
} else { } else {
newTopicName = taosArrayGet(newSub, i); newTopicName = taosArrayGet(newSub, i);
oldTopicName = ((SMqConsumerTopic*)taosArrayGet(oldSub, j))->name; oldTopicName = ((SMqConsumerTopic *)taosArrayGet(oldSub, j))->name;
int comp = compareLenPrefixedStr(newTopicName, oldTopicName); int comp = compareLenPrefixedStr(newTopicName, oldTopicName);
if (comp == 0) { if (comp == 0) {
// do nothing // do nothing
oldTopicName = newTopicName = NULL; oldTopicName = newTopicName = NULL;
...@@ -374,19 +460,25 @@ static int32_t mndProcessSubscribeReq(SMnodeMsg *pMsg) { ...@@ -374,19 +460,25 @@ static int32_t mndProcessSubscribeReq(SMnodeMsg *pMsg) {
// set unassigned vg // set unassigned vg
mndInitUnassignedVg(pMnode, pTopic, pSub->unassignedVg); mndInitUnassignedVg(pMnode, pTopic, pSub->unassignedVg);
} }
taosArrayPush(pSub->availConsumer, &consumerId);
// TODO: no need
SMqConsumerTopic *pConsumerTopic = tNewConsumerTopic(consumerId, pTopic, pSub); SMqConsumerTopic *pConsumerTopic = tNewConsumerTopic(consumerId, pTopic, pSub);
taosArrayPush(pConsumer->topics, pConsumerTopic); taosArrayPush(pConsumer->topics, pConsumerTopic);
if (taosArrayGetSize(pConsumerTopic->pVgInfo) > 0) { if (taosArrayGetSize(pConsumerTopic->pVgInfo) > 0) {
int32_t vgId = *(int32_t *)taosArrayGetLast(pConsumerTopic->pVgInfo); int32_t vgId = *(int32_t *)taosArrayGetLast(pConsumerTopic->pVgInfo);
// send setmsg to vnode // send setmsg to vnode
if (mndBuildMqSetConsumerVgReq(pMnode, pTrans, pConsumer, pConsumerTopic) < 0) { if (mndBuildMqSetConsumerVgReq(pMnode, pTrans, pConsumer, pConsumerTopic, pTopic) < 0) {
// TODO // TODO
return -1; return -1;
} }
} }
taosArrayDestroy(pConsumerTopic->pVgInfo); taosArrayDestroy(pConsumerTopic->pVgInfo);
free(pConsumerTopic); free(pConsumerTopic);
SSdbRaw *pRaw = mndSubActionEncode(pSub);
/*sdbSetRawStatus(pRaw, SDB_STATUS_READY);*/
mndTransAppendRedolog(pTrans, pRaw);
#if 0 #if 0
SMqCGroup *pGroup = taosHashGet(pTopic->cgroups, consumerGroup, cgroupLen); SMqCGroup *pGroup = taosHashGet(pTopic->cgroups, consumerGroup, cgroupLen);
if (pGroup == NULL) { if (pGroup == NULL) {
...@@ -448,7 +540,10 @@ static int32_t mndProcessSubscribeReq(SMnodeMsg *pMsg) { ...@@ -448,7 +540,10 @@ static int32_t mndProcessSubscribeReq(SMnodeMsg *pMsg) {
return 0; return 0;
} }
static int32_t mndProcessSubscribeInternalRsp(SMnodeMsg *pMsg) { return 0; } static int32_t mndProcessSubscribeInternalRsp(SMnodeMsg *pRsp) {
mndTransProcessRsp(pRsp);
return 0;
}
static int32_t mndProcessConsumerMetaMsg(SMnodeMsg *pMsg) { static int32_t mndProcessConsumerMetaMsg(SMnodeMsg *pMsg) {
SMnode *pMnode = pMsg->pMnode; SMnode *pMnode = pMsg->pMnode;
......
...@@ -92,6 +92,10 @@ static int32_t mndRestoreWal(SMnode *pMnode) { ...@@ -92,6 +92,10 @@ static int32_t mndRestoreWal(SMnode *pMnode) {
goto WAL_RESTORE_OVER; goto WAL_RESTORE_OVER;
} }
if (walCommit(pWal, sdbVer) != 0) {
goto WAL_RESTORE_OVER;
}
if (walBeginSnapshot(pWal, sdbVer) < 0) { if (walBeginSnapshot(pWal, sdbVer) < 0) {
goto WAL_RESTORE_OVER; goto WAL_RESTORE_OVER;
} }
...@@ -99,7 +103,6 @@ static int32_t mndRestoreWal(SMnode *pMnode) { ...@@ -99,7 +103,6 @@ static int32_t mndRestoreWal(SMnode *pMnode) {
if (walEndSnapshot(pWal) < 0) { if (walEndSnapshot(pWal) < 0) {
goto WAL_RESTORE_OVER; goto WAL_RESTORE_OVER;
} }
} }
code = 0; code = 0;
......
...@@ -540,35 +540,41 @@ static int32_t mndRetrieveVgroups(SMnodeMsg *pReq, SShowObj *pShow, char *data, ...@@ -540,35 +540,41 @@ static int32_t mndRetrieveVgroups(SMnodeMsg *pReq, SShowObj *pShow, char *data,
int32_t cols = 0; int32_t cols = 0;
char *pWrite; char *pWrite;
SDbObj *pDb = mndAcquireDb(pMnode, pShow->db);
if (pDb == NULL) return 0;
while (numOfRows < rows) { while (numOfRows < rows) {
pShow->pIter = sdbFetch(pSdb, SDB_VGROUP, pShow->pIter, (void **)&pVgroup); pShow->pIter = sdbFetch(pSdb, SDB_VGROUP, pShow->pIter, (void **)&pVgroup);
if (pShow->pIter == NULL) break; if (pShow->pIter == NULL) break;
cols = 0; if (pVgroup->dbUid == pDb->uid) {
cols = 0;
pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows;
*(int32_t *)pWrite = pVgroup->vgId;
cols++;
pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows;
*(int32_t *)pWrite = pVgroup->numOfTables;
cols++;
for (int32_t i = 0; i < pShow->replica; ++i) {
pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows;
*(int16_t *)pWrite = pVgroup->vnodeGid[i].dnodeId; *(int32_t *)pWrite = pVgroup->vgId;
cols++; cols++;
const char *role = mndGetRoleStr(pVgroup->vnodeGid[i].role);
pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows;
STR_WITH_MAXSIZE_TO_VARSTR(pWrite, role, pShow->bytes[cols]); *(int32_t *)pWrite = pVgroup->numOfTables;
cols++; cols++;
for (int32_t i = 0; i < pShow->replica; ++i) {
pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows;
*(int16_t *)pWrite = pVgroup->vnodeGid[i].dnodeId;
cols++;
const char *role = mndGetRoleStr(pVgroup->vnodeGid[i].role);
pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows;
STR_WITH_MAXSIZE_TO_VARSTR(pWrite, role, pShow->bytes[cols]);
cols++;
}
numOfRows++;
} }
sdbRelease(pSdb, pVgroup); sdbRelease(pSdb, pVgroup);
numOfRows++;
} }
mndReleaseDb(pMnode, pDb);
mndVacuumResult(data, pShow->numOfColumns, numOfRows, rows, pShow); mndVacuumResult(data, pShow->numOfColumns, numOfRows, rows, pShow);
pShow->numOfReads += numOfRows; pShow->numOfReads += numOfRows;
return numOfRows; return numOfRows;
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include "mndAuth.h" #include "mndAuth.h"
#include "mndBnode.h" #include "mndBnode.h"
#include "mndCluster.h" #include "mndCluster.h"
#include "mndConsumer.h"
#include "mndDb.h" #include "mndDb.h"
#include "mndDnode.h" #include "mndDnode.h"
#include "mndFunc.h" #include "mndFunc.h"
...@@ -27,6 +28,7 @@ ...@@ -27,6 +28,7 @@
#include "mndShow.h" #include "mndShow.h"
#include "mndSnode.h" #include "mndSnode.h"
#include "mndStb.h" #include "mndStb.h"
#include "mndSubscribe.h"
#include "mndSync.h" #include "mndSync.h"
#include "mndTelem.h" #include "mndTelem.h"
#include "mndTopic.h" #include "mndTopic.h"
...@@ -69,15 +71,15 @@ static void mndTransReExecute(void *param, void *tmrId) { ...@@ -69,15 +71,15 @@ static void mndTransReExecute(void *param, void *tmrId) {
taosTmrReset(mndTransReExecute, 3000, pMnode, pMnode->timer, &pMnode->transTimer); taosTmrReset(mndTransReExecute, 3000, pMnode, pMnode->timer, &pMnode->transTimer);
} }
static void mndCalMqRebalance(void* param, void* tmrId) { static void mndCalMqRebalance(void *param, void *tmrId) {
SMnode* pMnode = param; SMnode *pMnode = param;
if (mndIsMaster(pMnode)) { if (mndIsMaster(pMnode)) {
// iterate cgroup, cal rebalance SMqTmrMsg *pMsg = rpcMallocCont(sizeof(SMqTmrMsg));
// sync with raft SRpcMsg rpcMsg = {.msgType = TDMT_MND_MQ_TIMER, .pCont = pMsg, .contLen = sizeof(SMqTmrMsg)};
// write sdb pMnode->putReqToMWriteQFp(pMnode->pDnode, &rpcMsg);
} }
taosTmrReset(mndCalMqRebalance, 3000, pMnode, pMnode->timer, &pMnode->transTimer); taosTmrReset(mndCalMqRebalance, 3000, pMnode, pMnode->timer, &pMnode->mqTimer);
} }
static int32_t mndInitTimer(SMnode *pMnode) { static int32_t mndInitTimer(SMnode *pMnode) {
...@@ -95,6 +97,11 @@ static int32_t mndInitTimer(SMnode *pMnode) { ...@@ -95,6 +97,11 @@ static int32_t mndInitTimer(SMnode *pMnode) {
return -1; return -1;
} }
if (taosTmrReset(mndCalMqRebalance, 3000, pMnode, pMnode->timer, &pMnode->mqTimer)) {
terrno = TSDB_CODE_OUT_OF_MEMORY;
return -1;
}
return 0; return 0;
} }
...@@ -102,6 +109,8 @@ static void mndCleanupTimer(SMnode *pMnode) { ...@@ -102,6 +109,8 @@ static void mndCleanupTimer(SMnode *pMnode) {
if (pMnode->timer != NULL) { if (pMnode->timer != NULL) {
taosTmrStop(pMnode->transTimer); taosTmrStop(pMnode->transTimer);
pMnode->transTimer = NULL; pMnode->transTimer = NULL;
taosTmrStop(pMnode->mqTimer);
pMnode->mqTimer = NULL;
taosTmrCleanUp(pMnode->timer); taosTmrCleanUp(pMnode->timer);
pMnode->timer = NULL; pMnode->timer = NULL;
} }
...@@ -171,6 +180,8 @@ static int32_t mndInitSteps(SMnode *pMnode) { ...@@ -171,6 +180,8 @@ static int32_t mndInitSteps(SMnode *pMnode) {
if (mndAllocStep(pMnode, "mnode-auth", mndInitAuth, mndCleanupAuth) != 0) return -1; if (mndAllocStep(pMnode, "mnode-auth", mndInitAuth, mndCleanupAuth) != 0) return -1;
if (mndAllocStep(pMnode, "mnode-acct", mndInitAcct, mndCleanupAcct) != 0) return -1; if (mndAllocStep(pMnode, "mnode-acct", mndInitAcct, mndCleanupAcct) != 0) return -1;
if (mndAllocStep(pMnode, "mnode-topic", mndInitTopic, mndCleanupTopic) != 0) return -1; if (mndAllocStep(pMnode, "mnode-topic", mndInitTopic, mndCleanupTopic) != 0) return -1;
if (mndAllocStep(pMnode, "mnode-consumer", mndInitConsumer, mndCleanupConsumer) != 0) return -1;
if (mndAllocStep(pMnode, "mnode-subscribe", mndInitSubscribe, mndCleanupSubscribe) != 0) return -1;
if (mndAllocStep(pMnode, "mnode-vgroup", mndInitVgroup, mndCleanupVgroup) != 0) return -1; if (mndAllocStep(pMnode, "mnode-vgroup", mndInitVgroup, mndCleanupVgroup) != 0) return -1;
if (mndAllocStep(pMnode, "mnode-stb", mndInitStb, mndCleanupStb) != 0) return -1; if (mndAllocStep(pMnode, "mnode-stb", mndInitStb, mndCleanupStb) != 0) return -1;
if (mndAllocStep(pMnode, "mnode-db", mndInitDb, mndCleanupDb) != 0) return -1; if (mndAllocStep(pMnode, "mnode-db", mndInitDb, mndCleanupDb) != 0) return -1;
...@@ -377,7 +388,7 @@ SMnodeMsg *mndInitMsg(SMnode *pMnode, SRpcMsg *pRpcMsg) { ...@@ -377,7 +388,7 @@ SMnodeMsg *mndInitMsg(SMnode *pMnode, SRpcMsg *pRpcMsg) {
return NULL; return NULL;
} }
if (pRpcMsg->msgType != TDMT_MND_TRANS) { if (pRpcMsg->msgType != TDMT_MND_TRANS && pRpcMsg->msgType != TDMT_MND_MQ_TIMER) {
SRpcConnInfo connInfo = {0}; SRpcConnInfo connInfo = {0};
if ((pRpcMsg->msgType & 1U) && rpcGetConnInfo(pRpcMsg->handle, &connInfo) != 0) { if ((pRpcMsg->msgType & 1U) && rpcGetConnInfo(pRpcMsg->handle, &connInfo) != 0) {
taosFreeQitem(pMsg); taosFreeQitem(pMsg);
......
...@@ -25,6 +25,7 @@ target_link_libraries( ...@@ -25,6 +25,7 @@ target_link_libraries(
PUBLIC bdb PUBLIC bdb
PUBLIC tfs PUBLIC tfs
PUBLIC wal PUBLIC wal
PUBLIC scheduler
PUBLIC qworker PUBLIC qworker
) )
......
...@@ -18,14 +18,16 @@ ...@@ -18,14 +18,16 @@
#include "common.h" #include "common.h"
#include "mallocator.h" #include "mallocator.h"
#include "meta.h"
#include "os.h" #include "os.h"
#include "scheduler.h"
#include "taoserror.h" #include "taoserror.h"
#include "tmsg.h"
#include "tlist.h" #include "tlist.h"
#include "tmsg.h"
#include "trpc.h" #include "trpc.h"
#include "ttimer.h" #include "ttimer.h"
#include "tutil.h" #include "tutil.h"
#include "meta.h" #include "wal.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
...@@ -150,31 +152,52 @@ typedef struct STqListHandle { ...@@ -150,31 +152,52 @@ typedef struct STqListHandle {
} STqList; } STqList;
typedef struct STqGroup { typedef struct STqGroup {
int64_t clientId; int64_t clientId;
int64_t cgId; int64_t cgId;
void* ahandle; void* ahandle;
int32_t topicNum; int32_t topicNum;
STqList* head; STqList* head;
SList* topicList; // SList<STqTopic> SList* topicList; // SList<STqTopic>
STqRspHandle rspHandle; STqRspHandle rspHandle;
} STqGroup; } STqGroup;
typedef struct STqTaskItem {
int8_t status;
int64_t offset;
void* dst;
SSubQueryMsg* pMsg;
} STqTaskItem;
// new version
typedef struct STqBuffer {
int64_t firstOffset;
int64_t lastOffset;
STqTaskItem output[TQ_BUFFER_SIZE];
} STqBuffer;
typedef struct STqTopicHandle {
char topicName[TSDB_TOPIC_FNAME_LEN];
char cgroup[TSDB_TOPIC_FNAME_LEN];
char* sql;
char* logicalPlan;
char* physicalPlan;
int64_t committedOffset;
int64_t currentOffset;
STqBuffer buffer;
SWalReadHandle* pReadhandle;
} STqTopicHandle;
typedef struct STqConsumerHandle {
int64_t consumerId;
int64_t epoch;
SArray* topics; // SArray<STqClientTopic>
} STqConsumerHandle;
typedef struct STqQueryMsg { typedef struct STqQueryMsg {
STqMsgItem* item; STqMsgItem* item;
struct STqQueryMsg* next; struct STqQueryMsg* next;
} STqQueryMsg; } STqQueryMsg;
typedef struct STqLogHandle {
void* logHandle;
void* (*openLogReader)(void* logHandle);
void (*closeLogReader)(void* logReader);
int32_t (*logRead)(void* logReader, void** data, int64_t ver);
int64_t (*logGetFirstVer)(void* logHandle);
int64_t (*logGetSnapshotVer)(void* logHandle);
int64_t (*logGetLastVer)(void* logHandle);
} STqLogHandle;
typedef struct STqCfg { typedef struct STqCfg {
// TODO // TODO
} STqCfg; } STqCfg;
...@@ -253,7 +276,7 @@ typedef struct STqMetaStore { ...@@ -253,7 +276,7 @@ typedef struct STqMetaStore {
// a table head // a table head
STqMetaList* unpersistHead; STqMetaList* unpersistHead;
// topics that are not connectted // topics that are not connectted
STqMetaList* unconnectTopic; STqMetaList* unconnectTopic;
// TODO:temporaral use, to be replaced by unified tfile // TODO:temporaral use, to be replaced by unified tfile
int fileFd; int fileFd;
...@@ -272,9 +295,9 @@ typedef struct STQ { ...@@ -272,9 +295,9 @@ typedef struct STQ {
// the handle of meta kvstore // the handle of meta kvstore
char* path; char* path;
STqCfg* tqConfig; STqCfg* tqConfig;
STqLogHandle* tqLogHandle;
STqMemRef tqMemRef; STqMemRef tqMemRef;
STqMetaStore* tqMeta; STqMetaStore* tqMeta;
SWal* pWal;
} STQ; } STQ;
typedef struct STqMgmt { typedef struct STqMgmt {
...@@ -289,51 +312,44 @@ int tqInit(); ...@@ -289,51 +312,44 @@ int tqInit();
void tqCleanUp(); void tqCleanUp();
// open in each vnode // open in each vnode
STQ* tqOpen(const char* path, STqCfg* tqConfig, STqLogHandle* tqLogHandle, SMemAllocatorFactory* allocFac); STQ* tqOpen(const char* path, SWal* pWal, STqCfg* tqConfig, SMemAllocatorFactory* allocFac);
void tqClose(STQ*); void tqClose(STQ*);
// void* will be replace by a msg type // void* will be replace by a msg type
int tqPushMsg(STQ*, void* msg, int64_t version); int tqPushMsg(STQ*, void* msg, int64_t version);
int tqCommit(STQ*); int tqCommit(STQ*);
int tqConsume(STQ*, SRpcMsg* pReq, SRpcMsg** pRsp);
#if 0
int tqConsume(STQ*, SRpcMsg* pReq, SRpcMsg** pRsp);
int tqSetCursor(STQ*, STqSetCurReq* pMsg); int tqSetCursor(STQ*, STqSetCurReq* pMsg);
int tqBufferSetOffset(STqTopic*, int64_t offset); int tqBufferSetOffset(STqTopic*, int64_t offset);
STqTopic* tqFindTopic(STqGroup*, int64_t topicId); STqTopic* tqFindTopic(STqGroup*, int64_t topicId);
STqGroup* tqGetGroup(STQ*, int64_t clientId); STqGroup* tqGetGroup(STQ*, int64_t clientId);
STqGroup* tqOpenGroup(STQ*, int64_t topicId, int64_t cgId, int64_t cId); STqGroup* tqOpenGroup(STQ*, int64_t topicId, int64_t cgId, int64_t cId);
int tqCloseGroup(STQ*, int64_t topicId, int64_t cgId, int64_t cId); int tqCloseGroup(STQ*, int64_t topicId, int64_t cgId, int64_t cId);
int tqRegisterContext(STqGroup*, void* ahandle); int tqRegisterContext(STqGroup*, void* ahandle);
int tqSendLaunchQuery(STqMsgItem*, int64_t offset); int tqSendLaunchQuery(STqMsgItem*, int64_t offset);
#endif
int tqSerializeGroup(const STqGroup*, STqSerializedHead**); int32_t tqProcessConsumeReq(STQ* pTq, SRpcMsg* pMsg, SRpcMsg** ppRsp);
int32_t tqProcessSetConnReq(STQ* pTq, SMqSetCVgReq* pReq);
const void* tqDeserializeGroup(const STqSerializedHead*, STqGroup**);
static int tqQueryExecuting(int32_t status) { return status; }
typedef struct STqReadHandle { typedef struct STqReadHandle {
int64_t ver; int64_t ver;
SSubmitMsg* pMsg; SSubmitMsg* pMsg;
SSubmitBlk* pBlock; SSubmitBlk* pBlock;
SSubmitMsgIter msgIter; SSubmitMsgIter msgIter;
SSubmitBlkIter blkIter; SSubmitBlkIter blkIter;
SMeta* pMeta; SMeta* pMeta;
SArray* pColumnIdList;
} STqReadHandle; } STqReadHandle;
typedef struct SSubmitBlkScanInfo { STqReadHandle* tqInitSubmitMsgScanner(SMeta* pMeta, SArray* pColumnIdList);
void tqReadHandleSetMsg(STqReadHandle* pHandle, SSubmitMsg* pMsg, int64_t ver);
} SSubmitBlkScanInfo; bool tqNextDataBlock(STqReadHandle* pHandle);
int tqRetrieveDataBlockInfo(STqReadHandle* pHandle, SDataBlockInfo* pBlockInfo);
STqReadHandle* tqInitSubmitMsgScanner(SMeta* pMeta, SSubmitMsg *pMsg); // return SArray<SColumnInfoData>
bool tqNextDataBlock(STqReadHandle* pHandle); SArray* tqRetrieveDataBlock(STqReadHandle* pHandle);
int tqRetrieveDataBlockInfo(STqReadHandle* pHandle, SDataBlockInfo *pBlockInfo);
//return SArray<SColumnInfoData>
SArray *tqRetrieveDataBlock(STqReadHandle* pHandle, SArray* pColumnIdList);
//int tqLoadDataBlock(SExecTaskInfo* pTaskInfo, SSubmitBlkScanInfo* pSubmitBlkScanInfo, SSDataBlock* pBlock, uint32_t status);
#ifdef __cplusplus #ifdef __cplusplus
} }
......
...@@ -43,6 +43,9 @@ extern int32_t tqDebugFlag; ...@@ -43,6 +43,9 @@ extern int32_t tqDebugFlag;
// delete persistent storage for meta info // delete persistent storage for meta info
// int tqDropTCGroup(STQ*, const char* topic, int cgId); // int tqDropTCGroup(STQ*, const char* topic, int cgId);
int tqSerializeGroup(const STqGroup*, STqSerializedHead**);
const void* tqDeserializeGroup(const STqSerializedHead* pHead, STqGroup** ppGroup);
static int FORCE_INLINE tqQueryExecuting(int32_t status) { return status; }
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
......
...@@ -177,4 +177,4 @@ bool vmaIsFull(SVMemAllocator* pVMA); ...@@ -177,4 +177,4 @@ bool vmaIsFull(SVMemAllocator* pVMA);
} }
#endif #endif
#endif /*_TD_VNODE_DEF_H_*/ #endif /*_TD_VNODE_DEF_H_*/
\ No newline at end of file
...@@ -37,7 +37,7 @@ const void* tqDeserializeItem(const void* pBytes, STqMsgItem* pItem); ...@@ -37,7 +37,7 @@ const void* tqDeserializeItem(const void* pBytes, STqMsgItem* pItem);
int tqInit() { int tqInit() {
int8_t old = atomic_val_compare_exchange_8(&tqMgmt.inited, 0, 1); int8_t old = atomic_val_compare_exchange_8(&tqMgmt.inited, 0, 1);
if(old == 1) return 0; if (old == 1) return 0;
tqMgmt.timer = taosTmrInit(0, 0, 0, "TQ"); tqMgmt.timer = taosTmrInit(0, 0, 0, "TQ");
return 0; return 0;
...@@ -45,12 +45,12 @@ int tqInit() { ...@@ -45,12 +45,12 @@ int tqInit() {
void tqCleanUp() { void tqCleanUp() {
int8_t old = atomic_val_compare_exchange_8(&tqMgmt.inited, 1, 0); int8_t old = atomic_val_compare_exchange_8(&tqMgmt.inited, 1, 0);
if(old == 0) return; if (old == 0) return;
taosTmrStop(tqMgmt.timer); taosTmrStop(tqMgmt.timer);
taosTmrCleanUp(tqMgmt.timer); taosTmrCleanUp(tqMgmt.timer);
} }
STQ* tqOpen(const char* path, STqCfg* tqConfig, STqLogHandle* tqLogHandle, SMemAllocatorFactory* allocFac) { STQ* tqOpen(const char* path, SWal* pWal, STqCfg* tqConfig, SMemAllocatorFactory* allocFac) {
STQ* pTq = malloc(sizeof(STQ)); STQ* pTq = malloc(sizeof(STQ));
if (pTq == NULL) { if (pTq == NULL) {
terrno = TSDB_CODE_TQ_OUT_OF_MEMORY; terrno = TSDB_CODE_TQ_OUT_OF_MEMORY;
...@@ -58,7 +58,6 @@ STQ* tqOpen(const char* path, STqCfg* tqConfig, STqLogHandle* tqLogHandle, SMemA ...@@ -58,7 +58,6 @@ STQ* tqOpen(const char* path, STqCfg* tqConfig, STqLogHandle* tqLogHandle, SMemA
} }
pTq->path = strdup(path); pTq->path = strdup(path);
pTq->tqConfig = tqConfig; pTq->tqConfig = tqConfig;
pTq->tqLogHandle = tqLogHandle;
#if 0 #if 0
pTq->tqMemRef.pAllocatorFactory = allocFac; pTq->tqMemRef.pAllocatorFactory = allocFac;
pTq->tqMemRef.pAllocator = allocFac->create(allocFac); pTq->tqMemRef.pAllocator = allocFac->create(allocFac);
...@@ -150,7 +149,7 @@ int tqCreateGroup(STQ* pTq, int64_t topicId, int64_t cgId, int64_t cId, STqGroup ...@@ -150,7 +149,7 @@ int tqCreateGroup(STQ* pTq, int64_t topicId, int64_t cgId, int64_t cId, STqGroup
memset(pGroup, 0, sizeof(STqGroup)); memset(pGroup, 0, sizeof(STqGroup));
pGroup->topicList = tdListNew(sizeof(STqTopic)); pGroup->topicList = tdListNew(sizeof(STqTopic));
if(pGroup->topicList == NULL) { if (pGroup->topicList == NULL) {
free(pGroup); free(pGroup);
return -1; return -1;
} }
...@@ -190,7 +189,7 @@ static int tqFetch(STqGroup* pGroup, STqConsumeRsp** pRsp) { ...@@ -190,7 +189,7 @@ static int tqFetch(STqGroup* pGroup, STqConsumeRsp** pRsp) {
int totSize = 0; int totSize = 0;
int numOfMsgs = 0; int numOfMsgs = 0;
// TODO: make it a macro // TODO: make it a macro
int sizeLimit = 4 * 1024; int sizeLimit = 4 * 1024;
void* ptr = realloc(*pRsp, sizeof(STqConsumeRsp) + sizeLimit); void* ptr = realloc(*pRsp, sizeof(STqConsumeRsp) + sizeLimit);
if (ptr == NULL) { if (ptr == NULL) {
...@@ -329,9 +328,9 @@ int tqProcessCMsg(STQ* pTq, STqConsumeReq* pMsg, STqRspHandle* pRsp) { ...@@ -329,9 +328,9 @@ int tqProcessCMsg(STQ* pTq, STqConsumeReq* pMsg, STqRspHandle* pRsp) {
} }
int tqConsume(STQ* pTq, SRpcMsg* pReq, SRpcMsg** pRsp) { int tqConsume(STQ* pTq, SRpcMsg* pReq, SRpcMsg** pRsp) {
STqConsumeReq *pMsg = pReq->pCont; STqConsumeReq* pMsg = pReq->pCont;
int64_t clientId = pMsg->head.clientId; int64_t clientId = pMsg->head.clientId;
STqGroup* pGroup = tqGetGroup(pTq, clientId); STqGroup* pGroup = tqGetGroup(pTq, clientId);
if (pGroup == NULL) { if (pGroup == NULL) {
terrno = TSDB_CODE_TQ_GROUP_NOT_SET; terrno = TSDB_CODE_TQ_GROUP_NOT_SET;
return -1; return -1;
...@@ -343,9 +342,8 @@ int tqConsume(STQ* pTq, SRpcMsg* pReq, SRpcMsg** pRsp) { ...@@ -343,9 +342,8 @@ int tqConsume(STQ* pTq, SRpcMsg* pReq, SRpcMsg** pRsp) {
int numOfMsgs = 0; int numOfMsgs = 0;
int sizeLimit = 4096; int sizeLimit = 4096;
STqConsumeRsp* pCsmRsp = (*pRsp)->pCont;
STqConsumeRsp *pCsmRsp = (*pRsp)->pCont; void* ptr = realloc((*pRsp)->pCont, sizeof(STqConsumeRsp) + sizeLimit);
void* ptr = realloc((*pRsp)->pCont, sizeof(STqConsumeRsp) + sizeLimit);
if (ptr == NULL) { if (ptr == NULL) {
terrno = TSDB_CODE_TQ_OUT_OF_MEMORY; terrno = TSDB_CODE_TQ_OUT_OF_MEMORY;
return -1; return -1;
...@@ -356,16 +354,16 @@ int tqConsume(STQ* pTq, SRpcMsg* pReq, SRpcMsg** pRsp) { ...@@ -356,16 +354,16 @@ int tqConsume(STQ* pTq, SRpcMsg* pReq, SRpcMsg** pRsp) {
tdListInitIter(topicList, &iter, TD_LIST_FORWARD); tdListInitIter(topicList, &iter, TD_LIST_FORWARD);
STqMsgContent* buffer = NULL; STqMsgContent* buffer = NULL;
SArray* pArray = taosArrayInit(0, sizeof(void*)); SArray* pArray = taosArrayInit(0, sizeof(void*));
SListNode *pn; SListNode* pn;
while((pn = tdListNext(&iter)) != NULL) { while ((pn = tdListNext(&iter)) != NULL) {
STqTopic* pTopic = *(STqTopic**)pn->data; STqTopic* pTopic = *(STqTopic**)pn->data;
int idx = pTopic->floatingCursor % TQ_BUFFER_SIZE; int idx = pTopic->floatingCursor % TQ_BUFFER_SIZE;
STqMsgItem* pItem = &pTopic->buffer[idx]; STqMsgItem* pItem = &pTopic->buffer[idx];
if (pItem->content != NULL && pItem->offset == pTopic->floatingCursor) { if (pItem->content != NULL && pItem->offset == pTopic->floatingCursor) {
if(pItem->status == TQ_ITEM_READY) { if (pItem->status == TQ_ITEM_READY) {
//if has data // if has data
totSize += pTopic->buffer[idx].size; totSize += pTopic->buffer[idx].size;
if (totSize > sizeLimit) { if (totSize > sizeLimit) {
void* ptr = realloc((*pRsp)->pCont, sizeof(STqConsumeRsp) + totSize); void* ptr = realloc((*pRsp)->pCont, sizeof(STqConsumeRsp) + totSize);
...@@ -388,13 +386,13 @@ int tqConsume(STQ* pTq, SRpcMsg* pReq, SRpcMsg** pRsp) { ...@@ -388,13 +386,13 @@ int tqConsume(STQ* pTq, SRpcMsg* pReq, SRpcMsg** pRsp) {
if (totSize > sizeLimit) { if (totSize > sizeLimit) {
break; break;
} }
} else if(pItem->status == TQ_ITEM_PROCESS) { } else if (pItem->status == TQ_ITEM_PROCESS) {
//if not have data but in process // if not have data but in process
} else if(pItem->status == TQ_ITEM_EMPTY){ } else if (pItem->status == TQ_ITEM_EMPTY) {
//if not have data and not in process // if not have data and not in process
int32_t old = atomic_val_compare_exchange_32(&pItem->status, TQ_ITEM_EMPTY, TQ_ITEM_PROCESS); int32_t old = atomic_val_compare_exchange_32(&pItem->status, TQ_ITEM_EMPTY, TQ_ITEM_PROCESS);
if(old != TQ_ITEM_EMPTY) { if (old != TQ_ITEM_EMPTY) {
continue; continue;
} }
pItem->offset = pTopic->floatingCursor; pItem->offset = pTopic->floatingCursor;
...@@ -416,22 +414,22 @@ int tqConsume(STQ* pTq, SRpcMsg* pReq, SRpcMsg** pRsp) { ...@@ -416,22 +414,22 @@ int tqConsume(STQ* pTq, SRpcMsg* pReq, SRpcMsg** pRsp) {
} }
// fetched a num of msgs, rpc response // fetched a num of msgs, rpc response
for(int i = 0; i < pArray->size; i++) { for (int i = 0; i < pArray->size; i++) {
STqMsgItem* pItem = taosArrayGet(pArray, i); STqMsgItem* pItem = taosArrayGet(pArray, i);
//read from wal // read from wal
void* raw = NULL; void* raw = NULL;
/*int code = pTq->tqLogReader->logRead(, &raw, pItem->offset);*/ /*int code = pTq->tqLogReader->logRead(, &raw, pItem->offset);*/
int code = pTq->tqLogHandle->logRead(pItem->pTopic->logReader, &raw, pItem->offset); /*int code = pTq->tqLogHandle->logRead(pItem->pTopic->logReader, &raw, pItem->offset);*/
if(code < 0) { /*if (code < 0) {*/
//TODO: error // TODO: error
} /*}*/
//get msgType // get msgType
//if submitblk // if submitblk
pItem->executor->assign(pItem->executor->runtimeEnv, raw); pItem->executor->assign(pItem->executor->runtimeEnv, raw);
SSDataBlock* content = pItem->executor->exec(pItem->executor->runtimeEnv); SSDataBlock* content = pItem->executor->exec(pItem->executor->runtimeEnv);
pItem->content = content; pItem->content = content;
//if other type, send just put into buffer // if other type, send just put into buffer
/*pItem->content = raw;*/ /*pItem->content = raw;*/
int32_t old = atomic_val_compare_exchange_32(&pItem->status, TQ_ITEM_PROCESS, TQ_ITEM_READY); int32_t old = atomic_val_compare_exchange_32(&pItem->status, TQ_ITEM_PROCESS, TQ_ITEM_READY);
...@@ -608,69 +606,163 @@ int tqItemSSize() { ...@@ -608,69 +606,163 @@ int tqItemSSize() {
return 0; return 0;
} }
STqReadHandle* tqInitSubmitMsgScanner(SMeta* pMeta, SSubmitMsg *pMsg) { int32_t tqProcessConsumeReq(STQ* pTq, SRpcMsg* pMsg, SRpcMsg** ppRsp) {
SMqCVConsumeReq* pReq = pMsg->pCont;
int64_t reqId = pReq->reqId;
int64_t consumerId = pReq->consumerId;
int64_t offset = pReq->offset;
int64_t blockingTime = pReq->blockingTime;
STqConsumerHandle* pConsumer = tqHandleGet(pTq->tqMeta, consumerId);
int sz = taosArrayGetSize(pConsumer->topics);
for (int i = 0 ; i < sz; i++) {
STqTopicHandle *pHandle = taosArrayGet(pConsumer->topics, i);
int8_t pos = offset % TQ_BUFFER_SIZE;
int8_t old = atomic_val_compare_exchange_8(&pHandle->buffer.output[pos].status, 0, 1);
if (old == 1) {
// do nothing
continue;
}
if (walReadWithHandle(pHandle->pReadhandle, offset) < 0) {
// TODO
}
SWalHead* pHead = pHandle->pReadhandle->pHead;
while (pHead->head.msgType != TDMT_VND_SUBMIT) {
// read until find TDMT_VND_SUBMIT
}
SSubmitMsg* pCont = (SSubmitMsg*)&pHead->head.body;
SSubQueryMsg* pQueryMsg = pHandle->buffer.output[pos].pMsg;
// TODO: launch query and get output data
void* outputData;
pHandle->buffer.output[pos].dst = outputData;
if (pHandle->buffer.firstOffset == -1
|| pReq->offset < pHandle->buffer.firstOffset) {
pHandle->buffer.firstOffset = pReq->offset;
}
if (pHandle->buffer.lastOffset == -1
|| pReq->offset > pHandle->buffer.lastOffset) {
pHandle->buffer.lastOffset = pReq->offset;
}
atomic_store_8(&pHandle->buffer.output[pos].status, 1);
// put output into rsp
}
// launch query
// get result
SMqCvConsumeRsp* pRsp;
return 0;
}
int32_t tqProcessSetConnReq(STQ* pTq, SMqSetCVgReq* pReq) {
STqConsumerHandle* pConsumer = calloc(sizeof(STqConsumerHandle), 1);
if (pConsumer == NULL) {
return -1;
}
STqTopicHandle* pTopic = calloc(sizeof(STqTopicHandle), 1);
if (pTopic == NULL) {
free(pConsumer);
return -1;
}
strcpy(pTopic->topicName, pReq->topicName);
strcpy(pTopic->cgroup, pReq->cgroup);
strcpy(pTopic->sql, pReq->sql);
strcpy(pTopic->logicalPlan, pReq->logicalPlan);
strcpy(pTopic->physicalPlan, pReq->physicalPlan);
SArray *pArray;
//TODO: deserialize to SQueryDag
SQueryDag *pDag;
// convert to task
if (schedulerConvertDagToTaskList(pDag, &pArray) < 0) {
// TODO: handle error
}
ASSERT(taosArrayGetSize(pArray) == 0);
STaskInfo *pInfo = taosArrayGet(pArray, 0);
SArray* pTasks;
schedulerCopyTask(pInfo, &pTasks, TQ_BUFFER_SIZE);
pTopic->buffer.firstOffset = -1;
pTopic->buffer.lastOffset = -1;
for (int i = 0; i < TQ_BUFFER_SIZE; i++) {
SSubQueryMsg* pMsg = taosArrayGet(pTasks, i);
pTopic->buffer.output[i].pMsg = pMsg;
pTopic->buffer.output[i].status = 0;
}
pTopic->pReadhandle = walOpenReadHandle(pTq->pWal);
// write mq meta
return 0;
}
STqReadHandle* tqInitSubmitMsgScanner(SMeta* pMeta, SArray* pColumnIdList) {
STqReadHandle* pReadHandle = malloc(sizeof(STqReadHandle)); STqReadHandle* pReadHandle = malloc(sizeof(STqReadHandle));
if (pReadHandle == NULL) { if (pReadHandle == NULL) {
return NULL; return NULL;
} }
pReadHandle->pMeta = pMeta; pReadHandle->pMeta = pMeta;
pReadHandle->pMsg = pMsg; pReadHandle->pMsg = NULL;
tInitSubmitMsgIter(pMsg, &pReadHandle->msgIter);
pReadHandle->ver = -1; pReadHandle->ver = -1;
pReadHandle->pColumnIdList = pColumnIdList;
return NULL; return NULL;
} }
void tqReadHandleSetMsg(STqReadHandle* pReadHandle, SSubmitMsg* pMsg, int64_t ver) {
pReadHandle->pMsg = pMsg;
tInitSubmitMsgIter(pMsg, &pReadHandle->msgIter);
pReadHandle->ver = ver;
memset(&pReadHandle->blkIter, 0, sizeof(SSubmitBlkIter));
}
bool tqNextDataBlock(STqReadHandle* pHandle) { bool tqNextDataBlock(STqReadHandle* pHandle) {
if(tGetSubmitMsgNext(&pHandle->msgIter, &pHandle->pBlock) < 0) { if (tGetSubmitMsgNext(&pHandle->msgIter, &pHandle->pBlock) < 0) {
return false; return false;
} }
return true; return true;
} }
int tqRetrieveDataBlockInfo(STqReadHandle* pHandle, SDataBlockInfo* pBlockInfo) { int tqRetrieveDataBlockInfo(STqReadHandle* pHandle, SDataBlockInfo* pBlockInfo) {
SMemRow row; SMemRow row;
int32_t sversion = pHandle->pBlock->sversion; int32_t sversion = pHandle->pBlock->sversion;
SSchemaWrapper* pSchema = metaGetTableSchema(pHandle->pMeta, pHandle->pBlock->uid, sversion, false); SSchemaWrapper* pSchema = metaGetTableSchema(pHandle->pMeta, pHandle->pBlock->uid, sversion, false);
pBlockInfo->numOfCols = pSchema->nCols; pBlockInfo->numOfCols = pSchema->nCols;
pBlockInfo->rows = pHandle->pBlock->numOfRows; pBlockInfo->rows = pHandle->pBlock->numOfRows;
pBlockInfo->uid = pHandle->pBlock->uid; pBlockInfo->uid = pHandle->pBlock->uid;
//TODO: filter out unused column // TODO: filter out unused column
return 0; return 0;
} }
SArray *tqRetrieveDataBlock(STqReadHandle* pHandle, SArray* pColumnIdList) { SArray* tqRetrieveDataBlock(STqReadHandle* pHandle) {
int32_t sversion = pHandle->pBlock->sversion; int32_t sversion = pHandle->pBlock->sversion;
SSchemaWrapper* pSchemaWrapper = metaGetTableSchema(pHandle->pMeta, pHandle->pBlock->uid, sversion, true); SSchemaWrapper* pSchemaWrapper = metaGetTableSchema(pHandle->pMeta, pHandle->pBlock->uid, sversion, true);
STSchema* pTschema = metaGetTbTSchema(pHandle->pMeta, pHandle->pBlock->uid, sversion); STSchema* pTschema = metaGetTbTSchema(pHandle->pMeta, pHandle->pBlock->uid, sversion);
SArray *pArray = taosArrayInit(pSchemaWrapper->nCols, sizeof(SColumnInfoData)); SArray* pArray = taosArrayInit(pSchemaWrapper->nCols, sizeof(SColumnInfoData));
if (pArray == NULL) { if (pArray == NULL) {
return NULL; return NULL;
} }
SColumnInfoData colInfo; SColumnInfoData colInfo;
int sz = pSchemaWrapper->nCols * pSchemaWrapper->pSchema->bytes; int sz = pSchemaWrapper->nCols * pSchemaWrapper->pSchema->bytes;
colInfo.pData = malloc(sz); colInfo.pData = malloc(sz);
if (colInfo.pData == NULL) { if (colInfo.pData == NULL) {
return NULL; return NULL;
} }
for (int i = 0; i < pTschema->numOfCols; i++) {
//TODO: filter out unused column
taosArrayPush(pColumnIdList, &(schemaColAt(pTschema, i)->colId));
}
SMemRow row; SMemRow row;
int32_t kvIdx; int32_t kvIdx;
while ((row = tGetSubmitBlkNext(&pHandle->blkIter)) != NULL) { while ((row = tGetSubmitBlkNext(&pHandle->blkIter)) != NULL) {
for (int i = 0; i < pTschema->numOfCols && kvIdx < pTschema->numOfCols; i++) { for (int i = 0; i < pTschema->numOfCols && kvIdx < pTschema->numOfCols; i++) {
//TODO: filter out unused column // TODO: filter out unused column
STColumn *pCol = schemaColAt(pTschema, i); STColumn* pCol = schemaColAt(pTschema, i);
void* val = tdGetMemRowDataOfColEx(row, pCol->colId, pCol->type, TD_DATA_ROW_HEAD_SIZE + pCol->offset, &kvIdx); void* val = tdGetMemRowDataOfColEx(row, pCol->colId, pCol->type, TD_DATA_ROW_HEAD_SIZE + pCol->offset, &kvIdx);
//TODO: handle varlen // TODO: handle varlen
memcpy(POINTER_SHIFT(colInfo.pData, pCol->offset), val, pCol->bytes); memcpy(POINTER_SHIFT(colInfo.pData, pCol->offset), val, pCol->bytes);
} }
} }
taosArrayPush(pArray, &colInfo); taosArrayPush(pArray, &colInfo);
return pArray; return pArray;
} }
/*int tqLoadDataBlock(SExecTaskInfo* pTaskInfo, SSubmitBlkScanInfo* pSubmitBlkScanInfo, SSDataBlock* pBlock, uint32_t status) {*/ /*int tqLoadDataBlock(SExecTaskInfo* pTaskInfo, SSubmitBlkScanInfo* pSubmitBlkScanInfo, SSDataBlock* pBlock, uint32_t
/*return 0;*/ * status) {*/
/*return 0;*/
/*}*/ /*}*/
...@@ -117,14 +117,6 @@ static int vnodeOpenImpl(SVnode *pVnode) { ...@@ -117,14 +117,6 @@ static int vnodeOpenImpl(SVnode *pVnode) {
return -1; return -1;
} }
// TODO: Open TQ
sprintf(dir, "%s/tq", pVnode->path);
pVnode->pTq = tqOpen(dir, &(pVnode->config.tqCfg), NULL, vBufPoolGetMAF(pVnode));
if (pVnode->pTq == NULL) {
// TODO: handle error
return -1;
}
// Open WAL // Open WAL
sprintf(dir, "%s/wal", pVnode->path); sprintf(dir, "%s/wal", pVnode->path);
pVnode->pWal = walOpen(dir, &(pVnode->config.walCfg)); pVnode->pWal = walOpen(dir, &(pVnode->config.walCfg));
...@@ -133,6 +125,14 @@ static int vnodeOpenImpl(SVnode *pVnode) { ...@@ -133,6 +125,14 @@ static int vnodeOpenImpl(SVnode *pVnode) {
return -1; return -1;
} }
// Open TQ
sprintf(dir, "%s/tq", pVnode->path);
pVnode->pTq = tqOpen(dir, pVnode->pWal, &(pVnode->config.tqCfg), vBufPoolGetMAF(pVnode));
if (pVnode->pTq == NULL) {
// TODO: handle error
return -1;
}
// Open Query // Open Query
if (vnodeQueryOpen(pVnode)) { if (vnodeQueryOpen(pVnode)) {
return -1; return -1;
...@@ -151,4 +151,4 @@ static void vnodeCloseImpl(SVnode *pVnode) { ...@@ -151,4 +151,4 @@ static void vnodeCloseImpl(SVnode *pVnode) {
tqClose(pVnode->pTq); tqClose(pVnode->pTq);
walClose(pVnode->pWal); walClose(pVnode->pWal);
} }
} }
\ No newline at end of file
...@@ -55,6 +55,8 @@ int vnodeProcessFetchReq(SVnode *pVnode, SRpcMsg *pMsg, SRpcMsg **pRsp) { ...@@ -55,6 +55,8 @@ int vnodeProcessFetchReq(SVnode *pVnode, SRpcMsg *pMsg, SRpcMsg **pRsp) {
// return qWorkerProcessShowFetchMsg(pVnode->pMeta, pVnode->pQuery, pMsg); // return qWorkerProcessShowFetchMsg(pVnode->pMeta, pVnode->pQuery, pMsg);
case TDMT_VND_TABLE_META: case TDMT_VND_TABLE_META:
return vnodeGetTableMeta(pVnode, pMsg, pRsp); return vnodeGetTableMeta(pVnode, pMsg, pRsp);
case TDMT_VND_CONSUME:
return tqProcessConsumeReq(pVnode->pTq, pMsg, pRsp);
default: default:
vError("unknown msg type:%d in fetch queue", pMsg->msgType); vError("unknown msg type:%d in fetch queue", pMsg->msgType);
return TSDB_CODE_VND_APP_ERROR; return TSDB_CODE_VND_APP_ERROR;
...@@ -162,16 +164,26 @@ static int32_t vnodeGetTableList(SVnode *pVnode, SRpcMsg *pMsg) { ...@@ -162,16 +164,26 @@ static int32_t vnodeGetTableList(SVnode *pVnode, SRpcMsg *pMsg) {
char * name = NULL; char * name = NULL;
int32_t totalLen = 0; int32_t totalLen = 0;
int32_t numOfTables = 0;
while ((name = metaTbCursorNext(pCur)) != NULL) { while ((name = metaTbCursorNext(pCur)) != NULL) {
taosArrayPush(pArray, &name); if (numOfTables < 1000) { // TODO: temp get tables of vnode, and should del when show tables commad ok.
totalLen += strlen(name); taosArrayPush(pArray, &name);
totalLen += strlen(name);
}
numOfTables++;
}
// TODO: temp debug, and should del when show tables command ok
vError("====vgId:%d, numOfTables: %d", pVnode->vgId, numOfTables);
if (numOfTables > 1000) {
numOfTables = 1000;
} }
metaCloseTbCursor(pCur); metaCloseTbCursor(pCur);
int32_t rowLen = int32_t rowLen =
(TSDB_TABLE_NAME_LEN + VARSTR_HEADER_SIZE) + 8 + 2 + (TSDB_TABLE_NAME_LEN + VARSTR_HEADER_SIZE) + 8 + 4; (TSDB_TABLE_NAME_LEN + VARSTR_HEADER_SIZE) + 8 + 2 + (TSDB_TABLE_NAME_LEN + VARSTR_HEADER_SIZE) + 8 + 4;
int32_t numOfTables = (int32_t)taosArrayGetSize(pArray); //int32_t numOfTables = (int32_t)taosArrayGetSize(pArray);
int32_t payloadLen = rowLen * numOfTables; int32_t payloadLen = rowLen * numOfTables;
// SVShowTablesFetchReq *pFetchReq = pMsg->pCont; // SVShowTablesFetchReq *pFetchReq = pMsg->pCont;
...@@ -199,5 +211,6 @@ static int32_t vnodeGetTableList(SVnode *pVnode, SRpcMsg *pMsg) { ...@@ -199,5 +211,6 @@ static int32_t vnodeGetTableList(SVnode *pVnode, SRpcMsg *pMsg) {
}; };
rpcSendResponse(&rpcMsg); rpcSendResponse(&rpcMsg);
taosArrayDestroy(pArray);
return 0; return 0;
} }
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "tq.h"
#include "vnd.h" #include "vnd.h"
int vnodeProcessNoWalWMsgs(SVnode *pVnode, SRpcMsg *pMsg) { int vnodeProcessNoWalWMsgs(SVnode *pVnode, SRpcMsg *pMsg) {
...@@ -33,7 +34,7 @@ int vnodeProcessWMsgs(SVnode *pVnode, SArray *pMsgs) { ...@@ -33,7 +34,7 @@ int vnodeProcessWMsgs(SVnode *pVnode, SArray *pMsgs) {
pMsg = *(SRpcMsg **)taosArrayGet(pMsgs, i); pMsg = *(SRpcMsg **)taosArrayGet(pMsgs, i);
// ser request version // ser request version
void * pBuf = POINTER_SHIFT(pMsg->pCont, sizeof(SMsgHead)); void *pBuf = POINTER_SHIFT(pMsg->pCont, sizeof(SMsgHead));
int64_t ver = pVnode->state.processed++; int64_t ver = pVnode->state.processed++;
taosEncodeFixedU64(&pBuf, ver); taosEncodeFixedU64(&pBuf, ver);
...@@ -52,7 +53,7 @@ int vnodeProcessWMsgs(SVnode *pVnode, SArray *pMsgs) { ...@@ -52,7 +53,7 @@ int vnodeProcessWMsgs(SVnode *pVnode, SArray *pMsgs) {
int vnodeApplyWMsg(SVnode *pVnode, SRpcMsg *pMsg, SRpcMsg **pRsp) { int vnodeApplyWMsg(SVnode *pVnode, SRpcMsg *pMsg, SRpcMsg **pRsp) {
SVCreateTbReq vCreateTbReq; SVCreateTbReq vCreateTbReq;
SVCreateTbBatchReq vCreateTbBatchReq; SVCreateTbBatchReq vCreateTbBatchReq;
void * ptr = vnodeMalloc(pVnode, pMsg->contLen); void *ptr = vnodeMalloc(pVnode, pMsg->contLen);
if (ptr == NULL) { if (ptr == NULL) {
// TODO: handle error // TODO: handle error
} }
...@@ -108,6 +109,12 @@ int vnodeApplyWMsg(SVnode *pVnode, SRpcMsg *pMsg, SRpcMsg **pRsp) { ...@@ -108,6 +109,12 @@ int vnodeApplyWMsg(SVnode *pVnode, SRpcMsg *pMsg, SRpcMsg **pRsp) {
// TODO: handle error // TODO: handle error
} }
break; break;
case TDMT_VND_MQ_SET_CONN: {
SMqSetCVgReq req;
tDecodeSMqSetCVgReq(ptr, &req);
if (tqProcessSetConnReq(pVnode->pTq, &req) < 0) {
}
} break;
default: default:
ASSERT(0); ASSERT(0);
break; break;
......
...@@ -94,7 +94,7 @@ struct SUdfInfo; ...@@ -94,7 +94,7 @@ struct SUdfInfo;
int32_t getOutputInterResultBufSize(struct STaskAttr* pQueryAttr); int32_t getOutputInterResultBufSize(struct STaskAttr* pQueryAttr);
size_t getResultRowSize(struct STaskRuntimeEnv* pRuntimeEnv); size_t getResultRowSize(SArray* pExprInfo);
int32_t initResultRowInfo(SResultRowInfo* pResultRowInfo, int32_t size, int16_t type); int32_t initResultRowInfo(SResultRowInfo* pResultRowInfo, int32_t size, int16_t type);
void cleanupResultRowInfo(SResultRowInfo* pResultRowInfo); void cleanupResultRowInfo(SResultRowInfo* pResultRowInfo);
......
...@@ -414,18 +414,30 @@ typedef struct STagScanInfo { ...@@ -414,18 +414,30 @@ typedef struct STagScanInfo {
int32_t curPos; int32_t curPos;
} STagScanInfo; } STagScanInfo;
typedef struct SStreamBlockScanInfo {
} SStreamBlockScanInfo;
typedef struct SOptrBasicInfo { typedef struct SOptrBasicInfo {
SResultRowInfo resultRowInfo; SResultRowInfo resultRowInfo;
int32_t *rowCellInfoOffset; // offset value for each row result cell info int32_t *rowCellInfoOffset; // offset value for each row result cell info
SQLFunctionCtx *pCtx; SQLFunctionCtx *pCtx;
SSDataBlock *pRes; SSDataBlock *pRes;
void *keyBuf;
} SOptrBasicInfo; } SOptrBasicInfo;
typedef struct SOptrBasicInfo STableIntervalOperatorInfo; typedef struct SOptrBasicInfo STableIntervalOperatorInfo;
typedef struct SAggOperatorInfo { typedef struct SAggOperatorInfo {
SOptrBasicInfo binfo; SOptrBasicInfo binfo;
uint32_t seed; uint32_t seed;
SDiskbasedResultBuf *pResultBuf; // query result buffer based on blocked-wised disk file
SHashObj* pResultRowHashTable; // quick locate the window object for each result
SHashObj* pResultRowListSet; // used to check if current ResultRowInfo has ResultRow object or not
SArray* pResultRowArrayList; // The array list that contains the Result rows
char* keyBuf; // window key buffer
SResultRowPool* pool; // The window result objects pool, all the resultRow Objects are allocated and managed by this object.
STableQueryInfo *current;
} SAggOperatorInfo; } SAggOperatorInfo;
typedef struct SProjectOperatorInfo { typedef struct SProjectOperatorInfo {
...@@ -546,15 +558,14 @@ typedef struct SOrderOperatorInfo { ...@@ -546,15 +558,14 @@ typedef struct SOrderOperatorInfo {
SSDataBlock *pDataBlock; SSDataBlock *pDataBlock;
} SOrderOperatorInfo; } SOrderOperatorInfo;
void appendUpstream(SOperatorInfo* p, SOperatorInfo* pUpstream);
SOperatorInfo* createExchangeOperatorInfo(const SArray* pSources, const SArray* pSchema, SExecTaskInfo* pTaskInfo); SOperatorInfo* createExchangeOperatorInfo(const SArray* pSources, const SArray* pSchema, SExecTaskInfo* pTaskInfo);
SOperatorInfo* createDataBlocksOptScanInfo(void* pTsdbReadHandle, int32_t order, int32_t numOfOutput, int32_t repeatTime, int32_t reverseTime, SExecTaskInfo* pTaskInfo); SOperatorInfo* createDataBlocksOptScanInfo(void* pTsdbReadHandle, int32_t order, int32_t numOfOutput, int32_t repeatTime, int32_t reverseTime, SExecTaskInfo* pTaskInfo);
SOperatorInfo* createTableScanOperatorInfo(void* pTsdbReadHandle, int32_t order, int32_t numOfOutput, int32_t repeatTime, SExecTaskInfo* pTaskInfo); SOperatorInfo* createTableScanOperatorInfo(void* pTsdbReadHandle, int32_t order, int32_t numOfOutput, int32_t repeatTime, SExecTaskInfo* pTaskInfo);
SOperatorInfo* createTableSeqScanOperator(void* pTsdbReadHandle, STaskRuntimeEnv* pRuntimeEnv); SOperatorInfo* createTableSeqScanOperator(void* pTsdbReadHandle, STaskRuntimeEnv* pRuntimeEnv);
SOperatorInfo* createSubmitBlockScanOperatorInfo(void *pSubmitBlockReadHandle, int32_t numOfOutput, SExecTaskInfo* pTaskInfo);
SOperatorInfo* createAggregateOperatorInfo(SOperatorInfo* downstream, SExprInfo* pExpr, int32_t numOfOutput); SOperatorInfo* createAggregateOperatorInfo(SOperatorInfo* downstream, SArray* pExprInfo, SExecTaskInfo* pTaskInfo);
SOperatorInfo* createProjectOperatorInfo(STaskRuntimeEnv* pRuntimeEnv, SOperatorInfo* downstream, SExprInfo* pExpr, int32_t numOfOutput); SOperatorInfo* createProjectOperatorInfo(STaskRuntimeEnv* pRuntimeEnv, SOperatorInfo* downstream, SExprInfo* pExpr, int32_t numOfOutput);
SOperatorInfo* createLimitOperatorInfo(STaskRuntimeEnv* pRuntimeEnv, SOperatorInfo* downstream); SOperatorInfo* createLimitOperatorInfo(STaskRuntimeEnv* pRuntimeEnv, SOperatorInfo* downstream);
SOperatorInfo* createTimeIntervalOperatorInfo(STaskRuntimeEnv* pRuntimeEnv, SOperatorInfo* downstream, SExprInfo* pExpr, int32_t numOfOutput); SOperatorInfo* createTimeIntervalOperatorInfo(STaskRuntimeEnv* pRuntimeEnv, SOperatorInfo* downstream, SExprInfo* pExpr, int32_t numOfOutput);
...@@ -652,6 +663,6 @@ int32_t getMaximumIdleDurationSec(); ...@@ -652,6 +663,6 @@ int32_t getMaximumIdleDurationSec();
void doInvokeUdf(struct SUdfInfo* pUdfInfo, SQLFunctionCtx *pCtx, int32_t idx, int32_t type); void doInvokeUdf(struct SUdfInfo* pUdfInfo, SQLFunctionCtx *pCtx, int32_t idx, int32_t type);
void setTaskStatus(SExecTaskInfo *pTaskInfo, int8_t status); void setTaskStatus(SExecTaskInfo *pTaskInfo, int8_t status);
int32_t doCreateExecTaskInfo(SSubplan* pPlan, SExecTaskInfo** pTaskInfo, STableGroupInfo* pGroupInfo, void* readerHandle); int32_t doCreateExecTaskInfo(SSubplan* pPlan, SExecTaskInfo** pTaskInfo, void* readerHandle);
#endif // TDENGINE_EXECUTORIMPL_H #endif // TDENGINE_EXECUTORIMPL_H
...@@ -168,16 +168,14 @@ void clearResultRow(STaskRuntimeEnv *pRuntimeEnv, SResultRow *pResultRow, int16_ ...@@ -168,16 +168,14 @@ void clearResultRow(STaskRuntimeEnv *pRuntimeEnv, SResultRow *pResultRow, int16_
} }
// TODO refactor: use macro // TODO refactor: use macro
struct SResultRowEntryInfo* getResultCell(const SResultRow* pRow, int32_t index, int32_t* offset) { SResultRowEntryInfo* getResultCell(const SResultRow* pRow, int32_t index, int32_t* offset) {
assert(index >= 0 && offset != NULL); assert(index >= 0 && offset != NULL);
// return (SResultRowEntryInfo*)((char*) pRow->pCellInfo + offset[index]); return (SResultRowEntryInfo*)((char*) pRow->pEntryInfo + offset[index]);
return NULL;
} }
size_t getResultRowSize(STaskRuntimeEnv* pRuntimeEnv) { size_t getResultRowSize(SArray* pExprInfo) {
STaskAttr* pQueryAttr = pRuntimeEnv->pQueryAttr; size_t numOfOutput = taosArrayGetSize(pExprInfo);
return 0; return (numOfOutput * sizeof(SResultRowEntryInfo)) + /*pQueryAttr->interBufSize +*/ sizeof(SResultRow);
// return (pQueryAttr->numOfOutput * sizeof(SResultRowEntryInfo)) + pQueryAttr->interBufSize + sizeof(SResultRow);
} }
SResultRowPool* initResultRowPool(size_t size) { SResultRowPool* initResultRowPool(size_t size) {
......
...@@ -73,46 +73,7 @@ int32_t qCreateExecTask(void* tsdb, int32_t vgId, SSubplan* pSubplan, qTaskInfo_ ...@@ -73,46 +73,7 @@ int32_t qCreateExecTask(void* tsdb, int32_t vgId, SSubplan* pSubplan, qTaskInfo_
assert(tsdb != NULL && pSubplan != NULL); assert(tsdb != NULL && pSubplan != NULL);
SExecTaskInfo** pTask = (SExecTaskInfo**)pTaskInfo; SExecTaskInfo** pTask = (SExecTaskInfo**)pTaskInfo;
int32_t code = 0; int32_t code = doCreateExecTaskInfo(pSubplan, pTask, tsdb);
uint64_t uid = 0;
STimeWindow window = TSWINDOW_INITIALIZER;
int32_t tableType = 0;
SPhyNode* pPhyNode = pSubplan->pNode;
STableGroupInfo groupInfo = {0};
int32_t type = pPhyNode->info.type;
if (type == OP_TableScan || type == OP_DataBlocksOptScan) {
STableScanPhyNode* pTableScanNode = (STableScanPhyNode*)pPhyNode;
uid = pTableScanNode->scan.uid;
window = pTableScanNode->window;
tableType = pTableScanNode->scan.tableType;
if (tableType == TSDB_SUPER_TABLE) {
code =
tsdbQuerySTableByTagCond(tsdb, uid, window.skey, NULL, 0, 0, NULL, &groupInfo, NULL, 0, pSubplan->id.queryId);
if (code != TSDB_CODE_SUCCESS) {
goto _error;
}
} else { // Create one table group.
groupInfo.numOfTables = 1;
groupInfo.pGroupList = taosArrayInit(1, POINTER_BYTES);
SArray* pa = taosArrayInit(1, sizeof(STableKeyInfo));
STableKeyInfo info = {.pTable = NULL, .lastKey = 0, .uid = uid};
taosArrayPush(pa, &info);
taosArrayPush(groupInfo.pGroupList, &pa);
}
if (groupInfo.numOfTables == 0) {
code = 0;
// qDebug("no table qualified for query, reqId:0x%"PRIx64, (*pTask)->id.queryId);
goto _error;
}
}
code = doCreateExecTaskInfo(pSubplan, pTask, &groupInfo, tsdb);
if (code != TSDB_CODE_SUCCESS) { if (code != TSDB_CODE_SUCCESS) {
goto _error; goto _error;
} }
......
...@@ -12,11 +12,12 @@ ...@@ -12,11 +12,12 @@
* You should have received a copy of the GNU Affero General Public License * 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/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <parser.h>
#include "exception.h"
#include "os.h" #include "os.h"
#include "tmsg.h"
#include "tglobal.h" #include "tglobal.h"
#include "tmsg.h"
#include "ttime.h" #include "ttime.h"
#include "exception.h"
#include "executorimpl.h" #include "executorimpl.h"
#include "function.h" #include "function.h"
...@@ -176,7 +177,7 @@ static void setResultOutputBuf(STaskRuntimeEnv* pRuntimeEnv, SResultRow* pResult ...@@ -176,7 +177,7 @@ static void setResultOutputBuf(STaskRuntimeEnv* pRuntimeEnv, SResultRow* pResult
void setResultRowOutputBufInitCtx(STaskRuntimeEnv *pRuntimeEnv, SResultRow *pResult, SQLFunctionCtx* pCtx, int32_t numOfOutput, int32_t* rowCellInfoOffset); void setResultRowOutputBufInitCtx(STaskRuntimeEnv *pRuntimeEnv, SResultRow *pResult, SQLFunctionCtx* pCtx, int32_t numOfOutput, int32_t* rowCellInfoOffset);
static bool functionNeedToExecute(STaskRuntimeEnv *pRuntimeEnv, SQLFunctionCtx *pCtx); static bool functionNeedToExecute(STaskRuntimeEnv *pRuntimeEnv, SQLFunctionCtx *pCtx);
static void setBlockStatisInfo(SQLFunctionCtx *pCtx, SSDataBlock* pSDataBlock, SColIndex* pColIndex); static void setBlockStatisInfo(SQLFunctionCtx *pCtx, SSDataBlock* pSDataBlock, SColumn* pColumn);
static void destroyTableQueryInfoImpl(STableQueryInfo *pTableQueryInfo); static void destroyTableQueryInfoImpl(STableQueryInfo *pTableQueryInfo);
static bool hasMainOutput(STaskAttr *pQueryAttr); static bool hasMainOutput(STaskAttr *pQueryAttr);
...@@ -309,6 +310,31 @@ SSDataBlock* createOutputBuf(SExprInfo* pExpr, int32_t numOfOutput, int32_t numO ...@@ -309,6 +310,31 @@ SSDataBlock* createOutputBuf(SExprInfo* pExpr, int32_t numOfOutput, int32_t numO
return res; return res;
} }
SSDataBlock* createOutputBuf_rv(SArray* pExprInfo, int32_t numOfRows) {
const static int32_t minSize = 8;
size_t numOfOutput = taosArrayGetSize(pExprInfo);
SSDataBlock *res = calloc(1, sizeof(SSDataBlock));
res->info.numOfCols = numOfOutput;
res->pDataBlock = taosArrayInit(numOfOutput, sizeof(SColumnInfoData));
for (int32_t i = 0; i < numOfOutput; ++i) {
SColumnInfoData idata = {{0}};
SExprInfo* pExpr = taosArrayGetP(pExprInfo, i);
idata.info.type = pExpr->base.resSchema.type;
idata.info.bytes = pExpr->base.resSchema.bytes;
idata.info.colId = pExpr->base.resSchema.colId;
int32_t size = MAX(idata.info.bytes * numOfRows, minSize);
idata.pData = calloc(1, size); // at least to hold a pointer on x64 platform
taosArrayPush(res->pDataBlock, &idata);
}
return res;
}
void* destroyOutputBuf(SSDataBlock* pBlock) { void* destroyOutputBuf(SSDataBlock* pBlock) {
if (pBlock == NULL) { if (pBlock == NULL) {
return NULL; return NULL;
...@@ -357,8 +383,8 @@ static bool isProjQuery(STaskAttr *pQueryAttr) { ...@@ -357,8 +383,8 @@ static bool isProjQuery(STaskAttr *pQueryAttr) {
return true; return true;
} }
static bool hasNull(SColIndex* pColIndex, SColumnDataAgg *pStatis) { static bool hasNull(SColumn* pColumn, SColumnDataAgg *pStatis) {
if (TSDB_COL_IS_TAG(pColIndex->flag) || TSDB_COL_IS_UD_COL(pColIndex->flag) || pColIndex->colId == PRIMARYKEY_TIMESTAMP_COL_ID) { if (TSDB_COL_IS_TAG(pColumn->flag) || TSDB_COL_IS_UD_COL(pColumn->flag) || pColumn->info.colId == PRIMARYKEY_TIMESTAMP_COL_ID) {
return false; return false;
} }
...@@ -369,7 +395,7 @@ static bool hasNull(SColIndex* pColIndex, SColumnDataAgg *pStatis) { ...@@ -369,7 +395,7 @@ static bool hasNull(SColIndex* pColIndex, SColumnDataAgg *pStatis) {
return true; return true;
} }
static void prepareResultListBuffer(SResultRowInfo* pResultRowInfo, STaskRuntimeEnv* pRuntimeEnv) { static void prepareResultListBuffer(SResultRowInfo* pResultRowInfo, jmp_buf env) {
// more than the capacity, reallocate the resources // more than the capacity, reallocate the resources
if (pResultRowInfo->size < pResultRowInfo->capacity) { if (pResultRowInfo->size < pResultRowInfo->capacity) {
return; return;
...@@ -384,7 +410,7 @@ static void prepareResultListBuffer(SResultRowInfo* pResultRowInfo, STaskRuntime ...@@ -384,7 +410,7 @@ static void prepareResultListBuffer(SResultRowInfo* pResultRowInfo, STaskRuntime
char *t = realloc(pResultRowInfo->pResult, (size_t)(newCapacity * POINTER_BYTES)); char *t = realloc(pResultRowInfo->pResult, (size_t)(newCapacity * POINTER_BYTES));
if (t == NULL) { if (t == NULL) {
longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_OUT_OF_MEMORY); longjmp(env, TSDB_CODE_QRY_OUT_OF_MEMORY);
} }
pResultRowInfo->pResult = (SResultRow **)t; pResultRowInfo->pResult = (SResultRow **)t;
...@@ -473,7 +499,7 @@ static SResultRow* doSetResultOutBufByKey(STaskRuntimeEnv* pRuntimeEnv, SResultR ...@@ -473,7 +499,7 @@ static SResultRow* doSetResultOutBufByKey(STaskRuntimeEnv* pRuntimeEnv, SResultR
} }
if (!existed) { if (!existed) {
prepareResultListBuffer(pResultRowInfo, pRuntimeEnv); // prepareResultListBuffer(pResultRowInfo, pRuntimeEnv);
SResultRow *pResult = NULL; SResultRow *pResult = NULL;
if (p1 == NULL) { if (p1 == NULL) {
...@@ -507,6 +533,80 @@ static SResultRow* doSetResultOutBufByKey(STaskRuntimeEnv* pRuntimeEnv, SResultR ...@@ -507,6 +533,80 @@ static SResultRow* doSetResultOutBufByKey(STaskRuntimeEnv* pRuntimeEnv, SResultR
return pResultRowInfo->pResult[pResultRowInfo->curPos]; return pResultRowInfo->pResult[pResultRowInfo->curPos];
} }
static SResultRow* doSetResultOutBufByKey_rv(SResultRowInfo* pResultRowInfo, int64_t tid, char* pData, int16_t bytes,
bool masterscan, uint64_t tableGroupId, SExecTaskInfo* pTaskInfo, bool isIntervalQuery, SAggOperatorInfo* pAggInfo) {
bool existed = false;
SET_RES_WINDOW_KEY(pAggInfo->keyBuf, pData, bytes, tableGroupId);
SResultRow **p1 =
(SResultRow **)taosHashGet(pAggInfo->pResultRowHashTable, pAggInfo->keyBuf, GET_RES_WINDOW_KEY_LEN(bytes));
// in case of repeat scan/reverse scan, no new time window added.
if (isIntervalQuery) {
if (!masterscan) { // the *p1 may be NULL in case of sliding+offset exists.
return (p1 != NULL)? *p1:NULL;
}
if (p1 != NULL) {
if (pResultRowInfo->size == 0) {
existed = false;
assert(pResultRowInfo->curPos == -1);
} else if (pResultRowInfo->size == 1) {
existed = (pResultRowInfo->pResult[0] == (*p1));
pResultRowInfo->curPos = 0;
} else { // check if current pResultRowInfo contains the existed pResultRow
SET_RES_EXT_WINDOW_KEY(pAggInfo->keyBuf, pData, bytes, tid, pResultRowInfo);
int64_t* index = taosHashGet(pAggInfo->pResultRowListSet, pAggInfo->keyBuf, GET_RES_EXT_WINDOW_KEY_LEN(bytes));
if (index != NULL) {
pResultRowInfo->curPos = (int32_t) *index;
existed = true;
} else {
existed = false;
}
}
}
} else {
// In case of group by column query, the required SResultRow object must be existed in the pResultRowInfo object.
if (p1 != NULL) {
return *p1;
}
}
if (!existed) {
prepareResultListBuffer(pResultRowInfo, pTaskInfo->env);
SResultRow *pResult = NULL;
if (p1 == NULL) {
pResult = getNewResultRow(pAggInfo->pool);
int32_t ret = initResultRow(pResult);
if (ret != TSDB_CODE_SUCCESS) {
longjmp(pTaskInfo->env, TSDB_CODE_QRY_OUT_OF_MEMORY);
}
// add a new result set for a new group
taosHashPut(pAggInfo->pResultRowHashTable, pAggInfo->keyBuf, GET_RES_WINDOW_KEY_LEN(bytes), &pResult, POINTER_BYTES);
SResultRowCell cell = {.groupId = tableGroupId, .pRow = pResult};
taosArrayPush(pAggInfo->pResultRowArrayList, &cell);
} else {
pResult = *p1;
}
pResultRowInfo->curPos = pResultRowInfo->size;
pResultRowInfo->pResult[pResultRowInfo->size++] = pResult;
int64_t index = pResultRowInfo->curPos;
SET_RES_EXT_WINDOW_KEY(pAggInfo->keyBuf, pData, bytes, tid, pResultRowInfo);
taosHashPut(pAggInfo->pResultRowListSet, pAggInfo->keyBuf, GET_RES_EXT_WINDOW_KEY_LEN(bytes), &index, POINTER_BYTES);
}
// too many time window in query
if (pResultRowInfo->size > MAX_INTERVAL_TIME_WINDOW) {
longjmp(pTaskInfo->env, TSDB_CODE_QRY_TOO_MANY_TIMEWINDOW);
}
return pResultRowInfo->pResult[pResultRowInfo->curPos];
}
static void getInitialStartTimeWindow(STaskAttr* pQueryAttr, TSKEY ts, STimeWindow* w) { static void getInitialStartTimeWindow(STaskAttr* pQueryAttr, TSKEY ts, STimeWindow* w) {
if (QUERY_IS_ASC_QUERY(pQueryAttr)) { if (QUERY_IS_ASC_QUERY(pQueryAttr)) {
getAlignQueryTimeWindow(pQueryAttr, ts, ts, pQueryAttr->window.ekey, w); getAlignQueryTimeWindow(pQueryAttr, ts, ts, pQueryAttr->window.ekey, w);
...@@ -1023,43 +1123,52 @@ static void doSetInputDataBlockInfo(SOperatorInfo* pOperator, SQLFunctionCtx* pC ...@@ -1023,43 +1123,52 @@ static void doSetInputDataBlockInfo(SOperatorInfo* pOperator, SQLFunctionCtx* pC
} }
void setInputDataBlock(SOperatorInfo* pOperator, SQLFunctionCtx* pCtx, SSDataBlock* pBlock, int32_t order) { void setInputDataBlock(SOperatorInfo* pOperator, SQLFunctionCtx* pCtx, SSDataBlock* pBlock, int32_t order) {
if (pCtx[0].functionId == FUNCTION_ARITHM) { // if (pCtx[0].functionId == FUNCTION_ARITHM) {
// SScalar* pSupport = (SScalarFunctionSupport*) pCtx[0].param[1].pz; // SScalar* pSupport = (SScalarFunctionSupport*) pCtx[0].param[1].pz;
// if (pSupport->colList == NULL) { // if (pSupport->colList == NULL) {
// doSetInputDataBlock(pOperator, pCtx, pBlock, order); // doSetInputDataBlock(pOperator, pCtx, pBlock, order);
// } else { // } else {
// doSetInputDataBlockInfo(pOperator, pCtx, pBlock, order); // doSetInputDataBlockInfo(pOperator, pCtx, pBlock, order);
// } // }
} else { // } else {
if (pBlock->pDataBlock != NULL) { if (pBlock->pDataBlock != NULL) {
doSetInputDataBlock(pOperator, pCtx, pBlock, order); doSetInputDataBlock(pOperator, pCtx, pBlock, order);
} else { } else {
doSetInputDataBlockInfo(pOperator, pCtx, pBlock, order); doSetInputDataBlockInfo(pOperator, pCtx, pBlock, order);
} }
} // }
} }
static void doSetInputDataBlock(SOperatorInfo* pOperator, SQLFunctionCtx* pCtx, SSDataBlock* pBlock, int32_t order) { static void doSetInputDataBlock(SOperatorInfo* pOperator, SQLFunctionCtx* pCtx, SSDataBlock* pBlock, int32_t order) {
#if 0
for (int32_t i = 0; i < pOperator->numOfOutput; ++i) { for (int32_t i = 0; i < pOperator->numOfOutput; ++i) {
pCtx[i].order = order; pCtx[i].order = order;
pCtx[i].size = pBlock->info.rows; pCtx[i].size = pBlock->info.rows;
pCtx[i].currentStage = (uint8_t)pOperator->pRuntimeEnv->scanFlag; pCtx[i].currentStage = MAIN_SCAN/*(uint8_t)pOperator->pRuntimeEnv->scanFlag*/;
setBlockStatisInfo(&pCtx[i], pBlock, &pOperator->pExpr[i].base.colInfo); setBlockStatisInfo(&pCtx[i], pBlock, pOperator->pExpr[i].base.pColumns);
if (pCtx[i].functionId == FUNCTION_ARITHM) { if (pCtx[i].functionId == FUNCTION_ARITHM) {
// setArithParams((SScalarFunctionSupport*)pCtx[i].param[1].pz, &pOperator->pExpr[i], pBlock); // setArithParams((SScalarFunctionSupport*)pCtx[i].param[1].pz, &pOperator->pExpr[i], pBlock);
} else { } else {
SColIndex* pCol = &pOperator->pExpr[i].base.pColumns->info.; uint32_t flag = pOperator->pExpr[i].base.pColumns->flag;
if (TSDB_COL_IS_NORMAL_COL(pCol->flag) || (pCtx[i].functionId == FUNCTION_BLKINFO) || if (TSDB_COL_IS_NORMAL_COL(flag) /*|| (pCtx[i].functionId == FUNCTION_BLKINFO) ||
(TSDB_COL_IS_TAG(pCol->flag) && pOperator->pRuntimeEnv->scanFlag == MERGE_STAGE)) { (TSDB_COL_IS_TAG(flag) && pOperator->pRuntimeEnv->scanFlag == MERGE_STAGE)*/) {
SColIndex* pColIndex = &pOperator->pExpr[i].base.colInfo;
SColumnInfoData* p = taosArrayGet(pBlock->pDataBlock, pColIndex->colIndex); SColumn* pCol = pOperator->pExpr[i].base.pColumns;
if (pCtx[i].columnIndex == -1) {
for(int32_t j = 0; j < pBlock->info.numOfCols; ++j) {
SColumnInfoData* pColData = taosArrayGet(pBlock->pDataBlock, j);
if (pColData->info.colId == pCol->info.colId) {
pCtx[i].columnIndex = j;
break;
}
}
}
SColumnInfoData* p = taosArrayGet(pBlock->pDataBlock, pCtx[i].columnIndex);
// in case of the block distribution query, the inputBytes is not a constant value. // in case of the block distribution query, the inputBytes is not a constant value.
pCtx[i].pInput = p->pData; pCtx[i].pInput = p->pData;
assert(p->info.colId == pColIndex->info.colId && pCtx[i].inputType == p->info.type); assert(p->info.colId == pCol->info.colId);
if (pCtx[i].functionId < 0) { if (pCtx[i].functionId < 0) {
SColumnInfoData* tsInfo = taosArrayGet(pBlock->pDataBlock, 0); SColumnInfoData* tsInfo = taosArrayGet(pBlock->pDataBlock, 0);
...@@ -1070,37 +1179,33 @@ static void doSetInputDataBlock(SOperatorInfo* pOperator, SQLFunctionCtx* pCtx, ...@@ -1070,37 +1179,33 @@ static void doSetInputDataBlock(SOperatorInfo* pOperator, SQLFunctionCtx* pCtx,
// uint32_t status = aAggs[pCtx[i].functionId].status; // uint32_t status = aAggs[pCtx[i].functionId].status;
// if ((status & (FUNCSTATE_SELECTIVITY | FUNCSTATE_NEED_TS)) != 0) { // if ((status & (FUNCSTATE_SELECTIVITY | FUNCSTATE_NEED_TS)) != 0) {
// SColumnInfoData* tsInfo = taosArrayGet(pBlock->pDataBlock, 0); SColumnInfoData* tsInfo = taosArrayGet(pBlock->pDataBlock, 0);
// // In case of the top/bottom query again the nest query result, which has no timestamp column // In case of the top/bottom query again the nest query result, which has no timestamp column
// // don't set the ptsList attribute. // don't set the ptsList attribute.
// if (tsInfo->info.type == TSDB_DATA_TYPE_TIMESTAMP) { if (tsInfo->info.type == TSDB_DATA_TYPE_TIMESTAMP) {
// pCtx[i].ptsList = (int64_t*) tsInfo->pData; pCtx[i].ptsList = (int64_t*) tsInfo->pData;
// } else { } else {
// pCtx[i].ptsList = NULL; pCtx[i].ptsList = NULL;
// } }
// }
// } else if (TSDB_COL_IS_UD_COL(pCol->flag) && (pOperator->pRuntimeEnv->scanFlag == MERGE_STAGE)) {
// SColIndex* pColIndex = &pOperator->pExpr[i].base.colInfo;
// SColumnInfoData* p = taosArrayGet(pBlock->pDataBlock, pColIndex->colIndex);
//
// pCtx[i].pInput = p->pData;
// assert(p->info.colId == pColIndex->info.colId && pCtx[i].inputType == p->info.type);
// for(int32_t j = 0; j < pBlock->info.rows; ++j) {
// char* dst = p->pData + j * p->info.bytes;
// taosVariantDump(&pOperator->pExpr[i].base.param[1], dst, p->info.type, true);
// } // }
} else if (TSDB_COL_IS_UD_COL(pCol->flag) && (pOperator->pRuntimeEnv->scanFlag == MERGE_STAGE)) {
SColIndex* pColIndex = &pOperator->pExpr[i].base.colInfo;
SColumnInfoData* p = taosArrayGet(pBlock->pDataBlock, pColIndex->colIndex);
pCtx[i].pInput = p->pData;
assert(p->info.colId == pColIndex->info.colId && pCtx[i].inputType == p->info.type);
for(int32_t j = 0; j < pBlock->info.rows; ++j) {
char* dst = p->pData + j * p->info.bytes;
taosVariantDump(&pOperator->pExpr[i].base.param[1], dst, p->info.type, true);
}
} }
} }
} }
#endif
} }
static void doAggregateImpl(SOperatorInfo* pOperator, TSKEY startTs, SQLFunctionCtx* pCtx, SSDataBlock* pSDataBlock) { static void doAggregateImpl(SOperatorInfo* pOperator, TSKEY startTs, SQLFunctionCtx* pCtx, SSDataBlock* pSDataBlock) {
STaskRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv;
for (int32_t k = 0; k < pOperator->numOfOutput; ++k) { for (int32_t k = 0; k < pOperator->numOfOutput; ++k) {
if (functionNeedToExecute(pRuntimeEnv, &pCtx[k])) { if (functionNeedToExecute(NULL, &pCtx[k])) {
pCtx[k].startTs = startTs;// this can be set during create the struct pCtx[k].startTs = startTs;// this can be set during create the struct
pCtx[k].fpSet->addInput(&pCtx[k]); pCtx[k].fpSet->addInput(&pCtx[k]);
} }
...@@ -1719,7 +1824,6 @@ static int32_t getGroupbyColumnIndex(SGroupbyExpr *pGroupbyExpr, SSDataBlock* pD ...@@ -1719,7 +1824,6 @@ static int32_t getGroupbyColumnIndex(SGroupbyExpr *pGroupbyExpr, SSDataBlock* pD
static bool functionNeedToExecute(STaskRuntimeEnv *pRuntimeEnv, SQLFunctionCtx *pCtx) { static bool functionNeedToExecute(STaskRuntimeEnv *pRuntimeEnv, SQLFunctionCtx *pCtx) {
struct SResultRowEntryInfo *pResInfo = GET_RES_INFO(pCtx); struct SResultRowEntryInfo *pResInfo = GET_RES_INFO(pCtx);
STaskAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
// in case of timestamp column, always generated results. // in case of timestamp column, always generated results.
int32_t functionId = pCtx->functionId; int32_t functionId = pCtx->functionId;
...@@ -1732,28 +1836,28 @@ static bool functionNeedToExecute(STaskRuntimeEnv *pRuntimeEnv, SQLFunctionCtx * ...@@ -1732,28 +1836,28 @@ static bool functionNeedToExecute(STaskRuntimeEnv *pRuntimeEnv, SQLFunctionCtx *
} }
if (functionId == FUNCTION_FIRST_DST || functionId == FUNCTION_FIRST) { if (functionId == FUNCTION_FIRST_DST || functionId == FUNCTION_FIRST) {
return QUERY_IS_ASC_QUERY(pQueryAttr); // return QUERY_IS_ASC_QUERY(pQueryAttr);
} }
// denote the order type // denote the order type
if ((functionId == FUNCTION_LAST_DST || functionId == FUNCTION_LAST)) { if ((functionId == FUNCTION_LAST_DST || functionId == FUNCTION_LAST)) {
return pCtx->param[0].i == pQueryAttr->order.order; // return pCtx->param[0].i == pQueryAttr->order.order;
} }
// in the reverse table scan, only the following functions need to be executed // in the reverse table scan, only the following functions need to be executed
if (IS_REVERSE_SCAN(pRuntimeEnv) || // if (IS_REVERSE_SCAN(pRuntimeEnv) ||
(pRuntimeEnv->scanFlag == REPEAT_SCAN && functionId != FUNCTION_STDDEV && functionId != FUNCTION_PERCT)) { // (pRuntimeEnv->scanFlag == REPEAT_SCAN && functionId != FUNCTION_STDDEV && functionId != FUNCTION_PERCT)) {
return false; // return false;
} // }
return true; return true;
} }
void setBlockStatisInfo(SQLFunctionCtx *pCtx, SSDataBlock* pSDataBlock, SColIndex* pColIndex) { void setBlockStatisInfo(SQLFunctionCtx *pCtx, SSDataBlock* pSDataBlock, SColumn* pColumn) {
SColumnDataAgg *pAgg = NULL; SColumnDataAgg *pAgg = NULL;
if (pSDataBlock->pBlockAgg != NULL && TSDB_COL_IS_NORMAL_COL(pColIndex->flag)) { if (pSDataBlock->pBlockAgg != NULL && TSDB_COL_IS_NORMAL_COL(pColumn->flag)) {
pAgg = &pSDataBlock->pBlockAgg[pColIndex->colIndex]; pAgg = &pSDataBlock->pBlockAgg[pCtx->columnIndex];
pCtx->agg = *pAgg; pCtx->agg = *pAgg;
pCtx->isAggSet = true; pCtx->isAggSet = true;
...@@ -1762,10 +1866,10 @@ void setBlockStatisInfo(SQLFunctionCtx *pCtx, SSDataBlock* pSDataBlock, SColInde ...@@ -1762,10 +1866,10 @@ void setBlockStatisInfo(SQLFunctionCtx *pCtx, SSDataBlock* pSDataBlock, SColInde
pCtx->isAggSet = false; pCtx->isAggSet = false;
} }
pCtx->hasNull = hasNull(pColIndex, pAgg); pCtx->hasNull = hasNull(pColumn, pAgg);
// set the statistics data for primary time stamp column // set the statistics data for primary time stamp column
if (pCtx->functionId == FUNCTION_SPREAD && pColIndex->colId == PRIMARYKEY_TIMESTAMP_COL_ID) { if (pCtx->functionId == FUNCTION_SPREAD && pColumn->info.colId == PRIMARYKEY_TIMESTAMP_COL_ID) {
pCtx->isAggSet = true; pCtx->isAggSet = true;
pCtx->agg.min = pSDataBlock->info.window.skey; pCtx->agg.min = pSDataBlock->info.window.skey;
pCtx->agg.max = pSDataBlock->info.window.ekey; pCtx->agg.max = pSDataBlock->info.window.ekey;
...@@ -1918,7 +2022,9 @@ static SQLFunctionCtx* createSqlFunctionCtx(STaskRuntimeEnv* pRuntimeEnv, SExprI ...@@ -1918,7 +2022,9 @@ static SQLFunctionCtx* createSqlFunctionCtx(STaskRuntimeEnv* pRuntimeEnv, SExprI
return pFuncCtx; return pFuncCtx;
} }
static SQLFunctionCtx* createSqlFunctionCtx_rv(SExprInfo* pExpr, int32_t numOfOutput, int32_t** rowCellInfoOffset) { static SQLFunctionCtx* createSqlFunctionCtx_rv(SArray* pExprInfo, int32_t** rowCellInfoOffset) {
size_t numOfOutput = taosArrayGetSize(pExprInfo);
SQLFunctionCtx * pFuncCtx = (SQLFunctionCtx *)calloc(numOfOutput, sizeof(SQLFunctionCtx)); SQLFunctionCtx * pFuncCtx = (SQLFunctionCtx *)calloc(numOfOutput, sizeof(SQLFunctionCtx));
if (pFuncCtx == NULL) { if (pFuncCtx == NULL) {
return NULL; return NULL;
...@@ -1931,8 +2037,11 @@ static SQLFunctionCtx* createSqlFunctionCtx_rv(SExprInfo* pExpr, int32_t numOfOu ...@@ -1931,8 +2037,11 @@ static SQLFunctionCtx* createSqlFunctionCtx_rv(SExprInfo* pExpr, int32_t numOfOu
} }
for (int32_t i = 0; i < numOfOutput; ++i) { for (int32_t i = 0; i < numOfOutput; ++i) {
SSqlExpr *pSqlExpr = &pExpr[i].base; SExprInfo* pExpr = taosArrayGetP(pExprInfo, i);
SSqlExpr *pSqlExpr = &pExpr->base;
SQLFunctionCtx* pCtx = &pFuncCtx[i]; SQLFunctionCtx* pCtx = &pFuncCtx[i];
#if 0 #if 0
SColIndex *pIndex = &pSqlExpr->colInfo; SColIndex *pIndex = &pSqlExpr->colInfo;
...@@ -1943,15 +2052,16 @@ static SQLFunctionCtx* createSqlFunctionCtx_rv(SExprInfo* pExpr, int32_t numOfOu ...@@ -1943,15 +2052,16 @@ static SQLFunctionCtx* createSqlFunctionCtx_rv(SExprInfo* pExpr, int32_t numOfOu
pCtx->requireNull = false; pCtx->requireNull = false;
} }
#endif #endif
// pCtx->inputBytes = pSqlExpr->colBytes; // pCtx->inputBytes = pSqlExpr->;
// pCtx->inputType = pSqlExpr->colType; // pCtx->inputType = pSqlExpr->colType;
pCtx->ptsOutputBuf = NULL; pCtx->ptsOutputBuf = NULL;
pCtx->fpSet = fpSet;
pCtx->columnIndex = -1;
pCtx->resDataInfo.bytes = pSqlExpr->resSchema.bytes; pCtx->resDataInfo.bytes = pSqlExpr->resSchema.bytes;
pCtx->resDataInfo.type = pSqlExpr->resSchema.type; pCtx->resDataInfo.type = pSqlExpr->resSchema.type;
// pCtx->order = pQueryAttr->order.order; pCtx->order = TSDB_ORDER_ASC;
// pCtx->functionId = pSqlExpr->functionId; // pCtx->functionId = pSqlExpr->functionId;
// pCtx->stableQuery = pQueryAttr->stableQuery; // pCtx->stableQuery = pQueryAttr->stableQuery;
pCtx->resDataInfo.intermediateBytes = pSqlExpr->interBytes; pCtx->resDataInfo.intermediateBytes = pSqlExpr->interBytes;
...@@ -2007,12 +2117,12 @@ static SQLFunctionCtx* createSqlFunctionCtx_rv(SExprInfo* pExpr, int32_t numOfOu ...@@ -2007,12 +2117,12 @@ static SQLFunctionCtx* createSqlFunctionCtx_rv(SExprInfo* pExpr, int32_t numOfOu
} }
} }
// for(int32_t i = 1; i < numOfOutput; ++i) { for(int32_t i = 1; i < numOfOutput; ++i) {
// (*rowCellInfoOffset)[i] = (int32_t)((*rowCellInfoOffset)[i - 1] + sizeof(SResultRowEntryInfo) + pExpr[i - 1].base.interBytes); SExprInfo* pExpr = taosArrayGetP(pExprInfo, i - 1);
// } (*rowCellInfoOffset)[i] = (int32_t)((*rowCellInfoOffset)[i - 1] + sizeof(SResultRowEntryInfo) + pExpr->base.interBytes);
}
setCtxTagColumnInfo(pFuncCtx, numOfOutput); setCtxTagColumnInfo(pFuncCtx, numOfOutput);
return pFuncCtx; return pFuncCtx;
} }
...@@ -2044,7 +2154,7 @@ static int32_t setupQueryRuntimeEnv(STaskRuntimeEnv *pRuntimeEnv, int32_t numOfT ...@@ -2044,7 +2154,7 @@ static int32_t setupQueryRuntimeEnv(STaskRuntimeEnv *pRuntimeEnv, int32_t numOfT
pRuntimeEnv->pResultRowHashTable = taosHashInit(numOfTables, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK); pRuntimeEnv->pResultRowHashTable = taosHashInit(numOfTables, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
pRuntimeEnv->pResultRowListSet = taosHashInit(numOfTables * 10, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_NO_LOCK); pRuntimeEnv->pResultRowListSet = taosHashInit(numOfTables * 10, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_NO_LOCK);
pRuntimeEnv->keyBuf = malloc(pQueryAttr->maxTableColumnWidth + sizeof(int64_t) + POINTER_BYTES); pRuntimeEnv->keyBuf = malloc(pQueryAttr->maxTableColumnWidth + sizeof(int64_t) + POINTER_BYTES);
pRuntimeEnv->pool = initResultRowPool(getResultRowSize(pRuntimeEnv)); // pRuntimeEnv->pool = initResultRowPool(getResultRowSize(pRuntimeEnv));
pRuntimeEnv->pResultRowArrayList = taosArrayInit(numOfTables, sizeof(SResultRowCell)); pRuntimeEnv->pResultRowArrayList = taosArrayInit(numOfTables, sizeof(SResultRowCell));
pRuntimeEnv->prevRow = malloc(POINTER_BYTES * pQueryAttr->numOfCols + pQueryAttr->srcRowSize); pRuntimeEnv->prevRow = malloc(POINTER_BYTES * pQueryAttr->numOfCols + pQueryAttr->srcRowSize);
...@@ -3457,6 +3567,43 @@ void setDefaultOutputBuf(STaskRuntimeEnv *pRuntimeEnv, SOptrBasicInfo *pInfo, in ...@@ -3457,6 +3567,43 @@ void setDefaultOutputBuf(STaskRuntimeEnv *pRuntimeEnv, SOptrBasicInfo *pInfo, in
initCtxOutputBuffer(pCtx, pDataBlock->info.numOfCols); initCtxOutputBuffer(pCtx, pDataBlock->info.numOfCols);
} }
void setDefaultOutputBuf_rv(SAggOperatorInfo* pAggInfo, int64_t uid, int32_t stage, SExecTaskInfo* pTaskInfo) {
SOptrBasicInfo *pInfo = &pAggInfo->binfo;
SQLFunctionCtx* pCtx = pInfo->pCtx;
SSDataBlock* pDataBlock = pInfo->pRes;
int32_t* rowCellInfoOffset = pInfo->rowCellInfoOffset;
SResultRowInfo* pResultRowInfo = &pInfo->resultRowInfo;
int64_t tid = 0;
pInfo->keyBuf = realloc(pInfo->keyBuf, sizeof(tid) + sizeof(int64_t) + POINTER_BYTES);
SResultRow* pRow = doSetResultOutBufByKey_rv(pResultRowInfo, tid, (char *)&tid, sizeof(tid), true, uid, pTaskInfo, false, pAggInfo);
for (int32_t i = 0; i < pDataBlock->info.numOfCols; ++i) {
SColumnInfoData* pData = taosArrayGet(pDataBlock->pDataBlock, i);
/*
* set the output buffer information and intermediate buffer
* not all queries require the interResultBuf, such as COUNT/TAGPRJ/PRJ/TAG etc.
*/
struct SResultRowEntryInfo* pEntry = getResultCell(pRow, i, rowCellInfoOffset);
cleanupResultRowEntry(pEntry);
pCtx[i].resultInfo = pEntry;
pCtx[i].pOutput = pData->pData;
pCtx[i].currentStage = stage;
assert(pCtx[i].pOutput != NULL);
// set the timestamp output buffer for top/bottom/diff query
int32_t fid = pCtx[i].functionId;
if (fid == FUNCTION_TOP || fid == FUNCTION_BOTTOM || fid == FUNCTION_DIFF || fid == FUNCTION_DERIVATIVE) {
if (i > 0) pCtx[i].ptsOutputBuf = pCtx[i-1].pOutput;
}
}
initCtxOutputBuffer(pCtx, pDataBlock->info.numOfCols);
}
void updateOutputBuf(SOptrBasicInfo* pBInfo, int32_t *bufCapacity, int32_t numOfInputRows) { void updateOutputBuf(SOptrBasicInfo* pBInfo, int32_t *bufCapacity, int32_t numOfInputRows) {
SSDataBlock* pDataBlock = pBInfo->pRes; SSDataBlock* pDataBlock = pBInfo->pRes;
...@@ -3579,49 +3726,49 @@ static void setupEnvForReverseScan(STableScanInfo *pTableScanInfo, SQLFunctionCt ...@@ -3579,49 +3726,49 @@ static void setupEnvForReverseScan(STableScanInfo *pTableScanInfo, SQLFunctionCt
void finalizeQueryResult(SOperatorInfo* pOperator, SQLFunctionCtx* pCtx, SResultRowInfo* pResultRowInfo, int32_t* rowCellInfoOffset) { void finalizeQueryResult(SOperatorInfo* pOperator, SQLFunctionCtx* pCtx, SResultRowInfo* pResultRowInfo, int32_t* rowCellInfoOffset) {
STaskRuntimeEnv *pRuntimeEnv = pOperator->pRuntimeEnv; STaskRuntimeEnv *pRuntimeEnv = pOperator->pRuntimeEnv;
STaskAttr *pQueryAttr = pRuntimeEnv->pQueryAttr; // STaskAttr *pQueryAttr = pRuntimeEnv->pQueryAttr;
int32_t numOfOutput = pOperator->numOfOutput; int32_t numOfOutput = pOperator->numOfOutput;
if (pQueryAttr->groupbyColumn || QUERY_IS_INTERVAL_QUERY(pQueryAttr) || pQueryAttr->sw.gap > 0 || pQueryAttr->stateWindow) { // if (pQueryAttr->groupbyColumn || QUERY_IS_INTERVAL_QUERY(pQueryAttr) || pQueryAttr->sw.gap > 0 || pQueryAttr->stateWindow) {
// for each group result, call the finalize function for each column // // for each group result, call the finalize function for each column
if (pQueryAttr->groupbyColumn) { // if (pQueryAttr->groupbyColumn) {
closeAllResultRows(pResultRowInfo); // closeAllResultRows(pResultRowInfo);
} // }
//
for (int32_t i = 0; i < pResultRowInfo->size; ++i) { // for (int32_t i = 0; i < pResultRowInfo->size; ++i) {
SResultRow *buf = pResultRowInfo->pResult[i]; // SResultRow *buf = pResultRowInfo->pResult[i];
if (!isResultRowClosed(pResultRowInfo, i)) { // if (!isResultRowClosed(pResultRowInfo, i)) {
continue; // continue;
} // }
//
setResultOutputBuf(pRuntimeEnv, buf, pCtx, numOfOutput, rowCellInfoOffset); // setResultOutputBuf(pRuntimeEnv, buf, pCtx, numOfOutput, rowCellInfoOffset);
//
for (int32_t j = 0; j < numOfOutput; ++j) { // for (int32_t j = 0; j < numOfOutput; ++j) {
// pCtx[j].startTs = buf->win.skey; //// pCtx[j].startTs = buf->win.skey;
// if (pCtx[j].functionId < 0) { //// if (pCtx[j].functionId < 0) {
// doInvokeUdf(pRuntimeEnv->pUdfInfo, &pCtx[j], 0, TSDB_UDF_FUNC_FINALIZE); //// doInvokeUdf(pRuntimeEnv->pUdfInfo, &pCtx[j], 0, TSDB_UDF_FUNC_FINALIZE);
// } else { //// } else {
// aAggs[pCtx[j].functionId].xFinalize(&pCtx[j]); //// aAggs[pCtx[j].functionId].xFinalize(&pCtx[j]);
// } //// }
} // }
//
//
/* // /*
* set the number of output results for group by normal columns, the number of output rows usually is 1 except // * set the number of output results for group by normal columns, the number of output rows usually is 1 except
* the top and bottom query // * the top and bottom query
*/ // */
buf->numOfRows = (uint16_t)getNumOfResult(pCtx, numOfOutput); // buf->numOfRows = (uint16_t)getNumOfResult(pCtx, numOfOutput);
} // }
//
} else { // } else {
for (int32_t j = 0; j < numOfOutput; ++j) { for (int32_t j = 0; j < numOfOutput; ++j) {
// if (pCtx[j].functionId < 0) { // if (pCtx[j].functionId < 0) {
// doInvokeUdf(pRuntimeEnv->pUdfInfo, &pCtx[j], 0, TSDB_UDF_FUNC_FINALIZE); // doInvokeUdf(pRuntimeEnv->pUdfInfo, &pCtx[j], 0, TSDB_UDF_FUNC_FINALIZE);
// } else { // } else {
// aAggs[pCtx[j].functionId].xFinalize(&pCtx[j]); pCtx[j].fpSet->finalize(&pCtx[j]);
// } // }
} }
} // }
} }
static bool hasMainOutput(STaskAttr *pQueryAttr) { static bool hasMainOutput(STaskAttr *pQueryAttr) {
...@@ -5224,6 +5371,11 @@ SOperatorInfo* createTableBlockInfoScanOperator(void* pTsdbReadHandle, STaskRunt ...@@ -5224,6 +5371,11 @@ SOperatorInfo* createTableBlockInfoScanOperator(void* pTsdbReadHandle, STaskRunt
return pOperator; return pOperator;
} }
SOperatorInfo* createSubmitBlockScanOperatorInfo(void *pSubmitBlockReadHandle, int32_t numOfOutput, SExecTaskInfo* pTaskInfo) {
}
void setTableScanFilterOperatorInfo(STableScanInfo* pTableScanInfo, SOperatorInfo* pDownstream) { void setTableScanFilterOperatorInfo(STableScanInfo* pTableScanInfo, SOperatorInfo* pDownstream) {
assert(pTableScanInfo != NULL && pDownstream != NULL); assert(pTableScanInfo != NULL && pDownstream != NULL);
...@@ -5602,11 +5754,7 @@ static SSDataBlock* doAggregate(void* param, bool* newgroup) { ...@@ -5602,11 +5754,7 @@ static SSDataBlock* doAggregate(void* param, bool* newgroup) {
SAggOperatorInfo* pAggInfo = pOperator->info; SAggOperatorInfo* pAggInfo = pOperator->info;
SOptrBasicInfo* pInfo = &pAggInfo->binfo; SOptrBasicInfo* pInfo = &pAggInfo->binfo;
STaskRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv; int32_t order = TSDB_ORDER_ASC;
STaskAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
int32_t order = pQueryAttr->order.order;
SOperatorInfo* downstream = pOperator->pDownstream[0]; SOperatorInfo* downstream = pOperator->pDownstream[0];
while(1) { while(1) {
...@@ -5618,18 +5766,13 @@ static SSDataBlock* doAggregate(void* param, bool* newgroup) { ...@@ -5618,18 +5766,13 @@ static SSDataBlock* doAggregate(void* param, bool* newgroup) {
break; break;
} }
if (pRuntimeEnv->current != NULL) { // if (pAggInfo->current != NULL) {
setTagValue(pOperator, pRuntimeEnv->current->pTable, pInfo->pCtx, pOperator->numOfOutput); // setTagValue(pOperator, pAggInfo->current->pTable, pInfo->pCtx, pOperator->numOfOutput);
}
// if (downstream->operatorType == OP_DataBlocksOptScan) {
// STableScanInfo* pScanInfo = downstream->info;
// order = getTableScanOrder(pScanInfo);
// } // }
// the pDataBlock are always the same one, no need to call this again // the pDataBlock are always the same one, no need to call this again
setInputDataBlock(pOperator, pInfo->pCtx, pBlock, order); setInputDataBlock(pOperator, pInfo->pCtx, pBlock, order);
doAggregateImpl(pOperator, pQueryAttr->window.skey, pInfo->pCtx, pBlock); doAggregateImpl(pOperator, 0, pInfo->pCtx, pBlock);
} }
doSetOperatorCompleted(pOperator); doSetOperatorCompleted(pOperator);
...@@ -6516,19 +6659,31 @@ static void destroyOperatorInfo(SOperatorInfo* pOperator) { ...@@ -6516,19 +6659,31 @@ static void destroyOperatorInfo(SOperatorInfo* pOperator) {
tfree(pOperator); tfree(pOperator);
} }
SOperatorInfo* createAggregateOperatorInfo(SOperatorInfo* downstream, SExprInfo* pExpr, int32_t numOfOutput) { SOperatorInfo* createAggregateOperatorInfo(SOperatorInfo* downstream, SArray* pExprInfo, SExecTaskInfo* pTaskInfo) {
SAggOperatorInfo* pInfo = calloc(1, sizeof(SAggOperatorInfo)); SAggOperatorInfo* pInfo = calloc(1, sizeof(SAggOperatorInfo));
// STaskAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
int32_t numOfRows = 1;//(int32_t)(getRowNumForMultioutput(pQueryAttr, pQueryAttr->topBotQuery, pQueryAttr->stableQuery)); int32_t numOfRows = 1;//(int32_t)(getRowNumForMultioutput(pQueryAttr, pQueryAttr->topBotQuery, pQueryAttr->stableQuery));
pInfo->binfo.pRes = createOutputBuf(pExpr, numOfOutput, numOfRows); size_t numOfOutput = taosArrayGetSize(pExprInfo);
pInfo->binfo.pCtx = createSqlFunctionCtx_rv(pExpr, numOfOutput, &pInfo->binfo.rowCellInfoOffset); pInfo->binfo.pRes = createOutputBuf_rv(pExprInfo, numOfRows);
pInfo->binfo.pCtx = createSqlFunctionCtx_rv(pExprInfo, &pInfo->binfo.rowCellInfoOffset);
pInfo->pResultRowHashTable = taosHashInit(10, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
pInfo->pResultRowListSet = taosHashInit(100, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_NO_LOCK);
pInfo->keyBuf = malloc(1024 + sizeof(int64_t) + POINTER_BYTES); // TODO:
pInfo->pool = initResultRowPool(getResultRowSize(pExprInfo));
pInfo->pResultRowArrayList = taosArrayInit(10, sizeof(SResultRowCell));
initResultRowInfo(&pInfo->binfo.resultRowInfo, 8, TSDB_DATA_TYPE_INT); initResultRowInfo(&pInfo->binfo.resultRowInfo, 8, TSDB_DATA_TYPE_INT);
pInfo->seed = rand(); pInfo->seed = rand();
// setDefaultOutputBuf(pRuntimeEnv, &pInfo->binfo, pInfo->seed, MAIN_SCAN); setDefaultOutputBuf_rv(pInfo, pInfo->seed, MAIN_SCAN, pTaskInfo);
SExprInfo* p = calloc(numOfOutput, sizeof(SExprInfo));
for(int32_t i = 0; i < taosArrayGetSize(pExprInfo); ++i) {
SExprInfo* pExpr = taosArrayGetP(pExprInfo, i);
assignExprInfo(&p[i], pExpr);
}
SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo)); SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
pOperator->name = "TableAggregate"; pOperator->name = "TableAggregate";
...@@ -6536,10 +6691,11 @@ SOperatorInfo* createAggregateOperatorInfo(SOperatorInfo* downstream, SExprInfo* ...@@ -6536,10 +6691,11 @@ SOperatorInfo* createAggregateOperatorInfo(SOperatorInfo* downstream, SExprInfo*
pOperator->blockingOptr = true; pOperator->blockingOptr = true;
pOperator->status = OP_IN_EXECUTING; pOperator->status = OP_IN_EXECUTING;
pOperator->info = pInfo; pOperator->info = pInfo;
pOperator->pExpr = pExpr; pOperator->pExpr = p;
pOperator->numOfOutput = numOfOutput; pOperator->numOfOutput = numOfOutput;
pOperator->pRuntimeEnv = NULL; pOperator->pRuntimeEnv = NULL;
pOperator->pTaskInfo = pTaskInfo;
pOperator->exec = doAggregate; pOperator->exec = doAggregate;
pOperator->cleanup = destroyAggOperatorInfo; pOperator->cleanup = destroyAggOperatorInfo;
appendDownstream(pOperator, downstream); appendDownstream(pOperator, downstream);
...@@ -7472,58 +7628,113 @@ static SExecTaskInfo* createExecTaskInfo(uint64_t queryId) { ...@@ -7472,58 +7628,113 @@ static SExecTaskInfo* createExecTaskInfo(uint64_t queryId) {
return pTaskInfo; return pTaskInfo;
} }
SOperatorInfo* doCreateOperatorTreeNode(SPhyNode* pPhyNode, SExecTaskInfo* pTaskInfo, void* param) { static tsdbReadHandleT doCreateDataReadHandle(STableScanPhyNode* pTableScanNode, void* readerHandle, uint64_t queryId);
SOperatorInfo* doCreateOperatorTreeNode(SPhyNode* pPhyNode, SExecTaskInfo* pTaskInfo, void* readerHandle, uint64_t queryId) {
if (pPhyNode->pChildren == NULL || taosArrayGetSize(pPhyNode->pChildren) == 0) { if (pPhyNode->pChildren == NULL || taosArrayGetSize(pPhyNode->pChildren) == 0) {
if (pPhyNode->info.type == OP_TableScan) { if (pPhyNode->info.type == OP_TableScan) {
SScanPhyNode* pScanPhyNode = (SScanPhyNode*)pPhyNode; SScanPhyNode* pScanPhyNode = (SScanPhyNode*)pPhyNode;
size_t numOfCols = taosArrayGetSize(pPhyNode->pTargets); size_t numOfCols = taosArrayGetSize(pPhyNode->pTargets);
return createTableScanOperatorInfo(param, pScanPhyNode->order, numOfCols, pScanPhyNode->count, pTaskInfo);
tsdbReadHandleT tReaderHandle = doCreateDataReadHandle((STableScanPhyNode*) pPhyNode, readerHandle, (uint64_t) queryId);
return createTableScanOperatorInfo(tReaderHandle, pScanPhyNode->order, numOfCols, pScanPhyNode->count, pTaskInfo);
} else if (pPhyNode->info.type == OP_DataBlocksOptScan) { } else if (pPhyNode->info.type == OP_DataBlocksOptScan) {
SScanPhyNode* pScanPhyNode = (SScanPhyNode*)pPhyNode; SScanPhyNode* pScanPhyNode = (SScanPhyNode*)pPhyNode;
size_t numOfCols = taosArrayGetSize(pPhyNode->pTargets); size_t numOfCols = taosArrayGetSize(pPhyNode->pTargets);
return createDataBlocksOptScanInfo(param, pScanPhyNode->order, numOfCols, pScanPhyNode->count, pScanPhyNode->reverse, pTaskInfo);
tsdbReadHandleT tReaderHandle = doCreateDataReadHandle((STableScanPhyNode*) pPhyNode, readerHandle, (uint64_t) queryId);
return createDataBlocksOptScanInfo(tReaderHandle, pScanPhyNode->order, numOfCols, pScanPhyNode->count, pScanPhyNode->reverse, pTaskInfo);
} else if (pPhyNode->info.type == OP_Exchange) { } else if (pPhyNode->info.type == OP_Exchange) {
SExchangePhyNode* pEx = (SExchangePhyNode*) pPhyNode; SExchangePhyNode* pEx = (SExchangePhyNode*) pPhyNode;
return createExchangeOperatorInfo(pEx->pSrcEndPoints, pEx->node.pTargets, pTaskInfo); return createExchangeOperatorInfo(pEx->pSrcEndPoints, pEx->node.pTargets, pTaskInfo);
} else { }
assert(0); }
if (pPhyNode->info.type == OP_Aggregate) {
size_t size = taosArrayGetSize(pPhyNode->pChildren);
assert(size == 1);
for (int32_t i = 0; i < size; ++i) {
SPhyNode* pChildNode = taosArrayGetP(pPhyNode->pChildren, i);
SOperatorInfo* op = doCreateOperatorTreeNode(pChildNode, pTaskInfo, readerHandle, queryId);
return createAggregateOperatorInfo(op, pPhyNode->pTargets, pTaskInfo);
} }
} }
} }
int32_t doCreateExecTaskInfo(SSubplan* pPlan, SExecTaskInfo** pTaskInfo, STableGroupInfo* pGroupInfo, void* readerHandle) { static tsdbReadHandleT createDataReadHandle(STableScanPhyNode* pTableScanNode, STableGroupInfo* pGroupInfo, void* readerHandle, uint64_t queryId) {
STsdbQueryCond cond = {.loadExternalRows = false}; STsdbQueryCond cond = {.loadExternalRows = false};
tsdbReadHandleT tsdbReadHandle = NULL; cond.order = pTableScanNode->scan.order;
cond.numOfCols = taosArrayGetSize(pTableScanNode->scan.node.pTargets);
cond.colList = calloc(cond.numOfCols, sizeof(SColumnInfo));
cond.twindow = pTableScanNode->window;
cond.type = BLOCK_LOAD_OFFSET_SEQ_ORDER;
SPhyNode* pPhyNode = pPlan->pNode; for (int32_t i = 0; i < cond.numOfCols; ++i) {
if (pPhyNode->info.type == OP_TableScan || pPhyNode->info.type == OP_DataBlocksOptScan) { SExprInfo* pExprInfo = taosArrayGetP(pTableScanNode->scan.node.pTargets, i);
STableScanPhyNode* pTableScanNode = (STableScanPhyNode*)pPhyNode; assert(pExprInfo->pExpr->nodeType == TEXPR_COL_NODE);
cond.order = pTableScanNode->scan.order;
cond.numOfCols = taosArrayGetSize(pTableScanNode->scan.node.pTargets); SSchema* pSchema = pExprInfo->pExpr->pSchema;
cond.colList = calloc(cond.numOfCols, sizeof(SColumnInfo)); cond.colList[i].type = pSchema->type;
cond.twindow = pTableScanNode->window; cond.colList[i].bytes = pSchema->bytes;
cond.type = BLOCK_LOAD_OFFSET_SEQ_ORDER; cond.colList[i].colId = pSchema->colId;
}
for (int32_t i = 0; i < cond.numOfCols; ++i) {
SExprInfo* pExprInfo = taosArrayGetP(pTableScanNode->scan.node.pTargets, i); return tsdbQueryTables(readerHandle, &cond, pGroupInfo, queryId, NULL);
assert(pExprInfo->pExpr->nodeType == TEXPR_COL_NODE); }
SSchema* pSchema = pExprInfo->pExpr->pSchema; static tsdbReadHandleT doCreateDataReadHandle(STableScanPhyNode* pTableScanNode, void* readerHandle, uint64_t queryId) {
cond.colList[i].type = pSchema->type; int32_t code = 0;
cond.colList[i].bytes = pSchema->bytes; STableGroupInfo groupInfo = {0};
cond.colList[i].colId = pSchema->colId;
} uint64_t uid = pTableScanNode->scan.uid;
STimeWindow window = pTableScanNode->window;
*pTaskInfo = createExecTaskInfo((uint64_t) pPlan->id.queryId); int32_t tableType = pTableScanNode->scan.tableType;
tsdbReadHandle = tsdbQueryTables(readerHandle, &cond, pGroupInfo, (*pTaskInfo)->id.queryId, NULL);
} else if (pPhyNode->info.type == OP_Exchange) { if (tableType == TSDB_SUPER_TABLE) {
*pTaskInfo = createExecTaskInfo((uint64_t) pPlan->id.queryId); code =
} else { tsdbQuerySTableByTagCond(readerHandle, uid, window.skey, NULL, 0, 0, NULL, &groupInfo, NULL, 0, queryId);
assert(0); if (code != TSDB_CODE_SUCCESS) {
goto _error;
}
} else { // Create one table group.
groupInfo.numOfTables = 1;
groupInfo.pGroupList = taosArrayInit(1, POINTER_BYTES);
SArray* pa = taosArrayInit(1, sizeof(STableKeyInfo));
STableKeyInfo info = {.pTable = NULL, .lastKey = 0, .uid = uid};
taosArrayPush(pa, &info);
taosArrayPush(groupInfo.pGroupList, &pa);
}
if (groupInfo.numOfTables == 0) {
code = 0;
// qDebug("no table qualified for query, reqId:0x%"PRIx64, (*pTask)->id.queryId);
goto _error;
} }
(*pTaskInfo)->pRoot = doCreateOperatorTreeNode(pPlan->pNode, *pTaskInfo, tsdbReadHandle); return createDataReadHandle(pTableScanNode, &groupInfo, readerHandle, queryId);
_error:
terrno = code;
return NULL;
}
int32_t doCreateExecTaskInfo(SSubplan* pPlan, SExecTaskInfo** pTaskInfo, void* readerHandle) {
tsdbReadHandleT tReaderHandle = NULL;
int32_t code = 0;
uint64_t queryId = pPlan->id.queryId;
SPhyNode* pPhyNode = pPlan->pNode;
*pTaskInfo = createExecTaskInfo(queryId);
(*pTaskInfo)->pRoot = doCreateOperatorTreeNode(pPlan->pNode, *pTaskInfo, readerHandle, queryId);
if ((*pTaskInfo)->pRoot == NULL) { if ((*pTaskInfo)->pRoot == NULL) {
return terrno; return terrno;
} }
......
...@@ -8,5 +8,5 @@ target_include_directories( ...@@ -8,5 +8,5 @@ target_include_directories(
target_link_libraries( target_link_libraries(
function function
PRIVATE os util common PRIVATE os util common nodes
) )
\ No newline at end of file
/*
* 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 _TD_FUNCTION_MGT_INT_H_
#define _TD_FUNCTION_MGT_INT_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "functionMgt.h"
#define FUNC_MGT_DATA_TYPE_MASK(n) (1 << n)
#define FUNC_MGT_DATA_TYPE_NULL 0
#define FUNC_MGT_DATA_TYPE_BOOL FUNC_MGT_DATA_TYPE_MASK(0)
#define FUNC_MGT_DATA_TYPE_TINYINT FUNC_MGT_DATA_TYPE_MASK(1)
#define FUNC_MGT_DATA_TYPE_SMALLINT FUNC_MGT_DATA_TYPE_MASK(2)
#define FUNC_MGT_DATA_TYPE_INT FUNC_MGT_DATA_TYPE_MASK(3)
#define FUNC_MGT_DATA_TYPE_BIGINT FUNC_MGT_DATA_TYPE_MASK(4)
#define FUNC_MGT_DATA_TYPE_FLOAT FUNC_MGT_DATA_TYPE_MASK(5)
#define FUNC_MGT_DATA_TYPE_DOUBLE FUNC_MGT_DATA_TYPE_MASK(6)
#define FUNC_MGT_DATA_TYPE_BINARY FUNC_MGT_DATA_TYPE_MASK(7)
#define FUNC_MGT_DATA_TYPE_TIMESTAMP FUNC_MGT_DATA_TYPE_MASK(8)
#define FUNC_MGT_DATA_TYPE_NCHAR FUNC_MGT_DATA_TYPE_MASK(9)
#define FUNC_MGT_DATA_TYPE_UTINYINT FUNC_MGT_DATA_TYPE_MASK(10)
#define FUNC_MGT_DATA_TYPE_USMALLINT FUNC_MGT_DATA_TYPE_MASK(11)
#define FUNC_MGT_DATA_TYPE_UINT FUNC_MGT_DATA_TYPE_MASK(12)
#define FUNC_MGT_DATA_TYPE_UBIGINT FUNC_MGT_DATA_TYPE_MASK(13)
#define FUNC_MGT_DATA_TYPE_VARCHAR FUNC_MGT_DATA_TYPE_MASK(14)
#define FUNC_MGT_DATA_TYPE_VARBINARY FUNC_MGT_DATA_TYPE_MASK(15)
#define FUNC_MGT_DATA_TYPE_JSON FUNC_MGT_DATA_TYPE_MASK(16)
#define FUNC_MGT_DATA_TYPE_DECIMAL FUNC_MGT_DATA_TYPE_MASK(17)
#define FUNC_MGT_DATA_TYPE_BLOB FUNC_MGT_DATA_TYPE_MASK(18)
#define FUNC_MGT_EXACT_NUMERIC_DATA_TYPE \
(FUNC_MGT_DATA_TYPE_TINYINT | FUNC_MGT_DATA_TYPE_SMALLINT | FUNC_MGT_DATA_TYPE_INT | FUNC_MGT_DATA_TYPE_BIGINT \
| FUNC_MGT_DATA_TYPE_UTINYINT | FUNC_MGT_DATA_TYPE_USMALLINT | FUNC_MGT_DATA_TYPE_UINT | FUNC_MGT_DATA_TYPE_UBIGINT)
#define FUNC_MGT_APPRO_NUMERIC_DATA_TYPE (FUNC_MGT_DATA_TYPE_FLOAT | FUNC_MGT_DATA_TYPE_DOUBLE)
#define FUNC_MGT_NUMERIC_DATA_TYPE (FUNC_MGT_EXACT_NUMERIC_DATA_TYPE | FUNC_MGT_APPRO_NUMERIC_DATA_TYPE)
typedef void* FuncDef;
typedef struct SFuncElement {
FuncDef (*defineFunc)();
} SFuncElement;
extern const SFuncElement gBuiltinFuncs[];
FuncDef createFuncDef(const char* name, int32_t maxNumOfParams);
FuncDef setOneParamSignature(FuncDef def, int64_t resDataType, int64_t paramDataType);
FuncDef setTwoParamsSignature(FuncDef def, int64_t resDataType, int64_t p1DataType, int64_t p2DataType);
FuncDef setFollowParamSignature(FuncDef def, int64_t paramDataType);
FuncDef setFollowParamsSignature(FuncDef def, int64_t p1DataType, int64_t p2DataType, int32_t followNo);
FuncDef setExecFuncs(FuncDef def, FExecGetEnv getEnv, FExecInit init, FExecProcess process, FExecFinalize finalize);
#ifdef __cplusplus
}
#endif
#endif // _TD_FUNCTION_MGT_INT_H_
...@@ -28,14 +28,8 @@ extern "C" { ...@@ -28,14 +28,8 @@ extern "C" {
#include "function.h" #include "function.h"
#include "tudf.h" #include "tudf.h"
extern SAggFunctionInfo aggFunc[35];
typedef struct SResultRowEntryInfo { extern SAggFunctionInfo aggFunc[35];
int8_t hasResult; // result generated, not NULL value
bool initialized; // output buffer has been initialized
bool complete; // query has completed
uint32_t numOfRes; // num of output result in current buffer
} SResultRowEntryInfo;
#define FUNCSTATE_SO 0x0u #define FUNCSTATE_SO 0x0u
#define FUNCSTATE_MO 0x1u // dynamic number of output, not multinumber of output e.g., TOP/BOTTOM #define FUNCSTATE_MO 0x1u // dynamic number of output, not multinumber of output e.g., TOP/BOTTOM
...@@ -95,6 +89,10 @@ static FORCE_INLINE void initResultRowEntry(SResultRowEntryInfo *pResInfo, int32 ...@@ -95,6 +89,10 @@ static FORCE_INLINE void initResultRowEntry(SResultRowEntryInfo *pResInfo, int32
memset(GET_ROWCELL_INTERBUF(pResInfo), 0, bufLen); memset(GET_ROWCELL_INTERBUF(pResInfo), 0, bufLen);
} }
#include "functionMgtInt.h"
FuncDef defineCount();
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
......
/*
* 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 "functionMgtInt.h"
#include "taggfunction.h"
const SFuncElement gBuiltinFuncs[] = {
{.defineFunc = defineCount}
};
/*
* 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 "functionMgt.h"
#include "functionMgtInt.h"
#include "taos.h"
#include "taoserror.h"
#include "thash.h"
typedef struct SFuncMgtService {
SHashObj* pFuncNameHashTable;
} SFuncMgtService;
static SFuncMgtService gFunMgtService;
int32_t fmFuncMgtInit() {
gFunMgtService.pFuncNameHashTable = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
if (NULL == gFunMgtService.pFuncNameHashTable) {
return TSDB_CODE_FAILED;
}
return TSDB_CODE_SUCCESS;
}
typedef struct SFuncDef {
char name[TSDB_FUNC_NAME_LEN];
int32_t maxNumOfParams;
SFuncExecFuncs execFuncs;
} SFuncDef ;
FuncDef createFuncDef(const char* name, int32_t maxNumOfParams) {
SFuncDef* pDef = calloc(1, sizeof(SFuncDef));
if (NULL == pDef) {
return NULL;
}
strcpy(pDef->name, name);
pDef->maxNumOfParams = maxNumOfParams;
return pDef;
}
FuncDef setOneParamSignature(FuncDef def, int64_t resDataType, int64_t paramDataType) {
// todo
}
FuncDef setTwoParamsSignature(FuncDef def, int64_t resDataType, int64_t p1DataType, int64_t p2DataType) {
// todo
}
FuncDef setFollowParamSignature(FuncDef def, int64_t paramDataType) {
// todo
}
FuncDef setFollowParamsSignature(FuncDef def, int64_t p1DataType, int64_t p2DataType, int32_t followNo) {
// todo
}
FuncDef setExecFuncs(FuncDef def, FExecGetEnv getEnv, FExecInit init, FExecProcess process, FExecFinalize finalize) {
SFuncDef* pDef = (SFuncDef*)def;
pDef->execFuncs.getEnv = getEnv;
pDef->execFuncs.init = init;
pDef->execFuncs.process = process;
pDef->execFuncs.finalize = finalize;
return def;
}
int32_t registerFunc(FuncDef func) {
}
...@@ -4379,6 +4379,24 @@ int32_t functionCompatList[] = { ...@@ -4379,6 +4379,24 @@ int32_t functionCompatList[] = {
6, 8, 7, 6, 8, 7,
}; };
//typedef struct SFunctionFpSet {
// bool (*init)(struct SQLFunctionCtx *pCtx, struct SResultRowEntryInfo* pResultCellInfo); // setup the execute environment
// void (*addInput)(struct SQLFunctionCtx *pCtx);
//
// // finalizer must be called after all exec has been executed to generated final result.
// void (*finalize)(struct SQLFunctionCtx *pCtx);
// void (*combine)(struct SQLFunctionCtx *pCtx);
//} SFunctionFpSet;
SFunctionFpSet fpSet[1] = {
{
.init = function_setup,
.addInput = count_function,
.finalize = doFinalizer,
.combine = count_func_merge,
}
};
SAggFunctionInfo aggFunc[35] = {{ SAggFunctionInfo aggFunc[35] = {{
// 0, count function does not invoke the finalize function // 0, count function does not invoke the finalize function
"count", "count",
...@@ -4835,3 +4853,9 @@ SAggFunctionInfo aggFunc[35] = {{ ...@@ -4835,3 +4853,9 @@ SAggFunctionInfo aggFunc[35] = {{
statisRequired, statisRequired,
} }
}; };
FuncDef defineCount() {
FuncDef def = createFuncDef("count", 1);
// todo define signature
return setExecFuncs(def, NULL, function_setup, count_function, doFinalizer);
}
...@@ -30,7 +30,6 @@ SSchema *getTableTagSchema(const STableMeta* pTableMeta); ...@@ -30,7 +30,6 @@ SSchema *getTableTagSchema(const STableMeta* pTableMeta);
SArray *getCurrentExprList(SQueryStmtInfo* pQueryInfo); SArray *getCurrentExprList(SQueryStmtInfo* pQueryInfo);
size_t getNumOfExprs(SQueryStmtInfo* pQueryInfo); size_t getNumOfExprs(SQueryStmtInfo* pQueryInfo);
SExprInfo* createBinaryExprInfo(struct tExprNode* pNode, SSchema* pResSchema);
void addExprInfo(SArray* pExprList, int32_t index, SExprInfo* pExprInfo, int32_t level); void addExprInfo(SArray* pExprList, int32_t index, SExprInfo* pExprInfo, int32_t level);
void updateExprInfo(SExprInfo* pExprInfo, int16_t functionId, int32_t colId, int16_t srcColumnIndex, int16_t resType, int16_t resSize); void updateExprInfo(SExprInfo* pExprInfo, int16_t functionId, int32_t colId, int16_t srcColumnIndex, int16_t resType, int16_t resSize);
......
...@@ -2080,7 +2080,7 @@ static int32_t setColumnIndex(SQueryStmtInfo* pQueryInfo, SArray* pParamList, SC ...@@ -2080,7 +2080,7 @@ static int32_t setColumnIndex(SQueryStmtInfo* pQueryInfo, SArray* pParamList, SC
STableMeta* pTableMeta = getMetaInfo(pQueryInfo, 0)->pTableMeta; STableMeta* pTableMeta = getMetaInfo(pQueryInfo, 0)->pTableMeta;
if (pParamList == NULL) { if (pParamList == NULL) {
// count(*) is equalled to count(primary_timestamp_key) // count(*) is equalled to count(primary_timestamp_key)
*index = (SColumnIndex) {0, PRIMARYKEY_TIMESTAMP_COL_ID, false}; *index = (SColumnIndex) {0, 0, false};
*columnSchema = *(SSchema*) getOneColumnSchema(pTableMeta, index->columnIndex); *columnSchema = *(SSchema*) getOneColumnSchema(pTableMeta, index->columnIndex);
} else { } else {
tSqlExprItem* pParamElem = taosArrayGet(pParamList, 0); tSqlExprItem* pParamElem = taosArrayGet(pParamList, 0);
...@@ -3955,6 +3955,7 @@ int32_t qParserValidateSqlNode(SParseContext *pCtx, SSqlInfo* pInfo, SQueryStmtI ...@@ -3955,6 +3955,7 @@ int32_t qParserValidateSqlNode(SParseContext *pCtx, SSqlInfo* pInfo, SQueryStmtI
pQueryInfo->pTableMetaInfo[0]->name = *name; pQueryInfo->pTableMetaInfo[0]->name = *name;
pQueryInfo->numOfTables = 1; pQueryInfo->numOfTables = 1;
pQueryInfo->pTableMetaInfo[0]->tagColList = taosArrayInit(4, POINTER_BYTES); pQueryInfo->pTableMetaInfo[0]->tagColList = taosArrayInit(4, POINTER_BYTES);
strcpy(pQueryInfo->pTableMetaInfo[0]->aliasName, name->tname);
code = setTableVgroupList(pCtx, name, &pQueryInfo->pTableMetaInfo[0]->vgroupList); code = setTableVgroupList(pCtx, name, &pQueryInfo->pTableMetaInfo[0]->vgroupList);
if (code != TSDB_CODE_SUCCESS) { if (code != TSDB_CODE_SUCCESS) {
......
...@@ -26,18 +26,26 @@ static int32_t setShowInfo(SShowInfo* pShowInfo, SParseContext* pCtx, void** out ...@@ -26,18 +26,26 @@ static int32_t setShowInfo(SShowInfo* pShowInfo, SParseContext* pCtx, void** out
const char* msg4 = "pattern is invalid"; const char* msg4 = "pattern is invalid";
const char* msg5 = "database name is empty"; const char* msg5 = "database name is empty";
const char* msg6 = "pattern string is empty"; const char* msg6 = "pattern string is empty";
const char* msg7 = "db is not specified";
/* /*
* database prefix in pInfo->pMiscInfo->a[0] * database prefix in pInfo->pMiscInfo->a[0]
* wildcard in like clause in pInfo->pMiscInfo->a[1] * wildcard in like clause in pInfo->pMiscInfo->a[1]
*/ */
int16_t showType = pShowInfo->showType; int16_t showType = pShowInfo->showType;
if (showType == TSDB_MGMT_TABLE_TABLE) { if (showType == TSDB_MGMT_TABLE_TABLE) {
SVShowTablesReq* pShowReq = calloc(1, sizeof(SVShowTablesReq));
SArray* array = NULL; SArray* array = NULL;
SName name = {0}; SName name = {0};
tNameSetDbName(&name, pCtx->acctId, pCtx->db, strlen(pCtx->db));
if (pCtx->db == NULL && pShowInfo->prefix.n == 0) {
return buildInvalidOperationMsg(pMsgBuf, msg7);
}
SVShowTablesReq* pShowReq = calloc(1, sizeof(SVShowTablesReq));
if (pShowInfo->prefix.n > 0) {
tNameSetDbName(&name, pCtx->acctId, pShowInfo->prefix.z, pShowInfo->prefix.n);
} else {
tNameSetDbName(&name, pCtx->acctId, pCtx->db, strlen(pCtx->db));
}
char dbFname[TSDB_DB_FNAME_LEN] = {0}; char dbFname[TSDB_DB_FNAME_LEN] = {0};
tNameGetFullDbName(&name, dbFname); tNameGetFullDbName(&name, dbFname);
...@@ -715,6 +723,8 @@ SDclStmtInfo* qParserValidateDclSqlNode(SSqlInfo* pInfo, SParseContext* pCtx, ch ...@@ -715,6 +723,8 @@ SDclStmtInfo* qParserValidateDclSqlNode(SSqlInfo* pInfo, SParseContext* pCtx, ch
SMsgBuf m = {.buf = msgBuf, .len = msgBufLen}; SMsgBuf m = {.buf = msgBuf, .len = msgBufLen};
SMsgBuf* pMsgBuf = &m; SMsgBuf* pMsgBuf = &m;
pDcl->epSet = pCtx->mgmtEpSet;
switch (pInfo->type) { switch (pInfo->type) {
case TSDB_SQL_CREATE_USER: case TSDB_SQL_CREATE_USER:
case TSDB_SQL_ALTER_USER: { case TSDB_SQL_ALTER_USER: {
...@@ -768,7 +778,6 @@ SDclStmtInfo* qParserValidateDclSqlNode(SSqlInfo* pInfo, SParseContext* pCtx, ch ...@@ -768,7 +778,6 @@ SDclStmtInfo* qParserValidateDclSqlNode(SSqlInfo* pInfo, SParseContext* pCtx, ch
pDcl->pMsg = (char*)buildUserManipulationMsg(pInfo, &pDcl->msgLen, pCtx->requestId, msgBuf, msgBufLen); pDcl->pMsg = (char*)buildUserManipulationMsg(pInfo, &pDcl->msgLen, pCtx->requestId, msgBuf, msgBufLen);
pDcl->msgType = (pInfo->type == TSDB_SQL_CREATE_USER) ? TDMT_MND_CREATE_USER : TDMT_MND_ALTER_USER; pDcl->msgType = (pInfo->type == TSDB_SQL_CREATE_USER) ? TDMT_MND_CREATE_USER : TDMT_MND_ALTER_USER;
pDcl->epSet = pCtx->mgmtEpSet;
break; break;
} }
...@@ -810,7 +819,6 @@ SDclStmtInfo* qParserValidateDclSqlNode(SSqlInfo* pInfo, SParseContext* pCtx, ch ...@@ -810,7 +819,6 @@ SDclStmtInfo* qParserValidateDclSqlNode(SSqlInfo* pInfo, SParseContext* pCtx, ch
pDcl->pMsg = (char*)buildAcctManipulationMsg(pInfo, &pDcl->msgLen, pCtx->requestId, msgBuf, msgBufLen); pDcl->pMsg = (char*)buildAcctManipulationMsg(pInfo, &pDcl->msgLen, pCtx->requestId, msgBuf, msgBufLen);
pDcl->msgType = (pInfo->type == TSDB_SQL_CREATE_ACCT) ? TDMT_MND_CREATE_ACCT : TDMT_MND_ALTER_ACCT; pDcl->msgType = (pInfo->type == TSDB_SQL_CREATE_ACCT) ? TDMT_MND_CREATE_ACCT : TDMT_MND_ALTER_ACCT;
pDcl->epSet = pCtx->mgmtEpSet;
break; break;
} }
...@@ -818,7 +826,6 @@ SDclStmtInfo* qParserValidateDclSqlNode(SSqlInfo* pInfo, SParseContext* pCtx, ch ...@@ -818,7 +826,6 @@ SDclStmtInfo* qParserValidateDclSqlNode(SSqlInfo* pInfo, SParseContext* pCtx, ch
case TSDB_SQL_DROP_USER: { case TSDB_SQL_DROP_USER: {
pDcl->pMsg = (char*)buildDropUserMsg(pInfo, &pDcl->msgLen, pCtx->requestId, msgBuf, msgBufLen); pDcl->pMsg = (char*)buildDropUserMsg(pInfo, &pDcl->msgLen, pCtx->requestId, msgBuf, msgBufLen);
pDcl->msgType = (pInfo->type == TSDB_SQL_DROP_ACCT) ? TDMT_MND_DROP_ACCT : TDMT_MND_DROP_USER; pDcl->msgType = (pInfo->type == TSDB_SQL_DROP_ACCT) ? TDMT_MND_DROP_ACCT : TDMT_MND_DROP_USER;
pDcl->epSet = pCtx->mgmtEpSet;
break; break;
} }
...@@ -855,7 +862,6 @@ SDclStmtInfo* qParserValidateDclSqlNode(SSqlInfo* pInfo, SParseContext* pCtx, ch ...@@ -855,7 +862,6 @@ SDclStmtInfo* qParserValidateDclSqlNode(SSqlInfo* pInfo, SParseContext* pCtx, ch
pDcl->pMsg = (char*)pUseDbMsg; pDcl->pMsg = (char*)pUseDbMsg;
pDcl->msgLen = sizeof(SUseDbReq); pDcl->msgLen = sizeof(SUseDbReq);
pDcl->msgType = TDMT_MND_USE_DB; pDcl->msgType = TDMT_MND_USE_DB;
pDcl->epSet = pCtx->mgmtEpSet;
break; break;
} }
...@@ -884,7 +890,6 @@ SDclStmtInfo* qParserValidateDclSqlNode(SSqlInfo* pInfo, SParseContext* pCtx, ch ...@@ -884,7 +890,6 @@ SDclStmtInfo* qParserValidateDclSqlNode(SSqlInfo* pInfo, SParseContext* pCtx, ch
goto _error; goto _error;
} }
pDcl->epSet = pCtx->mgmtEpSet;
pDcl->pMsg = (char*)pCreateMsg; pDcl->pMsg = (char*)pCreateMsg;
pDcl->msgLen = sizeof(SCreateDbReq); pDcl->msgLen = sizeof(SCreateDbReq);
pDcl->msgType = (pInfo->type == TSDB_SQL_CREATE_DB) ? TDMT_MND_CREATE_DB : TDMT_MND_ALTER_DB; pDcl->msgType = (pInfo->type == TSDB_SQL_CREATE_DB) ? TDMT_MND_CREATE_DB : TDMT_MND_ALTER_DB;
...@@ -913,7 +918,6 @@ SDclStmtInfo* qParserValidateDclSqlNode(SSqlInfo* pInfo, SParseContext* pCtx, ch ...@@ -913,7 +918,6 @@ SDclStmtInfo* qParserValidateDclSqlNode(SSqlInfo* pInfo, SParseContext* pCtx, ch
pDcl->msgType = TDMT_MND_DROP_DB; pDcl->msgType = TDMT_MND_DROP_DB;
pDcl->msgLen = sizeof(SDropDbReq); pDcl->msgLen = sizeof(SDropDbReq);
pDcl->pMsg = (char*)pDropDbMsg; pDcl->pMsg = (char*)pDropDbMsg;
pDcl->epSet = pCtx->mgmtEpSet;
break; break;
} }
...@@ -926,7 +930,6 @@ SDclStmtInfo* qParserValidateDclSqlNode(SSqlInfo* pInfo, SParseContext* pCtx, ch ...@@ -926,7 +930,6 @@ SDclStmtInfo* qParserValidateDclSqlNode(SSqlInfo* pInfo, SParseContext* pCtx, ch
pDcl->pMsg = (char*)buildCreateStbMsg(pCreateTable, &pDcl->msgLen, pCtx, pMsgBuf); pDcl->pMsg = (char*)buildCreateStbMsg(pCreateTable, &pDcl->msgLen, pCtx, pMsgBuf);
pDcl->msgType = TDMT_MND_CREATE_STB; pDcl->msgType = TDMT_MND_CREATE_STB;
pDcl->epSet = pCtx->mgmtEpSet;
break; break;
} }
...@@ -947,7 +950,6 @@ SDclStmtInfo* qParserValidateDclSqlNode(SSqlInfo* pInfo, SParseContext* pCtx, ch ...@@ -947,7 +950,6 @@ SDclStmtInfo* qParserValidateDclSqlNode(SSqlInfo* pInfo, SParseContext* pCtx, ch
} }
pDcl->msgType = TDMT_MND_CREATE_DNODE; pDcl->msgType = TDMT_MND_CREATE_DNODE;
pDcl->epSet = pCtx->mgmtEpSet;
break; break;
} }
...@@ -958,7 +960,6 @@ SDclStmtInfo* qParserValidateDclSqlNode(SSqlInfo* pInfo, SParseContext* pCtx, ch ...@@ -958,7 +960,6 @@ SDclStmtInfo* qParserValidateDclSqlNode(SSqlInfo* pInfo, SParseContext* pCtx, ch
} }
pDcl->msgType = TDMT_MND_DROP_DNODE; pDcl->msgType = TDMT_MND_DROP_DNODE;
pDcl->epSet = pCtx->mgmtEpSet;
break; break;
} }
......
...@@ -1947,6 +1947,7 @@ int32_t KvRowAppend(const void *value, int32_t len, void *param) { ...@@ -1947,6 +1947,7 @@ int32_t KvRowAppend(const void *value, int32_t len, void *param) {
int32_t createSName(SName* pName, SToken* pTableName, SParseContext* pParseCtx, SMsgBuf* pMsgBuf) { int32_t createSName(SName* pName, SToken* pTableName, SParseContext* pParseCtx, SMsgBuf* pMsgBuf) {
const char* msg1 = "name too long"; const char* msg1 = "name too long";
const char* msg2 = "invalid database name"; const char* msg2 = "invalid database name";
const char* msg3 = "db is not specified";
int32_t code = TSDB_CODE_SUCCESS; int32_t code = TSDB_CODE_SUCCESS;
char* p = strnchr(pTableName->z, TS_PATH_DELIMITER[0], pTableName->n, true); char* p = strnchr(pTableName->z, TS_PATH_DELIMITER[0], pTableName->n, true);
...@@ -1984,6 +1985,10 @@ int32_t createSName(SName* pName, SToken* pTableName, SParseContext* pParseCtx, ...@@ -1984,6 +1985,10 @@ int32_t createSName(SName* pName, SToken* pTableName, SParseContext* pParseCtx,
strncpy(name, pTableName->z, pTableName->n); strncpy(name, pTableName->z, pTableName->n);
strdequote(name); strdequote(name);
if (pParseCtx->db == NULL) {
return buildInvalidOperationMsg(pMsgBuf, msg3);
}
code = tNameSetDbName(pName, pParseCtx->acctId, pParseCtx->db, strlen(pParseCtx->db)); code = tNameSetDbName(pName, pParseCtx->acctId, pParseCtx->db, strlen(pParseCtx->db));
if (code != TSDB_CODE_SUCCESS) { if (code != TSDB_CODE_SUCCESS) {
code = buildInvalidOperationMsg(pMsgBuf, msg2); code = buildInvalidOperationMsg(pMsgBuf, msg2);
......
...@@ -13,9 +13,10 @@ ...@@ -13,9 +13,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <function.h>
#include "function.h"
#include "os.h" #include "os.h"
#include "parser.h" #include "parser.h"
#include "function.h"
#include "plannerInt.h" #include "plannerInt.h"
typedef struct SFillEssInfo { typedef struct SFillEssInfo {
...@@ -197,23 +198,23 @@ static SQueryPlanNode* doAddTableColumnNode(const SQueryStmtInfo* pQueryInfo, SQ ...@@ -197,23 +198,23 @@ static SQueryPlanNode* doAddTableColumnNode(const SQueryStmtInfo* pQueryInfo, SQ
SQueryPlanNode* pNode = createQueryNode(QNODE_TABLESCAN, "TableScan", NULL, 0, NULL, 0, info); SQueryPlanNode* pNode = createQueryNode(QNODE_TABLESCAN, "TableScan", NULL, 0, NULL, 0, info);
if (!pQueryInfo->info.projectionQuery) { if (!pQueryInfo->info.projectionQuery) {
STableMetaInfo* pTableMetaInfo1 = getMetaInfo(pQueryInfo, 0); SArray* p = pQueryInfo->exprList[0];
// table source column projection, generate the projection expr // table source column projection, generate the projection expr
int32_t numOfCols = (int32_t) taosArrayGetSize(tableCols); int32_t numOfCols = (int32_t) taosArrayGetSize(tableCols);
SExprInfo** pExpr = calloc(numOfCols, POINTER_BYTES);
for (int32_t i = 0; i < numOfCols; ++i) {
SColumn* pCol = taosArrayGetP(tableCols, i);
SSourceParam param = {0};
addIntoSourceParam(&param, NULL, pCol);
SSchema s = createSchema(pCol->info.type, pCol->info.bytes, pCol->info.colId, pCol->name);
SExprInfo* p = createExprInfo(pTableMetaInfo1, "project", &param, &s, 0);
pExpr[i] = p;
}
pNode = createQueryNode(QNODE_PROJECT, "Projection", &pNode, 1, pExpr, numOfCols, NULL); pNode->numOfExpr = numOfCols;
tfree(pExpr); pNode->pExpr = taosArrayInit(numOfCols, POINTER_BYTES);
for(int32_t i = 0; i < numOfCols; ++i) {
SExprInfo* pExprInfo = taosArrayGetP(p, i);
SColumn* pCol = pExprInfo->base.pColumns;
SSchema schema = createSchema(pCol->info.type, pCol->info.bytes, pCol->info.colId, pCol->name);
tExprNode* pExprNode = pExprInfo->pExpr->_function.pChild[0];
SExprInfo* px = createBinaryExprInfo(pExprNode, &schema);
taosArrayPush(pNode->pExpr, &px);
}
} }
return pNode; return pNode;
......
...@@ -117,6 +117,26 @@ static bool fromPnode(const cJSON* json, const char* name, FFromJson func, void* ...@@ -117,6 +117,26 @@ static bool fromPnode(const cJSON* json, const char* name, FFromJson func, void*
return func(jObj, *obj); return func(jObj, *obj);
} }
static bool fromPnodeArray(const cJSON* json, const char* name, FFromJson func, SArray** array) {
const cJSON* jArray = cJSON_GetObjectItem(json, name);
int32_t size = (NULL == jArray ? 0 : cJSON_GetArraySize(jArray));
if (size > 0) {
*array = taosArrayInit(size, POINTER_BYTES);
if (NULL == *array) {
return false;
}
}
for (int32_t i = 0; i < size; ++i) {
cJSON* jItem = cJSON_GetArrayItem(jArray, i);
void* item = calloc(1, getPnodeTypeSize(jItem));
if (NULL == item || !func(jItem, item)) {
return false;
}
taosArrayPush(*array, &item);
}
return true;
}
static bool addTarray(cJSON* json, const char* name, FToJson func, const SArray* array, bool isPoint) { static bool addTarray(cJSON* json, const char* name, FToJson func, const SArray* array, bool isPoint) {
size_t size = (NULL == array) ? 0 : taosArrayGetSize(array); size_t size = (NULL == array) ? 0 : taosArrayGetSize(array);
if (size > 0) { if (size > 0) {
...@@ -387,8 +407,8 @@ static const char* jkFunctionChild = "Child"; ...@@ -387,8 +407,8 @@ static const char* jkFunctionChild = "Child";
static bool functionToJson(const void* obj, cJSON* jFunc) { static bool functionToJson(const void* obj, cJSON* jFunc) {
const tExprNode* exprInfo = (const tExprNode*)obj; const tExprNode* exprInfo = (const tExprNode*)obj;
bool res = cJSON_AddStringToObject(jFunc, jkFunctionName, exprInfo->_function.functionName); bool res = cJSON_AddStringToObject(jFunc, jkFunctionName, exprInfo->_function.functionName);
if (res) { if (res && NULL != exprInfo->_function.pChild) {
res = addRawArray(jFunc, jkFunctionChild, exprNodeToJson, exprInfo->_function.pChild, sizeof(tExprNode*), exprInfo->_function.num); res = addRawArray(jFunc, jkFunctionChild, exprNodeToJson, exprInfo->_function.pChild, sizeof(tExprNode*), exprInfo->_function.num);
} }
return res; return res;
} }
...@@ -396,6 +416,10 @@ static bool functionToJson(const void* obj, cJSON* jFunc) { ...@@ -396,6 +416,10 @@ static bool functionToJson(const void* obj, cJSON* jFunc) {
static bool functionFromJson(const cJSON* json, void* obj) { static bool functionFromJson(const cJSON* json, void* obj) {
tExprNode* exprInfo = (tExprNode*)obj; tExprNode* exprInfo = (tExprNode*)obj;
copyString(json, jkFunctionName, exprInfo->_function.functionName); copyString(json, jkFunctionName, exprInfo->_function.functionName);
exprInfo->_function.pChild = calloc(1, sizeof(tExprNode*));
if (NULL == exprInfo->_function.pChild) {
return false;
}
return fromRawArrayWithAlloc(json, jkFunctionChild, exprNodeFromJson, (void**)exprInfo->_function.pChild, sizeof(tExprNode*), &exprInfo->_function.num); return fromRawArrayWithAlloc(json, jkFunctionChild, exprNodeFromJson, (void**)exprInfo->_function.pChild, sizeof(tExprNode*), &exprInfo->_function.num);
} }
...@@ -443,7 +467,7 @@ static const char* jkExprNodeColumn = "Column"; ...@@ -443,7 +467,7 @@ static const char* jkExprNodeColumn = "Column";
static const char* jkExprNodeValue = "Value"; static const char* jkExprNodeValue = "Value";
static bool exprNodeToJson(const void* obj, cJSON* jExprInfo) { static bool exprNodeToJson(const void* obj, cJSON* jExprInfo) {
const tExprNode* exprInfo = (const tExprNode*)obj; const tExprNode* exprInfo = *(const tExprNode**)obj;
bool res = cJSON_AddNumberToObject(jExprInfo, jkExprNodeType, exprInfo->nodeType); bool res = cJSON_AddNumberToObject(jExprInfo, jkExprNodeType, exprInfo->nodeType);
if (res) { if (res) {
switch (exprInfo->nodeType) { switch (exprInfo->nodeType) {
...@@ -531,7 +555,7 @@ static bool exprInfoToJson(const void* obj, cJSON* jExprInfo) { ...@@ -531,7 +555,7 @@ static bool exprInfoToJson(const void* obj, cJSON* jExprInfo) {
const SExprInfo* exprInfo = (const SExprInfo*)obj; const SExprInfo* exprInfo = (const SExprInfo*)obj;
bool res = addObject(jExprInfo, jkExprInfoBase, sqlExprToJson, &exprInfo->base); bool res = addObject(jExprInfo, jkExprInfoBase, sqlExprToJson, &exprInfo->base);
if (res) { if (res) {
res = addObject(jExprInfo, jkExprInfoExpr, exprNodeToJson, exprInfo->pExpr); res = addObject(jExprInfo, jkExprInfoExpr, exprNodeToJson, &exprInfo->pExpr);
} }
return res; return res;
} }
...@@ -851,7 +875,7 @@ static bool specificPhyNodeFromJson(const cJSON* json, void* obj) { ...@@ -851,7 +875,7 @@ static bool specificPhyNodeFromJson(const cJSON* json, void* obj) {
case OP_SystemTableScan: case OP_SystemTableScan:
return scanNodeFromJson(json, obj); return scanNodeFromJson(json, obj);
case OP_Aggregate: case OP_Aggregate:
break; // todo return aggNodeFromJson(json, obj);
case OP_Project: case OP_Project:
return true; return true;
// case OP_Groupby: // case OP_Groupby:
...@@ -922,7 +946,7 @@ static bool phyNodeFromJson(const cJSON* json, void* obj) { ...@@ -922,7 +946,7 @@ static bool phyNodeFromJson(const cJSON* json, void* obj) {
res = fromObject(json, jkPnodeSchema, dataBlockSchemaFromJson, &node->targetSchema, true); res = fromObject(json, jkPnodeSchema, dataBlockSchemaFromJson, &node->targetSchema, true);
} }
if (res) { if (res) {
res = fromArray(json, jkPnodeChildren, phyNodeFromJson, &node->pChildren, sizeof(SSlotSchema)); res = fromPnodeArray(json, jkPnodeChildren, phyNodeFromJson, &node->pChildren);
} }
if (res) { if (res) {
res = fromObject(json, node->info.name, specificPhyNodeFromJson, node, true); res = fromObject(json, node->info.name, specificPhyNodeFromJson, node, true);
......
...@@ -1217,7 +1217,7 @@ int32_t schLaunchTask(SSchJob *pJob, SSchTask *pTask) { ...@@ -1217,7 +1217,7 @@ int32_t schLaunchTask(SSchJob *pJob, SSchTask *pTask) {
SCH_ERR_JRET(code); SCH_ERR_JRET(code);
} }
printf("physical plan:%s\n", pTask->msg); // printf("physical plan:%s\n", pTask->msg);
} }
SCH_ERR_JRET(schSetTaskCandidateAddrs(pJob, pTask)); SCH_ERR_JRET(schSetTaskCandidateAddrs(pJob, pTask));
......
...@@ -6,4 +6,8 @@ target_include_directories( ...@@ -6,4 +6,8 @@ target_include_directories(
PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/inc" PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/inc"
) )
target_link_libraries(tfs os util common) target_link_libraries(tfs os util common)
\ No newline at end of file
if(${BUILD_TEST})
add_subdirectory(test)
endif(${BUILD_TEST})
\ No newline at end of file
...@@ -22,7 +22,6 @@ ...@@ -22,7 +22,6 @@
#include "taoserror.h" #include "taoserror.h"
#include "tcoding.h" #include "tcoding.h"
#include "tfs.h" #include "tfs.h"
#include "tglobal.h"
#include "thash.h" #include "thash.h"
#include "tlog.h" #include "tlog.h"
......
...@@ -141,6 +141,7 @@ const char *tfsGetDiskPath(STfs *pTfs, SDiskID diskId) { return TFS_DISK_AT(pTfs ...@@ -141,6 +141,7 @@ const char *tfsGetDiskPath(STfs *pTfs, SDiskID diskId) { return TFS_DISK_AT(pTfs
void tfsInitFile(STfs *pTfs, STfsFile *pFile, SDiskID diskId, const char *rname) { void tfsInitFile(STfs *pTfs, STfsFile *pFile, SDiskID diskId, const char *rname) {
STfsDisk *pDisk = TFS_DISK_AT(pTfs, diskId); STfsDisk *pDisk = TFS_DISK_AT(pTfs, diskId);
if (pDisk == NULL) return;
pFile->did = diskId; pFile->did = diskId;
tstrncpy(pFile->rname, rname, TSDB_FILENAME_LEN); tstrncpy(pFile->rname, rname, TSDB_FILENAME_LEN);
...@@ -197,9 +198,7 @@ void tfsDirname(const STfsFile *pFile, char *dest) { ...@@ -197,9 +198,7 @@ void tfsDirname(const STfsFile *pFile, char *dest) {
tstrncpy(dest, dirname(tname), TSDB_FILENAME_LEN); tstrncpy(dest, dirname(tname), TSDB_FILENAME_LEN);
} }
int32_t tfsRemoveFile(const STfsFile *pFile) { int32_t tfsRemoveFile(const STfsFile *pFile) { return remove(pFile->aname); }
return remove(pFile->aname);
}
int32_t tfsCopyFile(const STfsFile *pFile1, const STfsFile *pFile2) { int32_t tfsCopyFile(const STfsFile *pFile1, const STfsFile *pFile2) {
return taosCopyFile(pFile1->aname, pFile2->aname); return taosCopyFile(pFile1->aname, pFile2->aname);
...@@ -291,6 +290,8 @@ int32_t tfsRename(STfs *pTfs, char *orname, char *nrname) { ...@@ -291,6 +290,8 @@ int32_t tfsRename(STfs *pTfs, char *orname, char *nrname) {
snprintf(oaname, TMPNAME_LEN, "%s%s%s", pDisk->path, TD_DIRSEP, orname); snprintf(oaname, TMPNAME_LEN, "%s%s%s", pDisk->path, TD_DIRSEP, orname);
snprintf(naname, TMPNAME_LEN, "%s%s%s", pDisk->path, TD_DIRSEP, nrname); snprintf(naname, TMPNAME_LEN, "%s%s%s", pDisk->path, TD_DIRSEP, nrname);
if (taosRenameFile(oaname, naname) != 0) { if (taosRenameFile(oaname, naname) != 0) {
terrno = TAOS_SYSTEM_ERROR(errno);
fError("failed to rename %s to %s since %s", oaname, naname, terrstr());
return -1; return -1;
} }
} }
...@@ -330,7 +331,12 @@ const STfsFile *tfsReaddir(STfsDir *pDir) { ...@@ -330,7 +331,12 @@ const STfsFile *tfsReaddir(STfsDir *pDir) {
// Skip . and .. // Skip . and ..
if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0) continue; if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0) continue;
snprintf(bname, TMPNAME_LEN * 2, "%s%s%s", pDir->dirname, TD_DIRSEP, dp->d_name); if (pDir->dirname == NULL || pDir->dirname[0] == 0) {
snprintf(bname, TMPNAME_LEN * 2, "%s", dp->d_name);
} else {
snprintf(bname, TMPNAME_LEN * 2, "%s%s%s", pDir->dirname, TD_DIRSEP, dp->d_name);
}
tfsInitFile(pDir->pTfs, &pDir->tfile, pDir->did, bname); tfsInitFile(pDir->pTfs, &pDir->tfile, pDir->did, bname);
return &pDir->tfile; return &pDir->tfile;
} }
...@@ -402,8 +408,7 @@ static int32_t tfsCheckAndFormatCfg(STfs *pTfs, SDiskCfg *pCfg) { ...@@ -402,8 +408,7 @@ static int32_t tfsCheckAndFormatCfg(STfs *pTfs, SDiskCfg *pCfg) {
} }
if (tfsFormatDir(pCfg->dir, dirName) < 0) { if (tfsFormatDir(pCfg->dir, dirName) < 0) {
fError("failed to mount %s to FS since invalid dir format", pCfg->dir); fError("failed to mount %s to FS since %s", pCfg->dir, terrstr());
terrno = TSDB_CODE_FS_INVLD_CFG;
return -1; return -1;
} }
...@@ -501,7 +506,11 @@ static int32_t tfsOpendirImpl(STfs *pTfs, STfsDir *pDir) { ...@@ -501,7 +506,11 @@ static int32_t tfsOpendirImpl(STfs *pTfs, STfsDir *pDir) {
pDir->did.level = pDisk->level; pDir->did.level = pDisk->level;
pDir->did.id = pDisk->id; pDir->did.id = pDisk->id;
snprintf(adir, TMPNAME_LEN * 2, "%s%s%s", pDisk->path, TD_DIRSEP, pDir->dirname); if (pDisk->path == NULL || pDisk->path[0] == 0) {
snprintf(adir, TMPNAME_LEN * 2, "%s", pDir->dirname);
} else {
snprintf(adir, TMPNAME_LEN * 2, "%s%s%s", pDisk->path, TD_DIRSEP, pDir->dirname);
}
pDir->dir = opendir(adir); pDir->dir = opendir(adir);
if (pDir->dir != NULL) break; if (pDir->dir != NULL) break;
} }
......
enable_testing()
aux_source_directory(. TFS_TEST_SRC)
add_executable(tfs_test ${TFS_TEST_SRC})
target_link_libraries(
tfs_test
PUBLIC tfs
PUBLIC gtest_main
)
add_test(
NAME tfs_test
COMMAND tfs_test
)
/**
* @file tfsTest.cpp
* @author slguan (slguan@taosdata.com)
* @brief TFS module tests
* @version 1.0
* @date 2022-01-20
*
* @copyright Copyright (c) 2022
*
*/
#include <gtest/gtest.h>
#include "os.h"
#include "tfs.h"
class TfsTest : public ::testing::Test {
protected:
static void SetUpTestSuite() { root = "/tmp/tfsTest"; }
static void TearDownTestSuite() {}
public:
void SetUp() override {}
void TearDown() override {}
static const char *root;
};
const char *TfsTest::root;
TEST_F(TfsTest, 01_Open_Close) {
SDiskCfg dCfg = {0};
tstrncpy(dCfg.dir, root, TSDB_FILENAME_LEN);
dCfg.level = 0;
dCfg.primary = 1;
taosRemoveDir(root);
STfs *pTfs = tfsOpen(&dCfg, 1);
ASSERT_EQ(pTfs, nullptr);
taosMkDir(root);
pTfs = tfsOpen(&dCfg, 1);
ASSERT_NE(pTfs, nullptr);
tfsUpdateSize(pTfs);
SDiskSize size = tfsGetSize(pTfs);
EXPECT_GT(size.avail, 0);
EXPECT_GT(size.used, 0);
EXPECT_GT(size.total, size.avail);
EXPECT_GT(size.total, size.used);
tfsClose(pTfs);
}
TEST_F(TfsTest, 02_AllocDisk) {
int32_t code = 0;
SDiskCfg dCfg = {0};
tstrncpy(dCfg.dir, root, TSDB_FILENAME_LEN);
dCfg.level = 0;
dCfg.primary = 1;
taosRemoveDir(root);
taosMkDir(root);
STfs *pTfs = tfsOpen(&dCfg, 1);
ASSERT_NE(pTfs, nullptr);
SDiskID did;
did.id = 0;
did.level = 0;
code = tfsAllocDisk(pTfs, 0, &did);
EXPECT_EQ(code, 0);
EXPECT_EQ(did.id, 0);
EXPECT_EQ(did.level, 0);
did.id = 1;
did.level = 1;
code = tfsAllocDisk(pTfs, 0, &did);
EXPECT_EQ(code, 0);
EXPECT_EQ(did.id, 0);
EXPECT_EQ(did.level, 0);
did.id = 1;
did.level = 2;
code = tfsAllocDisk(pTfs, 0, &did);
EXPECT_EQ(code, 0);
EXPECT_EQ(did.id, 0);
EXPECT_EQ(did.level, 0);
did.id = 1;
did.level = 3;
code = tfsAllocDisk(pTfs, 0, &did);
EXPECT_EQ(code, 0);
EXPECT_EQ(did.id, 0);
EXPECT_EQ(did.level, 0);
const char *primary = tfsGetPrimaryPath(pTfs);
EXPECT_STREQ(primary, root);
const char *path = tfsGetDiskPath(pTfs, did);
EXPECT_STREQ(path, root);
tfsClose(pTfs);
}
TEST_F(TfsTest, 03_Dir) {
int32_t code = 0;
SDiskCfg dCfg = {0};
tstrncpy(dCfg.dir, root, TSDB_FILENAME_LEN);
dCfg.level = 0;
dCfg.primary = 1;
taosRemoveDir(root);
taosMkDir(root);
STfs *pTfs = tfsOpen(&dCfg, 1);
ASSERT_NE(pTfs, nullptr);
char p1[] = "p1";
char ap1[128] = {0};
snprintf(ap1, 128, "%s%s%s", root, TD_DIRSEP, p1);
EXPECT_NE(taosDirExist(ap1), 0);
EXPECT_EQ(tfsMkdir(pTfs, p1), 0);
EXPECT_EQ(taosDirExist(ap1), 0);
char p2[] = "p2";
char ap2[128] = {0};
snprintf(ap2, 128, "%s%s%s", root, TD_DIRSEP, p2);
SDiskID did = {0};
EXPECT_NE(taosDirExist(ap2), 0);
EXPECT_EQ(tfsMkdirAt(pTfs, p2, did), 0);
EXPECT_EQ(taosDirExist(ap2), 0);
char p3[] = "p3/p2/p1/p0";
char ap3[128] = {0};
snprintf(ap3, 128, "%s%s%s", root, TD_DIRSEP, p3);
EXPECT_NE(taosDirExist(ap3), 0);
EXPECT_NE(tfsMkdir(pTfs, p3), 0);
EXPECT_NE(tfsMkdirAt(pTfs, p3, did), 0);
EXPECT_EQ(tfsMkdirRecurAt(pTfs, p3, did), 0);
EXPECT_EQ(taosDirExist(ap3), 0);
EXPECT_EQ(tfsRmdir(pTfs, p3), 0);
EXPECT_NE(taosDirExist(ap3), 0);
char p45[] = "p5";
char p44[] = "p4";
char p4[] = "p4/p2/p1/p0";
char ap4[128] = {0};
snprintf(ap4, 128, "%s%s%s", root, TD_DIRSEP, p4);
EXPECT_NE(taosDirExist(ap4), 0);
EXPECT_EQ(tfsMkdirRecurAt(pTfs, p4, did), 0);
EXPECT_EQ(taosDirExist(ap4), 0);
EXPECT_EQ(tfsRename(pTfs, p44, p45), 0);
EXPECT_EQ(tfsRmdir(pTfs, p4), 0);
EXPECT_NE(taosDirExist(ap4), 0);
tfsClose(pTfs);
}
TEST_F(TfsTest, 04_File) {
int32_t code = 0;
SDiskCfg dCfg = {0};
tstrncpy(dCfg.dir, root, TSDB_FILENAME_LEN);
dCfg.level = 0;
dCfg.primary = 1;
taosRemoveDir(root);
taosMkDir(root);
STfs *pTfs = tfsOpen(&dCfg, 1);
ASSERT_NE(pTfs, nullptr);
STfsFile file0;
STfsFile file1;
STfsFile file2;
STfsFile file3;
STfsFile file4;
SDiskID did0 = {0};
SDiskID did1 = {0};
SDiskID did2 = {0};
SDiskID did3 = {0};
SDiskID did4 = {0};
did3.id = 1;
did4.level = 1;
tfsInitFile(pTfs, &file0, did0, "fname");
tfsInitFile(pTfs, &file1, did1, "fname");
tfsInitFile(pTfs, &file2, did2, "fnamex");
tfsInitFile(pTfs, &file3, did3, "fname");
tfsInitFile(pTfs, &file4, did4, "fname");
EXPECT_TRUE(tfsIsSameFile(&file0, &file1));
EXPECT_FALSE(tfsIsSameFile(&file0, &file2));
EXPECT_FALSE(tfsIsSameFile(&file0, &file3));
EXPECT_FALSE(tfsIsSameFile(&file0, &file4));
{
int32_t size = 1024;
void *ret = malloc(size + sizeof(size_t));
*(size_t *)ret = size;
void *buf = (void *)((char *)ret + sizeof(size_t));
file0.did.id = 0;
file0.did.level = 0;
int32_t len = tfsEncodeFile((void **)&buf, &file0);
EXPECT_EQ(len, 8);
STfsFile outfile = {0};
char *outbuf = (char *)tfsDecodeFile(pTfs, (void *)((char *)buf - len), &outfile);
int32_t decodeLen = (outbuf - (char *)buf);
EXPECT_EQ(outfile.did.id, 0);
EXPECT_EQ(outfile.did.level, 0);
EXPECT_STREQ(outfile.aname, file0.aname);
EXPECT_STREQ(outfile.rname, "fname");
EXPECT_EQ(outfile.pTfs, pTfs);
}
{
char n1[] = "t3/t1.json";
char n2[] = "t3/t2.json";
STfsFile f1 = {0};
STfsFile f2 = {0};
SDiskID did;
did.id = 0;
did.level = 0;
tfsInitFile(pTfs, &f1, did, n1);
tfsInitFile(pTfs, &f2, did, n2);
EXPECT_EQ(tfsMkdir(pTfs, "t3"), 0);
FILE *fp = fopen(f1.aname, "w");
ASSERT_NE(fp, nullptr);
fwrite("12345678", 1, 5, fp);
fclose(fp);
char base[128] = {0};
tfsBasename(&f1, base);
char dir[128] = {0};
tfsDirname(&f1, dir);
EXPECT_STREQ(base, "t1.json");
char fulldir[128];
snprintf(fulldir, 128, "%s%s%s", root, TD_DIRSEP, "t3");
EXPECT_STREQ(dir, fulldir);
EXPECT_NE(tfsCopyFile(&f1, &f2), 0);
char af2[128] = {0};
snprintf(af2, 128, "%s%s%s", root, TD_DIRSEP, n2);
EXPECT_EQ(taosDirExist(af2), 0);
tfsRemoveFile(&f2);
EXPECT_NE(taosDirExist(af2), 0);
EXPECT_NE(tfsCopyFile(&f1, &f2), 0);
{
STfsDir *pDir = tfsOpendir(pTfs, "");
const STfsFile *pf1 = tfsReaddir(pDir);
EXPECT_STREQ(pf1->rname, "t3");
EXPECT_EQ(pf1->did.id, 0);
EXPECT_EQ(pf1->did.level, 0);
EXPECT_EQ(pf1->pTfs, pTfs);
const STfsFile *pf2 = tfsReaddir(pDir);
EXPECT_EQ(pf2, nullptr);
tfsClosedir(pDir);
}
{
STfsDir *pDir = tfsOpendir(pTfs, "t3");
const STfsFile *pf1 = tfsReaddir(pDir);
EXPECT_NE(pf1, nullptr);
EXPECT_EQ(pf1->did.id, 0);
EXPECT_EQ(pf1->did.level, 0);
EXPECT_EQ(pf1->pTfs, pTfs);
const STfsFile *pf2 = tfsReaddir(pDir);
EXPECT_NE(pf2, nullptr);
const STfsFile *pf3 = tfsReaddir(pDir);
EXPECT_EQ(pf3, nullptr);
tfsClosedir(pDir);
}
}
tfsClose(pTfs);
}
\ No newline at end of file
aux_source_directory(src NODES_SRC)
add_library(nodes STATIC ${NODES_SRC})
target_include_directories(
nodes
PUBLIC "${CMAKE_SOURCE_DIR}/include/nodes"
PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/inc"
)
target_link_libraries(
nodes
PRIVATE os util
)
if(${BUILD_TEST})
ADD_SUBDIRECTORY(test)
endif(${BUILD_TEST})
\ No newline at end of file
/*
* 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 "nodes.h"
void cloneNode(const SNode* pNode) {
}
/*
* 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 "nodes.h"
int32_t nodeToString(const SNode* pNode, char** pStr, int32_t* pLen) {
}
int32_t stringToNode(const char* pStr, SNode** pNode) {
}
/*
* 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 "nodes.h"
#define COMPARE_SCALAR_FIELD(fldname) \
do { \
if (a->fldname != b->fldname) \
return false; \
} while (0)
#define COMPARE_STRING(a, b) \
(((a) != NULL && (b) != NULL) ? (strcmp(a, b) == 0) : (a) == (b))
#define COMPARE_STRING_FIELD(fldname) \
do { \
if (!COMPARE_STRING(a->fldname, b->fldname)) \
return false; \
} while (0)
#define COMPARE_NODE_FIELD(fldname) \
do { \
if (!nodeEqual(a->fldname, b->fldname)) \
return false; \
} while (0)
#define COMPARE_ARRAY_FIELD(fldname) \
do { \
if (!nodeArrayEqual(a->fldname, b->fldname)) \
return false; \
} while (0)
static bool nodeArrayEqual(const SArray* a, const SArray* b) {
if (a == b) {
return true;
}
if (NULL == a || NULL == b) {
return false;
}
if (taosArrayGetSize(a) != taosArrayGetSize(b)) {
return false;
}
size_t size = taosArrayGetSize(a);
for (size_t i = 0; i < size; ++i) {
if (!nodeEqual((SNode*)taosArrayGetP(a, i), (SNode*)taosArrayGetP(b, i))) {
return false;
}
}
return true;
}
static bool columnNodeEqual(const SColumnNode* a, const SColumnNode* b) {
COMPARE_STRING_FIELD(dbName);
COMPARE_STRING_FIELD(tableName);
COMPARE_STRING_FIELD(colName);
return true;
}
static bool valueNodeEqual(const SValueNode* a, const SValueNode* b) {
COMPARE_STRING_FIELD(literal);
return true;
}
static bool operatorNodeEqual(const SOperatorNode* a, const SOperatorNode* b) {
COMPARE_SCALAR_FIELD(opType);
COMPARE_NODE_FIELD(pLeft);
COMPARE_NODE_FIELD(pRight);
return true;
}
static bool logicConditionNodeEqual(const SLogicConditionNode* a, const SLogicConditionNode* b) {
COMPARE_SCALAR_FIELD(condType);
COMPARE_ARRAY_FIELD(pParameterList);
return true;
}
static bool isNullConditionNodeEqual(const SIsNullCondNode* a, const SIsNullCondNode* b) {
COMPARE_NODE_FIELD(pExpr);
COMPARE_SCALAR_FIELD(isNot);
return true;
}
static bool functionNodeEqual(const SFunctionNode* a, const SFunctionNode* b) {
COMPARE_SCALAR_FIELD(funcId);
COMPARE_ARRAY_FIELD(pParameterList);
return true;
}
bool nodeEqual(const SNode* a, const SNode* b) {
if (a == b) {
return true;
}
if (NULL == a || NULL == b) {
return false;
}
if (nodeType(a) != nodeType(b)) {
return false;
}
switch (nodeType(a)) {
case QUERY_NODE_COLUMN:
return columnNodeEqual((const SColumnNode*)a, (const SColumnNode*)b);
case QUERY_NODE_VALUE:
return valueNodeEqual((const SValueNode*)a, (const SValueNode*)b);
case QUERY_NODE_OPERATOR:
return operatorNodeEqual((const SOperatorNode*)a, (const SOperatorNode*)b);
case QUERY_NODE_LOGIC_CONDITION:
return logicConditionNodeEqual((const SLogicConditionNode*)a, (const SLogicConditionNode*)b);
case QUERY_NODE_IS_NULL_CONDITION:
return isNullConditionNodeEqual((const SIsNullCondNode*)a, (const SIsNullCondNode*)b);
case QUERY_NODE_FUNCTION:
return functionNodeEqual((const SFunctionNode*)a, (const SFunctionNode*)b);
case QUERY_NODE_REAL_TABLE:
case QUERY_NODE_TEMP_TABLE:
case QUERY_NODE_JOIN_TABLE:
case QUERY_NODE_GROUPING_SET:
case QUERY_NODE_ORDER_BY_EXPR:
return false; // todo
default:
break;
}
return false;
}
/*
* 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 "nodes.h"
typedef bool (*FQueryNodeWalker)(SNode* pNode, void* pContext);
bool nodeArrayWalker(SArray* pArray, FQueryNodeWalker walker, void* pContext) {
size_t size = taosArrayGetSize(pArray);
for (size_t i = 0; i < size; ++i) {
if (!nodeTreeWalker((SNode*)taosArrayGetP(pArray, i), walker, pContext)) {
return false;
}
}
return true;
}
bool nodeTreeWalker(SNode* pNode, FQueryNodeWalker walker, void* pContext) {
if (NULL == pNode) {
return true;
}
if (!walker(pNode, pContext)) {
return false;
}
switch (nodeType(pNode)) {
case QUERY_NODE_COLUMN:
case QUERY_NODE_VALUE:
// these node types with no subnodes
return true;
case QUERY_NODE_OPERATOR: {
SOperatorNode* pOpNode = (SOperatorNode*)pNode;
if (!nodeTreeWalker(pOpNode->pLeft, walker, pContext)) {
return false;
}
return nodeTreeWalker(pOpNode->pRight, walker, pContext);
}
case QUERY_NODE_LOGIC_CONDITION:
return nodeArrayWalker(((SLogicConditionNode*)pNode)->pParameterList, walker, pContext);
case QUERY_NODE_IS_NULL_CONDITION:
return nodeTreeWalker(((SIsNullCondNode*)pNode)->pExpr, walker, pContext);
case QUERY_NODE_FUNCTION:
return nodeArrayWalker(((SFunctionNode*)pNode)->pParameterList, walker, pContext);
case QUERY_NODE_REAL_TABLE:
case QUERY_NODE_TEMP_TABLE:
return true; // todo
case QUERY_NODE_JOIN_TABLE: {
SJoinTableNode* pJoinTableNode = (SJoinTableNode*)pNode;
if (!nodeTreeWalker(pJoinTableNode->pLeft, walker, pContext)) {
return false;
}
if (!nodeTreeWalker(pJoinTableNode->pRight, walker, pContext)) {
return false;
}
return nodeTreeWalker(pJoinTableNode->pOnCond, walker, pContext);
}
case QUERY_NODE_GROUPING_SET:
return nodeArrayWalker(((SGroupingSetNode*)pNode)->pParameterList, walker, pContext);
case QUERY_NODE_ORDER_BY_EXPR:
return nodeTreeWalker(((SOrderByExprNode*)pNode)->pExpr, walker, pContext);
default:
break;
}
return false;
}
bool stmtWalker(SNode* pNode, FQueryNodeWalker walker, void* pContext) {
}
/*
* 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 "nodes.h"
bool isTimeorderQuery(const SNode* pQuery) {
}
bool isTimelineQuery(const SNode* pQuery) {
}
MESSAGE(STATUS "build nodes unit test")
# GoogleTest requires at least C++11
SET(CMAKE_CXX_STANDARD 11)
AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} SOURCE_LIST)
ADD_EXECUTABLE(nodesTest ${SOURCE_LIST})
TARGET_INCLUDE_DIRECTORIES(
nodesTest
PUBLIC "${CMAKE_SOURCE_DIR}/include/nodes/"
PRIVATE "${CMAKE_SOURCE_DIR}/source/nodes/inc"
)
TARGET_LINK_LIBRARIES(
nodesTest
PUBLIC os util common nodes gtest
)
/*
* 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>
TEST(NodesTest, traverseTest) {
// todo
}
int main(int argc, char* argv[]) {
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
# Base components
add_subdirectory(os)
add_subdirectory(util)
add_subdirectory(common)
# Library components
# Service components
# add_subdirectory(mnode)
# add_subdirectory(vnode)
# add_subdirectory(qnode)
add_subdirectory(dnode)
Subproject commit b8f76da4a708d158ec3cc4b844571dc4414e36b4
Subproject commit 4a4d79099b076b8ff12d5b4fdbcba54049a6866d
Subproject commit ce5201014136503d34fecbd56494b67b4961056c
CMAKE_MINIMUM_REQUIRED(VERSION 2.8...3.20)
PROJECT(TDengine)
INCLUDE_DIRECTORIES(inc)
INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/client/inc)
INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/query/inc)
AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/src SRC)
ADD_LIBRARY(tcq ${SRC})
IF (TD_SOMODE_STATIC)
TARGET_LINK_LIBRARIES(tcq tutil common taos_static)
ELSE ()
TARGET_LINK_LIBRARIES(tcq tutil common taos)
ENDIF ()
ADD_SUBDIRECTORY(test)
/*
* 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/>.
*/
#define _DEFAULT_SOURCE
#include <errno.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include "../../../include/client/taos.h"
#include "taosdef.h"
#include "tmsg.h"
#include "tcq.h"
#include "tdataformat.h"
#include "tglobal.h"
#include "tlog.h"
#include "tsclient.h"
#include "ttimer.h"
#include "twal.h"
#define cFatal(...) { if (cqDebugFlag & DEBUG_FATAL) { taosPrintLog("CQ FATAL ", 255, __VA_ARGS__); }}
#define cError(...) { if (cqDebugFlag & DEBUG_ERROR) { taosPrintLog("CQ ERROR ", 255, __VA_ARGS__); }}
#define cWarn(...) { if (cqDebugFlag & DEBUG_WARN) { taosPrintLog("CQ WARN ", 255, __VA_ARGS__); }}
#define cInfo(...) { if (cqDebugFlag & DEBUG_INFO) { taosPrintLog("CQ ", 255, __VA_ARGS__); }}
#define cDebug(...) { if (cqDebugFlag & DEBUG_DEBUG) { taosPrintLog("CQ ", cqDebugFlag, __VA_ARGS__); }}
#define cTrace(...) { if (cqDebugFlag & DEBUG_TRACE) { taosPrintLog("CQ ", cqDebugFlag, __VA_ARGS__); }}
typedef struct SCqObj {
tmr_h tmrId;
int64_t rid;
uint64_t uid;
int32_t tid; // table ID
int32_t rowSize; // bytes of a row
char * dstTable;
char * sqlStr; // SQL string
STSchema * pSchema; // pointer to schema array
void * pStream;
struct SCqObj *prev;
struct SCqObj *next;
SCqContext * pContext;
} SCqObj;
static void cqProcessStreamRes(void *param, TAOS_RES *tres, TAOS_ROW row);
static void cqCreateStream(SCqContext *pContext, SCqObj *pObj);
int32_t cqObjRef = -1;
int32_t cqVnodeNum = 0;
void cqRmFromList(SCqObj *pObj) {
//LOCK in caller
SCqContext *pContext = pObj->pContext;
if (pObj->prev) {
pObj->prev->next = pObj->next;
} else {
pContext->pHead = pObj->next;
}
if (pObj->next) {
pObj->next->prev = pObj->prev;
}
}
static void freeSCqContext(void *handle) {
if (handle == NULL) {
return;
}
SCqContext *pContext = handle;
pthread_mutex_destroy(&pContext->mutex);
taosTmrCleanUp(pContext->tmrCtrl);
pContext->tmrCtrl = NULL;
cDebug("vgId:%d, CQ is closed", pContext->vgId);
free(pContext);
}
void cqFree(void *handle) {
if (tsEnableStream == 0) {
return;
}
SCqObj *pObj = handle;
SCqContext *pContext = pObj->pContext;
int32_t delete = 0;
pthread_mutex_lock(&pContext->mutex);
// free the resources associated
if (pObj->pStream) {
taos_close_stream(pObj->pStream);
pObj->pStream = NULL;
} else {
taosTmrStop(pObj->tmrId);
pObj->tmrId = 0;
}
cInfo("vgId:%d, id:%d CQ:%s is dropped", pContext->vgId, pObj->tid, pObj->sqlStr);
tdFreeSchema(pObj->pSchema);
free(pObj->dstTable);
free(pObj->sqlStr);
free(pObj);
pContext->cqObjNum--;
if (pContext->cqObjNum <= 0 && pContext->delete) {
delete = 1;
}
pthread_mutex_unlock(&pContext->mutex);
if (delete) {
freeSCqContext(pContext);
}
}
void cqCreateRef() {
int32_t ref = atomic_load_32(&cqObjRef);
if (ref == -1) {
ref = taosOpenRef(4096, cqFree);
if (atomic_val_compare_exchange_32(&cqObjRef, -1, ref) != -1) {
taosCloseRef(ref);
}
}
}
void *cqOpen(void *ahandle, const SCqCfg *pCfg) {
if (tsEnableStream == 0) {
return NULL;
}
SCqContext *pContext = calloc(sizeof(SCqContext), 1);
if (pContext == NULL) {
terrno = TAOS_SYSTEM_ERROR(errno);
return NULL;
}
atomic_add_fetch_32(&cqVnodeNum, 1);
cqCreateRef();
pContext->tmrCtrl = taosTmrInit(0, 0, 0, "CQ");
tstrncpy(pContext->user, pCfg->user, sizeof(pContext->user));
tstrncpy(pContext->pass, pCfg->pass, sizeof(pContext->pass));
const char* db = pCfg->db;
for (const char* p = db; *p != 0; p++) {
if (*p == '.') {
db = p + 1;
break;
}
}
tstrncpy(pContext->db, db, sizeof(pContext->db));
pContext->vgId = pCfg->vgId;
pContext->cqWrite = pCfg->cqWrite;
tscEmbedded = 1;
pthread_mutex_init(&pContext->mutex, NULL);
cDebug("vgId:%d, CQ is opened", pContext->vgId);
return pContext;
}
void cqClose(void *handle) {
if (tsEnableStream == 0) {
return;
}
SCqContext *pContext = handle;
if (handle == NULL) return;
pContext->delete = 1;
int32_t hasCq = 0;
int32_t existLoop = 0;
// stop all CQs
cqStop(pContext);
int64_t rid = 0;
while (1) {
pthread_mutex_lock(&pContext->mutex);
SCqObj *pObj = pContext->pHead;
if (pObj) {
cqRmFromList(pObj);
rid = pObj->rid;
hasCq = 1;
if (pContext->pHead == NULL) {
existLoop = 1;
}
} else {
pthread_mutex_unlock(&pContext->mutex);
break;
}
pthread_mutex_unlock(&pContext->mutex);
taosRemoveRef(cqObjRef, rid);
if (existLoop) {
break;
}
}
if (hasCq == 0) {
freeSCqContext(pContext);
}
int32_t remainn = atomic_sub_fetch_32(&cqVnodeNum, 1);
if (remainn <= 0) {
int32_t ref = cqObjRef;
cqObjRef = -1;
taosCloseRef(ref);
}
}
void cqStart(void *handle) {
if (tsEnableStream == 0) {
return;
}
SCqContext *pContext = handle;
if (pContext->dbConn || pContext->master) return;
cDebug("vgId:%d, start all CQs", pContext->vgId);
pthread_mutex_lock(&pContext->mutex);
pContext->master = 1;
SCqObj *pObj = pContext->pHead;
while (pObj) {
cqCreateStream(pContext, pObj);
pObj = pObj->next;
}
pthread_mutex_unlock(&pContext->mutex);
}
void cqStop(void *handle) {
if (tsEnableStream == 0) {
return;
}
SCqContext *pContext = handle;
cDebug("vgId:%d, stop all CQs", pContext->vgId);
if (pContext->dbConn == NULL || pContext->master == 0) return;
pthread_mutex_lock(&pContext->mutex);
pContext->master = 0;
SCqObj *pObj = pContext->pHead;
while (pObj) {
if (pObj->pStream) {
taos_close_stream(pObj->pStream);
pObj->pStream = NULL;
cInfo("vgId:%d, id:%d CQ:%s is closed", pContext->vgId, pObj->tid, pObj->sqlStr);
} else {
taosTmrStop(pObj->tmrId);
pObj->tmrId = 0;
}
pObj = pObj->next;
}
if (pContext->dbConn) taos_close(pContext->dbConn);
pContext->dbConn = NULL;
pthread_mutex_unlock(&pContext->mutex);
}
void *cqCreate(void *handle, uint64_t uid, int32_t sid, const char* dstTable, char *sqlStr, STSchema *pSchema, int start) {
if (tsEnableStream == 0) {
return NULL;
}
SCqContext *pContext = handle;
int64_t rid = 0;
pthread_mutex_lock(&pContext->mutex);
SCqObj *pObj = pContext->pHead;
while (pObj) {
if (pObj->uid == uid) {
rid = pObj->rid;
pthread_mutex_unlock(&pContext->mutex);
return (void *)rid;
}
pObj = pObj->next;
}
pthread_mutex_unlock(&pContext->mutex);
pObj = calloc(sizeof(SCqObj), 1);
if (pObj == NULL) return NULL;
pObj->uid = uid;
pObj->tid = sid;
if (dstTable != NULL) {
pObj->dstTable = strdup(dstTable);
}
pObj->sqlStr = strdup(sqlStr);
pObj->pSchema = tdDupSchema(pSchema);
pObj->rowSize = schemaTLen(pSchema);
cInfo("vgId:%d, id:%d CQ:%s is created", pContext->vgId, pObj->tid, pObj->sqlStr);
pthread_mutex_lock(&pContext->mutex);
pObj->next = pContext->pHead;
if (pContext->pHead) pContext->pHead->prev = pObj;
pContext->pHead = pObj;
pContext->cqObjNum++;
pObj->rid = taosAddRef(cqObjRef, pObj);
if(start && pContext->master) {
cqCreateStream(pContext, pObj);
} else {
pObj->pContext = pContext;
}
rid = pObj->rid;
pthread_mutex_unlock(&pContext->mutex);
return (void *)rid;
}
void cqDrop(void *handle) {
if (tsEnableStream == 0) {
return;
}
SCqObj* pObj = (SCqObj*)taosAcquireRef(cqObjRef, (int64_t)handle);
if (pObj == NULL) {
return;
}
SCqContext *pContext = pObj->pContext;
pthread_mutex_lock(&pContext->mutex);
cqRmFromList(pObj);
// free the resources associated
if (pObj->pStream) {
taos_close_stream(pObj->pStream);
pObj->pStream = NULL;
} else {
taosTmrStop(pObj->tmrId);
pObj->tmrId = 0;
}
pthread_mutex_unlock(&pContext->mutex);
taosRemoveRef(cqObjRef, (int64_t)handle);
taosReleaseRef(cqObjRef, (int64_t)handle);
}
static void doCreateStream(void *param, TAOS_RES *result, int32_t code) {
SCqObj* pObj = (SCqObj*)taosAcquireRef(cqObjRef, (int64_t)param);
if (pObj == NULL) {
return;
}
SCqContext* pContext = pObj->pContext;
SSqlObj* pSql = (SSqlObj*)result;
if (code == TSDB_CODE_SUCCESS) {
if (atomic_val_compare_exchange_ptr(&(pContext->dbConn), NULL, pSql->pTscObj) != NULL) {
taos_close(pSql->pTscObj);
}
}
pthread_mutex_lock(&pContext->mutex);
cqCreateStream(pContext, pObj);
pthread_mutex_unlock(&pContext->mutex);
taosReleaseRef(cqObjRef, (int64_t)param);
}
static void cqProcessCreateTimer(void *param, void *tmrId) {
SCqObj* pObj = (SCqObj*)taosAcquireRef(cqObjRef, (int64_t)param);
if (pObj == NULL) {
return;
}
SCqContext* pContext = pObj->pContext;
if (pContext->dbConn == NULL) {
cDebug("vgId:%d, try connect to TDengine", pContext->vgId);
taos_connect_a(NULL, pContext->user, pContext->pass, pContext->db, 0, doCreateStream, param, NULL);
} else {
pthread_mutex_lock(&pContext->mutex);
cqCreateStream(pContext, pObj);
pthread_mutex_unlock(&pContext->mutex);
}
taosReleaseRef(cqObjRef, (int64_t)param);
}
// inner implement in tscStream.c
TAOS_STREAM *taos_open_stream_withname(TAOS *taos, const char* desName, const char *sqlstr, void (*fp)(void *param, TAOS_RES *, TAOS_ROW row),
int64_t stime, void *param, void (*callback)(void *), void* cqhandle);
static void cqCreateStream(SCqContext *pContext, SCqObj *pObj) {
pObj->pContext = pContext;
if (pContext->dbConn == NULL) {
cDebug("vgId:%d, create dbConn after 1000 ms", pContext->vgId);
pObj->tmrId = taosTmrStart(cqProcessCreateTimer, 1000, (void *)pObj->rid, pContext->tmrCtrl);
return;
}
pObj->tmrId = 0;
if (pObj->pStream == NULL) {
pObj->pStream = taos_open_stream_withname(pContext->dbConn, pObj->dstTable, pObj->sqlStr, cqProcessStreamRes, \
INT64_MIN, (void *)pObj->rid, NULL, pContext);
// TODO the pObj->pStream may be released if error happens
if (pObj->pStream) {
pContext->num++;
cDebug("vgId:%d, id:%d CQ:%s is opened", pContext->vgId, pObj->tid, pObj->sqlStr);
} else {
cError("vgId:%d, id:%d CQ:%s, failed to open", pContext->vgId, pObj->tid, pObj->sqlStr);
}
}
}
static void cqProcessStreamRes(void *param, TAOS_RES *tres, TAOS_ROW row) {
SCqObj* pObj = (SCqObj*)taosAcquireRef(cqObjRef, (int64_t)param);
if (pObj == NULL) {
return;
}
if (tres == NULL && row == NULL) {
taos_close_stream(pObj->pStream);
pObj->pStream = NULL;
taosReleaseRef(cqObjRef, (int64_t)param);
return;
}
SCqContext *pContext = pObj->pContext;
STSchema *pSchema = pObj->pSchema;
if (pObj->pStream == NULL) {
taosReleaseRef(cqObjRef, (int64_t)param);
return;
}
cDebug("vgId:%d, id:%d CQ:%s stream result is ready", pContext->vgId, pObj->tid, pObj->sqlStr);
int32_t size = sizeof(SWalHead) + sizeof(SSubmitMsg) + sizeof(SSubmitBlk) + TD_MEM_ROW_DATA_HEAD_SIZE + pObj->rowSize;
char *buffer = calloc(size, 1);
SWalHead *pHead = (SWalHead *)buffer;
SSubmitMsg *pMsg = (SSubmitMsg *) (buffer + sizeof(SWalHead));
SSubmitBlk *pBlk = (SSubmitBlk *) (buffer + sizeof(SWalHead) + sizeof(SSubmitMsg));
SMemRow trow = (SMemRow)pBlk->data;
SDataRow dataRow = (SDataRow)memRowDataBody(trow);
memRowSetType(trow, SMEM_ROW_DATA);
tdInitDataRow(dataRow, pSchema);
for (int32_t i = 0; i < pSchema->numOfCols; i++) {
STColumn *c = pSchema->columns + i;
void *val = row[i];
if (val == NULL) {
val = (void *)getNullValue(c->type);
} else if (c->type == TSDB_DATA_TYPE_BINARY) {
val = ((char*)val) - sizeof(VarDataLenT);
} else if (c->type == TSDB_DATA_TYPE_NCHAR) {
char buf[TSDB_MAX_NCHAR_LEN];
int32_t len = taos_fetch_lengths(tres)[i];
taosMbsToUcs4(val, len, buf, sizeof(buf), &len);
memcpy((char *)val + sizeof(VarDataLenT), buf, len);
varDataLen(val) = len;
}
tdAppendColVal(dataRow, val, c->type, c->offset);
}
pBlk->dataLen = htonl(memRowDataTLen(trow));
pBlk->schemaLen = 0;
pBlk->uid = htobe64(pObj->uid);
pBlk->tid = htonl(pObj->tid);
pBlk->numOfRows = htons(1);
pBlk->sversion = htonl(pSchema->version);
pBlk->padding = 0;
pHead->len = sizeof(SSubmitMsg) + sizeof(SSubmitBlk) + memRowDataTLen(trow);
pMsg->header.vgId = htonl(pContext->vgId);
pMsg->header.contLen = htonl(pHead->len);
pMsg->length = pMsg->header.contLen;
pMsg->numOfBlocks = htonl(1);
pHead->msgType = TDMT_VND_SUBMIT;
pHead->version = 0;
// write into vnode write queue
pContext->cqWrite(pContext->vgId, pHead, TAOS_QTYPE_CQ, NULL);
free(buffer);
taosReleaseRef(cqObjRef, (int64_t)param);
}
CMAKE_MINIMUM_REQUIRED(VERSION 2.8...3.20)
PROJECT(TDengine)
LIST(APPEND CQTEST_SRC ./cqtest.c)
ADD_EXECUTABLE(cqtest ${CQTEST_SRC})
TARGET_LINK_LIBRARIES(cqtest tcq taos_static)
/*
* 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/>.
*/
//#define _DEFAULT_SOURCE
#include "os.h"
#include "taosdef.h"
#include "tmsg.h"
#include "tglobal.h"
#include "tlog.h"
#include "tcq.h"
int64_t ver = 0;
void *pCq = NULL;
int writeToQueue(int32_t vgId, void *data, int type, void *pMsg) {
return 0;
}
int main(int argc, char *argv[]) {
int num = 3;
for (int i=1; i<argc; ++i) {
if (strcmp(argv[i], "-d")==0 && i < argc-1) {
dDebugFlag = atoi(argv[++i]);
} else if (strcmp(argv[i], "-n") == 0 && i <argc-1) {
num = atoi(argv[++i]);
} else {
printf("\nusage: %s [options] \n", argv[0]);
printf(" [-n num]: number of streams, default:%d\n", num);
printf(" [-d debugFlag]: debug flag, default:%d\n", dDebugFlag);
printf(" [-h help]: print out this help\n\n");
exit(0);
}
}
taosInitLog("cq.log", 100000, 10);
SCqCfg cqCfg;
strcpy(cqCfg.user, TSDB_DEFAULT_USER);
strcpy(cqCfg.pass, TSDB_DEFAULT_PASS);
cqCfg.vgId = 2;
cqCfg.cqWrite = writeToQueue;
pCq = cqOpen(NULL, &cqCfg);
if (pCq == NULL) {
printf("failed to open CQ\n");
exit(-1);
}
STSchemaBuilder schemaBuilder = {0};
tdInitTSchemaBuilder(&schemaBuilder, 0);
tdAddColToSchema(&schemaBuilder, TSDB_DATA_TYPE_TIMESTAMP, 0, 8);
tdAddColToSchema(&schemaBuilder, TSDB_DATA_TYPE_INT, 1, 4);
STSchema *pSchema = tdGetSchemaFromBuilder(&schemaBuilder);
tdDestroyTSchemaBuilder(&schemaBuilder);
for (int sid =1; sid<10; ++sid) {
cqCreate(pCq, sid, sid, NULL, "select avg(speed) from demo.t1 sliding(1s) interval(5s)", pSchema, 1);
}
tdFreeSchema(pSchema);
while (1) {
char c = (char)getchar();
switch(c) {
case 's':
cqStart(pCq);
break;
case 't':
cqStop(pCq);
break;
case 'c':
// create a CQ
break;
case 'd':
// drop a CQ
break;
case 'q':
break;
default:
printf("invalid command:%c", c);
}
if (c=='q') break;
}
cqClose(pCq);
taosCloseLog();
return 0;
}
/*
* 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_QUERY_H
#define TDENGINE_QUERY_H
#ifdef __cplusplus
extern "C" {
#endif
typedef void* qinfo_t;
/**
* create the qinfo object according to QueryTableMsg
* @param tsdb
* @param pQueryTableMsg
* @param qinfo
* @return
*/
int32_t qCreateQueryInfo(void* tsdb, int32_t vgId, SQueryTableMsg* pQueryTableMsg, qinfo_t* qinfo, uint64_t qId);
/**
* the main query execution function, including query on both table and multitables,
* which are decided according to the tag or table name query conditions
*
* @param qinfo
* @return
*/
bool qTableQuery(qinfo_t qinfo, uint64_t *qId);
/**
* Retrieve the produced results information, if current query is not paused or completed,
* this function will be blocked to wait for the query execution completed or paused,
* in which case enough results have been produced already.
*
* @param qinfo
* @return
*/
int32_t qRetrieveQueryResultInfo(qinfo_t qinfo, bool* buildRes, void* pRspContext);
/**
*
* Retrieve the actual results to fill the response message payload.
* Note that this function must be executed after qRetrieveQueryResultInfo is invoked.
*
* @param qinfo qinfo object
* @param pRsp response message
* @param contLen payload length
* @return
*/
int32_t qDumpRetrieveResult(qinfo_t qinfo, SRetrieveTableRsp** pRsp, int32_t* contLen, bool* continueExec);
/**
*
* @param qinfo
* @return
*/
void* qGetResultRetrieveMsg(qinfo_t qinfo);
/**
* kill current ongoing query and free query handle automatically
* @param qinfo qhandle
* @return
*/
int32_t qKillQuery(qinfo_t qinfo);
//kill by qid
int32_t qKillQueryByQId(void* pMgmt, int64_t qId, int32_t waitMs, int32_t waitCount);
bool qSolveCommitNoBlock(void* pRepo, void* pMgmt);
int32_t qQueryCompleted(qinfo_t qinfo);
/**
* destroy query info structure
* @param qHandle
*/
void qDestroyQueryInfo(qinfo_t qHandle);
void* qOpenQueryMgmt(int32_t vgId);
void qQueryMgmtNotifyClosed(void* pExecutor);
void qQueryMgmtReOpen(void *pExecutor);
void qCleanupQueryMgmt(void* pExecutor);
void** qRegisterQInfo(void* pMgmt, uint64_t qId, void *qInfo);
void** qAcquireQInfo(void* pMgmt, uint64_t key);
void** qReleaseQInfo(void* pMgmt, void* pQInfo, bool freeHandle);
bool checkQIdEqual(void *qHandle, uint64_t qId);
int64_t genQueryId(void);
#ifdef __cplusplus
}
#endif
#endif // TDENGINE_QUERY_H
/*
* 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 _TD_CQ_H_
#define _TD_CQ_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "tdataformat.h"
typedef int32_t (*FCqWrite)(int32_t vgId, void *pHead, int32_t qtype, void *pMsg);
typedef struct {
int32_t vgId;
char user[TSDB_USER_LEN];
char pass[TSDB_PASSWORD_LEN];
char db[TSDB_ACCT_ID_LEN + TSDB_DB_NAME_LEN]; // size must same with SVnodeObj.db[TSDB_ACCT_ID_LEN + TSDB_DB_NAME_LEN]
FCqWrite cqWrite;
} SCqCfg;
// SCqContext
typedef struct {
int32_t vgId;
int32_t master;
int32_t num; // number of continuous streams
char user[TSDB_USER_LEN];
char pass[TSDB_PASSWORD_LEN];
char db[TSDB_DB_NAME_LEN];
FCqWrite cqWrite;
struct SCqObj *pHead;
void *dbConn;
void *tmrCtrl;
pthread_mutex_t mutex;
int32_t delete;
int32_t cqObjNum;
} SCqContext;
// the following API shall be called by vnode
void *cqOpen(void *ahandle, const SCqCfg *pCfg);
void cqClose(void *handle);
// if vnode is master, vnode call this API to start CQ
void cqStart(void *handle);
// if vnode is slave/unsynced, vnode shall call this API to stop CQ
void cqStop(void *handle);
// cqCreate is called by TSDB to start an instance of CQ
void *cqCreate(void *handle, uint64_t uid, int32_t sid, const char* dstTable, char *sqlStr, STSchema *pSchema, int start);
// cqDrop is called by TSDB to stop an instance of CQ, handle is the return value of cqCreate
void cqDrop(void *handle);
extern int32_t cqDebugFlag;
#ifdef __cplusplus
}
#endif
#endif // _TD_CQ_H_
/*
* 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 _TD_TSDB_H_
#define _TD_TSDB_H_
#include <pthread.h>
#include <stdbool.h>
#include <stdint.h>
#include "taosdef.h"
#include "tmsg.h"
#include "tarray.h"
#include "tdataformat.h"
#include "tname.h"
#include "hash.h"
#include "tlockfree.h"
#include "tlist.h"
#ifdef __cplusplus
extern "C" {
#endif
#define TSDB_VERSION_MAJOR 1
#define TSDB_VERSION_MINOR 0
#define TSDB_INVALID_SUPER_TABLE_ID -1
#define TSDB_STATUS_COMMIT_START 1
#define TSDB_STATUS_COMMIT_OVER 2
#define TSDB_STATUS_COMMIT_NOBLOCK 3 //commit no block, need to be solved
// TSDB STATE DEFINITION
#define TSDB_STATE_OK 0x0
#define TSDB_STATE_BAD_META 0x1
#define TSDB_STATE_BAD_DATA 0x2
// --------- TSDB APPLICATION HANDLE DEFINITION
typedef struct {
void *appH;
void *cqH;
int (*notifyStatus)(void *, int status, int eno);
int (*eventCallBack)(void *);
void *(*cqCreateFunc)(void *handle, uint64_t uid, int32_t sid, const char *dstTable, char *sqlStr, STSchema *pSchema, int start);
void (*cqDropFunc)(void *handle);
} STsdbAppH;
// --------- TSDB REPOSITORY CONFIGURATION DEFINITION
typedef struct {
int32_t tsdbId;
int32_t cacheBlockSize;
int32_t totalBlocks;
int32_t daysPerFile; // day per file sharding policy
int32_t keep; // day of data to keep
int32_t keep1;
int32_t keep2;
int32_t minRowsPerFileBlock; // minimum rows per file block
int32_t maxRowsPerFileBlock; // maximum rows per file block
int8_t precision;
int8_t compression;
int8_t update;
int8_t cacheLastRow; // 0:no cache, 1: cache last row, 2: cache last NULL column 3: 1&2
} STsdbCfg;
#define CACHE_NO_LAST(c) ((c)->cacheLastRow == 0)
#define CACHE_LAST_ROW(c) (((c)->cacheLastRow & 1) > 0)
#define CACHE_LAST_NULL_COLUMN(c) (((c)->cacheLastRow & 2) > 0)
// --------- TSDB REPOSITORY USAGE STATISTICS
typedef struct {
int64_t totalStorage; // total bytes occupie
int64_t compStorage;
int64_t pointsWritten; // total data points written
} STsdbStat;
typedef struct STsdbRepo STsdbRepo;
STsdbCfg *tsdbGetCfg(const STsdbRepo *repo);
// --------- TSDB REPOSITORY DEFINITION
int32_t tsdbCreateRepo(int repoid);
int32_t tsdbDropRepo(int repoid);
STsdbRepo *tsdbOpenRepo(STsdbCfg *pCfg, STsdbAppH *pAppH);
int tsdbCloseRepo(STsdbRepo *repo, int toCommit);
int32_t tsdbConfigRepo(STsdbRepo *repo, STsdbCfg *pCfg);
int tsdbGetState(STsdbRepo *repo);
int8_t tsdbGetCompactState(STsdbRepo *repo);
// --------- TSDB TABLE DEFINITION
typedef struct {
uint64_t uid; // the unique table ID
int32_t tid; // the table ID in the repository.
} STableId;
// --------- TSDB TABLE configuration
typedef struct {
ETableType type;
char * name;
STableId tableId;
int32_t sversion;
char * sname; // super table name
uint64_t superUid;
STSchema * schema;
STSchema * tagSchema;
SKVRow tagValues;
char * sql;
} STableCfg;
void tsdbClearTableCfg(STableCfg *config);
void *tsdbGetTableTagVal(const void *pTable, int32_t colId, int16_t type, int16_t bytes);
char *tsdbGetTableName(void *pTable);
#define TSDB_TABLEID(_table) ((STableId*) (_table))
#define TSDB_PREV_ROW 0x1
#define TSDB_NEXT_ROW 0x2
STableCfg *tsdbCreateTableCfgFromMsg(SMDCreateTableMsg *pMsg);
int tsdbCreateTable(STsdbRepo *repo, STableCfg *pCfg);
int tsdbDropTable(STsdbRepo *pRepo, STableId tableId);
int tsdbUpdateTableTagValue(STsdbRepo *repo, SUpdateTableTagValMsg *pMsg);
uint32_t tsdbGetFileInfo(STsdbRepo *repo, char *name, uint32_t *index, uint32_t eindex, int64_t *size);
// the TSDB repository info
typedef struct STsdbRepoInfo {
STsdbCfg tsdbCfg;
uint64_t version; // version of the repository
int64_t tsdbTotalDataSize; // the original inserted data size
int64_t tsdbTotalDiskSize; // the total disk size taken by this TSDB repository
// TODO: Other informations to add
} STsdbRepoInfo;
STsdbRepoInfo *tsdbGetStatus(STsdbRepo *pRepo);
// the meter information report structure
typedef struct {
STableCfg tableCfg;
uint64_t version;
int64_t tableTotalDataSize; // In bytes
int64_t tableTotalDiskSize; // In bytes
} STableInfo;
// -- FOR INSERT DATA
/**
* Insert data to a table in a repository
* @param pRepo the TSDB repository handle
* @param pData the data to insert (will give a more specific description)
*
* @return the number of points inserted, -1 for failure and the error number is set
*/
int32_t tsdbInsertData(STsdbRepo *repo, SSubmitMsg *pMsg, SShellSubmitRspMsg *pRsp);
// -- FOR QUERY TIME SERIES DATA
typedef void *TsdbQueryHandleT; // Use void to hide implementation details
#define BLOCK_LOAD_OFFSET_SEQ_ORDER 1
#define BLOCK_LOAD_TABLE_SEQ_ORDER 2
#define BLOCK_LOAD_TABLE_RR_ORDER 3
// query condition to build multi-table data block iterator
typedef struct STsdbQueryCond {
STimeWindow twindow;
int32_t order; // desc|asc order to iterate the data block
int32_t numOfCols;
SColumnInfo *colList;
bool loadExternalRows; // load external rows or not
int32_t type; // data block load type:
} STsdbQueryCond;
typedef struct STableData STableData;
typedef struct {
T_REF_DECLARE()
SRWLatch latch;
TSKEY keyFirst;
TSKEY keyLast;
int64_t numOfRows;
int32_t maxTables;
STableData **tData;
SList * actList;
SList * extraBuffList;
SList * bufBlockList;
int64_t pointsAdd; // TODO
int64_t storageAdd; // TODO
} SMemTable;
typedef struct {
SMemTable* mem;
SMemTable* imem;
SMemTable mtable;
SMemTable* omem;
} SMemSnapshot;
typedef struct SMemRef {
int32_t ref;
SMemSnapshot snapshot;
} SMemRef;
typedef struct SDataBlockInfo {
STimeWindow window;
int32_t rows;
int32_t numOfCols;
int64_t uid;
int32_t tid;
} SDataBlockInfo;
typedef struct SFileBlockInfo {
int32_t numBlocksOfStep;
} SFileBlockInfo;
typedef struct {
void *pTable;
TSKEY lastKey;
} STableKeyInfo;
typedef struct {
uint32_t numOfTables;
SArray *pGroupList;
SHashObj *map; // speedup acquire the tableQueryInfo by table uid
} STableGroupInfo;
#define TSDB_BLOCK_DIST_STEP_ROWS 16
typedef struct {
uint16_t rowSize;
uint16_t numOfFiles;
uint32_t numOfTables;
uint64_t totalSize;
uint64_t totalRows;
int32_t maxRows;
int32_t minRows;
int32_t firstSeekTimeUs;
uint32_t numOfRowsInMemTable;
uint32_t numOfSmallBlocks;
SArray *dataBlockInfos;
} STableBlockDist;
/**
* Get the data block iterator, starting from position according to the query condition
*
* @param tsdb tsdb handle
* @param pCond query condition, including time window, result set order, and basic required columns for each block
* @param tableInfoGroup table object list in the form of set, grouped into different sets according to the
* group by condition
* @param qinfo query info handle from query processor
* @return
*/
TsdbQueryHandleT *tsdbQueryTables(STsdbRepo *tsdb, STsdbQueryCond *pCond, STableGroupInfo *tableInfoGroup, uint64_t qId,
SMemRef *pRef);
/**
* Get the last row of the given query time window for all the tables in STableGroupInfo object.
* Note that only one data block with only row will be returned while invoking retrieve data block function for
* all tables in this group.
*
* @param tsdb tsdb handle
* @param pCond query condition, including time window, result set order, and basic required columns for each block
* @param tableInfo table list.
* @return
*/
TsdbQueryHandleT tsdbQueryLastRow(STsdbRepo *tsdb, STsdbQueryCond *pCond, STableGroupInfo *tableInfo, uint64_t qId,
SMemRef *pRef);
TsdbQueryHandleT tsdbQueryCacheLast(STsdbRepo *tsdb, STsdbQueryCond *pCond, STableGroupInfo *groupList, uint64_t qId, SMemRef* pMemRef);
bool isTsdbCacheLastRow(TsdbQueryHandleT* pTsdbReadHandle);
/**
* get the queried table object list
* @param pHandle
* @return
*/
SArray *tsdbGetQueriedTableList(TsdbQueryHandleT *pHandle);
/**
* get the group list according to table id from client
* @param tsdb
* @param pCond
* @param groupList
* @param qinfo
* @return
*/
TsdbQueryHandleT tsdbQueryRowsInExternalWindow(STsdbRepo *tsdb, STsdbQueryCond *pCond, STableGroupInfo *groupList,
uint64_t qId, SMemRef *pRef);
/**
* get num of rows in mem table
*
* @param pHandle
* @return row size
*/
int64_t tsdbGetNumOfRowsInMemTable(TsdbQueryHandleT* pHandle);
/**
* move to next block if exists
*
* @param pTsdbReadHandle
* @return
*/
bool tsdbNextDataBlock(TsdbQueryHandleT pTsdbReadHandle);
/**
* Get current data block information
*
* @param pTsdbReadHandle
* @param pBlockInfo
* @return
*/
void tsdbRetrieveDataBlockInfo(TsdbQueryHandleT *pTsdbReadHandle, SDataBlockInfo *pBlockInfo);
/**
*
* Get the pre-calculated information w.r.t. current data block.
*
* In case of data block in cache, the pBlockStatis will always be NULL.
* If a block is not completed loaded from disk, the pBlockStatis will be NULL.
* @pBlockStatis the pre-calculated value for current data blocks. if the block is a cache block, always return 0
* @return
*/
int32_t tsdbRetrieveDataBlockStatisInfo(TsdbQueryHandleT *pTsdbReadHandle, SDataStatis **pBlockStatis);
/**
*
* The query condition with primary timestamp is passed to iterator during its constructor function,
* the returned data block must be satisfied with the time window condition in any cases,
* which means the SData data block is not actually the completed disk data blocks.
*
* @param pTsdbReadHandle query handle
* @param pColumnIdList required data columns id list
* @return
*/
SArray *tsdbRetrieveDataBlock(TsdbQueryHandleT *pTsdbReadHandle, SArray *pColumnIdList);
/**
* Get the qualified table id for a super table according to the tag query expression.
* @param stableid. super table sid
* @param pTagCond. tag query condition
*/
int32_t tsdbQuerySTableByTagCond(STsdbRepo *tsdb, uint64_t uid, TSKEY key, const char *pTagCond, size_t len,
int16_t tagNameRelType, const char *tbnameCond, STableGroupInfo *pGroupList,
SColIndex *pColIndex, int32_t numOfCols);
/**
* destroy the created table group list, which is generated by tag query
* @param pGroupList
*/
void tsdbDestroyTableGroup(STableGroupInfo *pGroupList);
/**
* create the table group result including only one table, used to handle the normal table query
*
* @param tsdb tsdbHandle
* @param uid table uid
* @param pGroupInfo the generated result
* @return
*/
int32_t tsdbGetOneTableGroup(STsdbRepo *tsdb, uint64_t uid, TSKEY startKey, STableGroupInfo *pGroupInfo);
/**
*
* @param tsdb
* @param pTableIdList
* @param pGroupInfo
* @return
*/
int32_t tsdbGetTableGroupFromIdList(STsdbRepo *tsdb, SArray *pTableIdList, STableGroupInfo *pGroupInfo);
/**
* clean up the query handle
* @param queryHandle
*/
void tsdbCleanupQueryHandle(TsdbQueryHandleT queryHandle);
void tsdbResetQueryHandle(TsdbQueryHandleT queryHandle, STsdbQueryCond *pCond);
void tsdbResetQueryHandleForNewTable(TsdbQueryHandleT queryHandle, STsdbQueryCond *pCond, STableGroupInfo* groupList);
int32_t tsdbGetFileBlocksDistInfo(TsdbQueryHandleT* queryHandle, STableBlockDist* pTableBlockInfo);
/**
* get the statistics of repo usage
* @param repo. point to the tsdbrepo
* @param totalPoints. total data point written
* @param totalStorage. total bytes took by the tsdb
* @param compStorage. total bytes took by the tsdb after compressed
*/
void tsdbReportStat(void *repo, int64_t *totalPoints, int64_t *totalStorage, int64_t *compStorage);
int tsdbInitCommitQueue();
void tsdbDestroyCommitQueue();
int tsdbSyncCommit(STsdbRepo *repo);
void tsdbIncCommitRef(int vgId);
void tsdbDecCommitRef(int vgId);
// For TSDB file sync
int tsdbSyncSend(void *pRepo, SOCKET socketFd);
int tsdbSyncRecv(void *pRepo, SOCKET socketFd);
// For TSDB Compact
int tsdbCompact(STsdbRepo *pRepo);
// For TSDB Health Monitor
// no problem return true
bool tsdbNoProblem(STsdbRepo* pRepo);
#ifdef __cplusplus
}
#endif
#endif // _TD_TSDB_H_
...@@ -53,22 +53,22 @@ curr_dir=$(readlink -f "$(dirname "$0")") ...@@ -53,22 +53,22 @@ curr_dir=$(readlink -f "$(dirname "$0")")
echo $curr_dir echo $curr_dir
${curr_dir}/cleanCluster.sh -r "/data" ${curr_dir}/cleanCluster.sh -r "/data"
${curr_dir}/cleanCluster.sh -r "/data2" #${curr_dir}/cleanCluster.sh -r "/data2"
if [[ "${updateSrc}" == "yes" ]]; then if [[ "${updateSrc}" == "yes" ]]; then
${curr_dir}/compileVersion.sh -r ${curr_dir}/../../../../ -v "3.0" ${curr_dir}/compileVersion.sh -r ${curr_dir}/../../../../ -v "3.0"
fi fi
${curr_dir}/setupDnodes.sh -r "/data" -n ${dnodeNumber} -f ${firstEp} -p 7000 ${curr_dir}/setupDnodes.sh -r "/data" -n ${dnodeNumber} -f ${firstEp} -p 7000
${curr_dir}/setupDnodes.sh -r "/data2" -n ${dnodeNumber} -f ${firstEp} -p 8000 #${curr_dir}/setupDnodes.sh -r "/data2" -n ${dnodeNumber} -f ${firstEp} -p 8000
if [[ "${masterDnode}" == "master" ]]; then if [[ "${masterDnode}" == "master" ]]; then
# create all dnode into cluster # create all dnode into cluster
taos -s "create dnode trd02 port 8000;" #taos -s "create dnode trd02 port 8000;"
taos -s "create dnode trd03 port 7000;" taos -s "create dnode trd03 port 7000;"
taos -s "create dnode trd03 port 8000;" #taos -s "create dnode trd03 port 8000;"
taos -s "create dnode trd04 port 7000;" taos -s "create dnode trd04 port 7000;"
taos -s "create dnode trd04 port 8000;" #taos -s "create dnode trd04 port 8000;"
fi fi
......
...@@ -4,7 +4,7 @@ system sh/exec.sh -n dnode1 -s start ...@@ -4,7 +4,7 @@ system sh/exec.sh -n dnode1 -s start
sql connect sql connect
print =============== create database print =============== create database
sql create database d1 sql create database d1 vgroups 2
sql show databases sql show databases
if $rows != 1 then if $rows != 1 then
return -1 return -1
...@@ -22,6 +22,21 @@ if $data03 != 0 then ...@@ -22,6 +22,21 @@ if $data03 != 0 then
return -1 return -1
endi endi
print =============== show vgroups1
sql use d1
sql show vgroups
if $rows != 2 then
return -1
endi
if $data00 != 2 then
return -1
endi
if $data10 != 3 then
return -1
endi
print =============== drop database print =============== drop database
sql drop database d1 sql drop database d1
sql show databases sql show databases
...@@ -30,14 +45,68 @@ if $rows != 0 then ...@@ -30,14 +45,68 @@ if $rows != 0 then
endi endi
print =============== more databases print =============== more databases
sql create database d2 sql create database d2 vgroups 2
sql create database d3 sql create database d3 vgroups 3
sql create database d4 sql create database d4 vgroups 4
sql show databases sql show databases
if $rows != 3 then if $rows != 3 then
return -1 return -1
endi endi
print =============== show vgroups2
sql show d2.vgroups
if $rows != 2 then
return -1
endi
if $data00 != 4 then
return -1
endi
if $data10 != 5 then
return -1
endi
print =============== show vgroups3
sql show d3.vgroups
if $rows != 3 then
return -1
endi
if $data00 != 6 then
return -1
endi
if $data10 != 7 then
return -1
endi
if $data20 != 8 then
return -1
endi
print =============== show vgroups4
sql show d4.vgroups
if $rows != 4 then
return -1
endi
if $data00 != 9 then
return -1
endi
if $data10 != 10 then
return -1
endi
if $data20 != 11 then
return -1
endi
if $data30 != 12 then
return -1
endi
print =============== drop database print =============== drop database
sql drop database d2 sql drop database d2
sql drop database d3 sql drop database d3
...@@ -50,7 +119,7 @@ if $data00 != d4 then ...@@ -50,7 +119,7 @@ if $data00 != d4 then
return -1 return -1
endi endi
if $data02 != 2 then if $data02 != 4 then
return -1 return -1
endi endi
...@@ -58,19 +127,12 @@ if $data03 != 0 then ...@@ -58,19 +127,12 @@ if $data03 != 0 then
return -1 return -1
endi endi
print =============== show vgroups print =============== show vgroups4 again
sql show databases
if $rows != 1 then
return -1
endi
sql_error use d1 sql_error use d1
sql use d4 sql use d4
sql show vgroups sql show vgroups
if $rows != 4 then
if $rows != 2 then
return -1 return -1
endi endi
...@@ -81,15 +143,17 @@ if $data00 != 1 then ...@@ -81,15 +143,17 @@ if $data00 != 1 then
return -1 return -1
endi endi
if $data02 != 2 then if $data02 != 4 then
return -1 return -1
endi endi
print =============== restart
system sh/exec.sh -n dnode1 -s stop -x SIGKILL system sh/exec.sh -n dnode1 -s stop -x SIGKILL
system sh/exec.sh -n dnode1 -s start system sh/exec.sh -n dnode1 -s start
print =============== show databases
sql show databases sql show databases
if $rows != 1 then if $rows != 1 then
return -1 return -1
endi endi
...@@ -99,7 +163,27 @@ sql_error use d1 ...@@ -99,7 +163,27 @@ sql_error use d1
sql use d4 sql use d4
sql show vgroups sql show vgroups
if $rows != 2 then if $rows != 4 then
return -1
endi
print =============== create databases
sql create database d5 vgroups 5;
print =============== show vgroups
sql use d5
sql show vgroups
if $rows != 5 then
return -1
endi
sql show d4.vgroups
if $rows != 4 then
return -1
endi
sql show d5.vgroups
if $rows != 5 then
return -1 return -1
endi endi
......
...@@ -7,8 +7,10 @@ print ============================ dnode1 start ...@@ -7,8 +7,10 @@ print ============================ dnode1 start
$i = 0 $i = 0
$dbPrefix = db $dbPrefix = db
$stPrefix = st
$tbPrefix = tb $tbPrefix = tb
$db = $dbPrefix . $i $db = $dbPrefix . $i
$st = $stPrefix . $i
$tb = $tbPrefix . $i $tb = $tbPrefix . $i
print =============== step1 print =============== step1
...@@ -68,12 +70,47 @@ if $data06 != 15 then ...@@ -68,12 +70,47 @@ if $data06 != 15 then
return -1 return -1
endi endi
return
print =============== step6 print =============== step6
$i = $i + 1 $i = $i + 1
while $i < 5 while $i < 5
$db = $dbPrefix . $i $db = $dbPrefix . $i
$st = $stPrefix . $i
$tb = $tbPrefix . $i
print create database $db
sql create database $db sql create database $db
print use $db
sql use $db sql use $db
print create table $st (ts timestamp, i int) tags (j int)
sql create table $st (ts timestamp, i int) tags (j int)
print create table $tb using $st tags(1)
sql create table $tb using $st tags(1)
sql show stables
if $rows != 1 then
return -1
endi
print $data00 $data01 $data02 $data03
if $data00 != $st then
return -1
endi
sql show tables
if $rows != 1 then
return -1
endi
print $data00 $data01 $data02 $data03
if $data00 != $tb then
return -1
endi
$i = $i + 1 $i = $i + 1
endw endw
...@@ -86,93 +123,179 @@ while $i < 5 ...@@ -86,93 +123,179 @@ while $i < 5
endw endw
print =============== step8 print =============== step8
$i = 0 $i = 1
$db = $dbPrefix . $i $db = $dbPrefix . $i
$st = $stPrefix . $i
$tb = $tbPrefix . $i $tb = $tbPrefix . $i
sql create database $db sql create database $db
sql use $db sql use $db
sql create table st (ts timestamp, i int) tags (j int) sql create table $st (ts timestamp, i int) tags (j int)
sql create table $tb using st tags(1) sql create table $tb using $st tags(1)
return sql show stables
system sh/exec.sh -n dnode1 -s stop -x SIGINT if $rows != 1 then
return -1
endi
if $data00 != $st then
return -1
endi
sql show tables sql show tables
if $rows != 1 then if $rows != 1 then
return -1 return -1
endi endi
if $data00 != $tb then
return -1
endi
print =============== step9 print =============== step9
sql drop database $db sql drop database $db
print =============== step10 print =============== step10
sql create database $db sql create database $db
sql use $db sql use $db
sql show stables
if $rows != 0 then
return -1
endi
sql show tables sql show tables
if $rows != 0 then if $rows != 0 then
return -1 return -1
endi endi
print =============== step11 print =============== step11
sql create table st (ts timestamp, i int) tags (j int) sql create table $st (ts timestamp, i int) tags (j int)
sql create table $tb using st tags(1) sql create table $tb using $st tags(1)
sql show stables
if $rows != 1 then
return -1
endi
if $data00 != $st then
return -1
endi
sql show tables sql show tables
if $rows != 1 then if $rows != 1 then
return -1 return -1
endi endi
if $data00 != $tb then
return -1
endi
print =============== step12 print =============== step12
sql drop database $db sql drop database $db
print =============== step13 print =============== step13
sql create database $db sql create database $db
sql use $db sql use $db
sql show stables
if $rows != 0 then
return -1
endi
sql show tables sql show tables
if $rows != 0 then if $rows != 0 then
return -1 return -1
endi endi
sql create table st (ts timestamp, i int) tags (j int) print ============== step14
sql create table $tb using st tags(1) sql create table $st (ts timestamp, i int) tags (j int)
sql create table $tb using $st tags(1)
sql show stables
if $rows != 1 then
return -1
endi
if $data00 != $st then
return -1
endi
sql show tables sql show tables
if $rows != 1 then if $rows != 1 then
return -1 return -1
endi endi
if $data00 != $tb then
return -1
endi
sql insert into $tb values (now+1a, 0) sql insert into $tb values (now+1a, 0)
sql insert into $tb values (now+2a, 1) sql insert into $tb values (now+2a, 1)
sql insert into $tb values (now+3a, 2) sql insert into $tb values (now+3a, 2)
sql insert into $tb values (now+4a, 3) sql insert into $tb values (now+4a, 3)
sql insert into $tb values (now+5a, 4) sql insert into $tb values (now+5a, 4)
return
sql select * from $tb sql select * from $tb
if $rows != 5 then if $rows != 5 then
return -1 return -1
endi endi
sql select * from $stb
if $rows != 5 then
return -1
endi
print =============== step14 print =============== step14
sql drop database $db sql drop database $db
print =============== step15 print =============== step15
sql create database $db sql create database $db
sql use $db sql use $db
sql show stables
if $rows != 0 then
return -1
endi
sql show tables sql show tables
if $rows != 0 then if $rows != 0 then
return -1 return -1
endi endi
print =============== step16 print =============== step16
sql create table st (ts timestamp, i int) tags (j int) sql create table $st (ts timestamp, i int) tags (j int)
sql create table $tb using st tags(1) sql create table $tb using $st tags(1)
sql show stables
if $rows != 1 then
return -1
endi
if $data00 != $st then
return -1
endi
sql show tables sql show tables
if $rows != 1 then if $rows != 1 then
return -1 return -1
endi endi
if $data00 != $tb then
return -1
endi
sql insert into $tb values (now+1a, 0)
sql insert into $tb values (now+2a, 1)
sql insert into $tb values (now+3a, 2)
sql insert into $tb values (now+4a, 3)
sql insert into $tb values (now+5a, 4)
sql select * from $tb sql select * from $tb
if $rows != 0 then if $rows != 5 then
return -1
endi
sql select * from $stb
if $rows != 5 then
return -1 return -1
endi endi
......
...@@ -78,8 +78,8 @@ if $data02 != master then ...@@ -78,8 +78,8 @@ if $data02 != master then
return -1 return -1
endi endi
print =============== create table print =============== create database
sql create database d1; sql create database d1 vgroups 4;
sql create database d2; sql create database d2;
sql show databases sql show databases
...@@ -90,10 +90,98 @@ endi ...@@ -90,10 +90,98 @@ endi
sql use d1 sql use d1
sql show vgroups; sql show vgroups;
if $rows != 2 then if $rows != 4 then
return -1
endi
print =============== create table
sql use d1
sql create table st (ts timestamp, i int) tags (j int)
sql show stables
if $rows != 1 then
return -1
endi
print $data00 $data01 $data02
sql create table c1 using st tags(1)
sql create table c2 using st tags(2)
sql create table c3 using st tags(2)
sql create table c4 using st tags(2)
sql create table c5 using st tags(2)
sql show tables
print $data00 $data01 $data02
if $rows != 5 then
return -1
endi
print =============== insert data
sql insert into c1 values(now+1s, 1)
sql insert into c1 values(now+2s, 2)
sql insert into c1 values(now+3s, 3)
sql insert into c2 values(now+1s, 1)
sql insert into c2 values(now+2s, 2)
sql insert into c2 values(now+3s, 3)
sql insert into c3 values(now+1s, 1)
sql insert into c3 values(now+2s, 2)
sql insert into c3 values(now+3s, 3)
sql insert into c4 values(now+1s, 1)
sql insert into c4 values(now+2s, 2)
sql insert into c4 values(now+3s, 3)
sql insert into c5 values(now+1s, 1)
sql insert into c5 values(now+2s, 2)
sql insert into c5 values(now+3s, 3)
print =============== query data
sql select * from c1
if $rows != 3 then
return -1
endi
print $data00 $data01
print $data10 $data11
print $data20 $data11
if $data01 != 1 then
return -1
endi
if $data11 != 2 then
return -1
endi
if $data21 != 3 then
return -1
endi
sql select * from c2
if $rows != 3 then
return -1 return -1
endi endi
sql select * from c3
if $rows != 3 then
return -1
endi
sql select * from c4
if $rows != 3 then
return -1
endi
sql select * from c5
if $rows != 3 then
return -1
endi
sql select * from st
#if $rows != 15 then
# return -1
#endi
print =============== drop dnode print =============== drop dnode
sql drop dnode 2; sql drop dnode 2;
sql show dnodes; sql show dnodes;
......
...@@ -66,6 +66,24 @@ print =============== insert data ...@@ -66,6 +66,24 @@ print =============== insert data
sql insert into c1 values(now+1s, 1) sql insert into c1 values(now+1s, 1)
sql insert into c1 values(now+2s, 2) sql insert into c1 values(now+2s, 2)
sql insert into c1 values(now+3s, 3) sql insert into c1 values(now+3s, 3)
sql insert into c2 values(now+1s, 1)
sql insert into c2 values(now+2s, 2)
sql insert into c2 values(now+3s, 3)
sql insert into c3 values(now+1s, 1)
sql insert into c3 values(now+2s, 2)
sql insert into c3 values(now+3s, 3)
sql insert into c4 values(now+1s, 1)
sql insert into c4 values(now+2s, 2)
sql insert into c4 values(now+3s, 3)
sql insert into c5 values(now+1s, 1)
sql insert into c5 values(now+2s, 2)
sql insert into c5 values(now+3s, 3)
sql insert into c6 values(now+1s, 1)
sql insert into c6 values(now+2s, 2)
sql insert into c6 values(now+3s, 3)
sql insert into c7 values(now+1s, 1)
sql insert into c7 values(now+2s, 2)
sql insert into c7 values(now+3s, 3)
print =============== query data print =============== query data
sql select * from c1 sql select * from c1
...@@ -89,6 +107,42 @@ if $data21 != 3 then ...@@ -89,6 +107,42 @@ if $data21 != 3 then
return -1 return -1
endi endi
sql select * from c2
if $rows != 3 then
return -1
endi
sql select * from c3
if $rows != 3 then
return -1
endi
sql select * from c4
if $rows != 3 then
return -1
endi
sql select * from c5
if $rows != 3 then
return -1
endi
sql select * from c6
if $rows != 3 then
return -1
endi
sql select * from c7
if $rows != 3 then
return -1
endi
print =============== query data frpm st
sql select * from st
#if $rows != 21 then
# return -1
#endi
system sh/exec.sh -n dnode1 -s stop -x SIGINT system sh/exec.sh -n dnode1 -s stop -x SIGINT
system sh/exec.sh -n dnode1 -s start system sh/exec.sh -n dnode1 -s start
...@@ -114,4 +168,40 @@ if $data21 != 3 then ...@@ -114,4 +168,40 @@ if $data21 != 3 then
return -1 return -1
endi endi
sql select * from c2
if $rows != 3 then
return -1
endi
sql select * from c3
if $rows != 3 then
return -1
endi
sql select * from c4
if $rows != 3 then
return -1
endi
sql select * from c5
if $rows != 3 then
return -1
endi
sql select * from c6
if $rows != 3 then
return -1
endi
sql select * from c7
if $rows != 3 then
return -1
endi
print =============== query data frpm st
sql select * from st
#if $rows != 21 then
# return -1
#endi
system sh/exec.sh -n dnode1 -s stop -x SIGINT system sh/exec.sh -n dnode1 -s stop -x SIGINT
\ No newline at end of file
...@@ -26,11 +26,17 @@ char dbName[32] = "db"; ...@@ -26,11 +26,17 @@ char dbName[32] = "db";
char stbName[64] = "st"; char stbName[64] = "st";
int32_t numOfThreads = 1; int32_t numOfThreads = 1;
int64_t numOfTables = 200000; int64_t numOfTables = 200000;
int64_t startOffset = 0;
int32_t createTable = 1; int32_t createTable = 1;
int32_t insertData = 0; int32_t insertData = 0;
int32_t batchNum = 100; int32_t batchNumOfTbl = 100;
int32_t batchNumOfRow = 1;
int32_t numOfVgroups = 2; int32_t numOfVgroups = 2;
int32_t showTablesFlag = 0; int32_t showTablesFlag = 0;
int32_t queryFlag = 0;
int64_t startTimestamp = 1640966400000; // 2020-01-01 00:00:00.000
typedef struct { typedef struct {
int64_t tableBeginIndex; int64_t tableBeginIndex;
...@@ -79,7 +85,7 @@ void createDbAndStb() { ...@@ -79,7 +85,7 @@ void createDbAndStb() {
} }
taos_free_result(pRes); taos_free_result(pRes);
sprintf(qstr, "create table %s (ts timestamp, i int) tags (j int)", stbName); sprintf(qstr, "create table if not exists %s (ts timestamp, i int) tags (j int)", stbName);
pRes = taos_query(con, qstr); pRes = taos_query(con, qstr);
code = taos_errno(pRes); code = taos_errno(pRes);
if (code != 0) { if (code != 0) {
...@@ -167,7 +173,7 @@ void showTables() { ...@@ -167,7 +173,7 @@ void showTables() {
void *threadFunc(void *param) { void *threadFunc(void *param) {
SThreadInfo *pInfo = (SThreadInfo *)param; SThreadInfo *pInfo = (SThreadInfo *)param;
char *qstr = malloc(2000 * 1000); char *qstr = malloc(batchNumOfTbl * batchNumOfRow * 128);
int32_t code = 0; int32_t code = 0;
TAOS *con = taos_connect(NULL, "root", "taosdata", NULL, 0); TAOS *con = taos_connect(NULL, "root", "taosdata", NULL, 0);
...@@ -192,7 +198,7 @@ void *threadFunc(void *param) { ...@@ -192,7 +198,7 @@ void *threadFunc(void *param) {
// batch = MIN(batch, batchNum); // batch = MIN(batch, batchNum);
int32_t len = sprintf(qstr, "create table"); int32_t len = sprintf(qstr, "create table");
for (int32_t i = 0; i < batchNum;) { for (int32_t i = 0; i < batchNumOfTbl;) {
len += sprintf(qstr + len, " %s_t%" PRId64 " using %s tags(%" PRId64 ")", stbName, t, stbName, t); len += sprintf(qstr + len, " %s_t%" PRId64 " using %s tags(%" PRId64 ")", stbName, t, stbName, t);
t++; t++;
i++; i++;
...@@ -205,7 +211,7 @@ void *threadFunc(void *param) { ...@@ -205,7 +211,7 @@ void *threadFunc(void *param) {
TAOS_RES *pRes = taos_query(con, qstr); TAOS_RES *pRes = taos_query(con, qstr);
code = taos_errno(pRes); code = taos_errno(pRes);
if ((code != 0) && (code != TSDB_CODE_RPC_AUTH_REQUIRED)) { if ((code != 0) && (code != TSDB_CODE_RPC_AUTH_REQUIRED)) {
pError("failed to create table t%" PRId64 ", code: %d, reason:%s", t, code, tstrerror(code)); pError("failed to create table t%" PRId64 ", reason:%s", t, tstrerror(code));
} }
taos_free_result(pRes); taos_free_result(pRes);
int64_t endTs = taosGetTimestampUs(); int64_t endTs = taosGetTimestampUs();
...@@ -227,31 +233,49 @@ void *threadFunc(void *param) { ...@@ -227,31 +233,49 @@ void *threadFunc(void *param) {
if (insertData) { if (insertData) {
int64_t curMs = 0; int64_t curMs = 0;
int64_t beginMs = taosGetTimestampMs(); int64_t beginMs = taosGetTimestampMs();
pInfo->startMs = beginMs;
int64_t t = pInfo->tableBeginIndex;
for (; t <= pInfo->tableEndIndex;) {
// int64_t batch = (pInfo->tableEndIndex - t);
// batch = MIN(batch, batchNum);
pInfo->startMs = taosGetTimestampMs(); int32_t len = sprintf(qstr, "insert into ");
for (int64_t t = pInfo->tableBeginIndex; t < pInfo->tableEndIndex; ++t) {
int64_t batch = (pInfo->tableEndIndex - t); for (int32_t i = 0; i < batchNumOfTbl;) {
batch = MIN(batch, batchNum); int64_t ts = startTimestamp;
len += sprintf(qstr + len, "%s_t%" PRId64 " values ", stbName, t);
int32_t len = sprintf(qstr, "insert into"); for (int32_t j = 0; j < batchNumOfRow; j++) {
for (int32_t i = 0; i < batch; ++i) { len += sprintf(qstr + len, "(%" PRId64 ", 6666) ", ts++);
len += sprintf(qstr + len, " t%" PRId64 " values(now, %" PRId64 ")", t + i, t + i); }
}
t++;
i++;
if (t > pInfo->tableEndIndex) {
break;
}
}
int64_t startTs = taosGetTimestampUs();
TAOS_RES *pRes = taos_query(con, qstr); TAOS_RES *pRes = taos_query(con, qstr);
code = taos_errno(pRes); code = taos_errno(pRes);
if (code != 0) { if ((code != 0) && (code != TSDB_CODE_RPC_AUTH_REQUIRED)) {
pError("failed to insert table t%" PRId64 ", reason:%s", t, tstrerror(code)); pError("failed to insert %s_t%" PRId64 ", reason:%s", stbName, t, tstrerror(code));
} }
taos_free_result(pRes); taos_free_result(pRes);
int64_t endTs = taosGetTimestampUs();
int64_t delay = endTs - startTs;
// printf("==== %"PRId64" - %"PRId64", %"PRId64"\n", startTs, endTs, delay);
if (delay > pInfo->maxDelay) pInfo->maxDelay = delay;
if (delay < pInfo->minDelay) pInfo->minDelay = delay;
curMs = taosGetTimestampMs(); curMs = taosGetTimestampMs();
if (curMs - beginMs > 10000) { if (curMs - beginMs > 10000) {
beginMs = curMs;
// printf("==== tableBeginIndex: %"PRId64", t: %"PRId64"\n", pInfo->tableBeginIndex, t);
printInsertProgress(pInfo, t); printInsertProgress(pInfo, t);
} }
t += (batch - 1);
} }
printInsertProgress(pInfo, pInfo->tableEndIndex); printInsertProgress(pInfo, t);
} }
taos_close(con); taos_close(con);
...@@ -273,6 +297,8 @@ void printHelp() { ...@@ -273,6 +297,8 @@ void printHelp() {
printf("%s%s%s%d\n", indent, indent, "numOfThreads, default is ", numOfThreads); printf("%s%s%s%d\n", indent, indent, "numOfThreads, default is ", numOfThreads);
printf("%s%s\n", indent, "-n"); printf("%s%s\n", indent, "-n");
printf("%s%s%s%" PRId64 "\n", indent, indent, "numOfTables, default is ", numOfTables); printf("%s%s%s%" PRId64 "\n", indent, indent, "numOfTables, default is ", numOfTables);
printf("%s%s\n", indent, "-o");
printf("%s%s%s%" PRId64 "\n", indent, indent, "startOffset, default is ", startOffset);
printf("%s%s\n", indent, "-v"); printf("%s%s\n", indent, "-v");
printf("%s%s%s%d\n", indent, indent, "numOfVgroups, default is ", numOfVgroups); printf("%s%s%s%d\n", indent, indent, "numOfVgroups, default is ", numOfVgroups);
printf("%s%s\n", indent, "-a"); printf("%s%s\n", indent, "-a");
...@@ -280,9 +306,13 @@ void printHelp() { ...@@ -280,9 +306,13 @@ void printHelp() {
printf("%s%s\n", indent, "-i"); printf("%s%s\n", indent, "-i");
printf("%s%s%s%d\n", indent, indent, "insertData, default is ", insertData); printf("%s%s%s%d\n", indent, indent, "insertData, default is ", insertData);
printf("%s%s\n", indent, "-b"); printf("%s%s\n", indent, "-b");
printf("%s%s%s%d\n", indent, indent, "batchNum, default is ", batchNum); printf("%s%s%s%d\n", indent, indent, "batchNumOfTbl, default is ", batchNumOfTbl);
printf("%s%s\n", indent, "-w"); printf("%s%s\n", indent, "-w");
printf("%s%s%s%d\n", indent, indent, "showTablesFlag, default is ", showTablesFlag); printf("%s%s%s%d\n", indent, indent, "showTablesFlag, default is ", showTablesFlag);
printf("%s%s\n", indent, "-q");
printf("%s%s%s%d\n", indent, indent, "queryFlag, default is ", queryFlag);
printf("%s%s\n", indent, "-l");
printf("%s%s%s%d\n", indent, indent, "batchNumOfRow, default is ", batchNumOfRow);
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
} }
...@@ -302,6 +332,8 @@ void parseArgument(int32_t argc, char *argv[]) { ...@@ -302,6 +332,8 @@ void parseArgument(int32_t argc, char *argv[]) {
numOfThreads = atoi(argv[++i]); numOfThreads = atoi(argv[++i]);
} else if (strcmp(argv[i], "-n") == 0) { } else if (strcmp(argv[i], "-n") == 0) {
numOfTables = atoll(argv[++i]); numOfTables = atoll(argv[++i]);
} else if (strcmp(argv[i], "-o") == 0) {
startOffset = atoll(argv[++i]);
} else if (strcmp(argv[i], "-v") == 0) { } else if (strcmp(argv[i], "-v") == 0) {
numOfVgroups = atoi(argv[++i]); numOfVgroups = atoi(argv[++i]);
} else if (strcmp(argv[i], "-a") == 0) { } else if (strcmp(argv[i], "-a") == 0) {
...@@ -309,23 +341,31 @@ void parseArgument(int32_t argc, char *argv[]) { ...@@ -309,23 +341,31 @@ void parseArgument(int32_t argc, char *argv[]) {
} else if (strcmp(argv[i], "-i") == 0) { } else if (strcmp(argv[i], "-i") == 0) {
insertData = atoi(argv[++i]); insertData = atoi(argv[++i]);
} else if (strcmp(argv[i], "-b") == 0) { } else if (strcmp(argv[i], "-b") == 0) {
batchNum = atoi(argv[++i]); batchNumOfTbl = atoi(argv[++i]);
} else if (strcmp(argv[i], "-l") == 0) {
batchNumOfRow = atoi(argv[++i]);
} else if (strcmp(argv[i], "-w") == 0) { } else if (strcmp(argv[i], "-w") == 0) {
showTablesFlag = atoi(argv[++i]); showTablesFlag = atoi(argv[++i]);
} else if (strcmp(argv[i], "-q") == 0) {
queryFlag = atoi(argv[++i]);
} else { } else {
pPrint("%s unknow para: %s %s", GREEN, argv[++i], NC);
} }
} }
pPrint("%s dbName:%s %s", GREEN, dbName, NC); pPrint("%s dbName:%s %s", GREEN, dbName, NC);
pPrint("%s stbName:%s %s", GREEN, stbName, NC); pPrint("%s stbName:%s %s", GREEN, stbName, NC);
pPrint("%s configDir:%s %s", GREEN, configDir, NC); pPrint("%s configDir:%s %s", GREEN, configDir, NC);
pPrint("%s numOfTables:%" PRId64 " %s", GREEN, numOfTables, NC); pPrint("%s numOfTables:%" PRId64 " %s", GREEN, numOfTables, NC);
pPrint("%s startOffset:%" PRId64 " %s", GREEN, startOffset, NC);
pPrint("%s numOfThreads:%d %s", GREEN, numOfThreads, NC); pPrint("%s numOfThreads:%d %s", GREEN, numOfThreads, NC);
pPrint("%s numOfVgroups:%d %s", GREEN, numOfVgroups, NC); pPrint("%s numOfVgroups:%d %s", GREEN, numOfVgroups, NC);
pPrint("%s createTable:%d %s", GREEN, createTable, NC); pPrint("%s createTable:%d %s", GREEN, createTable, NC);
pPrint("%s insertData:%d %s", GREEN, insertData, NC); pPrint("%s insertData:%d %s", GREEN, insertData, NC);
pPrint("%s batchNum:%d %s", GREEN, batchNum, NC); pPrint("%s batchNumOfTbl:%d %s", GREEN, batchNumOfTbl, NC);
pPrint("%s batchNumOfRow:%d %s", GREEN, batchNumOfRow, NC);
pPrint("%s showTablesFlag:%d %s", GREEN, showTablesFlag, NC); pPrint("%s showTablesFlag:%d %s", GREEN, showTablesFlag, NC);
pPrint("%s queryFlag:%d %s", GREEN, queryFlag, NC);
pPrint("%s start create table performace test %s", GREEN, NC); pPrint("%s start create table performace test %s", GREEN, NC);
} }
...@@ -338,9 +378,16 @@ int32_t main(int32_t argc, char *argv[]) { ...@@ -338,9 +378,16 @@ int32_t main(int32_t argc, char *argv[]) {
return 0; return 0;
} }
createDbAndStb(); if (queryFlag) {
//selectRowsFromTable();
return 0;
}
pPrint("%d threads are spawned to create %" PRId64 " tables", numOfThreads, numOfTables); if (createTable) {
createDbAndStb();
}
pPrint("%d threads are spawned to create %" PRId64 " tables, offset is %" PRId64 " ", numOfThreads, numOfTables, startOffset);
pthread_attr_t thattr; pthread_attr_t thattr;
pthread_attr_init(&thattr); pthread_attr_init(&thattr);
...@@ -365,8 +412,8 @@ int32_t main(int32_t argc, char *argv[]) { ...@@ -365,8 +412,8 @@ int32_t main(int32_t argc, char *argv[]) {
int64_t tableFrom = 0; int64_t tableFrom = 0;
for (int32_t i = 0; i < numOfThreads; ++i) { for (int32_t i = 0; i < numOfThreads; ++i) {
pInfo[i].tableBeginIndex = tableFrom; pInfo[i].tableBeginIndex = tableFrom + startOffset;
pInfo[i].tableEndIndex = i < b ? tableFrom + a : tableFrom + a - 1; pInfo[i].tableEndIndex = (i < b ? tableFrom + a : tableFrom + a - 1) + startOffset;
tableFrom = pInfo[i].tableEndIndex + 1; tableFrom = pInfo[i].tableEndIndex + 1;
pInfo[i].threadIndex = i; pInfo[i].threadIndex = i;
pInfo[i].minDelay = INT64_MAX; pInfo[i].minDelay = INT64_MAX;
...@@ -396,9 +443,11 @@ int32_t main(int32_t argc, char *argv[]) { ...@@ -396,9 +443,11 @@ int32_t main(int32_t argc, char *argv[]) {
insertDataSpeed += pInfo[i].insertDataSpeed; insertDataSpeed += pInfo[i].insertDataSpeed;
} }
pPrint("%s total %" PRId64 " tables, %.1f tables/second, threads:%d, maxDelay: %" PRId64 "us, minDelay: %" PRId64 if (createTable) {
pPrint("%s total %" PRId64 " tables, %.1f tables/second, threads:%d, maxDelay: %" PRId64 "us, minDelay: %" PRId64
"us %s", "us %s",
GREEN, numOfTables, createTableSpeed, numOfThreads, maxDelay, minDelay, NC); GREEN, numOfTables, createTableSpeed, numOfThreads, maxDelay, minDelay, NC);
}
if (insertData) { if (insertData) {
pPrint("%s total %" PRId64 " tables, %.1f rows/second, threads:%d %s", GREEN, numOfTables, insertDataSpeed, pPrint("%s total %" PRId64 " tables, %.1f rows/second, threads:%d %s", GREEN, numOfTables, insertDataSpeed,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册