diff --git a/include/common/common.h b/include/common/common.h index 0913c12597..1c3a0e22f7 100644 --- a/include/common/common.h +++ b/include/common/common.h @@ -55,10 +55,18 @@ typedef struct SDataBlockInfo { int64_t uid; } SDataBlockInfo; +typedef struct SConstantItem { + SColumnInfo info; + int32_t startIndex; // run-length-encoding to save the space for multiple rows + int32_t endIndex; + SVariant value; +} SConstantItem; + typedef struct SSDataBlock { SColumnDataAgg *pBlockAgg; - SArray *pDataBlock; // SArray - SDataBlockInfo info; + SArray *pDataBlock; // SArray + SArray *pConstantList; // SArray, it is a constant/tags value of the corresponding result value. + SDataBlockInfo info; } SSDataBlock; typedef struct SColumnInfoData { @@ -82,7 +90,7 @@ typedef struct SLimit { typedef struct SOrder { uint32_t order; - int32_t orderColId; + SColumn col; } SOrder; typedef struct SGroupbyExpr { diff --git a/include/common/taosmsg.h b/include/common/taosmsg.h index e14788be47..2769f8bc7a 100644 --- a/include/common/taosmsg.h +++ b/include/common/taosmsg.h @@ -281,7 +281,7 @@ typedef struct SSchema { uint8_t type; char name[TSDB_COL_NAME_LEN]; int16_t colId; - int16_t bytes; + int32_t bytes; } SSchema; //#endif @@ -360,10 +360,10 @@ typedef struct { } SConnectMsg; typedef struct SEpSet { - int8_t inUse; - int8_t numOfEps; - uint16_t port[TSDB_MAX_REPLICA]; - char fqdn[TSDB_MAX_REPLICA][TSDB_FQDN_LEN]; + int8_t inUse; + int8_t numOfEps; + uint16_t port[TSDB_MAX_REPLICA]; + char fqdn[TSDB_MAX_REPLICA][TSDB_FQDN_LEN]; } SEpSet; typedef struct { @@ -383,14 +383,9 @@ typedef struct { int32_t maxUsers; int32_t maxDbs; int32_t maxTimeSeries; - int32_t maxConnections; int32_t maxStreams; - int32_t maxPointsPerSecond; - int64_t maxStorage; // In unit of GB - int64_t maxQueryTime; // In unit of hour - int64_t maxInbound; - int64_t maxOutbound; - int8_t accessState; // Configured only by command + int64_t maxStorage; // In unit of GB + int32_t accessState; // Configured only by command } SCreateAcctMsg, SAlterAcctMsg; typedef struct { @@ -398,8 +393,8 @@ typedef struct { } SDropUserMsg, SDropAcctMsg; typedef struct { - char user[TSDB_USER_LEN]; - char pass[TSDB_KEY_LEN]; + char user[TSDB_USER_LEN]; + char pass[TSDB_KEY_LEN]; } SCreateUserMsg, SAlterUserMsg; typedef struct { @@ -418,10 +413,10 @@ typedef struct { } SDropSTableMsg; typedef struct SColIndex { - int16_t colId; // column id - int16_t colIndex; // column index in colList if it is a normal column or index in tagColList if a tag - uint16_t flag; // denote if it is a tag or a normal column - char name[TSDB_COL_NAME_LEN + TSDB_DB_NAME_LEN + 1]; + int16_t colId; // column id + int16_t colIndex; // column index in colList if it is a normal column or index in tagColList if a tag + int16_t flag; // denote if it is a tag or a normal column + char name[TSDB_COL_NAME_LEN + TSDB_DB_NAME_LEN + 1]; } SColIndex; typedef struct SColumnFilterInfo { @@ -515,8 +510,8 @@ typedef struct { int16_t numOfCols; // the number of columns will be load from vnode SInterval interval; // SSessionWindow sw; // session window - uint16_t tagCondLen; // tag length in current query - uint16_t colCondLen; // column length in current query + int16_t tagCondLen; // tag length in current query + int16_t colCondLen; // column length in current query int16_t numOfGroupCols; // num of group by columns int16_t orderByIdx; int16_t orderType; // used in group by xx order by xxx @@ -524,10 +519,10 @@ typedef struct { int16_t prjOrder; // global order in super table projection query. int64_t limit; int64_t offset; - uint32_t queryType; // denote another query process + int32_t queryType; // denote another query process int16_t numOfOutput; // final output columns numbers int16_t fillType; // interpolate type - uint64_t fillVal; // default value array list + int64_t fillVal; // default value array list int32_t secondStageOutput; STsBufInfo tsBuf; // tsBuf info int32_t numOfTags; // number of tags columns involved @@ -542,63 +537,71 @@ typedef struct { } SQueryTableMsg; typedef struct { - int32_t code; - union{uint64_t qhandle; uint64_t qId;}; // query handle + int32_t code; + union { + uint64_t qhandle; + uint64_t qId; + }; // query handle } SQueryTableRsp; // todo: the show handle should be replaced with id typedef struct { SMsgHead header; - union{uint64_t qhandle; uint64_t qId;}; // query handle - uint16_t free; + union { + int32_t showId; + int64_t qhandle; + int64_t qId; + }; // query handle + int8_t free; } SRetrieveTableMsg; typedef struct SRetrieveTableRsp { int32_t numOfRows; - int8_t completed; // all results are returned to client - int16_t precision; - int64_t offset; // updated offset value for multi-vnode projection query + int64_t offset; // updated offset value for multi-vnode projection query int64_t useconds; + int8_t completed; // all results are returned to client + int8_t precision; int8_t compressed; + int8_t reserved; int32_t compLen; char data[]; } SRetrieveTableRsp; typedef struct { - char db[TSDB_FULL_DB_NAME_LEN]; - int32_t cacheBlockSize; //MB - int32_t totalBlocks; - int32_t maxTables; - int32_t daysPerFile; - int32_t daysToKeep0; - int32_t daysToKeep1; - int32_t daysToKeep2; - int32_t minRowsPerFileBlock; - int32_t maxRowsPerFileBlock; - int32_t commitTime; - int32_t fsyncPeriod; - uint8_t precision; // time resolution - int8_t compression; - int8_t walLevel; - int8_t replications; - int8_t quorum; - int8_t ignoreExist; - int8_t update; - int8_t cacheLastRow; - int8_t dbType; - int16_t partitions; - int8_t reserve[5]; + char db[TSDB_FULL_DB_NAME_LEN]; + int32_t cacheBlockSize; // MB + int32_t totalBlocks; + int32_t maxTables; + int32_t daysPerFile; + int32_t daysToKeep0; + int32_t daysToKeep1; + int32_t daysToKeep2; + int32_t minRowsPerFileBlock; + int32_t maxRowsPerFileBlock; + int32_t commitTime; + int32_t fsyncPeriod; + int8_t precision; // time resolution + int8_t compression; + int8_t walLevel; + int8_t replications; + int8_t quorum; + int8_t ignoreExist; + int8_t update; + int8_t cacheLastRow; + int8_t dbType; + int16_t partitions; + int8_t reserve[5]; } SCreateDbMsg, SAlterDbMsg; typedef struct { - char name[TSDB_FUNC_NAME_LEN]; - char path[PATH_MAX]; - int32_t funcType; - uint8_t outputType; - int16_t outputLen; - int32_t bufSize; - int32_t codeLen; - char code[]; + char name[TSDB_FUNC_NAME_LEN]; + char path[PATH_MAX]; + int32_t funcType; + int8_t outputType; + int16_t outputLen; + int32_t bufSize; + int32_t codeLen; + char code[]; } SCreateFuncMsg; typedef struct { @@ -626,8 +629,8 @@ typedef struct { } SDropFuncMsg; typedef struct { - char db[TSDB_TABLE_FNAME_LEN]; - uint8_t ignoreNotExists; + char db[TSDB_TABLE_FNAME_LEN]; + int8_t ignoreNotExists; } SDropDbMsg, SUseDbMsg, SSyncDbMsg; typedef struct { @@ -701,7 +704,7 @@ typedef struct { typedef struct { char db[TSDB_FULL_DB_NAME_LEN]; - uint32_t vgId; + int32_t vgId; int32_t cacheBlockSize; int32_t totalBlocks; int32_t daysPerFile; @@ -762,32 +765,31 @@ typedef struct { } SVgroupsMsg, SVgroupsInfo; typedef struct STableMetaMsg { - int32_t contLen; - char tableFname[TSDB_TABLE_FNAME_LEN]; // table id - uint8_t numOfTags; - uint8_t precision; - uint8_t tableType; - int16_t numOfColumns; - int16_t sversion; - int16_t tversion; - int32_t tid; - uint64_t uid; - SVgroupMsg vgroup; - - char sTableName[TSDB_TABLE_FNAME_LEN]; - uint64_t suid; - SSchema schema[]; + int32_t contLen; + char tableFname[TSDB_TABLE_FNAME_LEN]; // table id + int8_t numOfTags; + int8_t precision; + int8_t tableType; + int16_t numOfColumns; + int16_t sversion; + int16_t tversion; + int32_t tid; + int64_t uid; + SVgroupMsg vgroup; + char sTableName[TSDB_TABLE_FNAME_LEN]; + int64_t suid; + SSchema schema[]; } STableMetaMsg; typedef struct SMultiTableMeta { - int32_t numOfTables; - int32_t numOfVgroup; - int32_t numOfUdf; - int32_t contLen; - uint8_t compressed; // denote if compressed or not - uint32_t rawLen; // size before compress - uint8_t metaClone; // make meta clone after retrieve meta from mnode - char meta[]; + int32_t numOfTables; + int32_t numOfVgroup; + int32_t numOfUdf; + int32_t contLen; + int8_t compressed; // denote if compressed or not + int32_t rawLen; // size before compress + uint8_t metaClone; // make meta clone after retrieve meta from mnode + char meta[]; } SMultiTableMeta; typedef struct { @@ -802,10 +804,10 @@ typedef struct { * payloadLen is the length of payload */ typedef struct { - int8_t type; - char db[TSDB_FULL_DB_NAME_LEN]; - uint16_t payloadLen; - char payload[]; + int8_t type; + char db[TSDB_FULL_DB_NAME_LEN]; + int16_t payloadLen; + char payload[]; } SShowMsg; typedef struct { @@ -815,7 +817,7 @@ typedef struct { } SCompactMsg; typedef struct SShowRsp { - uint64_t qhandle; + int32_t showId; STableMetaMsg tableMeta; } SShowRsp; @@ -837,8 +839,8 @@ typedef struct { } SConfigTableMsg; typedef struct { - uint32_t dnodeId; - int32_t vgId; + int32_t dnodeId; + int32_t vgId; } SConfigVnodeMsg; typedef struct { @@ -847,29 +849,29 @@ typedef struct { } SCfgDnodeMsg; typedef struct { - char sql[TSDB_SHOW_SQL_LEN]; - uint32_t queryId; - int64_t useconds; - int64_t stime; - uint64_t qId; - uint64_t sqlObjId; - int32_t pid; - char fqdn[TSDB_FQDN_LEN]; - uint8_t stableQuery; - int32_t numOfSub; - char subSqlInfo[TSDB_SHOW_SUBQUERY_LEN]; //include subqueries' index, Obj IDs and states(C-complete/I-imcomplete) + char sql[TSDB_SHOW_SQL_LEN]; + int32_t queryId; + int64_t useconds; + int64_t stime; + int64_t qId; + int64_t sqlObjId; + int32_t pid; + char fqdn[TSDB_FQDN_LEN]; + int8_t stableQuery; + int32_t numOfSub; + char subSqlInfo[TSDB_SHOW_SUBQUERY_LEN]; // include subqueries' index, Obj IDs and states(C-complete/I-imcomplete) } SQueryDesc; typedef struct { - char sql[TSDB_SHOW_SQL_LEN]; - char dstTable[TSDB_TABLE_NAME_LEN]; - uint32_t streamId; - int64_t num; // number of computing/cycles - int64_t useconds; - int64_t ctime; - int64_t stime; - int64_t slidingTime; - int64_t interval; + char sql[TSDB_SHOW_SQL_LEN]; + char dstTable[TSDB_TABLE_NAME_LEN]; + int32_t streamId; + int64_t num; // number of computing/cycles + int64_t useconds; + int64_t ctime; + int64_t stime; + int64_t slidingTime; + int64_t interval; } SStreamDesc; typedef struct { @@ -893,8 +895,18 @@ typedef struct { } SHeartBeatRsp; typedef struct { - char queryId[TSDB_KILL_MSG_LEN + 1]; -} SKillQueryMsg, SKillConnMsg; + int32_t connId; + int32_t streamId; +} SKillStreamMsg; + +typedef struct { + int32_t connId; + int32_t queryId; +} SKillQueryMsg; + +typedef struct { + int32_t connId; +} SKillConnMsg; typedef struct { char user[TSDB_USER_LEN]; diff --git a/include/common/tglobal.h b/include/common/tglobal.h index f478e96766..d0f95b786a 100644 --- a/include/common/tglobal.h +++ b/include/common/tglobal.h @@ -54,6 +54,7 @@ extern int32_t tsCompressColData; extern int32_t tsMaxNumOfDistinctResults; extern char tsTempDir[]; extern int64_t tsMaxVnodeQueuedBytes; +extern int tsCompatibleModel; // 2.0 compatible model //query buffer management extern int32_t tsQueryBufferSize; // maximum allowed usage buffer size in MB for each data node during query processing diff --git a/include/dnode/mgmt/dnode.h b/include/dnode/mgmt/dnode.h index 50886932ce..540a501f3a 100644 --- a/include/dnode/mgmt/dnode.h +++ b/include/dnode/mgmt/dnode.h @@ -31,6 +31,7 @@ typedef struct { int16_t numOfSupportMnodes; int16_t numOfSupportVnodes; int16_t numOfSupportQnodes; + int8_t enableTelem; int32_t statusInterval; int32_t mnodeEqualVnodeNum; float numOfThreadsPerCore; @@ -45,6 +46,8 @@ typedef struct { char timezone[TSDB_TIMEZONE_LEN]; char locale[TSDB_LOCALE_LEN]; char charset[TSDB_LOCALE_LEN]; + char buildinfo[64]; + char gitinfo[48]; } SDnodeOpt; /* ------------------------ SDnode ------------------------ */ diff --git a/include/dnode/mnode/mnode.h b/include/dnode/mnode/mnode.h index 0a897b93f8..8a8346fbc0 100644 --- a/include/dnode/mnode/mnode.h +++ b/include/dnode/mnode/mnode.h @@ -43,24 +43,31 @@ typedef struct SMnodeLoad { int64_t compStorage; } SMnodeLoad; +typedef struct SMnodeCfg { + int32_t sver; + int8_t enableTelem; + int32_t statusInterval; + int32_t mnodeEqualVnodeNum; + int32_t shellActivityTimer; + char *timezone; + char *locale; + char *charset; + char *buildinfo; + char *gitinfo; +} SMnodeCfg; + typedef struct { int32_t dnodeId; int32_t clusterId; int8_t replica; int8_t selfIndex; SReplica replicas[TSDB_MAX_REPLICA]; + SMnodeCfg cfg; SDnode *pDnode; PutMsgToMnodeQFp putMsgToApplyMsgFp; SendMsgToDnodeFp sendMsgToDnodeFp; SendMsgToMnodeFp sendMsgToMnodeFp; SendRedirectMsgFp sendRedirectMsgFp; - int32_t sver; - int32_t statusInterval; - int32_t mnodeEqualVnodeNum; - int32_t shellActivityTimer; - char *timezone; - char *locale; - char *charset; } SMnodeOpt; /* ------------------------ SMnode ------------------------ */ diff --git a/include/libs/function/function.h b/include/libs/function/function.h index 92d8c972f5..d7360a81bc 100644 --- a/include/libs/function/function.h +++ b/include/libs/function/function.h @@ -229,7 +229,7 @@ typedef struct SScalarFunctionInfo { typedef struct SMultiFunctionsDesc { bool stableQuery; bool groupbyColumn; - bool simpleAgg; + bool agg; bool arithmeticOnAgg; bool projectionQuery; bool hasFilter; @@ -261,6 +261,7 @@ int32_t qIsBuiltinFunction(const char* name, int32_t len, bool* scalarFunction); bool qIsValidUdf(SArray* pUdfInfo, const char* name, int32_t len, int32_t* functionId); bool qIsAggregateFunction(const char* functionName); +bool qIsSelectivityFunction(const char* functionName); tExprNode* exprTreeFromBinary(const void* data, size_t size); diff --git a/include/libs/parser/parser.h b/include/libs/parser/parser.h index 9e6a033f10..0e6c352d71 100644 --- a/include/libs/parser/parser.h +++ b/include/libs/parser/parser.h @@ -86,7 +86,7 @@ typedef struct SQueryStmtInfo { SLimit slimit; STagCond tagCond; SArray * colCond; - SOrder order; + SArray * order; int16_t numOfTables; int16_t curTableIdx; STableMetaInfo **pTableMetaInfo; @@ -108,10 +108,10 @@ typedef struct SQueryStmtInfo { SArray *pUdfInfo; struct SQueryStmtInfo *sibling; // sibling - SArray *pUpstream; // SArray struct SQueryStmtInfo *pDownstream; + SMultiFunctionsDesc info; + SArray *pUpstream; // SArray int32_t havingFieldNum; - SMultiFunctionsDesc info; int32_t exprListLevelIndex; } SQueryStmtInfo; @@ -176,6 +176,7 @@ typedef struct SSourceParam { SExprInfo* createExprInfo(STableMetaInfo* pTableMetaInfo, const char* funcName, SSourceParam* pSource, SSchema* pResSchema, int16_t interSize); int32_t copyExprInfoList(SArray* dst, const SArray* src, uint64_t uid, bool deepcopy); +int32_t getExprFunctionLevel(SQueryStmtInfo* pQueryInfo); STableMetaInfo* getMetaInfo(SQueryStmtInfo* pQueryInfo, int32_t tableIndex); SSchema *getOneColumnSchema(const STableMeta* pTableMeta, int32_t colIndex); diff --git a/include/libs/planner/planner.h b/include/libs/planner/planner.h index 3ccc4bf4cd..1ff3f02da5 100644 --- a/include/libs/planner/planner.h +++ b/include/libs/planner/planner.h @@ -23,6 +23,35 @@ extern "C" { #define QUERY_TYPE_MERGE 1 #define QUERY_TYPE_PARTIAL 2 +enum OPERATOR_TYPE_E { + OP_TableScan = 1, + OP_DataBlocksOptScan = 2, + OP_TableSeqScan = 3, + OP_TagScan = 4, + OP_TableBlockInfoScan= 5, + OP_Aggregate = 6, + OP_Project = 7, + OP_Groupby = 8, + OP_Limit = 9, + OP_SLimit = 10, + OP_TimeWindow = 11, + OP_SessionWindow = 12, + OP_StateWindow = 22, + OP_Fill = 13, + OP_MultiTableAggregate = 14, + OP_MultiTableTimeInterval = 15, +// OP_DummyInput = 16, //TODO remove it after fully refactor. +// OP_MultiwayMergeSort = 17, // multi-way data merge into one input stream. +// OP_GlobalAggregate = 18, // global merge for the multi-way data sources. + OP_Filter = 19, + OP_Distinct = 20, + OP_Join = 21, + OP_AllTimeWindow = 23, + OP_AllMultiTableTimeInterval = 24, + OP_Order = 25, + OP_Exchange = 26, +}; + struct SEpSet; struct SQueryPlanNode; struct SQueryDistPlanNode; diff --git a/include/util/taoserror.h b/include/util/taoserror.h index 413c84fe31..f6cefa96df 100644 --- a/include/util/taoserror.h +++ b/include/util/taoserror.h @@ -76,6 +76,10 @@ int32_t* taosGetErrno(); #define TSDB_CODE_REF_ALREADY_EXIST TAOS_DEF_ERROR_CODE(0, 0x0114) #define TSDB_CODE_REF_NOT_EXIST TAOS_DEF_ERROR_CODE(0, 0x0115) +#define TSDB_CODE_INVALID_VERSION_NUMBER TAOS_DEF_ERROR_CODE(0, 0x0120) +#define TSDB_CODE_INVALID_VERSION_STRING TAOS_DEF_ERROR_CODE(0, 0x0121) +#define TSDB_CODE_VERSION_NOT_COMPATIBLE TAOS_DEF_ERROR_CODE(0, 0x0122) + //client #define TSDB_CODE_TSC_INVALID_OPERATION TAOS_DEF_ERROR_CODE(0, 0x0200) //"Invalid Operation") #define TSDB_CODE_TSC_INVALID_QHANDLE TAOS_DEF_ERROR_CODE(0, 0x0201) //"Invalid qhandle") diff --git a/include/util/tversion.h b/include/util/tversion.h new file mode 100644 index 0000000000..3d7a7e1b66 --- /dev/null +++ b/include/util/tversion.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * 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 . + */ + +#ifndef _TD_UTIL_VERSION_H +#define _TD_UTIL_VERSION_H + +#ifdef __cplusplus +extern "C" { +#endif + +int32_t taosVersionStrToInt(const char *vstr, int32_t *vint); +int32_t taosVersionIntToStr(int32_t vint, char *vstr, int32_t len); +int32_t taosCheckVersionCompatible(int32_t clientVer, int32_t serverVer, int32_t comparedSegments); + +#ifdef __cplusplus +} +#endif + +#endif /*_TD_UTIL_VERSION_H*/ diff --git a/source/common/src/tglobal.c b/source/common/src/tglobal.c index 8d57218a64..1737bd9def 100644 --- a/source/common/src/tglobal.c +++ b/source/common/src/tglobal.c @@ -75,6 +75,11 @@ int32_t tsCompressMsgSize = -1; */ int32_t tsCompressColData = -1; +/* + * denote if 3.0 query pattern compatible for 2.0 + */ +int32_t tsCompatibleModel = 1; + // client int32_t tsMaxSQLStringLen = TSDB_MAX_ALLOWED_SQL_LEN; int32_t tsMaxWildCardsLen = TSDB_PATTERN_STRING_DEFAULT_LEN; diff --git a/source/common/src/versionUtil.c b/source/common/src/versionUtil.c deleted file mode 100644 index 22c50fa5cf..0000000000 --- a/source/common/src/versionUtil.c +++ /dev/null @@ -1,63 +0,0 @@ -#include "os.h" -#include "tdef.h" -#include "ulog.h" -#include "taoserror.h" - -bool taosGetVersionNumber(char *versionStr, int *versionNubmer) { - if (versionStr == NULL || versionNubmer == NULL) { - return false; - } - - int versionNumberPos[5] = {0}; - int len = (int)strlen(versionStr); - int dot = 0; - for (int pos = 0; pos < len && dot < 4; ++pos) { - if (versionStr[pos] == '.') { - versionStr[pos] = 0; - versionNumberPos[++dot] = pos + 1; - } - } - - if (dot != 3) { - return false; - } - - for (int pos = 0; pos < 4; ++pos) { - versionNubmer[pos] = atoi(versionStr + versionNumberPos[pos]); - } - versionStr[versionNumberPos[1] - 1] = '.'; - versionStr[versionNumberPos[2] - 1] = '.'; - versionStr[versionNumberPos[3] - 1] = '.'; - - return true; -} - -int taosCheckVersion(char *input_client_version, char *input_server_version, int comparedSegments) { - char client_version[TSDB_VERSION_LEN] = {0}; - char server_version[TSDB_VERSION_LEN] = {0}; - int clientVersionNumber[4] = {0}; - int serverVersionNumber[4] = {0}; - - tstrncpy(client_version, input_client_version, sizeof(client_version)); - tstrncpy(server_version, input_server_version, sizeof(server_version)); - - if (!taosGetVersionNumber(client_version, clientVersionNumber)) { - uError("invalid client version:%s", client_version); - return TSDB_CODE_TSC_INVALID_VERSION; - } - - if (!taosGetVersionNumber(server_version, serverVersionNumber)) { - uError("invalid server version:%s", server_version); - return TSDB_CODE_TSC_INVALID_VERSION; - } - - for(int32_t i = 0; i < comparedSegments; ++i) { - if (clientVersionNumber[i] != serverVersionNumber[i]) { - uError("the %d-th number of server version:%s not matched with client version:%s", i, server_version, - client_version); - return TSDB_CODE_TSC_INVALID_VERSION; - } - } - - return 0; -} diff --git a/source/dnode/mgmt/daemon/src/daemon.c b/source/dnode/mgmt/daemon/src/daemon.c index 08624f20f4..cf9a960062 100644 --- a/source/dnode/mgmt/daemon/src/daemon.c +++ b/source/dnode/mgmt/daemon/src/daemon.c @@ -136,7 +136,7 @@ void dmnWaitSignal() { } void dmnInitOption(SDnodeOpt *pOption) { - pOption->sver = tsVersion; + pOption->sver = 30000000; //3.0.0.0 pOption->numOfCores = tsNumOfCores; pOption->numOfSupportMnodes = 1; pOption->numOfSupportVnodes = 1; @@ -155,6 +155,8 @@ void dmnInitOption(SDnodeOpt *pOption) { tstrncpy(pOption->timezone, tsTimezone, TSDB_TIMEZONE_LEN); tstrncpy(pOption->locale, tsLocale, TSDB_LOCALE_LEN); tstrncpy(pOption->charset, tsCharset, TSDB_LOCALE_LEN); + tstrncpy(pOption->buildinfo, buildinfo, 64); + tstrncpy(pOption->gitinfo, gitinfo, 48); } int dmnRunDnode() { diff --git a/source/dnode/mgmt/impl/src/dndMnode.c b/source/dnode/mgmt/impl/src/dndMnode.c index 4afce4655d..374a2f2b2c 100644 --- a/source/dnode/mgmt/impl/src/dndMnode.c +++ b/source/dnode/mgmt/impl/src/dndMnode.c @@ -331,13 +331,16 @@ static void dndInitMnodeOption(SDnode *pDnode, SMnodeOpt *pOption) { pOption->putMsgToApplyMsgFp = dndPutMsgIntoMnodeApplyQueue; pOption->dnodeId = dndGetDnodeId(pDnode); pOption->clusterId = dndGetClusterId(pDnode); - pOption->sver = pDnode->opt.sver; - pOption->statusInterval = pDnode->opt.statusInterval; - pOption->mnodeEqualVnodeNum = pDnode->opt.mnodeEqualVnodeNum; - pOption->shellActivityTimer = pDnode->opt.shellActivityTimer; - pOption->timezone = pDnode->opt.timezone; - pOption->charset = pDnode->opt.charset; - pOption->locale = pDnode->opt.locale; + pOption->cfg.sver = pDnode->opt.sver; + pOption->cfg.enableTelem = pDnode->opt.enableTelem; + pOption->cfg.statusInterval = pDnode->opt.statusInterval; + pOption->cfg.mnodeEqualVnodeNum = pDnode->opt.mnodeEqualVnodeNum; + pOption->cfg.shellActivityTimer = pDnode->opt.shellActivityTimer; + pOption->cfg.timezone = pDnode->opt.timezone; + pOption->cfg.charset = pDnode->opt.charset; + pOption->cfg.locale = pDnode->opt.locale; + pOption->cfg.gitinfo = pDnode->opt.gitinfo; + pOption->cfg.buildinfo = pDnode->opt.buildinfo; } static void dndBuildMnodeDeployOption(SDnode *pDnode, SMnodeOpt *pOption) { diff --git a/source/dnode/mgmt/impl/test/CMakeLists.txt b/source/dnode/mgmt/impl/test/CMakeLists.txt index 95ffa548b2..e7aa103996 100644 --- a/source/dnode/mgmt/impl/test/CMakeLists.txt +++ b/source/dnode/mgmt/impl/test/CMakeLists.txt @@ -1 +1,4 @@ -add_subdirectory(test01) \ No newline at end of file +add_subdirectory(acct) +add_subdirectory(cluster) +add_subdirectory(profile) +add_subdirectory(show) diff --git a/source/dnode/mgmt/impl/test/test01/CMakeLists.txt b/source/dnode/mgmt/impl/test/acct/CMakeLists.txt similarity index 64% rename from source/dnode/mgmt/impl/test/test01/CMakeLists.txt rename to source/dnode/mgmt/impl/test/acct/CMakeLists.txt index 5f88e9c116..3e963df2e6 100644 --- a/source/dnode/mgmt/impl/test/test01/CMakeLists.txt +++ b/source/dnode/mgmt/impl/test/acct/CMakeLists.txt @@ -1,20 +1,20 @@ -add_executable(dndTest01 "") +add_executable(dndTestAcct "") -target_sources(dndTest01 +target_sources(dndTestAcct PRIVATE - "test01.cpp" + "acct.cpp" "../sut/deploy.cpp" ) target_link_libraries( - dndTest01 + dndTestAcct PUBLIC dnode PUBLIC util PUBLIC os PUBLIC gtest_main ) -target_include_directories(dndTest01 +target_include_directories(dndTestAcct PUBLIC "${CMAKE_SOURCE_DIR}/include/server/dnode/mgmt" "${CMAKE_CURRENT_SOURCE_DIR}/../../inc" @@ -24,6 +24,6 @@ target_include_directories(dndTest01 enable_testing() add_test( - NAME dndTest01 - COMMAND dndTest01 + NAME dndTestAcct + COMMAND dndTestAcct ) diff --git a/source/dnode/mgmt/impl/test/acct/acct.cpp b/source/dnode/mgmt/impl/test/acct/acct.cpp new file mode 100644 index 0000000000..cda44a3be8 --- /dev/null +++ b/source/dnode/mgmt/impl/test/acct/acct.cpp @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * 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 . + */ + +#include "deploy.h" + +class DndTestAcct : public ::testing::Test { + protected: + void SetUp() override {} + void TearDown() override {} + + static void SetUpTestSuite() { + const char* user = "root"; + const char* pass = "taosdata"; + const char* path = "/tmp/dndTestAcct"; + const char* fqdn = "localhost"; + uint16_t port = 9520; + + pServer = createServer(path, fqdn, port); + ASSERT(pServer); + pClient = createClient(user, pass, fqdn, port); + } + + static void TearDownTestSuite() { + dropServer(pServer); + dropClient(pClient); + } + + static SServer* pServer; + static SClient* pClient; + static int32_t connId; +}; + +SServer* DndTestAcct::pServer; +SClient* DndTestAcct::pClient; +int32_t DndTestAcct::connId; + +TEST_F(DndTestAcct, CreateAcct) { + ASSERT_NE(pClient, nullptr); + + SCreateAcctMsg* pReq = (SCreateAcctMsg*)rpcMallocCont(sizeof(SCreateAcctMsg)); + + SRpcMsg rpcMsg = {0}; + rpcMsg.pCont = pReq; + rpcMsg.contLen = sizeof(SCreateAcctMsg); + rpcMsg.msgType = TSDB_MSG_TYPE_CREATE_ACCT; + + sendMsg(pClient, &rpcMsg); + SRpcMsg* pMsg = pClient->pRsp; + ASSERT_NE(pMsg, nullptr); + ASSERT_EQ(pMsg->code, TSDB_CODE_MND_MSG_NOT_PROCESSED); +} + +TEST_F(DndTestAcct, AlterAcct) { + ASSERT_NE(pClient, nullptr); + + SAlterAcctMsg* pReq = (SAlterAcctMsg*)rpcMallocCont(sizeof(SAlterAcctMsg)); + + SRpcMsg rpcMsg = {0}; + rpcMsg.pCont = pReq; + rpcMsg.contLen = sizeof(SAlterAcctMsg); + rpcMsg.msgType = TSDB_MSG_TYPE_ALTER_ACCT; + + sendMsg(pClient, &rpcMsg); + SRpcMsg* pMsg = pClient->pRsp; + ASSERT_NE(pMsg, nullptr); + ASSERT_EQ(pMsg->code, TSDB_CODE_MND_MSG_NOT_PROCESSED); +} + +TEST_F(DndTestAcct, DropAcct) { + ASSERT_NE(pClient, nullptr); + + SDropAcctMsg* pReq = (SDropAcctMsg*)rpcMallocCont(sizeof(SDropAcctMsg)); + + SRpcMsg rpcMsg = {0}; + rpcMsg.pCont = pReq; + rpcMsg.contLen = sizeof(SDropAcctMsg); + rpcMsg.msgType = TSDB_MSG_TYPE_DROP_ACCT; + + sendMsg(pClient, &rpcMsg); + SRpcMsg* pMsg = pClient->pRsp; + ASSERT_NE(pMsg, nullptr); + ASSERT_EQ(pMsg->code, TSDB_CODE_MND_MSG_NOT_PROCESSED); +} + +TEST_F(DndTestAcct, ShowAcct) { + ASSERT_NE(pClient, nullptr); + + SShowMsg* pReq = (SShowMsg*)rpcMallocCont(sizeof(SShowMsg)); + pReq->type = TSDB_MGMT_TABLE_ACCT; + + SRpcMsg rpcMsg = {0}; + rpcMsg.pCont = pReq; + rpcMsg.contLen = sizeof(SShowMsg); + rpcMsg.msgType = TSDB_MSG_TYPE_SHOW; + + sendMsg(pClient, &rpcMsg); + SRpcMsg* pMsg = pClient->pRsp; + ASSERT_NE(pMsg, nullptr); + ASSERT_EQ(pMsg->code, TSDB_CODE_MND_INVALID_MSG_TYPE); +} \ No newline at end of file diff --git a/source/dnode/mgmt/impl/test/cluster/CMakeLists.txt b/source/dnode/mgmt/impl/test/cluster/CMakeLists.txt new file mode 100644 index 0000000000..b513f290e4 --- /dev/null +++ b/source/dnode/mgmt/impl/test/cluster/CMakeLists.txt @@ -0,0 +1,29 @@ +add_executable(dndTestCluster "") + +target_sources(dndTestCluster + PRIVATE + "cluster.cpp" + "../sut/deploy.cpp" +) + +target_link_libraries( + dndTestCluster + PUBLIC dnode + PUBLIC util + PUBLIC os + PUBLIC gtest_main +) + +target_include_directories(dndTestCluster + PUBLIC + "${CMAKE_SOURCE_DIR}/include/server/dnode/mgmt" + "${CMAKE_CURRENT_SOURCE_DIR}/../../inc" + "${CMAKE_CURRENT_SOURCE_DIR}/../sut" +) + +enable_testing() + +add_test( + NAME dndTestCluster + COMMAND dndTestCluster +) diff --git a/source/dnode/mgmt/impl/test/cluster/cluster.cpp b/source/dnode/mgmt/impl/test/cluster/cluster.cpp new file mode 100644 index 0000000000..d7f9bca5ed --- /dev/null +++ b/source/dnode/mgmt/impl/test/cluster/cluster.cpp @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * 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 . + */ + +#include "deploy.h" + +class DndTestCluster : public ::testing::Test { + protected: + void SetUp() override {} + void TearDown() override {} + + static void SetUpTestSuite() { + const char* user = "root"; + const char* pass = "taosdata"; + const char* path = "/tmp/dndTestCluster"; + const char* fqdn = "localhost"; + uint16_t port = 9521; + + pServer = createServer(path, fqdn, port); + ASSERT(pServer); + pClient = createClient(user, pass, fqdn, port); + } + + static void TearDownTestSuite() { + dropServer(pServer); + dropClient(pClient); + } + + static SServer* pServer; + static SClient* pClient; + static int32_t connId; +}; + +SServer* DndTestCluster::pServer; +SClient* DndTestCluster::pClient; +int32_t DndTestCluster::connId; + +TEST_F(DndTestCluster, ShowCluster) { + ASSERT_NE(pClient, nullptr); + int32_t showId = 0; + + { + SShowMsg* pReq = (SShowMsg*)rpcMallocCont(sizeof(SShowMsg)); + pReq->type = TSDB_MGMT_TABLE_CLUSTER; + strcpy(pReq->db, ""); + + SRpcMsg rpcMsg = {0}; + rpcMsg.pCont = pReq; + rpcMsg.contLen = sizeof(SShowMsg); + rpcMsg.msgType = TSDB_MSG_TYPE_SHOW; + + sendMsg(pClient, &rpcMsg); + SRpcMsg* pMsg = pClient->pRsp; + ASSERT_NE(pMsg, nullptr); + + SShowRsp* pRsp = (SShowRsp*)pMsg->pCont; + ASSERT_NE(pRsp, nullptr); + pRsp->showId = htonl(pRsp->showId); + STableMetaMsg* pMeta = &pRsp->tableMeta; + pMeta->contLen = htonl(pMeta->contLen); + pMeta->numOfColumns = htons(pMeta->numOfColumns); + pMeta->sversion = htons(pMeta->sversion); + pMeta->tversion = htons(pMeta->tversion); + pMeta->tid = htonl(pMeta->tid); + pMeta->uid = htobe64(pMeta->uid); + pMeta->suid = htobe64(pMeta->suid); + + showId = pRsp->showId; + + EXPECT_NE(pRsp->showId, 0); + EXPECT_EQ(pMeta->contLen, 0); + EXPECT_STREQ(pMeta->tableFname, "show cluster"); + EXPECT_EQ(pMeta->numOfTags, 0); + EXPECT_EQ(pMeta->precision, 0); + EXPECT_EQ(pMeta->tableType, 0); + EXPECT_EQ(pMeta->numOfColumns, 3); + EXPECT_EQ(pMeta->sversion, 0); + EXPECT_EQ(pMeta->tversion, 0); + EXPECT_EQ(pMeta->tid, 0); + EXPECT_EQ(pMeta->uid, 0); + EXPECT_STREQ(pMeta->sTableName, ""); + EXPECT_EQ(pMeta->suid, 0); + + SSchema* pSchema = NULL; + pSchema = &pMeta->schema[0]; + pSchema->bytes = htons(pSchema->bytes); + EXPECT_EQ(pSchema->colId, 0); + EXPECT_EQ(pSchema->type, TSDB_DATA_TYPE_INT); + EXPECT_EQ(pSchema->bytes, 4); + EXPECT_STREQ(pSchema->name, "id"); + + pSchema = &pMeta->schema[1]; + pSchema->bytes = htons(pSchema->bytes); + EXPECT_EQ(pSchema->colId, 0); + EXPECT_EQ(pSchema->type, TSDB_DATA_TYPE_BINARY); + EXPECT_EQ(pSchema->bytes, TSDB_CLUSTER_ID_LEN + VARSTR_HEADER_SIZE); + EXPECT_STREQ(pSchema->name, "name"); + + pSchema = &pMeta->schema[2]; + pSchema->bytes = htons(pSchema->bytes); + EXPECT_EQ(pSchema->colId, 0); + EXPECT_EQ(pSchema->type, TSDB_DATA_TYPE_TIMESTAMP); + EXPECT_EQ(pSchema->bytes, 8); + EXPECT_STREQ(pSchema->name, "create_time"); + } + + { + SRetrieveTableMsg* pReq = (SRetrieveTableMsg*)rpcMallocCont(sizeof(SRetrieveTableMsg)); + pReq->showId = htonl(showId); + pReq->free = 0; + + SRpcMsg rpcMsg = {0}; + rpcMsg.pCont = pReq; + rpcMsg.contLen = sizeof(SRetrieveTableMsg); + rpcMsg.msgType = TSDB_MSG_TYPE_SHOW_RETRIEVE; + + sendMsg(pClient, &rpcMsg); + SRpcMsg* pMsg = pClient->pRsp; + ASSERT_NE(pMsg, nullptr); + ASSERT_EQ(pMsg->code, 0); + + SRetrieveTableRsp* pRsp = (SRetrieveTableRsp*)pMsg->pCont; + ASSERT_NE(pRsp, nullptr); + pRsp->numOfRows = htonl(pRsp->numOfRows); + pRsp->offset = htobe64(pRsp->offset); + pRsp->useconds = htobe64(pRsp->useconds); + pRsp->compLen = htonl(pRsp->compLen); + + EXPECT_EQ(pRsp->numOfRows, 1); + EXPECT_EQ(pRsp->offset, 0); + EXPECT_EQ(pRsp->useconds, 0); + EXPECT_EQ(pRsp->completed, 1); + EXPECT_EQ(pRsp->precision, TSDB_TIME_PRECISION_MILLI); + EXPECT_EQ(pRsp->compressed, 0); + EXPECT_EQ(pRsp->reserved, 0); + EXPECT_EQ(pRsp->compLen, 0); + + char* pData = pRsp->data; + int32_t pos = 0; + + int32_t id = *((int32_t*)(pData + pos)); + pos += sizeof(int32_t); + + int32_t nameLen = varDataLen(pData + pos); + pos += sizeof(VarDataLenT); + + char* name = (char*)(pData + pos); + pos += TSDB_CLUSTER_ID_LEN; + + int64_t create_time = *((int64_t*)(pData + pos)); + pos += sizeof(int64_t); + + EXPECT_NE(id, 0); + EXPECT_EQ(nameLen, 36); + EXPECT_STRNE(name, ""); + EXPECT_GT(create_time, 0); + printf("--- id:%d nameLen:%d name:%s time:%" PRId64 " --- \n", id, nameLen, name, create_time); + } +} \ No newline at end of file diff --git a/source/dnode/mgmt/impl/test/profile/CMakeLists.txt b/source/dnode/mgmt/impl/test/profile/CMakeLists.txt new file mode 100644 index 0000000000..2e99a2e53d --- /dev/null +++ b/source/dnode/mgmt/impl/test/profile/CMakeLists.txt @@ -0,0 +1,29 @@ +add_executable(dndTestProfile "") + +target_sources(dndTestProfile + PRIVATE + "profile.cpp" + "../sut/deploy.cpp" +) + +target_link_libraries( + dndTestProfile + PUBLIC dnode + PUBLIC util + PUBLIC os + PUBLIC gtest_main +) + +target_include_directories(dndTestProfile + PUBLIC + "${CMAKE_SOURCE_DIR}/include/server/dnode/mgmt" + "${CMAKE_CURRENT_SOURCE_DIR}/../../inc" + "${CMAKE_CURRENT_SOURCE_DIR}/../sut" +) + +enable_testing() + +add_test( + NAME dndTestProfile + COMMAND dndTestProfile +) diff --git a/source/dnode/mgmt/impl/test/profile/profile.cpp b/source/dnode/mgmt/impl/test/profile/profile.cpp new file mode 100644 index 0000000000..14e8dda457 --- /dev/null +++ b/source/dnode/mgmt/impl/test/profile/profile.cpp @@ -0,0 +1,736 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * 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 . + */ + +#include "deploy.h" + +class DndTestProfile : public ::testing::Test { + protected: + void SetUp() override {} + void TearDown() override {} + + static void SetUpTestSuite() { + const char* user = "root"; + const char* pass = "taosdata"; + const char* path = "/tmp/dndTestProfile"; + const char* fqdn = "localhost"; + uint16_t port = 9522; + + pServer = createServer(path, fqdn, port); + ASSERT(pServer); + pClient = createClient(user, pass, fqdn, port); + } + + static void TearDownTestSuite() { + dropServer(pServer); + dropClient(pClient); + } + + static SServer* pServer; + static SClient* pClient; + static int32_t connId; +}; + +SServer* DndTestProfile::pServer; +SClient* DndTestProfile::pClient; +int32_t DndTestProfile::connId; + +TEST_F(DndTestProfile, SConnectMsg_01) { + ASSERT_NE(pClient, nullptr); + + SConnectMsg* pReq = (SConnectMsg*)rpcMallocCont(sizeof(SConnectMsg)); + pReq->pid = htonl(1234); + strcpy(pReq->app, "dndTestProfile"); + strcpy(pReq->db, ""); + + SRpcMsg rpcMsg = {0}; + rpcMsg.pCont = pReq; + rpcMsg.contLen = sizeof(SConnectMsg); + rpcMsg.msgType = TSDB_MSG_TYPE_CONNECT; + + sendMsg(pClient, &rpcMsg); + SRpcMsg* pMsg = pClient->pRsp; + ASSERT_NE(pMsg, nullptr); + + SConnectRsp* pRsp = (SConnectRsp*)pMsg->pCont; + ASSERT_NE(pRsp, nullptr); + pRsp->acctId = htonl(pRsp->acctId); + pRsp->clusterId = htonl(pRsp->clusterId); + pRsp->connId = htonl(pRsp->connId); + pRsp->epSet.port[0] = htons(pRsp->epSet.port[0]); + + EXPECT_EQ(pRsp->acctId, 1); + EXPECT_GT(pRsp->clusterId, 0); + EXPECT_EQ(pRsp->connId, 1); + EXPECT_EQ(pRsp->superAuth, 1); + EXPECT_EQ(pRsp->readAuth, 1); + EXPECT_EQ(pRsp->writeAuth, 1); + + EXPECT_EQ(pRsp->epSet.inUse, 0); + EXPECT_EQ(pRsp->epSet.numOfEps, 1); + EXPECT_EQ(pRsp->epSet.port[0], 9522); + EXPECT_STREQ(pRsp->epSet.fqdn[0], "localhost"); + + connId = pRsp->connId; +} + +TEST_F(DndTestProfile, SConnectMsg_02) { + ASSERT_NE(pClient, nullptr); + + SConnectMsg* pReq = (SConnectMsg*)rpcMallocCont(sizeof(SConnectMsg)); + pReq->pid = htonl(1234); + strcpy(pReq->app, "dndTestProfile"); + strcpy(pReq->db, "invalid_db"); + + SRpcMsg rpcMsg = {0}; + rpcMsg.pCont = pReq; + rpcMsg.contLen = sizeof(SConnectMsg); + rpcMsg.msgType = TSDB_MSG_TYPE_CONNECT; + + sendMsg(pClient, &rpcMsg); + SRpcMsg* pMsg = pClient->pRsp; + ASSERT_NE(pMsg, nullptr); + ASSERT_EQ(pMsg->code, TSDB_CODE_MND_INVALID_DB); + ASSERT_EQ(pMsg->contLen, 0); +} + +TEST_F(DndTestProfile, SConnectMsg_03) { + ASSERT_NE(pClient, nullptr); + int32_t showId = 0; + + { + SShowMsg* pReq = (SShowMsg*)rpcMallocCont(sizeof(SShowMsg)); + pReq->type = TSDB_MGMT_TABLE_CONNS; + strcpy(pReq->db, ""); + + SRpcMsg rpcMsg = {0}; + rpcMsg.pCont = pReq; + rpcMsg.contLen = sizeof(SShowMsg); + rpcMsg.msgType = TSDB_MSG_TYPE_SHOW; + + sendMsg(pClient, &rpcMsg); + SRpcMsg* pMsg = pClient->pRsp; + ASSERT_NE(pMsg, nullptr); + + SShowRsp* pRsp = (SShowRsp*)pMsg->pCont; + ASSERT_NE(pRsp, nullptr); + pRsp->showId = htonl(pRsp->showId); + STableMetaMsg* pMeta = &pRsp->tableMeta; + pMeta->contLen = htonl(pMeta->contLen); + pMeta->numOfColumns = htons(pMeta->numOfColumns); + pMeta->sversion = htons(pMeta->sversion); + pMeta->tversion = htons(pMeta->tversion); + pMeta->tid = htonl(pMeta->tid); + pMeta->uid = htobe64(pMeta->uid); + pMeta->suid = htobe64(pMeta->suid); + + showId = pRsp->showId; + + EXPECT_NE(pRsp->showId, 0); + EXPECT_EQ(pMeta->contLen, 0); + EXPECT_STREQ(pMeta->tableFname, ""); + EXPECT_EQ(pMeta->numOfTags, 0); + EXPECT_EQ(pMeta->precision, 0); + EXPECT_EQ(pMeta->tableType, 0); + EXPECT_EQ(pMeta->numOfColumns, 7); + EXPECT_EQ(pMeta->sversion, 0); + EXPECT_EQ(pMeta->tversion, 0); + EXPECT_EQ(pMeta->tid, 0); + EXPECT_EQ(pMeta->uid, 0); + EXPECT_STREQ(pMeta->sTableName, ""); + EXPECT_EQ(pMeta->suid, 0); + + SSchema* pSchema = NULL; + pSchema = &pMeta->schema[0]; + pSchema->bytes = htons(pSchema->bytes); + EXPECT_EQ(pSchema->colId, 0); + EXPECT_EQ(pSchema->type, TSDB_DATA_TYPE_INT); + EXPECT_EQ(pSchema->bytes, 4); + EXPECT_STREQ(pSchema->name, "connId"); + + pSchema = &pMeta->schema[1]; + pSchema->bytes = htons(pSchema->bytes); + EXPECT_EQ(pSchema->colId, 0); + EXPECT_EQ(pSchema->type, TSDB_DATA_TYPE_BINARY); + EXPECT_EQ(pSchema->bytes, TSDB_USER_LEN + VARSTR_HEADER_SIZE); + EXPECT_STREQ(pSchema->name, "user"); + + pSchema = &pMeta->schema[2]; + pSchema->bytes = htons(pSchema->bytes); + EXPECT_EQ(pSchema->colId, 0); + EXPECT_EQ(pSchema->type, TSDB_DATA_TYPE_BINARY); + EXPECT_EQ(pSchema->bytes, TSDB_USER_LEN + VARSTR_HEADER_SIZE); + EXPECT_STREQ(pSchema->name, "program"); + + pSchema = &pMeta->schema[3]; + pSchema->bytes = htons(pSchema->bytes); + EXPECT_EQ(pSchema->colId, 0); + EXPECT_EQ(pSchema->type, TSDB_DATA_TYPE_INT); + EXPECT_EQ(pSchema->bytes, 4); + EXPECT_STREQ(pSchema->name, "pid"); + + pSchema = &pMeta->schema[4]; + pSchema->bytes = htons(pSchema->bytes); + EXPECT_EQ(pSchema->colId, 0); + EXPECT_EQ(pSchema->type, TSDB_DATA_TYPE_BINARY); + EXPECT_EQ(pSchema->bytes, TSDB_IPv4ADDR_LEN + 6 + VARSTR_HEADER_SIZE); + EXPECT_STREQ(pSchema->name, "ip:port"); + + pSchema = &pMeta->schema[5]; + pSchema->bytes = htons(pSchema->bytes); + EXPECT_EQ(pSchema->colId, 0); + EXPECT_EQ(pSchema->type, TSDB_DATA_TYPE_TIMESTAMP); + EXPECT_EQ(pSchema->bytes, 8); + EXPECT_STREQ(pSchema->name, "login_time"); + + pSchema = &pMeta->schema[6]; + pSchema->bytes = htons(pSchema->bytes); + EXPECT_EQ(pSchema->colId, 0); + EXPECT_EQ(pSchema->type, TSDB_DATA_TYPE_TIMESTAMP); + EXPECT_EQ(pSchema->bytes, 8); + EXPECT_STREQ(pSchema->name, "last_access"); + } + + { + SRetrieveTableMsg* pReq = (SRetrieveTableMsg*)rpcMallocCont(sizeof(SRetrieveTableMsg)); + pReq->showId = htonl(showId); + pReq->free = 0; + + SRpcMsg rpcMsg = {0}; + rpcMsg.pCont = pReq; + rpcMsg.contLen = sizeof(SRetrieveTableMsg); + rpcMsg.msgType = TSDB_MSG_TYPE_SHOW_RETRIEVE; + + sendMsg(pClient, &rpcMsg); + SRpcMsg* pMsg = pClient->pRsp; + ASSERT_NE(pMsg, nullptr); + ASSERT_EQ(pMsg->code, 0); + + SRetrieveTableRsp* pRsp = (SRetrieveTableRsp*)pMsg->pCont; + ASSERT_NE(pRsp, nullptr); + pRsp->numOfRows = htonl(pRsp->numOfRows); + pRsp->offset = htobe64(pRsp->offset); + pRsp->useconds = htobe64(pRsp->useconds); + pRsp->compLen = htonl(pRsp->compLen); + + EXPECT_EQ(pRsp->numOfRows, 1); + EXPECT_EQ(pRsp->offset, 0); + EXPECT_EQ(pRsp->useconds, 0); + EXPECT_EQ(pRsp->completed, 1); + EXPECT_EQ(pRsp->precision, TSDB_TIME_PRECISION_MILLI); + EXPECT_EQ(pRsp->compressed, 0); + EXPECT_EQ(pRsp->reserved, 0); + EXPECT_EQ(pRsp->compLen, 0); + } +} + +TEST_F(DndTestProfile, SHeartBeatMsg_01) { + ASSERT_NE(pClient, nullptr); + + SHeartBeatMsg* pReq = (SHeartBeatMsg*)rpcMallocCont(sizeof(SHeartBeatMsg)); + pReq->connId = htonl(connId); + pReq->pid = htonl(1234); + pReq->numOfQueries = htonl(0); + pReq->numOfStreams = htonl(0); + strcpy(pReq->app, "dndTestProfile"); + + SRpcMsg rpcMsg = {0}; + rpcMsg.pCont = pReq; + rpcMsg.contLen = sizeof(SHeartBeatMsg); + rpcMsg.msgType = TSDB_MSG_TYPE_HEARTBEAT; + + sendMsg(pClient, &rpcMsg); + SRpcMsg* pMsg = pClient->pRsp; + ASSERT_NE(pMsg, nullptr); + + SHeartBeatRsp* pRsp = (SHeartBeatRsp*)pMsg->pCont; + ASSERT_NE(pRsp, nullptr); + pRsp->connId = htonl(pRsp->connId); + pRsp->queryId = htonl(pRsp->queryId); + pRsp->streamId = htonl(pRsp->streamId); + pRsp->totalDnodes = htonl(pRsp->totalDnodes); + pRsp->onlineDnodes = htonl(pRsp->onlineDnodes); + pRsp->epSet.port[0] = htons(pRsp->epSet.port[0]); + + EXPECT_EQ(pRsp->connId, connId); + EXPECT_EQ(pRsp->queryId, 0); + EXPECT_EQ(pRsp->streamId, 0); + EXPECT_EQ(pRsp->totalDnodes, 1); + EXPECT_EQ(pRsp->onlineDnodes, 1); + EXPECT_EQ(pRsp->killConnection, 0); + + EXPECT_EQ(pRsp->epSet.inUse, 0); + EXPECT_EQ(pRsp->epSet.numOfEps, 1); + EXPECT_EQ(pRsp->epSet.port[0], 9522); + EXPECT_STREQ(pRsp->epSet.fqdn[0], "localhost"); +} + +TEST_F(DndTestProfile, SKillConnMsg_01) { + ASSERT_NE(pClient, nullptr); + + { + SKillConnMsg* pReq = (SKillConnMsg*)rpcMallocCont(sizeof(SKillConnMsg)); + pReq->connId = htonl(connId); + + SRpcMsg rpcMsg = {0}; + rpcMsg.pCont = pReq; + rpcMsg.contLen = sizeof(SKillConnMsg); + rpcMsg.msgType = TSDB_MSG_TYPE_KILL_CONN; + + sendMsg(pClient, &rpcMsg); + SRpcMsg* pMsg = pClient->pRsp; + ASSERT_NE(pMsg, nullptr); + ASSERT_EQ(pMsg->code, 0); + } + + { + SHeartBeatMsg* pReq = (SHeartBeatMsg*)rpcMallocCont(sizeof(SHeartBeatMsg)); + pReq->connId = htonl(connId); + pReq->pid = htonl(1234); + pReq->numOfQueries = htonl(0); + pReq->numOfStreams = htonl(0); + strcpy(pReq->app, "dndTestProfile"); + + SRpcMsg rpcMsg = {0}; + rpcMsg.pCont = pReq; + rpcMsg.contLen = sizeof(SHeartBeatMsg); + rpcMsg.msgType = TSDB_MSG_TYPE_HEARTBEAT; + + sendMsg(pClient, &rpcMsg); + SRpcMsg* pMsg = pClient->pRsp; + ASSERT_NE(pMsg, nullptr); + ASSERT_EQ(pMsg->code, TSDB_CODE_MND_INVALID_CONNECTION); + ASSERT_EQ(pMsg->contLen, 0); + } + + { + SConnectMsg* pReq = (SConnectMsg*)rpcMallocCont(sizeof(SConnectMsg)); + pReq->pid = htonl(1234); + strcpy(pReq->app, "dndTestProfile"); + strcpy(pReq->db, ""); + + SRpcMsg rpcMsg = {0}; + rpcMsg.pCont = pReq; + rpcMsg.contLen = sizeof(SConnectMsg); + rpcMsg.msgType = TSDB_MSG_TYPE_CONNECT; + + sendMsg(pClient, &rpcMsg); + SRpcMsg* pMsg = pClient->pRsp; + ASSERT_NE(pMsg, nullptr); + + SConnectRsp* pRsp = (SConnectRsp*)pMsg->pCont; + ASSERT_NE(pRsp, nullptr); + pRsp->acctId = htonl(pRsp->acctId); + pRsp->clusterId = htonl(pRsp->clusterId); + pRsp->connId = htonl(pRsp->connId); + pRsp->epSet.port[0] = htons(pRsp->epSet.port[0]); + + EXPECT_EQ(pRsp->acctId, 1); + EXPECT_GT(pRsp->clusterId, 0); + EXPECT_GT(pRsp->connId, connId); + EXPECT_EQ(pRsp->readAuth, 1); + EXPECT_EQ(pRsp->writeAuth, 1); + + EXPECT_EQ(pRsp->epSet.inUse, 0); + EXPECT_EQ(pRsp->epSet.numOfEps, 1); + EXPECT_EQ(pRsp->epSet.port[0], 9522); + EXPECT_STREQ(pRsp->epSet.fqdn[0], "localhost"); + + connId = pRsp->connId; + } +} + +TEST_F(DndTestProfile, SKillConnMsg_02) { + ASSERT_NE(pClient, nullptr); + + SKillConnMsg* pReq = (SKillConnMsg*)rpcMallocCont(sizeof(SKillConnMsg)); + pReq->connId = htonl(2345); + + SRpcMsg rpcMsg = {0}; + rpcMsg.pCont = pReq; + rpcMsg.contLen = sizeof(SKillConnMsg); + rpcMsg.msgType = TSDB_MSG_TYPE_KILL_CONN; + + sendMsg(pClient, &rpcMsg); + SRpcMsg* pMsg = pClient->pRsp; + ASSERT_NE(pMsg, nullptr); + ASSERT_EQ(pMsg->code, TSDB_CODE_MND_INVALID_CONN_ID); +} + +TEST_F(DndTestProfile, SKillQueryMsg_01) { + ASSERT_NE(pClient, nullptr); + + { + SKillQueryMsg* pReq = (SKillQueryMsg*)rpcMallocCont(sizeof(SKillQueryMsg)); + pReq->connId = htonl(connId); + pReq->queryId = htonl(1234); + + SRpcMsg rpcMsg = {0}; + rpcMsg.pCont = pReq; + rpcMsg.contLen = sizeof(SKillQueryMsg); + rpcMsg.msgType = TSDB_MSG_TYPE_KILL_QUERY; + + sendMsg(pClient, &rpcMsg); + SRpcMsg* pMsg = pClient->pRsp; + ASSERT_NE(pMsg, nullptr); + ASSERT_EQ(pMsg->code, 0); + ASSERT_EQ(pMsg->contLen, 0); + } + + { + SHeartBeatMsg* pReq = (SHeartBeatMsg*)rpcMallocCont(sizeof(SHeartBeatMsg)); + pReq->connId = htonl(connId); + pReq->pid = htonl(1234); + pReq->numOfQueries = htonl(0); + pReq->numOfStreams = htonl(0); + strcpy(pReq->app, "dndTestProfile"); + + SRpcMsg rpcMsg = {0}; + rpcMsg.pCont = pReq; + rpcMsg.contLen = sizeof(SHeartBeatMsg); + rpcMsg.msgType = TSDB_MSG_TYPE_HEARTBEAT; + + sendMsg(pClient, &rpcMsg); + SRpcMsg* pMsg = pClient->pRsp; + ASSERT_NE(pMsg, nullptr); + + SHeartBeatRsp* pRsp = (SHeartBeatRsp*)pMsg->pCont; + ASSERT_NE(pRsp, nullptr); + pRsp->connId = htonl(pRsp->connId); + pRsp->queryId = htonl(pRsp->queryId); + pRsp->streamId = htonl(pRsp->streamId); + pRsp->totalDnodes = htonl(pRsp->totalDnodes); + pRsp->onlineDnodes = htonl(pRsp->onlineDnodes); + pRsp->epSet.port[0] = htons(pRsp->epSet.port[0]); + + EXPECT_EQ(pRsp->connId, connId); + EXPECT_EQ(pRsp->queryId, 1234); + EXPECT_EQ(pRsp->streamId, 0); + EXPECT_EQ(pRsp->totalDnodes, 1); + EXPECT_EQ(pRsp->onlineDnodes, 1); + EXPECT_EQ(pRsp->killConnection, 0); + + EXPECT_EQ(pRsp->epSet.inUse, 0); + EXPECT_EQ(pRsp->epSet.numOfEps, 1); + EXPECT_EQ(pRsp->epSet.port[0], 9522); + EXPECT_STREQ(pRsp->epSet.fqdn[0], "localhost"); + } +} + +TEST_F(DndTestProfile, SKillQueryMsg_02) { + ASSERT_NE(pClient, nullptr); + + SKillQueryMsg* pReq = (SKillQueryMsg*)rpcMallocCont(sizeof(SKillQueryMsg)); + pReq->connId = htonl(2345); + pReq->queryId = htonl(1234); + + SRpcMsg rpcMsg = {0}; + rpcMsg.pCont = pReq; + rpcMsg.contLen = sizeof(SKillQueryMsg); + rpcMsg.msgType = TSDB_MSG_TYPE_KILL_QUERY; + + sendMsg(pClient, &rpcMsg); + SRpcMsg* pMsg = pClient->pRsp; + ASSERT_NE(pMsg, nullptr); + ASSERT_EQ(pMsg->code, TSDB_CODE_MND_INVALID_CONN_ID); +} + +TEST_F(DndTestProfile, SKillQueryMsg_03) { + ASSERT_NE(pClient, nullptr); + int32_t showId = 0; + + { + SShowMsg* pReq = (SShowMsg*)rpcMallocCont(sizeof(SShowMsg)); + pReq->type = TSDB_MGMT_TABLE_QUERIES; + strcpy(pReq->db, ""); + + SRpcMsg rpcMsg = {0}; + rpcMsg.pCont = pReq; + rpcMsg.contLen = sizeof(SShowMsg); + rpcMsg.msgType = TSDB_MSG_TYPE_SHOW; + + sendMsg(pClient, &rpcMsg); + SRpcMsg* pMsg = pClient->pRsp; + ASSERT_NE(pMsg, nullptr); + + SShowRsp* pRsp = (SShowRsp*)pMsg->pCont; + ASSERT_NE(pRsp, nullptr); + pRsp->showId = htonl(pRsp->showId); + STableMetaMsg* pMeta = &pRsp->tableMeta; + pMeta->contLen = htonl(pMeta->contLen); + pMeta->numOfColumns = htons(pMeta->numOfColumns); + pMeta->sversion = htons(pMeta->sversion); + pMeta->tversion = htons(pMeta->tversion); + pMeta->tid = htonl(pMeta->tid); + pMeta->uid = htobe64(pMeta->uid); + pMeta->suid = htobe64(pMeta->suid); + + showId = pRsp->showId; + + EXPECT_NE(pRsp->showId, 0); + EXPECT_EQ(pMeta->contLen, 0); + EXPECT_STREQ(pMeta->tableFname, ""); + EXPECT_EQ(pMeta->numOfTags, 0); + EXPECT_EQ(pMeta->precision, 0); + EXPECT_EQ(pMeta->tableType, 0); + EXPECT_EQ(pMeta->numOfColumns, 14); + EXPECT_EQ(pMeta->sversion, 0); + EXPECT_EQ(pMeta->tversion, 0); + EXPECT_EQ(pMeta->tid, 0); + EXPECT_EQ(pMeta->uid, 0); + EXPECT_STREQ(pMeta->sTableName, ""); + EXPECT_EQ(pMeta->suid, 0); + + SSchema* pSchema = NULL; + pSchema = &pMeta->schema[0]; + pSchema->bytes = htons(pSchema->bytes); + EXPECT_EQ(pSchema->colId, 0); + EXPECT_EQ(pSchema->type, TSDB_DATA_TYPE_INT); + EXPECT_EQ(pSchema->bytes, 4); + EXPECT_STREQ(pSchema->name, "queryId"); + + pSchema = &pMeta->schema[1]; + pSchema->bytes = htons(pSchema->bytes); + EXPECT_EQ(pSchema->colId, 0); + EXPECT_EQ(pSchema->type, TSDB_DATA_TYPE_INT); + EXPECT_EQ(pSchema->bytes, 4); + EXPECT_STREQ(pSchema->name, "connId"); + + pSchema = &pMeta->schema[2]; + pSchema->bytes = htons(pSchema->bytes); + EXPECT_EQ(pSchema->colId, 0); + EXPECT_EQ(pSchema->type, TSDB_DATA_TYPE_BINARY); + EXPECT_EQ(pSchema->bytes, TSDB_USER_LEN + VARSTR_HEADER_SIZE); + EXPECT_STREQ(pSchema->name, "user"); + + pSchema = &pMeta->schema[3]; + pSchema->bytes = htons(pSchema->bytes); + EXPECT_EQ(pSchema->colId, 0); + EXPECT_EQ(pSchema->type, TSDB_DATA_TYPE_BINARY); + EXPECT_EQ(pSchema->bytes, TSDB_IPv4ADDR_LEN + 6 + VARSTR_HEADER_SIZE); + EXPECT_STREQ(pSchema->name, "ip:port"); + } + + { + SRetrieveTableMsg* pReq = (SRetrieveTableMsg*)rpcMallocCont(sizeof(SRetrieveTableMsg)); + pReq->showId = htonl(showId); + pReq->free = 0; + + SRpcMsg rpcMsg = {0}; + rpcMsg.pCont = pReq; + rpcMsg.contLen = sizeof(SRetrieveTableMsg); + rpcMsg.msgType = TSDB_MSG_TYPE_SHOW_RETRIEVE; + + sendMsg(pClient, &rpcMsg); + SRpcMsg* pMsg = pClient->pRsp; + ASSERT_NE(pMsg, nullptr); + ASSERT_EQ(pMsg->code, 0); + + SRetrieveTableRsp* pRsp = (SRetrieveTableRsp*)pMsg->pCont; + ASSERT_NE(pRsp, nullptr); + pRsp->numOfRows = htonl(pRsp->numOfRows); + pRsp->offset = htobe64(pRsp->offset); + pRsp->useconds = htobe64(pRsp->useconds); + pRsp->compLen = htonl(pRsp->compLen); + + EXPECT_EQ(pRsp->numOfRows, 0); + EXPECT_EQ(pRsp->offset, 0); + EXPECT_EQ(pRsp->useconds, 0); + EXPECT_EQ(pRsp->completed, 1); + EXPECT_EQ(pRsp->precision, TSDB_TIME_PRECISION_MILLI); + EXPECT_EQ(pRsp->compressed, 0); + EXPECT_EQ(pRsp->reserved, 0); + EXPECT_EQ(pRsp->compLen, 0); + } +} + +TEST_F(DndTestProfile, SKillStreamMsg_01) { + ASSERT_NE(pClient, nullptr); + + { + SKillStreamMsg* pReq = (SKillStreamMsg*)rpcMallocCont(sizeof(SKillStreamMsg)); + pReq->connId = htonl(connId); + pReq->streamId = htonl(3579); + + SRpcMsg rpcMsg = {0}; + rpcMsg.pCont = pReq; + rpcMsg.contLen = sizeof(SKillStreamMsg); + rpcMsg.msgType = TSDB_MSG_TYPE_KILL_STREAM; + + sendMsg(pClient, &rpcMsg); + SRpcMsg* pMsg = pClient->pRsp; + ASSERT_NE(pMsg, nullptr); + ASSERT_EQ(pMsg->code, 0); + ASSERT_EQ(pMsg->contLen, 0); + } + + { + SHeartBeatMsg* pReq = (SHeartBeatMsg*)rpcMallocCont(sizeof(SHeartBeatMsg)); + pReq->connId = htonl(connId); + pReq->pid = htonl(1234); + pReq->numOfQueries = htonl(0); + pReq->numOfStreams = htonl(0); + strcpy(pReq->app, "dndTestProfile"); + + SRpcMsg rpcMsg = {0}; + rpcMsg.pCont = pReq; + rpcMsg.contLen = sizeof(SHeartBeatMsg); + rpcMsg.msgType = TSDB_MSG_TYPE_HEARTBEAT; + + sendMsg(pClient, &rpcMsg); + SRpcMsg* pMsg = pClient->pRsp; + ASSERT_NE(pMsg, nullptr); + + SHeartBeatRsp* pRsp = (SHeartBeatRsp*)pMsg->pCont; + ASSERT_NE(pRsp, nullptr); + pRsp->connId = htonl(pRsp->connId); + pRsp->queryId = htonl(pRsp->queryId); + pRsp->streamId = htonl(pRsp->streamId); + pRsp->totalDnodes = htonl(pRsp->totalDnodes); + pRsp->onlineDnodes = htonl(pRsp->onlineDnodes); + pRsp->epSet.port[0] = htons(pRsp->epSet.port[0]); + + EXPECT_EQ(pRsp->connId, connId); + EXPECT_EQ(pRsp->queryId, 0); + EXPECT_EQ(pRsp->streamId, 3579); + EXPECT_EQ(pRsp->totalDnodes, 1); + EXPECT_EQ(pRsp->onlineDnodes, 1); + EXPECT_EQ(pRsp->killConnection, 0); + + EXPECT_EQ(pRsp->epSet.inUse, 0); + EXPECT_EQ(pRsp->epSet.numOfEps, 1); + EXPECT_EQ(pRsp->epSet.port[0], 9522); + EXPECT_STREQ(pRsp->epSet.fqdn[0], "localhost"); + } +} + +TEST_F(DndTestProfile, SKillStreamMsg_02) { + ASSERT_NE(pClient, nullptr); + + SKillStreamMsg* pReq = (SKillStreamMsg*)rpcMallocCont(sizeof(SKillStreamMsg)); + pReq->connId = htonl(2345); + pReq->streamId = htonl(1234); + + SRpcMsg rpcMsg = {0}; + rpcMsg.pCont = pReq; + rpcMsg.contLen = sizeof(SKillStreamMsg); + rpcMsg.msgType = TSDB_MSG_TYPE_KILL_QUERY; + + sendMsg(pClient, &rpcMsg); + SRpcMsg* pMsg = pClient->pRsp; + ASSERT_NE(pMsg, nullptr); + ASSERT_EQ(pMsg->code, TSDB_CODE_MND_INVALID_CONN_ID); +} + +TEST_F(DndTestProfile, SKillStreamMsg_03) { + ASSERT_NE(pClient, nullptr); + int32_t showId = 0; + + { + SShowMsg* pReq = (SShowMsg*)rpcMallocCont(sizeof(SShowMsg)); + pReq->type = TSDB_MGMT_TABLE_STREAMS; + strcpy(pReq->db, ""); + + SRpcMsg rpcMsg = {0}; + rpcMsg.pCont = pReq; + rpcMsg.contLen = sizeof(SShowMsg); + rpcMsg.msgType = TSDB_MSG_TYPE_SHOW; + + sendMsg(pClient, &rpcMsg); + SRpcMsg* pMsg = pClient->pRsp; + ASSERT_NE(pMsg, nullptr); + + SShowRsp* pRsp = (SShowRsp*)pMsg->pCont; + ASSERT_NE(pRsp, nullptr); + pRsp->showId = htonl(pRsp->showId); + STableMetaMsg* pMeta = &pRsp->tableMeta; + pMeta->contLen = htonl(pMeta->contLen); + pMeta->numOfColumns = htons(pMeta->numOfColumns); + pMeta->sversion = htons(pMeta->sversion); + pMeta->tversion = htons(pMeta->tversion); + pMeta->tid = htonl(pMeta->tid); + pMeta->uid = htobe64(pMeta->uid); + pMeta->suid = htobe64(pMeta->suid); + + showId = pRsp->showId; + + EXPECT_NE(pRsp->showId, 0); + EXPECT_EQ(pMeta->contLen, 0); + EXPECT_STREQ(pMeta->tableFname, ""); + EXPECT_EQ(pMeta->numOfTags, 0); + EXPECT_EQ(pMeta->precision, 0); + EXPECT_EQ(pMeta->tableType, 0); + EXPECT_EQ(pMeta->numOfColumns, 10); + EXPECT_EQ(pMeta->sversion, 0); + EXPECT_EQ(pMeta->tversion, 0); + EXPECT_EQ(pMeta->tid, 0); + EXPECT_EQ(pMeta->uid, 0); + EXPECT_STREQ(pMeta->sTableName, ""); + EXPECT_EQ(pMeta->suid, 0); + + SSchema* pSchema = NULL; + pSchema = &pMeta->schema[0]; + pSchema->bytes = htons(pSchema->bytes); + EXPECT_EQ(pSchema->colId, 0); + EXPECT_EQ(pSchema->type, TSDB_DATA_TYPE_INT); + EXPECT_EQ(pSchema->bytes, 4); + EXPECT_STREQ(pSchema->name, "streamId"); + + pSchema = &pMeta->schema[1]; + pSchema->bytes = htons(pSchema->bytes); + EXPECT_EQ(pSchema->colId, 0); + EXPECT_EQ(pSchema->type, TSDB_DATA_TYPE_INT); + EXPECT_EQ(pSchema->bytes, 4); + EXPECT_STREQ(pSchema->name, "connId"); + + pSchema = &pMeta->schema[2]; + pSchema->bytes = htons(pSchema->bytes); + EXPECT_EQ(pSchema->colId, 0); + EXPECT_EQ(pSchema->type, TSDB_DATA_TYPE_BINARY); + EXPECT_EQ(pSchema->bytes, TSDB_USER_LEN + VARSTR_HEADER_SIZE); + EXPECT_STREQ(pSchema->name, "user"); + } + + { + SRetrieveTableMsg* pReq = (SRetrieveTableMsg*)rpcMallocCont(sizeof(SRetrieveTableMsg)); + pReq->showId = htonl(showId); + pReq->free = 0; + + SRpcMsg rpcMsg = {0}; + rpcMsg.pCont = pReq; + rpcMsg.contLen = sizeof(SRetrieveTableMsg); + rpcMsg.msgType = TSDB_MSG_TYPE_SHOW_RETRIEVE; + + sendMsg(pClient, &rpcMsg); + SRpcMsg* pMsg = pClient->pRsp; + ASSERT_NE(pMsg, nullptr); + ASSERT_EQ(pMsg->code, 0); + + SRetrieveTableRsp* pRsp = (SRetrieveTableRsp*)pMsg->pCont; + ASSERT_NE(pRsp, nullptr); + pRsp->numOfRows = htonl(pRsp->numOfRows); + pRsp->offset = htobe64(pRsp->offset); + pRsp->useconds = htobe64(pRsp->useconds); + pRsp->compLen = htonl(pRsp->compLen); + + EXPECT_EQ(pRsp->numOfRows, 0); + EXPECT_EQ(pRsp->offset, 0); + EXPECT_EQ(pRsp->useconds, 0); + EXPECT_EQ(pRsp->completed, 1); + EXPECT_EQ(pRsp->precision, TSDB_TIME_PRECISION_MILLI); + EXPECT_EQ(pRsp->compressed, 0); + EXPECT_EQ(pRsp->reserved, 0); + EXPECT_EQ(pRsp->compLen, 0); + } +} diff --git a/source/dnode/mgmt/impl/test/show/CMakeLists.txt b/source/dnode/mgmt/impl/test/show/CMakeLists.txt new file mode 100644 index 0000000000..5f1596ce95 --- /dev/null +++ b/source/dnode/mgmt/impl/test/show/CMakeLists.txt @@ -0,0 +1,29 @@ +add_executable(dndTestShow "") + +target_sources(dndTestShow + PRIVATE + "show.cpp" + "../sut/deploy.cpp" +) + +target_link_libraries( + dndTestShow + PUBLIC dnode + PUBLIC util + PUBLIC os + PUBLIC gtest_main +) + +target_include_directories(dndTestShow + PUBLIC + "${CMAKE_SOURCE_DIR}/include/server/dnode/mgmt" + "${CMAKE_CURRENT_SOURCE_DIR}/../../inc" + "${CMAKE_CURRENT_SOURCE_DIR}/../sut" +) + +enable_testing() + +add_test( + NAME dndTestShow + COMMAND dndTestShow +) diff --git a/source/dnode/mgmt/impl/test/show/show.cpp b/source/dnode/mgmt/impl/test/show/show.cpp new file mode 100644 index 0000000000..e8c8fa261c --- /dev/null +++ b/source/dnode/mgmt/impl/test/show/show.cpp @@ -0,0 +1,238 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * 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 . + */ + +#include "deploy.h" + +class DndTestShow : public ::testing::Test { + protected: + void SetUp() override {} + void TearDown() override {} + + static void SetUpTestSuite() { + const char* user = "root"; + const char* pass = "taosdata"; + const char* path = "/tmp/dndTestShow"; + const char* fqdn = "localhost"; + uint16_t port = 9523; + + pServer = createServer(path, fqdn, port); + ASSERT(pServer); + pClient = createClient(user, pass, fqdn, port); + } + + static void TearDownTestSuite() { + dropServer(pServer); + dropClient(pClient); + } + + static SServer* pServer; + static SClient* pClient; + static int32_t connId; +}; + +SServer* DndTestShow::pServer; +SClient* DndTestShow::pClient; +int32_t DndTestShow::connId; + +TEST_F(DndTestShow, SShowMsg_01) { + ASSERT_NE(pClient, nullptr); + + SConnectMsg* pReq = (SConnectMsg*)rpcMallocCont(sizeof(SConnectMsg)); + pReq->pid = htonl(1234); + strcpy(pReq->app, "dndTestShow"); + strcpy(pReq->db, ""); + + SRpcMsg rpcMsg = {0}; + rpcMsg.pCont = pReq; + rpcMsg.contLen = sizeof(SConnectMsg); + rpcMsg.msgType = TSDB_MSG_TYPE_CONNECT; + + sendMsg(pClient, &rpcMsg); + SRpcMsg* pMsg = pClient->pRsp; + ASSERT_NE(pMsg, nullptr); + + SConnectRsp* pRsp = (SConnectRsp*)pMsg->pCont; + ASSERT_NE(pRsp, nullptr); + pRsp->connId = htonl(pRsp->connId); + + EXPECT_EQ(pRsp->connId, 1); + connId = pRsp->connId; +} + +TEST_F(DndTestShow, SShowMsg_02) { + ASSERT_NE(pClient, nullptr); + + SShowMsg* pReq = (SShowMsg*)rpcMallocCont(sizeof(SShowMsg)); + pReq->type = TSDB_MGMT_TABLE_MAX; + strcpy(pReq->db, ""); + + SRpcMsg rpcMsg = {0}; + rpcMsg.pCont = pReq; + rpcMsg.contLen = sizeof(SShowMsg); + rpcMsg.msgType = TSDB_MSG_TYPE_SHOW; + + sendMsg(pClient, &rpcMsg); + SRpcMsg* pMsg = pClient->pRsp; + ASSERT_NE(pMsg, nullptr); + ASSERT_EQ(pMsg->code, TSDB_CODE_MND_INVALID_MSG_TYPE); +} + +TEST_F(DndTestShow, SShowMsg_03) { + ASSERT_NE(pClient, nullptr); + + SShowMsg* pReq = (SShowMsg*)rpcMallocCont(sizeof(SShowMsg)); + pReq->type = TSDB_MGMT_TABLE_START; + strcpy(pReq->db, ""); + + SRpcMsg rpcMsg = {0}; + rpcMsg.pCont = pReq; + rpcMsg.contLen = sizeof(SShowMsg); + rpcMsg.msgType = TSDB_MSG_TYPE_SHOW; + + sendMsg(pClient, &rpcMsg); + SRpcMsg* pMsg = pClient->pRsp; + ASSERT_NE(pMsg, nullptr); + ASSERT_EQ(pMsg->code, TSDB_CODE_MND_INVALID_MSG_TYPE); +} + +TEST_F(DndTestShow, SShowMsg_04) { + ASSERT_NE(pClient, nullptr); + int32_t showId = 0; + + { + SShowMsg* pReq = (SShowMsg*)rpcMallocCont(sizeof(SShowMsg)); + pReq->type = TSDB_MGMT_TABLE_CONNS; + strcpy(pReq->db, ""); + + SRpcMsg rpcMsg = {0}; + rpcMsg.pCont = pReq; + rpcMsg.contLen = sizeof(SShowMsg); + rpcMsg.msgType = TSDB_MSG_TYPE_SHOW; + + sendMsg(pClient, &rpcMsg); + SRpcMsg* pMsg = pClient->pRsp; + ASSERT_NE(pMsg, nullptr); + + SShowRsp* pRsp = (SShowRsp*)pMsg->pCont; + ASSERT_NE(pRsp, nullptr); + pRsp->showId = htonl(pRsp->showId); + STableMetaMsg* pMeta = &pRsp->tableMeta; + pMeta->contLen = htonl(pMeta->contLen); + pMeta->numOfColumns = htons(pMeta->numOfColumns); + pMeta->sversion = htons(pMeta->sversion); + pMeta->tversion = htons(pMeta->tversion); + pMeta->tid = htonl(pMeta->tid); + pMeta->uid = htobe64(pMeta->uid); + pMeta->suid = htobe64(pMeta->suid); + + showId = pRsp->showId; + + EXPECT_NE(pRsp->showId, 0); + EXPECT_EQ(pMeta->contLen, 0); + EXPECT_STREQ(pMeta->tableFname, ""); + EXPECT_EQ(pMeta->numOfTags, 0); + EXPECT_EQ(pMeta->precision, 0); + EXPECT_EQ(pMeta->tableType, 0); + EXPECT_EQ(pMeta->numOfColumns, 7); + EXPECT_EQ(pMeta->sversion, 0); + EXPECT_EQ(pMeta->tversion, 0); + EXPECT_EQ(pMeta->tid, 0); + EXPECT_EQ(pMeta->uid, 0); + EXPECT_STREQ(pMeta->sTableName, ""); + EXPECT_EQ(pMeta->suid, 0); + + SSchema* pSchema = NULL; + pSchema = &pMeta->schema[0]; + pSchema->bytes = htons(pSchema->bytes); + EXPECT_EQ(pSchema->colId, 0); + EXPECT_EQ(pSchema->type, TSDB_DATA_TYPE_INT); + EXPECT_EQ(pSchema->bytes, 4); + EXPECT_STREQ(pSchema->name, "connId"); + + pSchema = &pMeta->schema[1]; + pSchema->bytes = htons(pSchema->bytes); + EXPECT_EQ(pSchema->colId, 0); + EXPECT_EQ(pSchema->type, TSDB_DATA_TYPE_BINARY); + EXPECT_EQ(pSchema->bytes, TSDB_USER_LEN + VARSTR_HEADER_SIZE); + EXPECT_STREQ(pSchema->name, "user"); + + pSchema = &pMeta->schema[2]; + pSchema->bytes = htons(pSchema->bytes); + EXPECT_EQ(pSchema->colId, 0); + EXPECT_EQ(pSchema->type, TSDB_DATA_TYPE_BINARY); + EXPECT_EQ(pSchema->bytes, TSDB_USER_LEN + VARSTR_HEADER_SIZE); + EXPECT_STREQ(pSchema->name, "program"); + + pSchema = &pMeta->schema[3]; + pSchema->bytes = htons(pSchema->bytes); + EXPECT_EQ(pSchema->colId, 0); + EXPECT_EQ(pSchema->type, TSDB_DATA_TYPE_INT); + EXPECT_EQ(pSchema->bytes, 4); + EXPECT_STREQ(pSchema->name, "pid"); + + pSchema = &pMeta->schema[4]; + pSchema->bytes = htons(pSchema->bytes); + EXPECT_EQ(pSchema->colId, 0); + EXPECT_EQ(pSchema->type, TSDB_DATA_TYPE_BINARY); + EXPECT_EQ(pSchema->bytes, TSDB_IPv4ADDR_LEN + 6 + VARSTR_HEADER_SIZE); + EXPECT_STREQ(pSchema->name, "ip:port"); + + pSchema = &pMeta->schema[5]; + pSchema->bytes = htons(pSchema->bytes); + EXPECT_EQ(pSchema->colId, 0); + EXPECT_EQ(pSchema->type, TSDB_DATA_TYPE_TIMESTAMP); + EXPECT_EQ(pSchema->bytes, 8); + EXPECT_STREQ(pSchema->name, "login_time"); + + pSchema = &pMeta->schema[6]; + pSchema->bytes = htons(pSchema->bytes); + EXPECT_EQ(pSchema->colId, 0); + EXPECT_EQ(pSchema->type, TSDB_DATA_TYPE_TIMESTAMP); + EXPECT_EQ(pSchema->bytes, 8); + EXPECT_STREQ(pSchema->name, "last_access"); + } + + { + SRetrieveTableMsg* pReq = (SRetrieveTableMsg*)rpcMallocCont(sizeof(SRetrieveTableMsg)); + pReq->showId = htonl(showId); + pReq->free = 0; + + SRpcMsg rpcMsg = {0}; + rpcMsg.pCont = pReq; + rpcMsg.contLen = sizeof(SRetrieveTableMsg); + rpcMsg.msgType = TSDB_MSG_TYPE_SHOW_RETRIEVE; + + sendMsg(pClient, &rpcMsg); + SRpcMsg* pMsg = pClient->pRsp; + ASSERT_NE(pMsg, nullptr); + ASSERT_EQ(pMsg->code, 0); + + SRetrieveTableRsp* pRsp = (SRetrieveTableRsp*)pMsg->pCont; + ASSERT_NE(pRsp, nullptr); + pRsp->numOfRows = htonl(pRsp->numOfRows); + pRsp->offset = htobe64(pRsp->offset); + pRsp->useconds = htobe64(pRsp->useconds); + pRsp->compLen = htonl(pRsp->compLen); + + EXPECT_EQ(pRsp->numOfRows, 1); + EXPECT_EQ(pRsp->offset, 0); + EXPECT_EQ(pRsp->useconds, 0); + EXPECT_EQ(pRsp->completed, 1); + EXPECT_EQ(pRsp->precision, TSDB_TIME_PRECISION_MILLI); + EXPECT_EQ(pRsp->compressed, 0); + EXPECT_EQ(pRsp->reserved, 0); + EXPECT_EQ(pRsp->compLen, 0); + } +} diff --git a/source/dnode/mgmt/impl/test/sut/deploy.cpp b/source/dnode/mgmt/impl/test/sut/deploy.cpp index 132ce54ec6..ad1667eac5 100644 --- a/source/dnode/mgmt/impl/test/sut/deploy.cpp +++ b/source/dnode/mgmt/impl/test/sut/deploy.cpp @@ -15,8 +15,27 @@ #include "deploy.h" -void initLog(char *path) { +void initLog(const char* path) { + dDebugFlag = 0; + vDebugFlag = 0; mDebugFlag = 207; + cDebugFlag = 0; + jniDebugFlag = 0; + tmrDebugFlag = 0; + sdbDebugFlag = 0; + httpDebugFlag = 0; + mqttDebugFlag = 0; + monDebugFlag = 0; + uDebugFlag = 0; + rpcDebugFlag = 0; + odbcDebugFlag = 0; + qDebugFlag = 0; + wDebugFlag = 0; + sDebugFlag = 0; + tsdbDebugFlag = 0; + cqDebugFlag = 0; + debugFlag = 0; + char temp[PATH_MAX]; snprintf(temp, PATH_MAX, "%s/taosdlog", path); if (taosInitLog(temp, tsNumOfLogLines, 1) != 0) { @@ -32,7 +51,7 @@ void* runServer(void* param) { } } -void initOption(SDnodeOpt* pOption, char *path) { +void initOption(SDnodeOpt* pOption, const char* path, const char* fqdn, uint16_t port) { pOption->sver = 1; pOption->numOfCores = 1; pOption->numOfSupportMnodes = 1; @@ -44,19 +63,20 @@ void initOption(SDnodeOpt* pOption, char *path) { pOption->ratioOfQueryCores = 1; pOption->maxShellConns = 1000; pOption->shellActivityTimer = 30; - pOption->serverPort = 9527; + pOption->serverPort = port; strcpy(pOption->dataDir, path); - strcpy(pOption->localEp, "localhost:9527"); - strcpy(pOption->localFqdn, "localhost"); - strcpy(pOption->firstEp, "localhost:9527"); - - taosRemoveDir(path); - taosMkDir(path); + snprintf(pOption->localEp, TSDB_EP_LEN, "%s:%u", fqdn, port); + snprintf(pOption->localFqdn, TSDB_FQDN_LEN, "%s", fqdn); + snprintf(pOption->firstEp, TSDB_EP_LEN, "%s:%u", fqdn, port); } -SServer* createServer(char *path) { +SServer* createServer(const char* path, const char* fqdn, uint16_t port) { + taosRemoveDir(path); + taosMkDir(path); + initLog(path); + SDnodeOpt option = {0}; - initOption(&option, path); + initOption(&option, path, fqdn, port); SDnode* pDnode = dndInit(&option); ASSERT(pDnode); @@ -80,11 +100,11 @@ void dropServer(SServer* pServer) { void processClientRsp(void* parent, SRpcMsg* pMsg, SEpSet* pEpSet) { SClient* pClient = (SClient*)parent; pClient->pRsp = pMsg; - //taosMsleep(1000000); + // taosMsleep(1000000); tsem_post(&pClient->sem); } -SClient* createClient(char *user, char *pass) { +SClient* createClient(const char* user, const char* pass, const char* fqdn, uint16_t port) { SClient* pClient = (SClient*)calloc(1, sizeof(SClient)); ASSERT(pClient); @@ -93,14 +113,14 @@ SClient* createClient(char *user, char *pass) { SRpcInit rpcInit; memset(&rpcInit, 0, sizeof(rpcInit)); - rpcInit.label = "DND-C"; + rpcInit.label = (char*)"DND-C"; rpcInit.numOfThreads = 1; rpcInit.cfp = processClientRsp; rpcInit.sessions = 1024; rpcInit.connType = TAOS_CONN_CLIENT; rpcInit.idleTime = 30 * 1000; - rpcInit.user = user; - rpcInit.ckey = "key"; + rpcInit.user = (char*)user; + rpcInit.ckey = (char*)"key"; rpcInit.parent = pClient; rpcInit.secret = (char*)secretEncrypt; rpcInit.parent = pClient; @@ -110,6 +130,8 @@ SClient* createClient(char *user, char *pass) { ASSERT(pClient->clientRpc); tsem_init(&pClient->sem, 0, 0); + strcpy(pClient->fqdn, fqdn); + pClient->port = port; return pClient; } @@ -123,8 +145,8 @@ void sendMsg(SClient* pClient, SRpcMsg* pMsg) { SEpSet epSet = {0}; epSet.inUse = 0; epSet.numOfEps = 1; - epSet.port[0] = 9527; - strcpy(epSet.fqdn[0], "localhost"); + epSet.port[0] = pClient->port; + strcpy(epSet.fqdn[0], pClient->fqdn); rpcSendRequest(pClient->clientRpc, &epSet, pMsg, NULL); tsem_wait(&pClient->sem); diff --git a/source/dnode/mgmt/impl/test/sut/deploy.h b/source/dnode/mgmt/impl/test/sut/deploy.h index 6c47b03fe7..93188458ec 100644 --- a/source/dnode/mgmt/impl/test/sut/deploy.h +++ b/source/dnode/mgmt/impl/test/sut/deploy.h @@ -24,6 +24,7 @@ #include "trpc.h" #include "tthread.h" #include "ulog.h" +#include "tdataformat.h" typedef struct { SDnode* pDnode; @@ -31,13 +32,15 @@ typedef struct { } SServer; typedef struct { + char fqdn[TSDB_FQDN_LEN]; + uint16_t port; void* clientRpc; SRpcMsg* pRsp; tsem_t sem; } SClient; -SServer* createServer(char* path); +SServer* createServer(const char* path, const char* fqdn, uint16_t port); void dropServer(SServer* pServer); -SClient* createClient(char *user, char *pass); +SClient* createClient(const char* user, const char* pass, const char* fqdn, uint16_t port); void dropClient(SClient* pClient); void sendMsg(SClient* pClient, SRpcMsg* pMsg); diff --git a/source/dnode/mgmt/impl/test/test01/test01.cpp b/source/dnode/mgmt/impl/test/test01/test01.cpp deleted file mode 100644 index 6c440074dc..0000000000 --- a/source/dnode/mgmt/impl/test/test01/test01.cpp +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (c) 2019 TAOS Data, Inc. - * - * 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 . - */ - -#include "deploy.h" - -class DndTest01 : public ::testing::Test { - protected: - void SetUp() override { - pServer = createServer("/tmp/dndTest01"); - pClient = createClient("root", "taosdata"); - } - void TearDown() override { - dropServer(pServer); - dropClient(pClient); - } - - SServer* pServer; - SClient* pClient; -}; - -TEST_F(DndTest01, connectMsg) { - SConnectMsg* pReq = (SConnectMsg*)rpcMallocCont(sizeof(SConnectMsg)); - pReq->pid = htonl(1234); - strcpy(pReq->app, "test01"); - strcpy(pReq->db, ""); - - SRpcMsg rpcMsg = {0}; - rpcMsg.pCont = pReq; - rpcMsg.contLen = sizeof(SConnectMsg); - rpcMsg.msgType = TSDB_MSG_TYPE_CONNECT; - - sendMsg(pClient, &rpcMsg); - - SConnectRsp* pRsp = (SConnectRsp*)pClient->pRsp->pCont; - ASSERT_NE(pRsp, nullptr); - pRsp->acctId = htonl(pRsp->acctId); - pRsp->clusterId = htonl(pRsp->clusterId); - pRsp->connId = htonl(pRsp->connId); - pRsp->epSet.port[0] = htons(pRsp->epSet.port[0]); - - EXPECT_EQ(pRsp->acctId, 1); - EXPECT_GT(pRsp->clusterId, 0); - EXPECT_EQ(pRsp->connId, 1); - EXPECT_EQ(pRsp->superAuth, 1); - EXPECT_EQ(pRsp->readAuth, 1); - EXPECT_EQ(pRsp->writeAuth, 1); - - EXPECT_EQ(pRsp->epSet.inUse, 0); - EXPECT_EQ(pRsp->epSet.numOfEps, 1); - EXPECT_EQ(pRsp->epSet.port[0], 9527); - EXPECT_STREQ(pRsp->epSet.fqdn[0], "localhost"); -} - -// TEST_F(DndTest01, heartbeatMsg) { -// SHeartBeatMsg* pReq = (SHeartBeatMsg*)rpcMallocCont(sizeof(SHeartBeatMsg)); -// pReq->connId = htonl(1); -// pReq->pid = htonl(1234); -// pReq->numOfQueries = htonl(0); -// pReq->numOfStreams = htonl(0); -// strcpy(pReq->app, "test01"); - -// SRpcMsg rpcMsg = {0}; -// rpcMsg.pCont = pReq; -// rpcMsg.contLen = sizeof(SHeartBeatMsg); -// rpcMsg.msgType = TSDB_MSG_TYPE_HEARTBEAT; - -// sendMsg(pClient, &rpcMsg); - -// SHeartBeatRsp* pRsp = (SHeartBeatRsp*)pClient->pRsp; -// ASSERT(pRsp); - // pRsp->epSet.port[0] = htonl(pRsp->epSet.port[0]); - -// EXPECT_EQ(htonl(pRsp->connId), 1); -// EXPECT_GT(htonl(pRsp->queryId), 0); -// EXPECT_GT(htonl(pRsp->streamId), 1); -// EXPECT_EQ(htonl(pRsp->totalDnodes), 1); -// EXPECT_EQ(htonl(pRsp->onlineDnodes), 1); -// EXPECT_EQ(pRsp->killConnection, 0); - // EXPECT_EQ(pRsp->epSet.inUse, 0); - // EXPECT_EQ(pRsp->epSet.numOfEps, 1); - // EXPECT_EQ(pRsp->epSet.port[0], 9527); - // EXPECT_STREQ(pRsp->epSet.fqdn[0], "localhost"); -// } diff --git a/source/dnode/mnode/impl/inc/mndCluster.h b/source/dnode/mnode/impl/inc/mndCluster.h index efc1ada67d..0206695b88 100644 --- a/source/dnode/mnode/impl/inc/mndCluster.h +++ b/source/dnode/mnode/impl/inc/mndCluster.h @@ -24,6 +24,7 @@ extern "C" { int32_t mndInitCluster(SMnode *pMnode); void mndCleanupCluster(SMnode *pMnode); +int32_t mndGetClusterName(SMnode *pMnode, char *clusterName, int32_t len); #ifdef __cplusplus } diff --git a/source/dnode/mnode/impl/inc/mndDef.h b/source/dnode/mnode/impl/inc/mndDef.h index aaf86c15b6..9e4f922540 100644 --- a/source/dnode/mnode/impl/inc/mndDef.h +++ b/source/dnode/mnode/impl/inc/mndDef.h @@ -116,7 +116,7 @@ typedef struct STrans { typedef struct SClusterObj { int32_t id; - char uid[TSDB_CLUSTER_ID_LEN]; + char name[TSDB_CLUSTER_ID_LEN]; int64_t createdTime; int64_t updateTime; } SClusterObj; @@ -296,7 +296,6 @@ typedef struct SShowObj { void *pIter; void *pVgIter; SMnode *pMnode; - SShowObj **ppShow; char db[TSDB_FULL_DB_NAME_LEN]; int16_t offset[TSDB_MAX_COLUMNS]; int32_t bytes[TSDB_MAX_COLUMNS]; diff --git a/source/dnode/mnode/impl/inc/mndInt.h b/source/dnode/mnode/impl/inc/mndInt.h index dbca6ad057..8d20356e39 100644 --- a/source/dnode/mnode/impl/inc/mndInt.h +++ b/source/dnode/mnode/impl/inc/mndInt.h @@ -51,6 +51,15 @@ typedef struct { SCacheObj *cache; } SProfileMgmt; +typedef struct { + int8_t enable; + pthread_mutex_t lock; + pthread_cond_t cond; + volatile int32_t exit; + pthread_t thread; + char email[TSDB_FQDN_LEN]; +} STelemMgmt; + typedef struct SMnode { int32_t dnodeId; int32_t clusterId; @@ -59,23 +68,18 @@ typedef struct SMnode { SReplica replicas[TSDB_MAX_REPLICA]; tmr_h timer; char *path; + SMnodeCfg cfg; SSdb *pSdb; SDnode *pDnode; SArray *pSteps; SShowMgmt showMgmt; SProfileMgmt profileMgmt; + STelemMgmt telemMgmt; MndMsgFp msgFp[TSDB_MSG_TYPE_MAX]; SendMsgToDnodeFp sendMsgToDnodeFp; SendMsgToMnodeFp sendMsgToMnodeFp; SendRedirectMsgFp sendRedirectMsgFp; PutMsgToMnodeQFp putMsgToApplyMsgFp; - int32_t sver; - int32_t statusInterval; - int32_t mnodeEqualVnodeNum; - int32_t shellActivityTimer; - char *timezone; - char *locale; - char *charset; } SMnode; void mndSendMsgToDnode(SMnode *pMnode, SEpSet *pEpSet, SRpcMsg *rpcMsg); diff --git a/source/dnode/mnode/impl/src/mndCluster.c b/source/dnode/mnode/impl/src/mndCluster.c index 6013ac0c31..9fa7a06630 100644 --- a/source/dnode/mnode/impl/src/mndCluster.c +++ b/source/dnode/mnode/impl/src/mndCluster.c @@ -15,11 +15,52 @@ #define _DEFAULT_SOURCE #include "mndCluster.h" -#include "mndTrans.h" #include "mndShow.h" +#include "mndTrans.h" #define SDB_CLUSTER_VER 1 +static SSdbRaw *mndClusterActionEncode(SClusterObj *pCluster); +static SSdbRow *mndClusterActionDecode(SSdbRaw *pRaw); +static int32_t mndClusterActionInsert(SSdb *pSdb, SClusterObj *pCluster); +static int32_t mndClusterActionDelete(SSdb *pSdb, SClusterObj *pCluster); +static int32_t mndClusterActionUpdate(SSdb *pSdb, SClusterObj *pSrcCluster, SClusterObj *pDstCluster); +static int32_t mndCreateDefaultCluster(SMnode *pMnode); +static int32_t mndGetClusterMeta(SMnodeMsg *pMsg, SShowObj *pShow, STableMetaMsg *pMeta); +static int32_t mndRetrieveClusters(SMnodeMsg *pMsg, SShowObj *pShow, char *data, int32_t rows); +static void mndCancelGetNextCluster(SMnode *pMnode, void *pIter); + +int32_t mndInitCluster(SMnode *pMnode) { + SSdbTable table = {.sdbType = SDB_CLUSTER, + .keyType = SDB_KEY_INT32, + .deployFp = (SdbDeployFp)mndCreateDefaultCluster, + .encodeFp = (SdbEncodeFp)mndClusterActionEncode, + .decodeFp = (SdbDecodeFp)mndClusterActionDecode, + .insertFp = (SdbInsertFp)mndClusterActionInsert, + .updateFp = (SdbUpdateFp)mndClusterActionUpdate, + .deleteFp = (SdbDeleteFp)mndClusterActionDelete}; + + mndAddShowMetaHandle(pMnode, TSDB_MGMT_TABLE_CLUSTER, mndGetClusterMeta); + mndAddShowRetrieveHandle(pMnode, TSDB_MGMT_TABLE_CLUSTER, mndRetrieveClusters); + mndAddShowFreeIterHandle(pMnode, TSDB_MGMT_TABLE_CLUSTER, mndCancelGetNextCluster); + return sdbSetTable(pMnode->pSdb, table); +} + +void mndCleanupCluster(SMnode *pMnode) {} + +int32_t mndGetClusterName(SMnode *pMnode, char *clusterName, int32_t len) { + SSdb *pSdb = pMnode->pSdb; + + SClusterObj *pCluster = sdbAcquire(pSdb, SDB_CLUSTER, &pMnode->clusterId); + if (pCluster = NULL) { + return -1; + } + + tstrncpy(clusterName, pCluster->name, len); + sdbRelease(pSdb, pCluster); + return 0; +} + static SSdbRaw *mndClusterActionEncode(SClusterObj *pCluster) { SSdbRaw *pRaw = sdbAllocRaw(SDB_CLUSTER, SDB_CLUSTER_VER, sizeof(SClusterObj)); if (pRaw == NULL) return NULL; @@ -28,7 +69,7 @@ static SSdbRaw *mndClusterActionEncode(SClusterObj *pCluster) { SDB_SET_INT32(pRaw, dataPos, pCluster->id); SDB_SET_INT64(pRaw, dataPos, pCluster->createdTime) SDB_SET_INT64(pRaw, dataPos, pCluster->updateTime) - SDB_SET_BINARY(pRaw, dataPos, pCluster->uid, TSDB_CLUSTER_ID_LEN) + SDB_SET_BINARY(pRaw, dataPos, pCluster->name, TSDB_CLUSTER_ID_LEN) return pRaw; } @@ -51,7 +92,7 @@ static SSdbRow *mndClusterActionDecode(SSdbRaw *pRaw) { SDB_GET_INT32(pRaw, pRow, dataPos, &pCluster->id) SDB_GET_INT64(pRaw, pRow, dataPos, &pCluster->createdTime) SDB_GET_INT64(pRaw, pRow, dataPos, &pCluster->updateTime) - SDB_GET_BINARY(pRaw, pRow, dataPos, pCluster->uid, TSDB_CLUSTER_ID_LEN) + SDB_GET_BINARY(pRaw, pRow, dataPos, pCluster->name, TSDB_CLUSTER_ID_LEN) return pRow; } @@ -76,14 +117,14 @@ static int32_t mndCreateDefaultCluster(SMnode *pMnode) { clusterObj.createdTime = taosGetTimestampMs(); clusterObj.updateTime = clusterObj.createdTime; - int32_t code = taosGetSystemUid(clusterObj.uid, TSDB_CLUSTER_ID_LEN); + int32_t code = taosGetSystemUid(clusterObj.name, TSDB_CLUSTER_ID_LEN); if (code != 0) { - strcpy(clusterObj.uid, "tdengine2.0"); - mError("failed to get uid from system, set to default val %s", clusterObj.uid); + strcpy(clusterObj.name, "tdengine2.0"); + mError("failed to get name from system, set to default val %s", clusterObj.name); } else { - mDebug("cluster:%d, uid is %s", clusterObj.id, clusterObj.uid); + mDebug("cluster:%d, name is %s", clusterObj.id, clusterObj.name); } - clusterObj.id = MurmurHash3_32(clusterObj.uid, TSDB_CLUSTER_ID_LEN); + clusterObj.id = MurmurHash3_32(clusterObj.name, TSDB_CLUSTER_ID_LEN); clusterObj.id = abs(clusterObj.id); pMnode->clusterId = clusterObj.id; @@ -95,85 +136,79 @@ static int32_t mndCreateDefaultCluster(SMnode *pMnode) { return sdbWrite(pMnode->pSdb, pRaw); } +static int32_t mndGetClusterMeta(SMnodeMsg *pMsg, SShowObj *pShow, STableMetaMsg *pMeta) { + int32_t cols = 0; + SSchema *pSchema = pMeta->schema; -// static int32_t mnodeGetClusterMeta(STableMetaMsg *pMeta, SShowObj *pShow, void *pConn) { -// int32_t cols = 0; -// SSchema *pSchema = pMeta->schema; + pShow->bytes[cols] = 4; + pSchema[cols].type = TSDB_DATA_TYPE_INT; + strcpy(pSchema[cols].name, "id"); + pSchema[cols].bytes = htons(pShow->bytes[cols]); + cols++; -// pShow->bytes[cols] = TSDB_CLUSTER_ID_LEN + VARSTR_HEADER_SIZE; -// pSchema[cols].type = TSDB_DATA_TYPE_BINARY; -// strcpy(pSchema[cols].name, "clusterId"); -// pSchema[cols].bytes = htons(pShow->bytes[cols]); -// cols++; + pShow->bytes[cols] = TSDB_CLUSTER_ID_LEN + VARSTR_HEADER_SIZE; + pSchema[cols].type = TSDB_DATA_TYPE_BINARY; + strcpy(pSchema[cols].name, "name"); + pSchema[cols].bytes = htons(pShow->bytes[cols]); + cols++; -// pShow->bytes[cols] = 8; -// pSchema[cols].type = TSDB_DATA_TYPE_TIMESTAMP; -// strcpy(pSchema[cols].name, "create_time"); -// pSchema[cols].bytes = htons(pShow->bytes[cols]); -// cols++; + pShow->bytes[cols] = 8; + pSchema[cols].type = TSDB_DATA_TYPE_TIMESTAMP; + strcpy(pSchema[cols].name, "create_time"); + pSchema[cols].bytes = htons(pShow->bytes[cols]); + cols++; -// pMeta->numOfColumns = htons(cols); -// strcpy(pMeta->tableFname, "show cluster"); -// pShow->numOfColumns = cols; + pMeta->numOfColumns = htons(cols); + strcpy(pMeta->tableFname, "show cluster"); + pShow->numOfColumns = cols; -// pShow->offset[0] = 0; -// for (int32_t i = 1; i < cols; ++i) { -// pShow->offset[i] = pShow->offset[i - 1] + pShow->bytes[i - 1]; -// } + pShow->offset[0] = 0; + for (int32_t i = 1; i < cols; ++i) { + pShow->offset[i] = pShow->offset[i - 1] + pShow->bytes[i - 1]; + } -// pShow->numOfRows = 1; -// pShow->rowSize = pShow->offset[cols - 1] + pShow->bytes[cols - 1]; + pShow->numOfRows = 1; + pShow->rowSize = pShow->offset[cols - 1] + pShow->bytes[cols - 1]; -// return 0; -// } - -// static int32_t mnodeRetrieveClusters(SShowObj *pShow, char *data, int32_t rows, void *pConn) { -// int32_t numOfRows = 0; -// int32_t cols = 0; -// char * pWrite; -// SClusterObj *pCluster = NULL; - -// while (numOfRows < rows) { -// pShow->pIter = mnodeGetNextCluster(pShow->pIter, &pCluster); -// if (pCluster == NULL) break; - -// cols = 0; - -// pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; -// STR_WITH_MAXSIZE_TO_VARSTR(pWrite, pCluster->uid, TSDB_CLUSTER_ID_LEN); -// cols++; - -// pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; -// *(int64_t *) pWrite = pCluster->createdTime; -// cols++; - -// mnodeDecClusterRef(pCluster); -// numOfRows++; -// } - -// mnodeVacuumResult(data, pShow->numOfColumns, numOfRows, rows, pShow); -// pShow->numOfReads += numOfRows; -// return numOfRows; -// } - -// static void mnodeCancelGetNextCluster(void *pIter) { -// sdbFreeIter(tsClusterSdb, pIter); -// } - -int32_t mndInitCluster(SMnode *pMnode) { - SSdbTable table = {.sdbType = SDB_CLUSTER, - .keyType = SDB_KEY_INT32, - .deployFp = (SdbDeployFp)mndCreateDefaultCluster, - .encodeFp = (SdbEncodeFp)mndClusterActionEncode, - .decodeFp = (SdbDecodeFp)mndClusterActionDecode, - .insertFp = (SdbInsertFp)mndClusterActionInsert, - .updateFp = (SdbUpdateFp)mndClusterActionUpdate, - .deleteFp = (SdbDeleteFp)mndClusterActionDelete}; - - // mndAddShowMetaHandle(TSDB_MGMT_TABLE_CLUSTER, mnodeGetClusterMeta); - // mndAddShowRetrieveHandle(TSDB_MGMT_TABLE_CLUSTER, mnodeRetrieveClusters); - // mndAddShowFreeIterHandle(TSDB_MGMT_TABLE_CLUSTER, mnodeCancelGetNextCluster); - return sdbSetTable(pMnode->pSdb, table); + return 0; } -void mndCleanupCluster(SMnode *pMnode) {} +static int32_t mndRetrieveClusters(SMnodeMsg *pMsg, SShowObj *pShow, char *data, int32_t rows) { + SMnode *pMnode = pMsg->pMnode; + SSdb *pSdb = pMnode->pSdb; + int32_t numOfRows = 0; + int32_t cols = 0; + char *pWrite; + SClusterObj *pCluster = NULL; + + while (numOfRows < rows) { + pShow->pIter = sdbFetch(pSdb, SDB_CLUSTER, pShow->pIter, (void **)&pCluster); + if (pShow->pIter == NULL) break; + + cols = 0; + + pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; + *(int32_t *)pWrite = pCluster->id; + cols++; + + pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; + STR_WITH_MAXSIZE_TO_VARSTR(pWrite, pCluster->name, TSDB_CLUSTER_ID_LEN); + cols++; + + pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; + *(int64_t *)pWrite = pCluster->createdTime; + cols++; + + sdbRelease(pSdb, pCluster); + numOfRows++; + } + + mnodeVacuumResult(data, pShow->numOfColumns, numOfRows, rows, pShow); + pShow->numOfReads += numOfRows; + return numOfRows; +} + +static void mndCancelGetNextCluster(SMnode *pMnode, void *pIter) { + SSdb *pSdb = pMnode->pSdb; + sdbCancelFetch(pSdb, pIter); +} diff --git a/source/dnode/mnode/impl/src/mndDnode.c b/source/dnode/mnode/impl/src/mndDnode.c index 24e6113161..241b006293 100644 --- a/source/dnode/mnode/impl/src/mndDnode.c +++ b/source/dnode/mnode/impl/src/mndDnode.c @@ -179,32 +179,33 @@ static void mndGetDnodeData(SMnode *pMnode, SDnodeEps *pEps, int32_t numOfEps) { } static int32_t mndCheckClusterCfgPara(SMnode *pMnode, const SClusterCfg *pCfg) { - if (pCfg->mnodeEqualVnodeNum != pMnode->mnodeEqualVnodeNum) { - mError("\"mnodeEqualVnodeNum\"[%d - %d] cfg inconsistent", pCfg->mnodeEqualVnodeNum, pMnode->mnodeEqualVnodeNum); + if (pCfg->mnodeEqualVnodeNum != pMnode->cfg.mnodeEqualVnodeNum) { + mError("\"mnodeEqualVnodeNum\"[%d - %d] cfg inconsistent", pCfg->mnodeEqualVnodeNum, + pMnode->cfg.mnodeEqualVnodeNum); return DND_REASON_MN_EQUAL_VN_NOT_MATCH; } - if (pCfg->statusInterval != pMnode->statusInterval) { - mError("\"statusInterval\"[%d - %d] cfg inconsistent", pCfg->statusInterval, pMnode->statusInterval); + if (pCfg->statusInterval != pMnode->cfg.statusInterval) { + mError("\"statusInterval\"[%d - %d] cfg inconsistent", pCfg->statusInterval, pMnode->cfg.statusInterval); return DND_REASON_STATUS_INTERVAL_NOT_MATCH; } int64_t checkTime = 0; char timestr[32] = "1970-01-01 00:00:00.00"; (void)taosParseTime(timestr, &checkTime, (int32_t)strlen(timestr), TSDB_TIME_PRECISION_MILLI, 0); - if ((0 != strcasecmp(pCfg->timezone, pMnode->timezone)) && (checkTime != pCfg->checkTime)) { - mError("\"timezone\"[%s - %s] [%" PRId64 " - %" PRId64 "] cfg inconsistent", pCfg->timezone, tsTimezone, + if ((0 != strcasecmp(pCfg->timezone, pMnode->cfg.timezone)) && (checkTime != pCfg->checkTime)) { + mError("\"timezone\"[%s - %s] [%" PRId64 " - %" PRId64 "] cfg inconsistent", pCfg->timezone, pMnode->cfg.timezone, pCfg->checkTime, checkTime); return DND_REASON_TIME_ZONE_NOT_MATCH; } - if (0 != strcasecmp(pCfg->locale, pMnode->locale)) { - mError("\"locale\"[%s - %s] cfg parameters inconsistent", pCfg->locale, pMnode->locale); + if (0 != strcasecmp(pCfg->locale, pMnode->cfg.locale)) { + mError("\"locale\"[%s - %s] cfg parameters inconsistent", pCfg->locale, pMnode->cfg.locale); return DND_REASON_LOCALE_NOT_MATCH; } - if (0 != strcasecmp(pCfg->charset, pMnode->charset)) { - mError("\"charset\"[%s - %s] cfg parameters inconsistent.", pCfg->charset, pMnode->charset); + if (0 != strcasecmp(pCfg->charset, pMnode->cfg.charset)) { + mError("\"charset\"[%s - %s] cfg parameters inconsistent.", pCfg->charset, pMnode->cfg.charset); return DND_REASON_CHARSET_NOT_MATCH; } @@ -251,12 +252,12 @@ static int32_t mndProcessStatusMsg(SMnodeMsg *pMsg) { } } - if (pStatus->sver != pMnode->sver) { + if (pStatus->sver != pMnode->cfg.sver) { if (pDnode != NULL && pDnode->status != DND_STATUS_READY) { pDnode->offlineReason = DND_REASON_VERSION_NOT_MATCH; } mndReleaseDnode(pMnode, pDnode); - mError("dnode:%d, status msg version:%d not match cluster:%d", pStatus->dnodeId, pStatus->sver, pMnode->sver); + mError("dnode:%d, status msg version:%d not match cluster:%d", pStatus->dnodeId, pStatus->sver, pMnode->cfg.sver); return TSDB_CODE_MND_INVALID_MSG_VERSION; } diff --git a/source/dnode/mnode/impl/src/mndProfile.c b/source/dnode/mnode/impl/src/mndProfile.c index bdd0ab500a..ad7a6322bb 100644 --- a/source/dnode/mnode/impl/src/mndProfile.c +++ b/source/dnode/mnode/impl/src/mndProfile.c @@ -29,7 +29,7 @@ typedef struct { char user[TSDB_USER_LEN]; char app[TSDB_APP_NAME_LEN]; // app name that invokes taosc int32_t pid; // pid of app that invokes taosc - int32_t connId; + int32_t id; int8_t killed; int8_t align; uint16_t port; @@ -46,7 +46,7 @@ typedef struct { static SConnObj *mndCreateConn(SMnode *pMnode, char *user, uint32_t ip, uint16_t port, int32_t pid, const char *app); static void mndFreeConn(SConnObj *pConn); -static SConnObj *mndAcquireConn(SMnode *pMnode, int32_t connId, char *user, uint32_t ip, uint16_t port); +static SConnObj *mndAcquireConn(SMnode *pMnode, int32_t connId); static void mndReleaseConn(SMnode *pMnode, SConnObj *pConn); static void *mndGetNextConn(SMnode *pMnode, void *pIter, SConnObj **pConn); static void mndCancelGetNextConn(SMnode *pMnode, void *pIter); @@ -57,17 +57,17 @@ static int32_t mndProcessKillStreamMsg(SMnodeMsg *pMsg); static int32_t mndProcessKillConnectionMsg(SMnodeMsg *pMsg); static int32_t mndGetConnsMeta(SMnodeMsg *pMsg, SShowObj *pShow, STableMetaMsg *pMeta); static int32_t mndRetrieveConns(SMnodeMsg *pMsg, SShowObj *pShow, char *data, int32_t rows); -static int32_t mndGetQueryMeta(SMnodeMsg *pMsg, STableMetaMsg *pMeta, SShowObj *pShow); +static int32_t mndGetQueryMeta(SMnodeMsg *pMsg, SShowObj *pShow, STableMetaMsg *pMeta); static int32_t mndRetrieveQueries(SMnodeMsg *pMsg, SShowObj *pShow, char *data, int32_t rows); static void mndCancelGetNextQuery(SMnode *pMnode, void *pIter); -static int32_t mndGetStreamMeta(SMnodeMsg *pMsg, STableMetaMsg *pMeta, SShowObj *pShow); -static int32_t mndRetrieveStreams(SShowObj *pShow, char *data, int32_t rows, SMnodeMsg *pMsg); +static int32_t mndGetStreamMeta(SMnodeMsg *pMsg, SShowObj *pShow, STableMetaMsg *pMeta); +static int32_t mndRetrieveStreams(SMnodeMsg *pMsg, SShowObj *pShow, char *data, int32_t rows); static void mndCancelGetNextStream(SMnode *pMnode, void *pIter); int32_t mndInitProfile(SMnode *pMnode) { SProfileMgmt *pMgmt = &pMnode->profileMgmt; - int32_t connCheckTime = pMnode->shellActivityTimer * 2; + int32_t connCheckTime = pMnode->cfg.shellActivityTimer * 2; pMgmt->cache = taosCacheInit(TSDB_DATA_TYPE_INT, connCheckTime, true, (__cache_free_fn_t)mndFreeConn, "conn"); if (pMgmt->cache == NULL) { terrno = TSDB_CODE_OUT_OF_MEMORY; @@ -84,6 +84,12 @@ int32_t mndInitProfile(SMnode *pMnode) { mndAddShowMetaHandle(pMnode, TSDB_MGMT_TABLE_CONNS, mndGetConnsMeta); mndAddShowRetrieveHandle(pMnode, TSDB_MGMT_TABLE_CONNS, mndRetrieveConns); mndAddShowFreeIterHandle(pMnode, TSDB_MGMT_TABLE_CONNS, mndCancelGetNextConn); + mndAddShowMetaHandle(pMnode, TSDB_MGMT_TABLE_QUERIES, mndGetQueryMeta); + mndAddShowRetrieveHandle(pMnode, TSDB_MGMT_TABLE_QUERIES, mndRetrieveQueries); + mndAddShowFreeIterHandle(pMnode, TSDB_MGMT_TABLE_QUERIES, mndCancelGetNextQuery); + mndAddShowMetaHandle(pMnode, TSDB_MGMT_TABLE_STREAMS, mndGetStreamMeta); + mndAddShowRetrieveHandle(pMnode, TSDB_MGMT_TABLE_STREAMS, mndRetrieveStreams); + mndAddShowFreeIterHandle(pMnode, TSDB_MGMT_TABLE_STREAMS, mndCancelGetNextStream); return 0; } @@ -103,7 +109,7 @@ static SConnObj *mndCreateConn(SMnode *pMnode, char *user, uint32_t ip, uint16_t if (connId == 0) atomic_add_fetch_32(&pMgmt->connId, 1); SConnObj connObj = {.pid = pid, - .connId = connId, + .id = connId, .killed = 0, .port = port, .ip = ip, @@ -120,51 +126,45 @@ static SConnObj *mndCreateConn(SMnode *pMnode, char *user, uint32_t ip, uint16_t tstrncpy(connObj.user, user, TSDB_USER_LEN); tstrncpy(connObj.app, app, TSDB_APP_NAME_LEN); - int32_t keepTime = pMnode->shellActivityTimer * 3; + int32_t keepTime = pMnode->cfg.shellActivityTimer * 3; SConnObj *pConn = taosCachePut(pMgmt->cache, &connId, sizeof(int32_t), &connObj, sizeof(connObj), keepTime * 1000); - - mDebug("conn:%d, is created, user:%s", connId, user); - return pConn; + if (pConn == NULL) { + terrno = TSDB_CODE_OUT_OF_MEMORY; + mError("conn:%d, data:%p failed to put into cache since %s, user:%s", connId, pConn, user, terrstr()); + return NULL; + } else { + mTrace("conn:%d, data:%p created, user:%s", pConn->id, pConn, user); + return pConn; + } } static void mndFreeConn(SConnObj *pConn) { tfree(pConn->pQueries); tfree(pConn->pStreams); - tfree(pConn); - mDebug("conn:%d, is destroyed", pConn->connId); + mTrace("conn:%d, data:%p destroyed", pConn->id, pConn); } -static SConnObj *mndAcquireConn(SMnode *pMnode, int32_t connId, char *newUser, uint32_t newIp, uint16_t newPort) { +static SConnObj *mndAcquireConn(SMnode *pMnode, int32_t connId) { SProfileMgmt *pMgmt = &pMnode->profileMgmt; SConnObj *pConn = taosCacheAcquireByKey(pMgmt->cache, &connId, sizeof(int32_t)); if (pConn == NULL) { - mDebug("conn:%d, already destroyed, user:%s", connId, newUser); + mDebug("conn:%d, already destroyed", connId); return NULL; } - if (pConn->ip != newIp || pConn->port != newPort /* || strcmp(pConn->user, newUser) != 0 */) { - char oldIpStr[30]; - char newIpStr[30]; - taosIp2String(pConn->ip, oldIpStr); - taosIp2String(newIp, newIpStr); - mDebug("conn:%d, incoming conn user:%s ip:%s:%u, not match exist user:%s ip:%s:%u", connId, newUser, newIpStr, - newPort, pConn->user, oldIpStr, pConn->port); - - if (pMgmt->connId < connId) pMgmt->connId = connId + 1; - taosCacheRelease(pMgmt->cache, (void **)&pConn, false); - return NULL; - } - - int32_t keepTime = pMnode->shellActivityTimer * 3; + int32_t keepTime = pMnode->cfg.shellActivityTimer * 3; pConn->lastAccess = keepTime * 1000 + (uint64_t)taosGetTimestampMs(); + + mTrace("conn:%d, data:%p acquired from cache", pConn->id, pConn); return pConn; } static void mndReleaseConn(SMnode *pMnode, SConnObj *pConn) { - SProfileMgmt *pMgmt = &pMnode->profileMgmt; - if (pConn == NULL) return; + mTrace("conn:%d, data:%p released from cache", pConn->id, pConn); + + SProfileMgmt *pMgmt = &pMnode->profileMgmt; taosCacheRelease(pMgmt->cache, (void **)&pConn, false); } @@ -224,6 +224,7 @@ static int32_t mndProcessConnectMsg(SMnodeMsg *pMsg) { SConnectRsp *pRsp = rpcMallocCont(sizeof(SConnectRsp)); if (pRsp == NULL) { + mndReleaseConn(pMnode, pConn); terrno = TSDB_CODE_OUT_OF_MEMORY; mError("user:%s, failed to login from %s while create rsp since %s", pMsg->user, ip, terrstr()); return -1; @@ -239,12 +240,13 @@ static int32_t mndProcessConnectMsg(SMnodeMsg *pMsg) { } pRsp->clusterId = htonl(pMnode->clusterId); - pRsp->connId = htonl(pConn->connId); + pRsp->connId = htonl(pConn->id); mndGetMnodeEpSet(pMnode, &pRsp->epSet); + mndReleaseConn(pMnode, pConn); pMsg->contLen = sizeof(SConnectRsp); pMsg->pCont = pRsp; - mDebug("user:%s, login from %s, conn:%d", info.user, ip, pConn->connId); + mDebug("user:%s, login from %s, conn:%d", info.user, ip, pConn->id); return 0; } @@ -284,7 +286,9 @@ static int32_t mnodeSaveQueryStreamList(SConnObj *pConn, SHeartBeatMsg *pMsg) { } static int32_t mndProcessHeartBeatMsg(SMnodeMsg *pMsg) { - SMnode *pMnode = pMsg->pMnode; + SMnode *pMnode = pMsg->pMnode; + SProfileMgmt *pMgmt = &pMnode->profileMgmt; + SHeartBeatMsg *pReq = pMsg->rpcMsg.pCont; pReq->connId = htonl(pReq->connId); pReq->pid = htonl(pReq->pid); @@ -295,14 +299,32 @@ static int32_t mndProcessHeartBeatMsg(SMnodeMsg *pMsg) { return -1; } - SConnObj *pConn = mndAcquireConn(pMnode, pReq->connId, info.user, info.clientIp, info.clientPort); + SConnObj *pConn = mndAcquireConn(pMnode, pReq->connId); if (pConn == NULL) { pConn = mndCreateConn(pMnode, info.user, info.clientIp, info.clientPort, pReq->pid, pReq->app); if (pConn == NULL) { mError("user:%s, conn:%d is freed and failed to create new conn since %s", pMsg->user, pReq->connId, terrstr()); return -1; } else { - mDebug("user:%s, conn:%d is freed and create a new conn:%d", pMsg->user, pReq->connId, pConn->connId); + mDebug("user:%s, conn:%d is freed and create a new conn:%d", pMsg->user, pReq->connId, pConn->id); + } + } else if (pConn->killed) { + mError("user:%s, conn:%d is already killed", pMsg->user, pConn->id); + terrno = TSDB_CODE_MND_INVALID_CONNECTION; + return -1; + } else { + if (pConn->ip != info.clientIp || pConn->port != info.clientPort /* || strcmp(pConn->user, info.user) != 0 */) { + char oldIpStr[40]; + char newIpStr[40]; + taosIpPort2String(pConn->ip, pConn->port, oldIpStr); + taosIpPort2String(info.clientIp, info.clientPort, newIpStr); + mError("conn:%d, incoming conn user:%s ip:%s, not match exist user:%s ip:%s", pConn->id, info.user, newIpStr, + pConn->user, oldIpStr); + + if (pMgmt->connId < pConn->id) pMgmt->connId = pConn->id + 1; + taosCacheRelease(pMgmt->cache, (void **)&pConn, false); + terrno = TSDB_CODE_MND_INVALID_CONNECTION; + return -1; } } @@ -329,7 +351,7 @@ static int32_t mndProcessHeartBeatMsg(SMnodeMsg *pMsg) { pConn->queryId = 0; } - pRsp->connId = htonl(pConn->connId); + pRsp->connId = htonl(pConn->id); pRsp->totalDnodes = htonl(1); pRsp->onlineDnodes = htonl(1); mndGetMnodeEpSet(pMnode, &pRsp->epSet); @@ -354,28 +376,17 @@ static int32_t mndProcessKillQueryMsg(SMnodeMsg *pMsg) { mndReleaseUser(pMnode, pUser); SKillQueryMsg *pKill = pMsg->rpcMsg.pCont; - mInfo("kill query msg is received, queryId:%s", pKill->queryId); + int32_t connId = htonl(pKill->connId); + int32_t queryId = htonl(pKill->queryId); + mInfo("kill query msg is received, queryId:%d", pKill->queryId); - const char delim = ':'; - char *connIdStr = strtok(pKill->queryId, &delim); - char *queryIdStr = strtok(NULL, &delim); - - if (queryIdStr == NULL || connIdStr == NULL) { - mError("failed to kill query, queryId:%s", pKill->queryId); - terrno = TSDB_CODE_MND_INVALID_QUERY_ID; - return -1; - } - - int32_t queryId = (int32_t)strtol(queryIdStr, NULL, 10); - - int32_t connId = atoi(connIdStr); SConnObj *pConn = taosCacheAcquireByKey(pMgmt->cache, &connId, sizeof(int32_t)); if (pConn == NULL) { - mError("connId:%s, failed to kill queryId:%d, conn not exist", connIdStr, queryId); + mError("connId:%d, failed to kill queryId:%d, conn not exist", connId, queryId); terrno = TSDB_CODE_MND_INVALID_CONN_ID; return -1; } else { - mInfo("connId:%s, queryId:%d is killed by user:%s", connIdStr, queryId, pMsg->user); + mInfo("connId:%d, queryId:%d is killed by user:%s", connId, queryId, pMsg->user); pConn->queryId = queryId; taosCacheRelease(pMgmt->cache, (void **)&pConn, false); return 0; @@ -395,29 +406,18 @@ static int32_t mndProcessKillStreamMsg(SMnodeMsg *pMsg) { } mndReleaseUser(pMnode, pUser); - SKillQueryMsg *pKill = pMsg->rpcMsg.pCont; - mInfo("kill stream msg is received, streamId:%s", pKill->queryId); - - const char delim = ':'; - char *connIdStr = strtok(pKill->queryId, &delim); - char *streamIdStr = strtok(NULL, &delim); - - if (streamIdStr == NULL || connIdStr == NULL) { - mError("failed to kill stream, streamId:%s", pKill->queryId); - terrno = TSDB_CODE_MND_INVALID_STREAM_ID; - return -1; - } - - int32_t streamId = (int32_t)strtol(streamIdStr, NULL, 10); - int32_t connId = atoi(connIdStr); + SKillStreamMsg *pKill = pMsg->rpcMsg.pCont; + int32_t connId = htonl(pKill->connId); + int32_t streamId = htonl(pKill->streamId); + mDebug("kill stream msg is received, streamId:%d", streamId); SConnObj *pConn = taosCacheAcquireByKey(pMgmt->cache, &connId, sizeof(int32_t)); if (pConn == NULL) { - mError("connId:%s, failed to kill streamId:%d, conn not exist", connIdStr, streamId); + mError("connId:%d, failed to kill streamId:%d, conn not exist", connId, streamId); terrno = TSDB_CODE_MND_INVALID_CONN_ID; return -1; } else { - mInfo("connId:%s, streamId:%d is killed by user:%s", connIdStr, streamId, pMsg->user); + mInfo("connId:%d, streamId:%d is killed by user:%s", connId, streamId, pMsg->user); pConn->streamId = streamId; taosCacheRelease(pMgmt->cache, (void **)&pConn, false); return TSDB_CODE_SUCCESS; @@ -438,14 +438,15 @@ static int32_t mndProcessKillConnectionMsg(SMnodeMsg *pMsg) { mndReleaseUser(pMnode, pUser); SKillConnMsg *pKill = pMsg->rpcMsg.pCont; - int32_t connId = atoi(pKill->queryId); - SConnObj *pConn = taosCacheAcquireByKey(pMgmt->cache, &connId, sizeof(int32_t)); + int32_t connId = htonl(pKill->connId); + + SConnObj *pConn = taosCacheAcquireByKey(pMgmt->cache, &connId, sizeof(int32_t)); if (pConn == NULL) { - mError("connId:%s, failed to kill, conn not exist", pKill->queryId); + mError("connId:%d, failed to kill connection, conn not exist", connId); terrno = TSDB_CODE_MND_INVALID_CONN_ID; return -1; } else { - mInfo("connId:%s, is killed by user:%s", pKill->queryId, pMsg->user); + mInfo("connId:%d, is killed by user:%s", connId, pMsg->user); pConn->killed = 1; taosCacheRelease(pMgmt->cache, (void **)&pConn, false); return TSDB_CODE_SUCCESS; @@ -529,47 +530,47 @@ static int32_t mndGetConnsMeta(SMnodeMsg *pMsg, SShowObj *pShow, STableMetaMsg * static int32_t mndRetrieveConns(SMnodeMsg *pMsg, SShowObj *pShow, char *data, int32_t rows) { SMnode *pMnode = pMsg->pMnode; int32_t numOfRows = 0; - SConnObj *pConnObj = NULL; + SConnObj *pConn = NULL; int32_t cols = 0; char *pWrite; char ipStr[TSDB_IPv4ADDR_LEN + 6]; while (numOfRows < rows) { - pShow->pIter = mndGetNextConn(pMnode, pShow->pIter, &pConnObj); - if (pConnObj == NULL) break; + pShow->pIter = mndGetNextConn(pMnode, pShow->pIter, &pConn); + if (pConn == NULL) break; cols = 0; pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; - *(int32_t *)pWrite = pConnObj->connId; + *(int32_t *)pWrite = pConn->id; cols++; pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; - STR_WITH_MAXSIZE_TO_VARSTR(pWrite, pConnObj->user, pShow->bytes[cols]); + STR_WITH_MAXSIZE_TO_VARSTR(pWrite, pConn->user, pShow->bytes[cols]); cols++; // app name pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; - STR_WITH_MAXSIZE_TO_VARSTR(pWrite, pConnObj->app, pShow->bytes[cols]); + STR_WITH_MAXSIZE_TO_VARSTR(pWrite, pConn->app, pShow->bytes[cols]); cols++; // app pid pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; - *(int32_t *)pWrite = pConnObj->pid; + *(int32_t *)pWrite = pConn->pid; cols++; pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; - taosIpPort2String(pConnObj->ip, pConnObj->port, ipStr); + taosIpPort2String(pConn->ip, pConn->port, ipStr); STR_WITH_MAXSIZE_TO_VARSTR(pWrite, ipStr, pShow->bytes[cols]); cols++; pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; - *(int64_t *)pWrite = pConnObj->stime; + *(int64_t *)pWrite = pConn->stime; cols++; pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; - if (pConnObj->lastAccess < pConnObj->stime) pConnObj->lastAccess = pConnObj->stime; - *(int64_t *)pWrite = pConnObj->lastAccess; + if (pConn->lastAccess < pConn->stime) pConn->lastAccess = pConn->stime; + *(int64_t *)pWrite = pConn->lastAccess; cols++; numOfRows++; @@ -580,7 +581,7 @@ static int32_t mndRetrieveConns(SMnodeMsg *pMsg, SShowObj *pShow, char *data, in return numOfRows; } -static int32_t mndGetQueryMeta(SMnodeMsg *pMsg, STableMetaMsg *pMeta, SShowObj *pShow) { +static int32_t mndGetQueryMeta(SMnodeMsg *pMsg, SShowObj *pShow, STableMetaMsg *pMeta) { SMnode *pMnode = pMsg->pMnode; SProfileMgmt *pMgmt = &pMnode->profileMgmt; @@ -596,9 +597,15 @@ static int32_t mndGetQueryMeta(SMnodeMsg *pMsg, STableMetaMsg *pMeta, SShowObj * int32_t cols = 0; SSchema *pSchema = pMeta->schema; - pShow->bytes[cols] = QUERY_ID_SIZE + VARSTR_HEADER_SIZE; - pSchema[cols].type = TSDB_DATA_TYPE_BINARY; - strcpy(pSchema[cols].name, "query_id"); + pShow->bytes[cols] = 4; + pSchema[cols].type = TSDB_DATA_TYPE_INT; + strcpy(pSchema[cols].name, "queryId"); + pSchema[cols].bytes = htons(pShow->bytes[cols]); + cols++; + + pShow->bytes[cols] = 4; + pSchema[cols].type = TSDB_DATA_TYPE_INT; + strcpy(pSchema[cols].name, "connId"); pSchema[cols].bytes = htons(pShow->bytes[cols]); cols++; @@ -691,40 +698,43 @@ static int32_t mndGetQueryMeta(SMnodeMsg *pMsg, STableMetaMsg *pMeta, SShowObj * static int32_t mndRetrieveQueries(SMnodeMsg *pMsg, SShowObj *pShow, char *data, int32_t rows) { SMnode *pMnode = pMsg->pMnode; int32_t numOfRows = 0; - SConnObj *pConnObj = NULL; + SConnObj *pConn = NULL; int32_t cols = 0; char *pWrite; void *pIter; char str[TSDB_IPv4ADDR_LEN + 6] = {0}; while (numOfRows < rows) { - pIter = mndGetNextConn(pMnode, pShow->pIter, &pConnObj); - if (pConnObj == NULL) { + pIter = mndGetNextConn(pMnode, pShow->pIter, &pConn); + if (pConn == NULL) { pShow->pIter = pIter; break; } - if (numOfRows + pConnObj->numOfQueries >= rows) { + if (numOfRows + pConn->numOfQueries >= rows) { mndCancelGetNextConn(pMnode, pIter); break; } pShow->pIter = pIter; - for (int32_t i = 0; i < pConnObj->numOfQueries; ++i) { - SQueryDesc *pDesc = pConnObj->pQueries + i; + for (int32_t i = 0; i < pConn->numOfQueries; ++i) { + SQueryDesc *pDesc = pConn->pQueries + i; cols = 0; - snprintf(str, QUERY_ID_SIZE + 1, "%u:%u", pConnObj->connId, htonl(pDesc->queryId)); pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; - STR_WITH_MAXSIZE_TO_VARSTR(pWrite, str, pShow->bytes[cols]); + *(int64_t *)pWrite = htobe64(pDesc->queryId); cols++; pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; - STR_WITH_MAXSIZE_TO_VARSTR(pWrite, pConnObj->user, pShow->bytes[cols]); + *(int64_t *)pWrite = htobe64(pConn->id); cols++; pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; - snprintf(str, tListLen(str), "%s:%u", taosIpStr(pConnObj->ip), pConnObj->port); + STR_WITH_MAXSIZE_TO_VARSTR(pWrite, pConn->user, pShow->bytes[cols]); + cols++; + + pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; + snprintf(str, tListLen(str), "%s:%u", taosIpStr(pConn->ip), pConn->port); STR_WITH_MAXSIZE_TO_VARSTR(pWrite, str, pShow->bytes[cols]); cols++; @@ -753,7 +763,7 @@ static int32_t mndRetrieveQueries(SMnodeMsg *pMsg, SShowObj *pShow, char *data, cols++; char epBuf[TSDB_EP_LEN + 1] = {0}; - snprintf(epBuf, tListLen(epBuf), "%s:%u", pDesc->fqdn, pConnObj->port); + snprintf(epBuf, tListLen(epBuf), "%s:%u", pDesc->fqdn, pConn->port); pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; STR_WITH_MAXSIZE_TO_VARSTR(pWrite, epBuf, pShow->bytes[cols]); cols++; @@ -787,7 +797,7 @@ static void mndCancelGetNextQuery(SMnode *pMnode, void *pIter) { taosHashCancelIterate(pMgmt->cache->pHashTable, pIter); } -static int32_t mndGetStreamMeta(SMnodeMsg *pMsg, STableMetaMsg *pMeta, SShowObj *pShow) { +static int32_t mndGetStreamMeta(SMnodeMsg *pMsg, SShowObj *pShow, STableMetaMsg *pMeta) { SMnode *pMnode = pMsg->pMnode; SProfileMgmt *pMgmt = &pMnode->profileMgmt; @@ -803,12 +813,18 @@ static int32_t mndGetStreamMeta(SMnodeMsg *pMsg, STableMetaMsg *pMeta, SShowObj int32_t cols = 0; SSchema *pSchema = pMeta->schema; - pShow->bytes[cols] = QUERY_ID_SIZE + VARSTR_HEADER_SIZE; - pSchema[cols].type = TSDB_DATA_TYPE_BINARY; + pShow->bytes[cols] = 4; + pSchema[cols].type = TSDB_DATA_TYPE_INT; strcpy(pSchema[cols].name, "streamId"); pSchema[cols].bytes = htons(pShow->bytes[cols]); cols++; + pShow->bytes[cols] = 4; + pSchema[cols].type = TSDB_DATA_TYPE_INT; + strcpy(pSchema[cols].name, "connId"); + pSchema[cols].bytes = htons(pShow->bytes[cols]); + cols++; + pShow->bytes[cols] = TSDB_USER_LEN + VARSTR_HEADER_SIZE; pSchema[cols].type = TSDB_DATA_TYPE_BINARY; strcpy(pSchema[cols].name, "user"); @@ -871,39 +887,42 @@ static int32_t mndGetStreamMeta(SMnodeMsg *pMsg, STableMetaMsg *pMeta, SShowObj return 0; } -static int32_t mndRetrieveStreams(SShowObj *pShow, char *data, int32_t rows, SMnodeMsg *pMsg) { +static int32_t mndRetrieveStreams(SMnodeMsg *pMsg, SShowObj *pShow, char *data, int32_t rows) { SMnode *pMnode = pMsg->pMnode; int32_t numOfRows = 0; - SConnObj *pConnObj = NULL; + SConnObj *pConn = NULL; int32_t cols = 0; char *pWrite; void *pIter; char ipStr[TSDB_IPv4ADDR_LEN + 6]; while (numOfRows < rows) { - pIter = mndGetNextConn(pMnode, pShow->pIter, &pConnObj); - if (pConnObj == NULL) { + pIter = mndGetNextConn(pMnode, pShow->pIter, &pConn); + if (pConn == NULL) { pShow->pIter = pIter; break; } - if (numOfRows + pConnObj->numOfStreams >= rows) { + if (numOfRows + pConn->numOfStreams >= rows) { mndCancelGetNextConn(pMnode, pIter); break; } pShow->pIter = pIter; - for (int32_t i = 0; i < pConnObj->numOfStreams; ++i) { - SStreamDesc *pDesc = pConnObj->pStreams + i; + for (int32_t i = 0; i < pConn->numOfStreams; ++i) { + SStreamDesc *pDesc = pConn->pStreams + i; cols = 0; - snprintf(ipStr, QUERY_ID_SIZE + 1, "%u:%u", pConnObj->connId, htonl(pDesc->streamId)); pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; - STR_WITH_MAXSIZE_TO_VARSTR(pWrite, ipStr, pShow->bytes[cols]); + *(int64_t *)pWrite = htobe64(pDesc->streamId); cols++; pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; - STR_WITH_MAXSIZE_TO_VARSTR(pWrite, pConnObj->user, pShow->bytes[cols]); + *(int64_t *)pWrite = htobe64(pConn->id); + cols++; + + pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; + STR_WITH_MAXSIZE_TO_VARSTR(pWrite, pConn->user, pShow->bytes[cols]); cols++; pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; @@ -911,7 +930,7 @@ static int32_t mndRetrieveStreams(SShowObj *pShow, char *data, int32_t rows, SMn cols++; pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows; - snprintf(ipStr, sizeof(ipStr), "%s:%u", taosIpStr(pConnObj->ip), pConnObj->port); + snprintf(ipStr, sizeof(ipStr), "%s:%u", taosIpStr(pConn->ip), pConn->port); STR_WITH_MAXSIZE_TO_VARSTR(pWrite, ipStr, pShow->bytes[cols]); cols++; diff --git a/source/dnode/mnode/impl/src/mndShow.c b/source/dnode/mnode/impl/src/mndShow.c index e652f94957..747ea39237 100644 --- a/source/dnode/mnode/impl/src/mndShow.c +++ b/source/dnode/mnode/impl/src/mndShow.c @@ -16,19 +16,19 @@ #define _DEFAULT_SOURCE #include "mndShow.h" -static int32_t mndProcessShowMsg(SMnodeMsg *pMnodeMsg); -static int32_t mndProcessRetrieveMsg( SMnodeMsg *pMsg); -static bool mndCheckRetrieveFinished(SShowObj *pShow); -static int32_t mndAcquireShowObj(SMnode *pMnode, SShowObj *pShow); -static void mndReleaseShowObj(SShowObj *pShow, bool forceRemove); -static int32_t mndPutShowObj(SMnode *pMnode, SShowObj *pShow); -static void mndFreeShowObj(void *ppShow); -static char *mndShowStr(int32_t showType); +static SShowObj *mndCreateShowObj(SMnode *pMnode, SShowMsg *pMsg); +static void mndFreeShowObj(SShowObj *pShow); +static SShowObj *mndAcquireShowObj(SMnode *pMnode, int32_t showId); +static void mndReleaseShowObj(SShowObj *pShow, bool forceRemove); +static char *mndShowStr(int32_t showType); +static int32_t mndProcessShowMsg(SMnodeMsg *pMnodeMsg); +static int32_t mndProcessRetrieveMsg(SMnodeMsg *pMsg); +static bool mndCheckRetrieveFinished(SShowObj *pShow); int32_t mndInitShow(SMnode *pMnode) { SShowMgmt *pMgmt = &pMnode->showMgmt; - pMgmt->cache = taosCacheInit(TSDB_CACHE_PTR_KEY, 5, true, mndFreeShowObj, "show"); + pMgmt->cache = taosCacheInit(TSDB_DATA_TYPE_INT, 5, true, (__cache_free_fn_t)mndFreeShowObj, "show"); if (pMgmt->cache == NULL) { terrno = TSDB_CODE_OUT_OF_MEMORY; mError("failed to alloc show cache since %s", terrstr()); @@ -48,47 +48,41 @@ void mndCleanupShow(SMnode *pMnode) { } } -static int32_t mndAcquireShowObj(SMnode *pMnode, SShowObj *pShow) { - TSDB_CACHE_PTR_TYPE handleVal = (TSDB_CACHE_PTR_TYPE)pShow; - +static SShowObj *mndCreateShowObj(SMnode *pMnode, SShowMsg *pMsg) { SShowMgmt *pMgmt = &pMnode->showMgmt; - SShowObj **ppShow = taosCacheAcquireByKey(pMgmt->cache, &handleVal, sizeof(TSDB_CACHE_PTR_TYPE)); - if (ppShow) { - mTrace("show:%d, data:%p acquired from cache", pShow->id, ppShow); - return 0; - } - return -1; -} + int32_t showId = atomic_add_fetch_32(&pMgmt->showId, 1); + if (showId == 0) atomic_add_fetch_32(&pMgmt->showId, 1); -static void mndReleaseShowObj(SShowObj *pShow, bool forceRemove) { - SMnode *pMnode = pShow->pMnode; - SShowMgmt *pMgmt = &pMnode->showMgmt; - SShowObj **ppShow = (SShowObj **)pShow->ppShow; - taosCacheRelease(pMgmt->cache, (void **)(&ppShow), forceRemove); - mDebug("show:%d, data:%p released from cache, force:%d", pShow->id, ppShow, forceRemove); -} - -static int32_t mndPutShowObj(SMnode *pMnode, SShowObj *pShow) { - SShowMgmt *pMgmt = &pMnode->showMgmt; - int32_t lifeSpan = pMnode->shellActivityTimer * 6 * 1000; - - TSDB_CACHE_PTR_TYPE val = (TSDB_CACHE_PTR_TYPE)pShow; - pShow->id = atomic_add_fetch_32(&pMgmt->showId, 1); - SShowObj **ppShow = - taosCachePut(pMgmt->cache, &val, sizeof(TSDB_CACHE_PTR_TYPE), &pShow, sizeof(TSDB_CACHE_PTR_TYPE), lifeSpan); - if (ppShow == NULL) { + int32_t size = sizeof(SShowObj) + pMsg->payloadLen; + SShowObj *pShow = calloc(1, size); + if (pShow != NULL) { + pShow->id = showId; + pShow->pMnode = pMnode; + pShow->type = pMsg->type; + pShow->payloadLen = pMsg->payloadLen; + memcpy(pShow->db, pMsg->db, TSDB_FULL_DB_NAME_LEN); + memcpy(pShow->payload, pMsg->payload, pMsg->payloadLen); + } else { terrno = TSDB_CODE_OUT_OF_MEMORY; - mError("show:%d, failed to put into cache", pShow->id); - return -1; + mError("failed to process show-meta msg:%s since %s", mndShowStr(pMsg->type), terrstr()); + return NULL; } - mTrace("show:%d, data:%p put into cache", pShow->id, ppShow); - return 0; + int32_t keepTime = pMnode->cfg.shellActivityTimer * 6 * 1000; + SShowObj *pShowRet = taosCachePut(pMgmt->cache, &showId, sizeof(int32_t), pShow, size, keepTime); + free(pShow); + if (pShowRet == NULL) { + terrno = TSDB_CODE_OUT_OF_MEMORY; + mError("show:%d, failed to put into cache since %s", showId, terrstr()); + return NULL; + } else { + mTrace("show:%d, data:%p created", showId, pShowRet); + return pShowRet; + } } -static void mndFreeShowObj(void *ppShow) { - SShowObj *pShow = *(SShowObj **)ppShow; +static void mndFreeShowObj(SShowObj *pShow) { SMnode *pMnode = pShow->pMnode; SShowMgmt *pMgmt = &pMnode->showMgmt; @@ -103,8 +97,32 @@ static void mndFreeShowObj(void *ppShow) { } } - mDebug("show:%d, data:%p destroyed", pShow->id, ppShow); - tfree(pShow); + mTrace("show:%d, data:%p destroyed", pShow->id, pShow); +} + +static SShowObj *mndAcquireShowObj(SMnode *pMnode, int32_t showId) { + SShowMgmt *pMgmt = &pMnode->showMgmt; + + SShowObj *pShow = taosCacheAcquireByKey(pMgmt->cache, &showId, sizeof(int32_t)); + if (pShow == NULL) { + mError("show:%d, already destroyed", showId); + return NULL; + } + + mTrace("show:%d, data:%p acquired from cache", pShow->id, pShow); + return pShow; +} + +static void mndReleaseShowObj(SShowObj *pShow, bool forceRemove) { + if (pShow == NULL) return; + mTrace("show:%d, data:%p released from cache, force:%d", pShow->id, pShow, forceRemove); + + // A bug in tcache.c + forceRemove = 0; + + SMnode *pMnode = pShow->pMnode; + SShowMgmt *pMgmt = &pMnode->showMgmt; + taosCacheRelease(pMgmt->cache, (void **)(&pShow), forceRemove); } static int32_t mndProcessShowMsg(SMnodeMsg *pMnodeMsg) { @@ -112,7 +130,7 @@ static int32_t mndProcessShowMsg(SMnodeMsg *pMnodeMsg) { SShowMgmt *pMgmt = &pMnode->showMgmt; SShowMsg *pMsg = pMnodeMsg->rpcMsg.pCont; int8_t type = pMsg->type; - uint16_t payloadLen = htonl(pMsg->payloadLen); + int16_t payloadLen = htonl(pMsg->payloadLen); if (type <= TSDB_MGMT_TABLE_START || type >= TSDB_MGMT_TABLE_MAX) { terrno = TSDB_CODE_MND_INVALID_MSG_TYPE; @@ -127,27 +145,13 @@ static int32_t mndProcessShowMsg(SMnodeMsg *pMnodeMsg) { return -1; } - int32_t size = sizeof(SShowObj) + payloadLen; - SShowObj *pShow = calloc(1, size); - if (pShow != NULL) { - pShow->pMnode = pMnode; - pShow->type = type; - pShow->payloadLen = payloadLen; - memcpy(pShow->db, pMsg->db, TSDB_FULL_DB_NAME_LEN); - memcpy(pShow->payload, pMsg->payload, payloadLen); - } else { - terrno = TSDB_CODE_OUT_OF_MEMORY; + SShowObj *pShow = mndCreateShowObj(pMnode, pMsg); + if (pShow == NULL) { mError("failed to process show-meta msg:%s since %s", mndShowStr(type), terrstr()); return -1; } - if (mndPutShowObj(pMnode, pShow) == 0) { - mError("failed to process show-meta msg:%s since %s", mndShowStr(type), terrstr()); - free(pShow); - return -1; - } - - size = sizeof(SShowRsp) + sizeof(SSchema) * TSDB_MAX_COLUMNS + TSDB_EXTRA_PAYLOAD_SIZE; + int32_t size = sizeof(SShowRsp) + sizeof(SSchema) * TSDB_MAX_COLUMNS + TSDB_EXTRA_PAYLOAD_SIZE; SShowRsp *pRsp = rpcMallocCont(size); if (pRsp == NULL) { mndReleaseShowObj(pShow, true); @@ -156,15 +160,14 @@ static int32_t mndProcessShowMsg(SMnodeMsg *pMnodeMsg) { return -1; } - pRsp->qhandle = htobe64((uint64_t)pShow); - - int32_t code = (*metaFp)(pMnodeMsg,pShow, &pRsp->tableMeta); - mDebug("show:%d, type:%s, get meta finished, numOfRows:%d cols:%d result:%s", pShow->id, mndShowStr(type), - pShow->numOfRows, pShow->numOfColumns, tstrerror(code)); + int32_t code = (*metaFp)(pMnodeMsg, pShow, &pRsp->tableMeta); + mDebug("show:%d, data:%p get meta finished, numOfRows:%d cols:%d type:%s result:%s", pShow->id, pShow, + pShow->numOfRows, pShow->numOfColumns, mndShowStr(type), tstrerror(code)); if (code == TSDB_CODE_SUCCESS) { pMnodeMsg->contLen = sizeof(SShowRsp) + sizeof(SSchema) * pShow->numOfColumns; pMnodeMsg->pCont = pRsp; + pRsp->showId = htonl(pShow->id); mndReleaseShowObj(pShow, false); return TSDB_CODE_SUCCESS; } else { @@ -182,14 +185,10 @@ static int32_t mndProcessRetrieveMsg(SMnodeMsg *pMnodeMsg) { int32_t rowsRead = 0; SRetrieveTableMsg *pRetrieve = pMnodeMsg->rpcMsg.pCont; - pRetrieve->qhandle = htobe64(pRetrieve->qhandle); - SShowObj *pShow = (SShowObj *)pRetrieve->qhandle; + int32_t showId = htonl(pRetrieve->showId); - /* - * in case of server restart, apps may hold qhandle created by server before - * restart, which is actually invalid, therefore, signature check is required. - */ - if (mndAcquireShowObj(pMnode, pShow) != 0) { + SShowObj *pShow = mndAcquireShowObj(pMnode, showId); + if (pShow == NULL) { terrno = TSDB_CODE_MND_INVALID_SHOWOBJ; mError("failed to process show-retrieve msg:%p since %s", pShow, terrstr()); return -1; @@ -199,15 +198,16 @@ static int32_t mndProcessRetrieveMsg(SMnodeMsg *pMnodeMsg) { if (retrieveFp == NULL) { mndReleaseShowObj(pShow, false); terrno = TSDB_CODE_MSG_NOT_PROCESSED; - mError("show:%d, failed to retrieve data since %s", pShow->id, terrstr()); + mError("show:%d, data:%p failed to retrieve data since %s", pShow->id, pShow, terrstr()); return -1; } - mDebug("show:%d, type:%s, start retrieve data, numOfReads:%d numOfRows:%d", pShow->id, mndShowStr(pShow->type), - pShow->numOfReads, pShow->numOfRows); + mDebug("show:%d, data:%p start retrieve data, numOfReads:%d numOfRows:%d type:%s", pShow->id, pShow, + pShow->numOfReads, pShow->numOfRows, mndShowStr(pShow->type)); if (mndCheckRetrieveFinished(pShow)) { - mDebug("show:%d, read finished, numOfReads:%d numOfRows:%d", pShow->id, pShow->numOfReads, pShow->numOfRows); + mDebug("show:%d, data:%p read finished, numOfReads:%d numOfRows:%d", pShow->id, pShow, pShow->numOfReads, + pShow->numOfRows); pShow->numOfReads = pShow->numOfRows; } @@ -230,7 +230,7 @@ static int32_t mndProcessRetrieveMsg(SMnodeMsg *pMnodeMsg) { if (pRsp == NULL) { mndReleaseShowObj(pShow, false); terrno = TSDB_CODE_OUT_OF_MEMORY; - mError("show:%d, failed to retrieve data since %s", pShow->id, terrstr()); + mError("show:%d, data:%p failed to retrieve data since %s", pShow->id, pShow, terrstr()); return -1; } @@ -239,20 +239,20 @@ static int32_t mndProcessRetrieveMsg(SMnodeMsg *pMnodeMsg) { rowsRead = (*retrieveFp)(pMnodeMsg, pShow, pRsp->data, rowsToRead); } - mDebug("show:%d, stop retrieve data, rowsRead:%d rowsToRead:%d", pShow->id, rowsRead, rowsToRead); + mDebug("show:%d, data:%p stop retrieve data, rowsRead:%d rowsToRead:%d", pShow->id, pShow, rowsRead, rowsToRead); pRsp->numOfRows = htonl(rowsRead); - pRsp->precision = (int16_t)htonl(TSDB_TIME_PRECISION_MILLI); // millisecond time precision + pRsp->precision = TSDB_TIME_PRECISION_MILLI; // millisecond time precision pMnodeMsg->pCont = pRsp; pMnodeMsg->contLen = size; - if (rowsToRead == 0 || (rowsRead == rowsToRead && pShow->numOfRows == pShow->numOfReads)) { + if (rowsRead == 0 || rowsToRead == 0 || (rowsRead == rowsToRead && pShow->numOfRows == pShow->numOfReads)) { pRsp->completed = 1; - mDebug("%p, retrieve completed", pShow); + mDebug("show:%d, data:%p retrieve completed", pShow->id, pShow); mndReleaseShowObj(pShow, true); } else { - mDebug("%p, retrieve not completed yet", pShow); + mDebug("show:%d, data:%p retrieve not completed yet", pShow->id, pShow); mndReleaseShowObj(pShow, false); } @@ -307,7 +307,7 @@ static char *mndShowStr(int32_t showType) { static bool mndCheckRetrieveFinished(SShowObj *pShow) { if (pShow->pIter == NULL && pShow->numOfReads != 0) { return true; - } + } return false; } diff --git a/source/dnode/mnode/impl/src/mndTelem.c b/source/dnode/mnode/impl/src/mndTelem.c index f9f349aad8..663ae76506 100644 --- a/source/dnode/mnode/impl/src/mndTelem.c +++ b/source/dnode/mnode/impl/src/mndTelem.c @@ -15,27 +15,15 @@ #define _DEFAULT_SOURCE #include "mndTelem.h" -#include "tbuffer.h" -#include "tglobal.h" +#include "mndCluster.h" #include "mndSync.h" +#include "tbuffer.h" +#include "tversion.h" #define TELEMETRY_SERVER "telemetry.taosdata.com" #define TELEMETRY_PORT 80 #define REPORT_INTERVAL 86400 -/* - * sem_timedwait is NOT implemented on MacOSX - * thus we use pthread_mutex_t/pthread_cond_t to simulate - */ -static struct { - bool enable; - pthread_mutex_t lock; - pthread_cond_t cond; - volatile int32_t exit; - pthread_t thread; - char email[TSDB_FQDN_LEN]; -} tsTelem; - static void mndBeginObject(SBufferWriter* bw) { tbufWriteChar(bw, '{'); } static void mndCloseObject(SBufferWriter* bw) { @@ -86,7 +74,7 @@ static void mndAddStringField(SBufferWriter* bw, const char* k, const char* v) { tbufWriteChar(bw, ','); } -static void mndAddCpuInfo(SBufferWriter* bw) { +static void mndAddCpuInfo(SMnode* pMnode, SBufferWriter* bw) { char* line = NULL; size_t size = 0; int32_t done = 0; @@ -116,7 +104,7 @@ static void mndAddCpuInfo(SBufferWriter* bw) { fclose(fp); } -static void mndAddOsInfo(SBufferWriter* bw) { +static void mndAddOsInfo(SMnode* pMnode, SBufferWriter* bw) { char* line = NULL; size_t size = 0; @@ -142,7 +130,7 @@ static void mndAddOsInfo(SBufferWriter* bw) { fclose(fp); } -static void mndAddMemoryInfo(SBufferWriter* bw) { +static void mndAddMemoryInfo(SMnode* pMnode, SBufferWriter* bw) { char* line = NULL; size_t size = 0; @@ -165,16 +153,21 @@ static void mndAddMemoryInfo(SBufferWriter* bw) { fclose(fp); } -static void mndAddVersionInfo(SBufferWriter* bw) { - mndAddStringField(bw, "version", version); - mndAddStringField(bw, "buildInfo", buildinfo); - mndAddStringField(bw, "gitInfo", gitinfo); - mndAddStringField(bw, "email", tsTelem.email); +static void mndAddVersionInfo(SMnode* pMnode, SBufferWriter* bw) { + STelemMgmt* pMgmt = &pMnode->telemMgmt; + + char vstr[32] = {0}; + taosVersionIntToStr(pMnode->cfg.sver, vstr, 32); + + mndAddStringField(bw, "version", vstr); + mndAddStringField(bw, "buildInfo", pMnode->cfg.buildinfo); + mndAddStringField(bw, "gitInfo", pMnode->cfg.gitinfo); + mndAddStringField(bw, "email", pMgmt->email); } -static void mndAddRuntimeInfo(SBufferWriter* bw) { +static void mndAddRuntimeInfo(SMnode* pMnode, SBufferWriter* bw) { SMnodeLoad load = {0}; - if (mndGetLoad(NULL, &load) != 0) { + if (mndGetLoad(pMnode, &load) != 0) { return; } @@ -190,11 +183,13 @@ static void mndAddRuntimeInfo(SBufferWriter* bw) { mndAddIntField(bw, "compStorage", load.compStorage); } -static void mndSendTelemetryReport() { +static void mndSendTelemetryReport(SMnode* pMnode) { + STelemMgmt* pMgmt = &pMnode->telemMgmt; + char buf[128] = {0}; uint32_t ip = taosGetIpv4FromFqdn(TELEMETRY_SERVER); if (ip == 0xffffffff) { - mTrace("failed to get IP address of " TELEMETRY_SERVER ", reason:%s", strerror(errno)); + mTrace("failed to get IP address of " TELEMETRY_SERVER " since :%s", strerror(errno)); return; } SOCKET fd = taosOpenTcpClientSocket(ip, TELEMETRY_PORT, 0); @@ -203,19 +198,18 @@ static void mndSendTelemetryReport() { return; } - int32_t clusterId = 0; - char clusterIdStr[20] = {0}; - snprintf(clusterIdStr, sizeof(clusterIdStr), "%d", clusterId); + char clusterName[64] = {0}; + mndGetClusterName(pMnode, clusterName, sizeof(clusterName)); SBufferWriter bw = tbufInitWriter(NULL, false); mndBeginObject(&bw); - mndAddStringField(&bw, "instanceId", clusterIdStr); + mndAddStringField(&bw, "instanceId", clusterName); mndAddIntField(&bw, "reportVersion", 1); - mndAddOsInfo(&bw); - mndAddCpuInfo(&bw); - mndAddMemoryInfo(&bw); - mndAddVersionInfo(&bw); - mndAddRuntimeInfo(&bw); + mndAddOsInfo(pMnode, &bw); + mndAddCpuInfo(pMnode, &bw); + mndAddMemoryInfo(pMnode, &bw); + mndAddVersionInfo(pMnode, &bw); + mndAddRuntimeInfo(pMnode, &bw); mndCloseObject(&bw); const char* header = @@ -241,23 +235,26 @@ static void mndSendTelemetryReport() { } static void* mndTelemThreadFp(void* param) { + SMnode* pMnode = param; + STelemMgmt* pMgmt = &pMnode->telemMgmt; + struct timespec end = {0}; clock_gettime(CLOCK_REALTIME, &end); end.tv_sec += 300; // wait 5 minutes before send first report setThreadName("mnd-telem"); - while (!tsTelem.exit) { + while (!pMgmt->exit) { int32_t r = 0; struct timespec ts = end; - pthread_mutex_lock(&tsTelem.lock); - r = pthread_cond_timedwait(&tsTelem.cond, &tsTelem.lock, &ts); - pthread_mutex_unlock(&tsTelem.lock); + pthread_mutex_lock(&pMgmt->lock); + r = pthread_cond_timedwait(&pMgmt->cond, &pMgmt->lock, &ts); + pthread_mutex_unlock(&pMgmt->lock); if (r == 0) break; if (r != ETIMEDOUT) continue; - if (mndIsMaster(NULL)) { - mndSendTelemetryReport(); + if (mndIsMaster(pMnode)) { + mndSendTelemetryReport(pMnode); } end.tv_sec += REPORT_INTERVAL; } @@ -265,35 +262,39 @@ static void* mndTelemThreadFp(void* param) { return NULL; } -static void mndGetEmail(char* filepath) { +static void mndGetEmail(SMnode* pMnode, char* filepath) { + STelemMgmt* pMgmt = &pMnode->telemMgmt; + int32_t fd = taosOpenFileRead(filepath); if (fd < 0) { return; } - if (taosReadFile(fd, (void*)tsTelem.email, TSDB_FQDN_LEN) < 0) { + if (taosReadFile(fd, (void*)pMgmt->email, TSDB_FQDN_LEN) < 0) { mError("failed to read %d bytes from file %s since %s", TSDB_FQDN_LEN, filepath, strerror(errno)); } taosCloseFile(fd); } -int32_t mndInitTelem(SMnode *pMnode) { - tsTelem.enable = tsEnableTelemetryReporting; - if (!tsTelem.enable) return 0; +int32_t mndInitTelem(SMnode* pMnode) { + STelemMgmt* pMgmt = &pMnode->telemMgmt; + pMgmt->enable = pMnode->cfg.enableTelem; - tsTelem.exit = 0; - pthread_mutex_init(&tsTelem.lock, NULL); - pthread_cond_init(&tsTelem.cond, NULL); - tsTelem.email[0] = 0; + if (!pMgmt->enable) return 0; - mndGetEmail("/usr/local/taos/email"); + pMgmt->exit = 0; + pthread_mutex_init(&pMgmt->lock, NULL); + pthread_cond_init(&pMgmt->cond, NULL); + pMgmt->email[0] = 0; + + mndGetEmail(pMnode, "/usr/local/taos/email"); pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); - int32_t code = pthread_create(&tsTelem.thread, &attr, mndTelemThreadFp, NULL); + int32_t code = pthread_create(&pMgmt->thread, &attr, mndTelemThreadFp, pMnode); pthread_attr_destroy(&attr); if (code != 0) { mTrace("failed to create telemetry thread since :%s", strerror(code)); @@ -303,18 +304,19 @@ int32_t mndInitTelem(SMnode *pMnode) { return 0; } -void mndCleanupTelem(SMnode *pMnode) { - if (!tsTelem.enable) return; +void mndCleanupTelem(SMnode* pMnode) { + STelemMgmt* pMgmt = &pMnode->telemMgmt; + if (!pMgmt->enable) return; - if (taosCheckPthreadValid(tsTelem.thread)) { - pthread_mutex_lock(&tsTelem.lock); - tsTelem.exit = 1; - pthread_cond_signal(&tsTelem.cond); - pthread_mutex_unlock(&tsTelem.lock); + if (taosCheckPthreadValid(pMgmt->thread)) { + pthread_mutex_lock(&pMgmt->lock); + pMgmt->exit = 1; + pthread_cond_signal(&pMgmt->cond); + pthread_mutex_unlock(&pMgmt->lock); - pthread_join(tsTelem.thread, NULL); + pthread_join(pMgmt->thread, NULL); } - pthread_mutex_destroy(&tsTelem.lock); - pthread_cond_destroy(&tsTelem.cond); + pthread_mutex_destroy(&pMgmt->lock); + pthread_cond_destroy(&pMgmt->cond); } diff --git a/source/dnode/mnode/impl/src/mnode.c b/source/dnode/mnode/impl/src/mnode.c index b99de4a019..2fa0838ee8 100644 --- a/source/dnode/mnode/impl/src/mnode.c +++ b/source/dnode/mnode/impl/src/mnode.c @@ -203,22 +203,25 @@ static int32_t mndSetOptions(SMnode *pMnode, const SMnodeOpt *pOption) { pMnode->sendMsgToDnodeFp = pOption->sendMsgToDnodeFp; pMnode->sendMsgToMnodeFp = pOption->sendMsgToMnodeFp; pMnode->sendRedirectMsgFp = pOption->sendRedirectMsgFp; - pMnode->sver = pOption->sver; - pMnode->statusInterval = pOption->statusInterval; - pMnode->mnodeEqualVnodeNum = pOption->mnodeEqualVnodeNum; - pMnode->shellActivityTimer = pOption->shellActivityTimer; - pMnode->timezone = strdup(pOption->timezone); - pMnode->locale = strdup(pOption->locale); - pMnode->charset = strdup(pOption->charset); + pMnode->cfg.sver = pOption->cfg.sver; + pMnode->cfg.enableTelem = pOption->cfg.enableTelem; + pMnode->cfg.statusInterval = pOption->cfg.statusInterval; + pMnode->cfg.mnodeEqualVnodeNum = pOption->cfg.mnodeEqualVnodeNum; + pMnode->cfg.shellActivityTimer = pOption->cfg.shellActivityTimer; + pMnode->cfg.timezone = strdup(pOption->cfg.timezone); + pMnode->cfg.locale = strdup(pOption->cfg.locale); + pMnode->cfg.charset = strdup(pOption->cfg.charset); + pMnode->cfg.gitinfo = strdup(pOption->cfg.gitinfo); + pMnode->cfg.buildinfo = strdup(pOption->cfg.buildinfo); if (pMnode->sendMsgToDnodeFp == NULL || pMnode->sendMsgToMnodeFp == NULL || pMnode->sendRedirectMsgFp == NULL || pMnode->putMsgToApplyMsgFp == NULL || pMnode->dnodeId < 0 || pMnode->clusterId < 0 || - pMnode->statusInterval < 1 || pOption->mnodeEqualVnodeNum < 0) { + pMnode->cfg.statusInterval < 1 || pOption->cfg.mnodeEqualVnodeNum < 0) { terrno = TSDB_CODE_MND_INVALID_OPTIONS; return -1; } - if (pMnode->timezone == NULL || pMnode->locale == NULL || pMnode->charset == NULL) { + if (pMnode->cfg.timezone == NULL || pMnode->cfg.locale == NULL || pMnode->cfg.charset == NULL) { terrno = TSDB_CODE_OUT_OF_MEMORY; return -1; } @@ -289,9 +292,11 @@ void mndClose(SMnode *pMnode) { mDebug("start to close mnode"); mndCleanupSteps(pMnode, -1); tfree(pMnode->path); - tfree(pMnode->charset); - tfree(pMnode->locale); - tfree(pMnode->timezone); + tfree(pMnode->cfg.charset); + tfree(pMnode->cfg.locale); + tfree(pMnode->cfg.timezone); + tfree(pMnode->cfg.gitinfo); + tfree(pMnode->cfg.buildinfo); tfree(pMnode); mDebug("mnode is closed"); } diff --git a/source/libs/executor/inc/executorimpl.h b/source/libs/executor/inc/executorimpl.h index a99717a123..907fb4d2bf 100644 --- a/source/libs/executor/inc/executorimpl.h +++ b/source/libs/executor/inc/executorimpl.h @@ -279,34 +279,6 @@ enum { OP_EXEC_DONE = 3, }; -enum OPERATOR_TYPE_E { - OP_TableScan = 1, - OP_DataBlocksOptScan = 2, - OP_TableSeqScan = 3, - OP_TagScan = 4, - OP_TableBlockInfoScan= 5, - OP_Aggregate = 6, - OP_Project = 7, - OP_Groupby = 8, - OP_Limit = 9, - OP_SLimit = 10, - OP_TimeWindow = 11, - OP_SessionWindow = 12, - OP_Fill = 13, - OP_MultiTableAggregate = 14, - OP_MultiTableTimeInterval = 15, - OP_DummyInput = 16, //TODO remove it after fully refactor. - OP_MultiwayMergeSort = 17, // multi-way data merge into one input stream. - OP_GlobalAggregate = 18, // global merge for the multi-way data sources. - OP_Filter = 19, - OP_Distinct = 20, - OP_Join = 21, - OP_StateWindow = 22, - OP_AllTimeWindow = 23, - OP_AllMultiTableTimeInterval = 24, - OP_Order = 25, -}; - typedef struct SOperatorInfo { uint8_t operatorType; bool blockingOptr; // block operator or not diff --git a/source/libs/executor/src/executorimpl.c b/source/libs/executor/src/executorimpl.c index d70b61bb4a..0999c44fab 100644 --- a/source/libs/executor/src/executorimpl.c +++ b/source/libs/executor/src/executorimpl.c @@ -289,7 +289,7 @@ static void sortGroupResByOrderList(SGroupResInfo *pGroupResInfo, SQueryRuntimeE return; } - int32_t orderId = pRuntimeEnv->pQueryAttr->order.orderColId; + int32_t orderId = pRuntimeEnv->pQueryAttr->order.col.info.colId; if (orderId <= 0) { return; } @@ -1914,7 +1914,7 @@ static SQLFunctionCtx* createSQLFunctionCtx(SQueryRuntimeEnv* pRuntimeEnv, SExpr pCtx->param[3].i = functionId; pCtx->param[3].nType = TSDB_DATA_TYPE_BIGINT; - pCtx->param[1].i = pQueryAttr->order.orderColId; + pCtx->param[1].i = pQueryAttr->order.col.info.colId; } else if (functionId == FUNCTION_INTERP) { pCtx->param[2].i = (int8_t)pQueryAttr->fillType; if (pQueryAttr->fillVal != NULL) { @@ -2013,162 +2013,162 @@ static int32_t setupQueryRuntimeEnv(SQueryRuntimeEnv *pRuntimeEnv, int32_t numOf int32_t* op = taosArrayGet(pOperator, i); switch (*op) { - case OP_TagScan: { - pRuntimeEnv->proot = createTagScanOperatorInfo(pRuntimeEnv, pQueryAttr->pExpr1, pQueryAttr->numOfOutput); - break; - } - case OP_MultiTableTimeInterval: { - pRuntimeEnv->proot = - createMultiTableTimeIntervalOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQueryAttr->pExpr1, pQueryAttr->numOfOutput); - setTableScanFilterOperatorInfo(pRuntimeEnv->proot->upstream[0]->info, pRuntimeEnv->proot); - break; - } - case OP_AllMultiTableTimeInterval: { - pRuntimeEnv->proot = - createAllMultiTableTimeIntervalOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQueryAttr->pExpr1, pQueryAttr->numOfOutput); - setTableScanFilterOperatorInfo(pRuntimeEnv->proot->upstream[0]->info, pRuntimeEnv->proot); - break; - } - case OP_TimeWindow: { - pRuntimeEnv->proot = - createTimeIntervalOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQueryAttr->pExpr1, pQueryAttr->numOfOutput); - int32_t opType = pRuntimeEnv->proot->upstream[0]->operatorType; - if (opType != OP_DummyInput && opType != OP_Join) { - setTableScanFilterOperatorInfo(pRuntimeEnv->proot->upstream[0]->info, pRuntimeEnv->proot); - } - break; - } - case OP_AllTimeWindow: { - pRuntimeEnv->proot = - createAllTimeIntervalOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQueryAttr->pExpr1, pQueryAttr->numOfOutput); - int32_t opType = pRuntimeEnv->proot->upstream[0]->operatorType; - if (opType != OP_DummyInput && opType != OP_Join) { - setTableScanFilterOperatorInfo(pRuntimeEnv->proot->upstream[0]->info, pRuntimeEnv->proot); - } - break; - } - case OP_Groupby: { - pRuntimeEnv->proot = - createGroupbyOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQueryAttr->pExpr1, pQueryAttr->numOfOutput); - - int32_t opType = pRuntimeEnv->proot->upstream[0]->operatorType; - if (opType != OP_DummyInput) { - setTableScanFilterOperatorInfo(pRuntimeEnv->proot->upstream[0]->info, pRuntimeEnv->proot); - } - break; - } - case OP_SessionWindow: { - pRuntimeEnv->proot = - createSWindowOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQueryAttr->pExpr1, pQueryAttr->numOfOutput); - int32_t opType = pRuntimeEnv->proot->upstream[0]->operatorType; - if (opType != OP_DummyInput) { - setTableScanFilterOperatorInfo(pRuntimeEnv->proot->upstream[0]->info, pRuntimeEnv->proot); - } - break; - } - case OP_MultiTableAggregate: { - pRuntimeEnv->proot = - createMultiTableAggOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQueryAttr->pExpr1, pQueryAttr->numOfOutput); - setTableScanFilterOperatorInfo(pRuntimeEnv->proot->upstream[0]->info, pRuntimeEnv->proot); - break; - } - case OP_Aggregate: { - pRuntimeEnv->proot = - createAggregateOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQueryAttr->pExpr1, pQueryAttr->numOfOutput); - - int32_t opType = pRuntimeEnv->proot->upstream[0]->operatorType; - if (opType != OP_DummyInput && opType != OP_Join) { - setTableScanFilterOperatorInfo(pRuntimeEnv->proot->upstream[0]->info, pRuntimeEnv->proot); - } - break; - } - - case OP_Project: { // TODO refactor to remove arith operator. - SOperatorInfo* prev = pRuntimeEnv->proot; - if (i == 0) { - pRuntimeEnv->proot = createProjectOperatorInfo(pRuntimeEnv, prev, pQueryAttr->pExpr1, pQueryAttr->numOfOutput); - if (pRuntimeEnv->proot != NULL && prev->operatorType != OP_DummyInput && prev->operatorType != OP_Join) { // TODO refactor - setTableScanFilterOperatorInfo(prev->info, pRuntimeEnv->proot); - } - } else { - prev = pRuntimeEnv->proot; - assert(pQueryAttr->pExpr2 != NULL); - pRuntimeEnv->proot = createProjectOperatorInfo(pRuntimeEnv, prev, pQueryAttr->pExpr2, pQueryAttr->numOfExpr2); - } - break; - } - - case OP_StateWindow: { - pRuntimeEnv->proot = createStatewindowOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQueryAttr->pExpr1, pQueryAttr->numOfOutput); - int32_t opType = pRuntimeEnv->proot->upstream[0]->operatorType; - if (opType != OP_DummyInput) { - setTableScanFilterOperatorInfo(pRuntimeEnv->proot->upstream[0]->info, pRuntimeEnv->proot); - } - break; - } - - case OP_Limit: { - pRuntimeEnv->proot = createLimitOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot); - break; - } - - case OP_Filter: { // todo refactor - int32_t numOfFilterCols = 0; - if (pQueryAttr->stableQuery) { - SColumnInfo* pColInfo = - extractColumnFilterInfo(pQueryAttr->pExpr3, pQueryAttr->numOfExpr3, &numOfFilterCols); - pRuntimeEnv->proot = createFilterOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQueryAttr->pExpr3, - pQueryAttr->numOfExpr3, pColInfo, numOfFilterCols); - freeColumnInfo(pColInfo, pQueryAttr->numOfExpr3); - } else { - SColumnInfo* pColInfo = - extractColumnFilterInfo(pQueryAttr->pExpr1, pQueryAttr->numOfOutput, &numOfFilterCols); - pRuntimeEnv->proot = createFilterOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQueryAttr->pExpr1, - pQueryAttr->numOfOutput, pColInfo, numOfFilterCols); - freeColumnInfo(pColInfo, pQueryAttr->numOfOutput); - } - - break; - } - - case OP_Fill: { - SOperatorInfo* pInfo = pRuntimeEnv->proot; - pRuntimeEnv->proot = createFillOperatorInfo(pRuntimeEnv, pInfo, pInfo->pExpr, pInfo->numOfOutput, pQueryAttr->multigroupResult); - break; - } - - case OP_MultiwayMergeSort: { - pRuntimeEnv->proot = createMultiwaySortOperatorInfo(pRuntimeEnv, pQueryAttr->pExpr1, pQueryAttr->numOfOutput, 4096, merger); - break; - } - - case OP_GlobalAggregate: { // If fill operator exists, the result rows of different group can not be in the same SSDataBlock. - bool multigroupResult = pQueryAttr->multigroupResult; - if (pQueryAttr->multigroupResult) { - multigroupResult = (pQueryAttr->fillType == TSDB_FILL_NONE); - } - - pRuntimeEnv->proot = createGlobalAggregateOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQueryAttr->pExpr3, - pQueryAttr->numOfExpr3, merger, pQueryAttr->pUdfInfo, multigroupResult); - break; - } - - case OP_SLimit: { - int32_t num = pRuntimeEnv->proot->numOfOutput; - SExprInfo* pExpr = pRuntimeEnv->proot->pExpr; - pRuntimeEnv->proot = createSLimitOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pExpr, num, merger, pQueryAttr->multigroupResult); - break; - } - - case OP_Distinct: { - pRuntimeEnv->proot = createDistinctOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQueryAttr->pExpr1, pQueryAttr->numOfOutput); - break; - } - - case OP_Order: { - pRuntimeEnv->proot = createOrderOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQueryAttr->pExpr1, pQueryAttr->numOfOutput, &pQueryAttr->order); - break; - } +// case OP_TagScan: { +// pRuntimeEnv->proot = createTagScanOperatorInfo(pRuntimeEnv, pQueryAttr->pExpr1, pQueryAttr->numOfOutput); +// break; +// } +// case OP_MultiTableTimeInterval: { +// pRuntimeEnv->proot = +// createMultiTableTimeIntervalOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQueryAttr->pExpr1, pQueryAttr->numOfOutput); +// setTableScanFilterOperatorInfo(pRuntimeEnv->proot->upstream[0]->info, pRuntimeEnv->proot); +// break; +// } +// case OP_AllMultiTableTimeInterval: { +// pRuntimeEnv->proot = +// createAllMultiTableTimeIntervalOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQueryAttr->pExpr1, pQueryAttr->numOfOutput); +// setTableScanFilterOperatorInfo(pRuntimeEnv->proot->upstream[0]->info, pRuntimeEnv->proot); +// break; +// } +// case OP_TimeWindow: { +// pRuntimeEnv->proot = +// createTimeIntervalOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQueryAttr->pExpr1, pQueryAttr->numOfOutput); +// int32_t opType = pRuntimeEnv->proot->upstream[0]->operatorType; +// if (opType != OP_DummyInput && opType != OP_Join) { +// setTableScanFilterOperatorInfo(pRuntimeEnv->proot->upstream[0]->info, pRuntimeEnv->proot); +// } +// break; +// } +// case OP_AllTimeWindow: { +// pRuntimeEnv->proot = +// createAllTimeIntervalOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQueryAttr->pExpr1, pQueryAttr->numOfOutput); +// int32_t opType = pRuntimeEnv->proot->upstream[0]->operatorType; +// if (opType != OP_DummyInput && opType != OP_Join) { +// setTableScanFilterOperatorInfo(pRuntimeEnv->proot->upstream[0]->info, pRuntimeEnv->proot); +// } +// break; +// } +// case OP_Groupby: { +// pRuntimeEnv->proot = +// createGroupbyOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQueryAttr->pExpr1, pQueryAttr->numOfOutput); +// +// int32_t opType = pRuntimeEnv->proot->upstream[0]->operatorType; +// if (opType != OP_DummyInput) { +// setTableScanFilterOperatorInfo(pRuntimeEnv->proot->upstream[0]->info, pRuntimeEnv->proot); +// } +// break; +// } +// case OP_SessionWindow: { +// pRuntimeEnv->proot = +// createSWindowOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQueryAttr->pExpr1, pQueryAttr->numOfOutput); +// int32_t opType = pRuntimeEnv->proot->upstream[0]->operatorType; +// if (opType != OP_DummyInput) { +// setTableScanFilterOperatorInfo(pRuntimeEnv->proot->upstream[0]->info, pRuntimeEnv->proot); +// } +// break; +// } +// case OP_MultiTableAggregate: { +// pRuntimeEnv->proot = +// createMultiTableAggOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQueryAttr->pExpr1, pQueryAttr->numOfOutput); +// setTableScanFilterOperatorInfo(pRuntimeEnv->proot->upstream[0]->info, pRuntimeEnv->proot); +// break; +// } +// case OP_Aggregate: { +// pRuntimeEnv->proot = +// createAggregateOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQueryAttr->pExpr1, pQueryAttr->numOfOutput); +// +// int32_t opType = pRuntimeEnv->proot->upstream[0]->operatorType; +// if (opType != OP_DummyInput && opType != OP_Join) { +// setTableScanFilterOperatorInfo(pRuntimeEnv->proot->upstream[0]->info, pRuntimeEnv->proot); +// } +// break; +// } +// +// case OP_Project: { // TODO refactor to remove arith operator. +// SOperatorInfo* prev = pRuntimeEnv->proot; +// if (i == 0) { +// pRuntimeEnv->proot = createProjectOperatorInfo(pRuntimeEnv, prev, pQueryAttr->pExpr1, pQueryAttr->numOfOutput); +// if (pRuntimeEnv->proot != NULL && prev->operatorType != OP_DummyInput && prev->operatorType != OP_Join) { // TODO refactor +// setTableScanFilterOperatorInfo(prev->info, pRuntimeEnv->proot); +// } +// } else { +// prev = pRuntimeEnv->proot; +// assert(pQueryAttr->pExpr2 != NULL); +// pRuntimeEnv->proot = createProjectOperatorInfo(pRuntimeEnv, prev, pQueryAttr->pExpr2, pQueryAttr->numOfExpr2); +// } +// break; +// } +// +// case OP_StateWindow: { +// pRuntimeEnv->proot = createStatewindowOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQueryAttr->pExpr1, pQueryAttr->numOfOutput); +// int32_t opType = pRuntimeEnv->proot->upstream[0]->operatorType; +// if (opType != OP_DummyInput) { +// setTableScanFilterOperatorInfo(pRuntimeEnv->proot->upstream[0]->info, pRuntimeEnv->proot); +// } +// break; +// } +// +// case OP_Limit: { +// pRuntimeEnv->proot = createLimitOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot); +// break; +// } +// +// case OP_Filter: { // todo refactor +// int32_t numOfFilterCols = 0; +// if (pQueryAttr->stableQuery) { +// SColumnInfo* pColInfo = +// extractColumnFilterInfo(pQueryAttr->pExpr3, pQueryAttr->numOfExpr3, &numOfFilterCols); +// pRuntimeEnv->proot = createFilterOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQueryAttr->pExpr3, +// pQueryAttr->numOfExpr3, pColInfo, numOfFilterCols); +// freeColumnInfo(pColInfo, pQueryAttr->numOfExpr3); +// } else { +// SColumnInfo* pColInfo = +// extractColumnFilterInfo(pQueryAttr->pExpr1, pQueryAttr->numOfOutput, &numOfFilterCols); +// pRuntimeEnv->proot = createFilterOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQueryAttr->pExpr1, +// pQueryAttr->numOfOutput, pColInfo, numOfFilterCols); +// freeColumnInfo(pColInfo, pQueryAttr->numOfOutput); +// } +// +// break; +// } +// +// case OP_Fill: { +// SOperatorInfo* pInfo = pRuntimeEnv->proot; +// pRuntimeEnv->proot = createFillOperatorInfo(pRuntimeEnv, pInfo, pInfo->pExpr, pInfo->numOfOutput, pQueryAttr->multigroupResult); +// break; +// } +// +// case OP_MultiwayMergeSort: { +// pRuntimeEnv->proot = createMultiwaySortOperatorInfo(pRuntimeEnv, pQueryAttr->pExpr1, pQueryAttr->numOfOutput, 4096, merger); +// break; +// } +// +// case OP_GlobalAggregate: { // If fill operator exists, the result rows of different group can not be in the same SSDataBlock. +// bool multigroupResult = pQueryAttr->multigroupResult; +// if (pQueryAttr->multigroupResult) { +// multigroupResult = (pQueryAttr->fillType == TSDB_FILL_NONE); +// } +// +// pRuntimeEnv->proot = createGlobalAggregateOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQueryAttr->pExpr3, +// pQueryAttr->numOfExpr3, merger, pQueryAttr->pUdfInfo, multigroupResult); +// break; +// } +// +// case OP_SLimit: { +// int32_t num = pRuntimeEnv->proot->numOfOutput; +// SExprInfo* pExpr = pRuntimeEnv->proot->pExpr; +// pRuntimeEnv->proot = createSLimitOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pExpr, num, merger, pQueryAttr->multigroupResult); +// break; +// } +// +// case OP_Distinct: { +// pRuntimeEnv->proot = createDistinctOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQueryAttr->pExpr1, pQueryAttr->numOfOutput); +// break; +// } +// +// case OP_Order: { +// pRuntimeEnv->proot = createOrderOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQueryAttr->pExpr1, pQueryAttr->numOfOutput, &pQueryAttr->order); +// break; +// } default: { assert(0); @@ -4557,22 +4557,22 @@ int32_t doInitQInfo(SQInfo* pQInfo, STSBuf* pTsBuf, void* tsdb, void* sourceOptr setResultBufSize(pQueryAttr, &pRuntimeEnv->resultInfo); switch(tbScanner) { - case OP_TableBlockInfoScan: { - pRuntimeEnv->proot = createTableBlockInfoScanOperator(pRuntimeEnv->pQueryHandle, pRuntimeEnv); - break; - } - case OP_TableSeqScan: { - pRuntimeEnv->proot = createTableSeqScanOperator(pRuntimeEnv->pQueryHandle, pRuntimeEnv); - break; - } - case OP_DataBlocksOptScan: { - pRuntimeEnv->proot = createDataBlocksOptScanInfo(pRuntimeEnv->pQueryHandle, pRuntimeEnv, getNumOfScanTimes(pQueryAttr), pQueryAttr->needReverseScan? 1:0); - break; - } - case OP_TableScan: { - pRuntimeEnv->proot = createTableScanOperator(pRuntimeEnv->pQueryHandle, pRuntimeEnv, getNumOfScanTimes(pQueryAttr)); - break; - } +// case OP_TableBlockInfoScan: { +// pRuntimeEnv->proot = createTableBlockInfoScanOperator(pRuntimeEnv->pQueryHandle, pRuntimeEnv); +// break; +// } +// case OP_TableSeqScan: { +// pRuntimeEnv->proot = createTableSeqScanOperator(pRuntimeEnv->pQueryHandle, pRuntimeEnv); +// break; +// } +// case OP_DataBlocksOptScan: { +// pRuntimeEnv->proot = createDataBlocksOptScanInfo(pRuntimeEnv->pQueryHandle, pRuntimeEnv, getNumOfScanTimes(pQueryAttr), pQueryAttr->needReverseScan? 1:0); +// break; +// } +// case OP_TableScan: { +// pRuntimeEnv->proot = createTableScanOperator(pRuntimeEnv->pQueryHandle, pRuntimeEnv, getNumOfScanTimes(pQueryAttr)); +// break; +// } default: { // do nothing break; } @@ -4881,7 +4881,7 @@ SOperatorInfo* createTableScanOperator(void* pTsdbQueryHandle, SQueryRuntimeEnv* SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo)); pOperator->name = "TableScanOperator"; - pOperator->operatorType = OP_TableScan; +// pOperator->operatorType = OP_TableScan; pOperator->blockingOptr = false; pOperator->status = OP_IN_EXECUTING; pOperator->info = pInfo; @@ -4905,7 +4905,7 @@ SOperatorInfo* createTableSeqScanOperator(void* pTsdbQueryHandle, SQueryRuntimeE SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo)); pOperator->name = "TableSeqScanOperator"; - pOperator->operatorType = OP_TableSeqScan; +// pOperator->operatorType = OP_TableSeqScan; pOperator->blockingOptr = false; pOperator->status = OP_IN_EXECUTING; pOperator->info = pInfo; @@ -4930,7 +4930,7 @@ SOperatorInfo* createTableBlockInfoScanOperator(void* pTsdbQueryHandle, SQueryRu SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo)); pOperator->name = "TableBlockInfoScanOperator"; - pOperator->operatorType = OP_TableBlockInfoScan; +// pOperator->operatorType = OP_TableBlockInfoScan; pOperator->blockingOptr = false; pOperator->status = OP_IN_EXECUTING; pOperator->info = pInfo; @@ -4946,7 +4946,7 @@ void setTableScanFilterOperatorInfo(STableScanInfo* pTableScanInfo, SOperatorInf pTableScanInfo->pExpr = pDownstream->pExpr; // TODO refactor to use colId instead of pExpr pTableScanInfo->numOfOutput = pDownstream->numOfOutput; - +#if 0 if (pDownstream->operatorType == OP_Aggregate || pDownstream->operatorType == OP_MultiTableAggregate) { SAggOperatorInfo* pAggInfo = pDownstream->info; @@ -4995,6 +4995,8 @@ void setTableScanFilterOperatorInfo(STableScanInfo* pTableScanInfo, SOperatorInf } else { assert(0); } +#endif + } SOperatorInfo* createDataBlocksOptScanInfo(void* pTsdbQueryHandle, SQueryRuntimeEnv* pRuntimeEnv, int32_t repeatTime, int32_t reverseTime) { @@ -5009,7 +5011,7 @@ SOperatorInfo* createDataBlocksOptScanInfo(void* pTsdbQueryHandle, SQueryRuntime SOperatorInfo* pOptr = calloc(1, sizeof(SOperatorInfo)); pOptr->name = "DataBlocksOptimizedScanOperator"; - pOptr->operatorType = OP_DataBlocksOptScan; +// pOptr->operatorType = OP_DataBlocksOptScan; pOptr->pRuntimeEnv = pRuntimeEnv; pOptr->blockingOptr = false; pOptr->info = pInfo; @@ -5161,7 +5163,7 @@ SOperatorInfo* createGlobalAggregateOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo)); pOperator->name = "GlobalAggregate"; - pOperator->operatorType = OP_GlobalAggregate; +// pOperator->operatorType = OP_GlobalAggregate; pOperator->blockingOptr = true; pOperator->status = OP_IN_EXECUTING; pOperator->info = pInfo; @@ -5205,7 +5207,7 @@ SOperatorInfo *createMultiwaySortOperatorInfo(SQueryRuntimeEnv *pRuntimeEnv, SEx SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo)); pOperator->name = "MultiwaySortOperator"; - pOperator->operatorType = OP_MultiwayMergeSort; +// pOperator->operatorType = OP_MultiwayMergeSort; pOperator->blockingOptr = false; pOperator->status = OP_IN_EXECUTING; pOperator->info = pInfo; @@ -5312,7 +5314,7 @@ SOperatorInfo *createOrderOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorI SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo)); pOperator->name = "InMemoryOrder"; - pOperator->operatorType = OP_Order; +// pOperator->operatorType = OP_Order; pOperator->blockingOptr = true; pOperator->status = OP_IN_EXECUTING; pOperator->info = pInfo; @@ -5358,10 +5360,10 @@ static SSDataBlock* doAggregate(void* param, bool* newgroup) { setTagValue(pOperator, pRuntimeEnv->current->pTable, pInfo->pCtx, pOperator->numOfOutput); } - if (upstream->operatorType == OP_DataBlocksOptScan) { - STableScanInfo* pScanInfo = upstream->info; - order = getTableScanOrder(pScanInfo); - } +// if (upstream->operatorType == OP_DataBlocksOptScan) { +// STableScanInfo* pScanInfo = upstream->info; +// order = getTableScanOrder(pScanInfo); +// } // the pDataBlock are always the same one, no need to call this again setInputDataBlock(pOperator, pInfo->pCtx, pBlock, order); @@ -5413,10 +5415,10 @@ static SSDataBlock* doSTableAggregate(void* param, bool* newgroup) { setTagValue(pOperator, pRuntimeEnv->current->pTable, pInfo->pCtx, pOperator->numOfOutput); - if (upstream->operatorType == OP_DataBlocksOptScan) { - STableScanInfo* pScanInfo = upstream->info; - order = getTableScanOrder(pScanInfo); - } +// if (upstream->operatorType == OP_DataBlocksOptScan) { +// STableScanInfo* pScanInfo = upstream->info; +// order = getTableScanOrder(pScanInfo); +// } // the pDataBlock are always the same one, no need to call this again setInputDataBlock(pOperator, pInfo->pCtx, pBlock, order); @@ -6268,7 +6270,7 @@ SOperatorInfo* createAggregateOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOpera SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo)); pOperator->name = "TableAggregate"; - pOperator->operatorType = OP_Aggregate; +// pOperator->operatorType = OP_Aggregate; pOperator->blockingOptr = true; pOperator->status = OP_IN_EXECUTING; pOperator->info = pInfo; @@ -6363,7 +6365,7 @@ SOperatorInfo* createMultiTableAggOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SO SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo)); pOperator->name = "MultiTableAggregate"; - pOperator->operatorType = OP_MultiTableAggregate; +// pOperator->operatorType = OP_MultiTableAggregate; pOperator->blockingOptr = true; pOperator->status = OP_IN_EXECUTING; pOperator->info = pInfo; @@ -6393,7 +6395,7 @@ SOperatorInfo* createProjectOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperato SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo)); pOperator->name = "ProjectOperator"; - pOperator->operatorType = OP_Project; +// pOperator->operatorType = OP_Project; pOperator->blockingOptr = false; pOperator->status = OP_IN_EXECUTING; pOperator->info = pInfo; @@ -6452,7 +6454,7 @@ SOperatorInfo* createFilterOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperator SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo)); pOperator->name = "FilterOperator"; - pOperator->operatorType = OP_Filter; +// pOperator->operatorType = OP_Filter; pOperator->blockingOptr = false; pOperator->status = OP_IN_EXECUTING; pOperator->numOfOutput = numOfOutput; @@ -6473,7 +6475,7 @@ SOperatorInfo* createLimitOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorI SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo)); pOperator->name = "LimitOperator"; - pOperator->operatorType = OP_Limit; +// pOperator->operatorType = OP_Limit; pOperator->blockingOptr = false; pOperator->status = OP_IN_EXECUTING; pOperator->exec = doLimit; @@ -6494,7 +6496,7 @@ SOperatorInfo* createTimeIntervalOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOp SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo)); pOperator->name = "TimeIntervalAggOperator"; - pOperator->operatorType = OP_TimeWindow; +// pOperator->operatorType = OP_TimeWindow; pOperator->blockingOptr = true; pOperator->status = OP_IN_EXECUTING; pOperator->pExpr = pExpr; @@ -6519,7 +6521,7 @@ SOperatorInfo* createAllTimeIntervalOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo)); pOperator->name = "AllTimeIntervalAggOperator"; - pOperator->operatorType = OP_AllTimeWindow; +// pOperator->operatorType = OP_AllTimeWindow; pOperator->blockingOptr = true; pOperator->status = OP_IN_EXECUTING; pOperator->pExpr = pExpr; @@ -6543,7 +6545,7 @@ SOperatorInfo* createStatewindowOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOpe SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo)); pOperator->name = "StateWindowOperator"; - pOperator->operatorType = OP_StateWindow; +// pOperator->operatorType = OP_StateWindow; pOperator->blockingOptr = true; pOperator->status = OP_IN_EXECUTING; pOperator->pExpr = pExpr; @@ -6568,7 +6570,7 @@ SOperatorInfo* createSWindowOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperato SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo)); pOperator->name = "SessionWindowAggOperator"; - pOperator->operatorType = OP_SessionWindow; +// pOperator->operatorType = OP_SessionWindow; pOperator->blockingOptr = true; pOperator->status = OP_IN_EXECUTING; pOperator->pExpr = pExpr; @@ -6591,7 +6593,7 @@ SOperatorInfo* createMultiTableTimeIntervalOperatorInfo(SQueryRuntimeEnv* pRunti SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo)); pOperator->name = "MultiTableTimeIntervalOperator"; - pOperator->operatorType = OP_MultiTableTimeInterval; +// pOperator->operatorType = OP_MultiTableTimeInterval; pOperator->blockingOptr = true; pOperator->status = OP_IN_EXECUTING; pOperator->pExpr = pExpr; @@ -6615,7 +6617,7 @@ SOperatorInfo* createAllMultiTableTimeIntervalOperatorInfo(SQueryRuntimeEnv* pRu SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo)); pOperator->name = "AllMultiTableTimeIntervalOperator"; - pOperator->operatorType = OP_AllMultiTableTimeInterval; +// pOperator->operatorType = OP_AllMultiTableTimeInterval; pOperator->blockingOptr = true; pOperator->status = OP_IN_EXECUTING; pOperator->pExpr = pExpr; @@ -6651,7 +6653,7 @@ SOperatorInfo* createGroupbyOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperato pOperator->name = "GroupbyAggOperator"; pOperator->blockingOptr = true; pOperator->status = OP_IN_EXECUTING; - pOperator->operatorType = OP_Groupby; +// pOperator->operatorType = OP_Groupby; pOperator->pExpr = pExpr; pOperator->numOfOutput = numOfOutput; pOperator->info = pInfo; @@ -6690,7 +6692,7 @@ SOperatorInfo* createFillOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorIn pOperator->name = "FillOperator"; pOperator->blockingOptr = false; pOperator->status = OP_IN_EXECUTING; - pOperator->operatorType = OP_Fill; +// pOperator->operatorType = OP_Fill; pOperator->pExpr = pExpr; pOperator->numOfOutput = numOfOutput; pOperator->info = pInfo; @@ -6738,7 +6740,7 @@ SOperatorInfo* createSLimitOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperator SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo)); pOperator->name = "SLimitOperator"; - pOperator->operatorType = OP_SLimit; +// pOperator->operatorType = OP_SLimit; pOperator->blockingOptr = false; pOperator->status = OP_IN_EXECUTING; pOperator->exec = doSLimit; @@ -6894,7 +6896,7 @@ SOperatorInfo* createTagScanOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SExprInf SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo)); pOperator->name = "SeqTableTagScan"; - pOperator->operatorType = OP_TagScan; +// pOperator->operatorType = OP_TagScan; pOperator->blockingOptr = false; pOperator->status = OP_IN_EXECUTING; pOperator->info = pInfo; @@ -7035,7 +7037,7 @@ SOperatorInfo* createDistinctOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperat pOperator->name = "DistinctOperator"; pOperator->blockingOptr = false; pOperator->status = OP_IN_EXECUTING; - pOperator->operatorType = OP_Distinct; +// pOperator->operatorType = OP_Distinct; pOperator->pExpr = pExpr; pOperator->numOfOutput = numOfOutput; pOperator->info = pInfo; @@ -8034,7 +8036,7 @@ SQInfo* createQInfoImpl(SQueryTableMsg* pQueryMsg, SGroupbyExpr* pGroupbyExpr, S pQueryAttr->limit.limit = pQueryMsg->limit; pQueryAttr->limit.offset = pQueryMsg->offset; pQueryAttr->order.order = pQueryMsg->order; - pQueryAttr->order.orderColId = pQueryMsg->orderColId; + pQueryAttr->order.col.info.colId = pQueryMsg->orderColId; pQueryAttr->pExpr1 = pExprs; pQueryAttr->pExpr2 = pSecExprs; pQueryAttr->numOfExpr2 = pQueryMsg->secondStageOutput; diff --git a/source/libs/function/src/taggfunction.c b/source/libs/function/src/taggfunction.c index dc6eadf7d8..00f59e8b87 100644 --- a/source/libs/function/src/taggfunction.c +++ b/source/libs/function/src/taggfunction.c @@ -4589,7 +4589,7 @@ SAggFunctionInfo aggFunc[35] = {{ }, { // 16 - "ts", + "dummy", FUNCTION_TYPE_AGG, FUNCTION_TS, FUNCTION_TS, diff --git a/source/libs/function/src/texpr.c b/source/libs/function/src/texpr.c index 6970b85638..70a7e9973f 100644 --- a/source/libs/function/src/texpr.c +++ b/source/libs/function/src/texpr.c @@ -13,6 +13,7 @@ * along with this program. If not, see . */ +#include "function.h" #include "os.h" #include "exception.h" @@ -550,6 +551,15 @@ tExprNode* exprdup(tExprNode* pNode) { } else if (pNode->nodeType == TEXPR_COL_NODE) { pCloned->pSchema = calloc(1, sizeof(SSchema)); *pCloned->pSchema = *pNode->pSchema; + } else if (pNode->nodeType == TEXPR_FUNCTION_NODE) { + strcpy(pCloned->_function.functionName, pNode->_function.functionName); + + int32_t num = pNode->_function.num; + pCloned->_function.num = num; + pCloned->_function.pChild = calloc(num, POINTER_BYTES); + for(int32_t i = 0; i < num; ++i) { + pCloned->_function.pChild[i] = exprdup(pNode->_function.pChild[i]); + } } pCloned->nodeType = pNode->nodeType; diff --git a/source/libs/function/src/tfunction.c b/source/libs/function/src/tfunction.c index d3fc19a47f..9e70b9a68d 100644 --- a/source/libs/function/src/tfunction.c +++ b/source/libs/function/src/tfunction.c @@ -54,6 +54,18 @@ bool qIsAggregateFunction(const char* functionName) { return !scalarfunc; } +bool qIsSelectivityFunction(const char* functionName) { + assert(functionName != NULL); + pthread_once(&functionHashTableInit, doInitFunctionHashTable); + + size_t len = strlen(functionName); + SAggFunctionInfo** pInfo = taosHashGet(functionHashTable, functionName, len); + if (pInfo != NULL) { + return ((*pInfo)->status | FUNCSTATE_SELECTIVITY) != 0; + } + + return false; +} SAggFunctionInfo* qGetFunctionInfo(const char* name, int32_t len) { pthread_once(&functionHashTableInit, doInitFunctionHashTable); @@ -79,16 +91,17 @@ void qRemoveUdfInfo(uint64_t id, SUdfInfo* pUdfInfo) { bool isTagsQuery(SArray* pFunctionIdList) { int32_t num = (int32_t) taosArrayGetSize(pFunctionIdList); for (int32_t i = 0; i < num; ++i) { - int16_t f = *(int16_t*) taosArrayGet(pFunctionIdList, i); + char* f = *(char**) taosArrayGet(pFunctionIdList, i); + + // todo handle count(tbname) query + if (strcmp(f, "project") != 0 && strcmp(f, "count") != 0) { + return false; + } // "select count(tbname)" query // if (functId == FUNCTION_COUNT && pExpr->base.colpDesc->colId == TSDB_TBNAME_COLUMN_INDEX) { // continue; // } - - if (f != FUNCTION_TAGPRJ && f != FUNCTION_TID_TAG) { - return false; - } } return true; @@ -113,23 +126,13 @@ bool isTagsQuery(SArray* pFunctionIdList) { bool isProjectionQuery(SArray* pFunctionIdList) { int32_t num = (int32_t) taosArrayGetSize(pFunctionIdList); for (int32_t i = 0; i < num; ++i) { - int32_t f = *(int16_t*) taosArrayGet(pFunctionIdList, i); - if (f == FUNCTION_TS_DUMMY) { - continue; - } - - if (f != FUNCTION_PRJ && - f != FUNCTION_TAGPRJ && - f != FUNCTION_TAG && - f != FUNCTION_TS && - f != FUNCTION_ARITHM && - f != FUNCTION_DIFF && - f != FUNCTION_DERIVATIVE) { - return false; + char* f = *(char**) taosArrayGet(pFunctionIdList, i); + if (strcmp(f, "project") == 0) { + return true; } } - return true; + return false; } bool isDiffDerivativeQuery(SArray* pFunctionIdList) { @@ -182,30 +185,19 @@ bool isArithmeticQueryOnAggResult(SArray* pFunctionIdList) { return false; } -bool isGroupbyColumn(SArray* pFunctionIdList) { -// STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0); -// int32_t numOfCols = getNumOfColumns(pTableMetaInfo->pTableMeta); -// -// SGroupbyExpr* pGroupbyExpr = &pQueryInfo->groupbyExpr; -// for (int32_t k = 0; k < pGroupbyExpr->numOfGroupCols; ++k) { -// SColIndex* pIndex = taosArrayGet(pGroupbyExpr->columnInfo, k); -// if (!TSDB_COL_IS_TAG(pIndex->flag) && pIndex->colIndex < numOfCols) { // group by normal columns -// return true; -// } -// } - - return false; +bool isGroupbyColumn(SGroupbyExpr* pGroupby) { + return !pGroupby->groupbyTag; } bool isTopBotQuery(SArray* pFunctionIdList) { int32_t num = (int32_t) taosArrayGetSize(pFunctionIdList); for (int32_t i = 0; i < num; ++i) { - int32_t f = *(int16_t*) taosArrayGet(pFunctionIdList, i); - if (f == FUNCTION_TS) { + char* f = *(char**) taosArrayGet(pFunctionIdList, i); + if (strcmp(f, "project") == 0) { continue; } - if (f == FUNCTION_TOP || f == FUNCTION_BOTTOM) { + if (strcmp(f, "top") == 0 || strcmp(f, "bottom") == 0) { return true; } } @@ -284,49 +276,26 @@ bool needReverseScan(SArray* pFunctionIdList) { return false; } -bool isSimpleAggregateRv(SArray* pFunctionIdList) { -// if (pQueryInfo->interval.interval > 0 || pQueryInfo->sessionWindow.gap > 0) { -// return false; -// } -// -// if (tscIsDiffDerivQuery(pQueryInfo)) { -// return false; -// } -// -// size_t numOfExprs = getNumOfExprs(pQueryInfo); -// for (int32_t i = 0; i < numOfExprs; ++i) { -// SExprInfo* pExpr = getExprInfo(pQueryInfo, i); -// if (pExpr == NULL) { -// continue; -// } -// -// int32_t functionId = pExpr->base.functionId; -// if (functionId < 0) { -// SUdfInfo* pUdfInfo = taosArrayGet(pQueryInfo->pUdfInfo, -1 * functionId - 1); -// if (pUdfInfo->funcType == TSDB_UDF_TYPE_AGGREGATE) { -// return true; -// } -// -// continue; -// } -// -// if (functionId == FUNCTION_TS || functionId == FUNCTION_TS_DUMMY) { -// continue; -// } -// -// if ((!IS_MULTIOUTPUT(aAggs[functionId].status)) || -// (functionId == FUNCTION_TOP || functionId == FUNCTION_BOTTOM || functionId == FUNCTION_TS_COMP)) { -// return true; -// } -// } +bool isAgg(SArray* pFunctionIdList) { + size_t size = taosArrayGetSize(pFunctionIdList); + for (int32_t i = 0; i < size; ++i) { + char* f = *(char**) taosArrayGet(pFunctionIdList, i); + if (strcmp(f, "project") == 0) { + return false; + } + + if (qIsAggregateFunction(f)) { + return true; + } + } return false; } bool isBlockDistQuery(SArray* pFunctionIdList) { int32_t num = (int32_t) taosArrayGetSize(pFunctionIdList); - int32_t f = *(int16_t*) taosArrayGet(pFunctionIdList, 0); - return (num == 1 && f == FUNCTION_BLKINFO); + char* f = *(char**) taosArrayGet(pFunctionIdList, 0); + return (num == 1 && strcmp(f, "block_dist") == 0); } bool isTwoStageSTableQuery(SArray* pFunctionIdList, int32_t tableIndex) { @@ -432,13 +401,14 @@ bool hasTagValOutput(SArray* pFunctionIdList) { void extractFunctionDesc(SArray* pFunctionIdList, SMultiFunctionsDesc* pDesc) { assert(pFunctionIdList != NULL); - pDesc->blockDistribution = isBlockDistQuery(pFunctionIdList); if (pDesc->blockDistribution) { return; } - pDesc->projectionQuery = isProjectionQuery(pFunctionIdList); - pDesc->onlyTagQuery = isTagsQuery(pFunctionIdList); +// pDesc->projectionQuery = isProjectionQuery(pFunctionIdList); +// pDesc->onlyTagQuery = isTagsQuery(pFunctionIdList); pDesc->interpQuery = isInterpQuery(pFunctionIdList); + pDesc->topbotQuery = isTopBotQuery(pFunctionIdList); + pDesc->agg = isAgg(pFunctionIdList); } diff --git a/source/libs/parser/inc/astGenerator.h b/source/libs/parser/inc/astGenerator.h index 863c307f34..cb3d459de6 100644 --- a/source/libs/parser/inc/astGenerator.h +++ b/source/libs/parser/inc/astGenerator.h @@ -294,7 +294,10 @@ SCreateTableSql *tSetCreateTableInfo(SArray *pCols, SArray *pTags, SSqlNode *pSe SAlterTableInfo * tSetAlterTableInfo(SToken *pTableName, SArray *pCols, SArray *pVals, int32_t type, int16_t tableType); SCreatedTableInfo createNewChildTableInfo(SToken *pTableName, SArray *pTagNames, SArray *pTagVals, SToken *pToken, SToken *igExists); - +/*! + * test + * @param pSqlNode + */ void destroyAllSqlNode(struct SSubclause *pSqlNode); void destroySqlNode(SSqlNode *pSql); void freeCreateTableInfo(void* p); diff --git a/source/libs/parser/src/astGenerator.c b/source/libs/parser/src/astGenerator.c index 53d05c87b3..f328486556 100644 --- a/source/libs/parser/src/astGenerator.c +++ b/source/libs/parser/src/astGenerator.c @@ -59,8 +59,7 @@ SArray *tListItemAppendToken(SArray *pList, SToken *pAliasToken, uint8_t sortOrd if (pAliasToken) { SListItem item; - assert(0); -// taosVariantCreate(&item.pVar, pAliasToken); + taosVariantCreate(&item.pVar, pAliasToken->z, pAliasToken->n, pAliasToken->type); item.sortOrder = sortOrder; taosArrayPush(pList, &item); diff --git a/source/libs/parser/src/astValidate.c b/source/libs/parser/src/astValidate.c index 8e0f59b07e..7b6c423fb6 100644 --- a/source/libs/parser/src/astValidate.c +++ b/source/libs/parser/src/astValidate.c @@ -13,7 +13,6 @@ * along with this program. If not, see . */ -#include #include #include "astGenerator.h" #include "function.h" @@ -35,6 +34,11 @@ #define COLUMN_INDEX_INITIAL_VAL (-2) #define COLUMN_INDEX_INITIALIZER { COLUMN_INDEX_INITIAL_VAL, COLUMN_INDEX_INITIAL_VAL } +static int32_t resColId = 5000; +int32_t getNewResColId() { + return resColId++; +} + static int32_t validateSelectNodeList(SQueryStmtInfo* pQueryInfo, SArray* pSelNodeList, bool outerQuery, SMsgBuf* pMsgBuf); static int32_t extractFunctionParameterInfo(SQueryStmtInfo* pQueryInfo, int32_t tokenId, STableMetaInfo** pTableMetaInfo, SSchema* columnSchema, tExprNode** pNode, SColumnIndex* pIndex, tSqlExprItem* pParamElem, SMsgBuf* pMsgBuf); @@ -698,6 +702,8 @@ static int32_t parseSlidingClause(SQueryStmtInfo* pQueryInfo, SToken* pSliding, return TSDB_CODE_SUCCESS; } +static void setTsOutputExprInfo(SQueryStmtInfo* pQueryInfo, STableMetaInfo* pTableMetaInfo, int32_t outputIndex, int32_t tableIndex); + // validate the interval info int32_t validateIntervalNode(SQueryStmtInfo *pQueryInfo, SSqlNode* pSqlNode, SMsgBuf* pMsgBuf) { const char* msg1 = "sliding cannot be used without interval"; @@ -715,11 +721,6 @@ int32_t validateIntervalNode(SQueryStmtInfo *pQueryInfo, SSqlNode* pSqlNode, SMs } } - // orderby column not set yet, set it to be the primary timestamp column - if (pQueryInfo->order.orderColId == INT32_MIN) { - pQueryInfo->order.orderColId = PRIMARYKEY_TIMESTAMP_COL_ID; - } - // interval is not null SToken *t = &pSqlNode->interval.interval; if (parseNatualDuration(t->z, t->n, &pQueryInfo->interval.interval, @@ -748,6 +749,13 @@ int32_t validateIntervalNode(SQueryStmtInfo *pQueryInfo, SSqlNode* pSqlNode, SMs return TSDB_CODE_TSC_INVALID_OPERATION; } + if (tsCompatibleModel) { + SExprInfo* pFirstExpr = getExprInfo(pQueryInfo, 0); + if (pFirstExpr->pExpr->nodeType != TEXPR_FUNCTION_NODE || strcasecmp(pFirstExpr->pExpr->_function.functionName, "dummy") != 0) { + setTsOutputExprInfo(pQueryInfo, pTableMetaInfo, 0, 0); + } + } + // It is a time window query pQueryInfo->info.timewindow = true; return TSDB_CODE_SUCCESS; @@ -917,8 +925,6 @@ int32_t validateLimitNode(SQueryStmtInfo *pQueryInfo, SSqlNode* pSqlNode, SMsgBu } } -static void setTsOutputExprInfo(SQueryStmtInfo* pQueryInfo, STableMetaInfo* pTableMetaInfo, int32_t outputIndex, int32_t tableIndex); - int32_t validateOrderbyNode(SQueryStmtInfo *pQueryInfo, SSqlNode* pSqlNode, SMsgBuf* pMsgBuf) { const char* msg1 = "invalid column name in orderby clause"; const char* msg2 = "too many order by columns"; @@ -929,6 +935,8 @@ int32_t validateOrderbyNode(SQueryStmtInfo *pQueryInfo, SSqlNode* pSqlNode, SMsg return TSDB_CODE_SUCCESS; } + pQueryInfo->order = taosArrayInit(4, sizeof(SOrder)); + STableMetaInfo* pTableMetaInfo = getMetaInfo(pQueryInfo, 0); SArray* pSortOrder = pSqlNode->pSortOrder; @@ -939,40 +947,54 @@ int32_t validateOrderbyNode(SQueryStmtInfo *pQueryInfo, SSqlNode* pSqlNode, SMsg * for super table query, the order option must be less than 3. */ size_t size = taosArrayGetSize(pSortOrder); - if (UTIL_TABLE_IS_NORMAL_TABLE(pTableMetaInfo) || UTIL_TABLE_IS_TMP_TABLE(pTableMetaInfo)) { + if ((UTIL_TABLE_IS_NORMAL_TABLE(pTableMetaInfo) || UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo)) && (pQueryInfo->info.projectionQuery)) { if (size > 1) { return buildInvalidOperationMsg(pMsgBuf, msg3); } - } else { - if (size > 2) { - return buildInvalidOperationMsg(pMsgBuf, msg2); - } } // handle the first part of order by - SVariant* pVar = taosArrayGet(pSortOrder, 0); - SSchema s = {0}; - if (pVar->nType == TSDB_DATA_TYPE_BINARY) { - SColumnIndex index = COLUMN_INDEX_INITIALIZER; - SToken columnName = {pVar->nLen, pVar->nType, pVar->pz}; - if (getColumnIndexByName(&columnName, pQueryInfo, &index, pMsgBuf) != TSDB_CODE_SUCCESS) { - return buildInvalidOperationMsg(pMsgBuf, msg1); - } + bool found = false; + for(int32_t i = 0; i < taosArrayGetSize(pSortOrder); ++i) { + SListItem* pItem = taosArrayGet(pSortOrder, i); - s = *(SSchema*) getOneColumnSchema(pTableMetaInfo->pTableMeta, index.columnIndex); - } else { // order by [1|2|3] - if (pVar->i > getNumOfFields(&pQueryInfo->fieldsInfo)) { - return buildInvalidOperationMsg(pMsgBuf, msg4); - } + SVariant* pVar = &pItem->pVar; + if (pVar->nType == TSDB_DATA_TYPE_BINARY) { + SOrder order = {0}; - SExprInfo* pExprInfo = getExprInfo(pQueryInfo, pVar->i); - s = pExprInfo->base.resSchema; + // find the orde column among the result field. + for (int32_t j = 0; j < getNumOfFields(&pQueryInfo->fieldsInfo); ++j) { + SInternalField* pInfo = taosArrayGet(pQueryInfo->fieldsInfo.internalField, j); + SSchema* pSchema = &pInfo->pExpr->base.resSchema; + if (strcasecmp(pVar->pz, pSchema->name) == 0) { + setColumn(&order.col, pTableMetaInfo->pTableMeta->uid, pTableMetaInfo->aliasName, TSDB_COL_TMP, pSchema); + + order.order = pItem->sortOrder; + taosArrayPush(pQueryInfo->order, &order); + found = true; + break; + } + } + + if (!found) { + return buildInvalidOperationMsg(pMsgBuf, "invalid order by column"); + } + + } else { // order by [1|2|3] + if (pVar->i > getNumOfFields(&pQueryInfo->fieldsInfo)) { + return buildInvalidOperationMsg(pMsgBuf, msg4); + } + + int32_t index = pVar->i - 1; + SExprInfo* pExprInfo = getExprInfo(pQueryInfo, index); + + SOrder c = {0}; + setColumn(&c.col, pTableMetaInfo->pTableMeta->uid, pTableMetaInfo->aliasName, TSDB_COL_TMP, &pExprInfo->base.resSchema); + c.order = pItem->sortOrder; + taosArrayPush(pQueryInfo->order, &c); + } } - SListItem* pItem = taosArrayGet(pSqlNode->pSortOrder, 0); - pQueryInfo->order.order = pItem->sortOrder; - pQueryInfo->order.orderColId = s.colId; - return TSDB_CODE_SUCCESS; } @@ -1237,16 +1259,17 @@ int32_t checkForInvalidOrderby(SQueryStmtInfo *pQueryInfo, SSqlNode* pSqlNode, S #endif static int32_t checkFillQueryRange(SQueryStmtInfo* pQueryInfo, SMsgBuf* pMsgBuf) { - const char* msg3 = "start(end) time of time range required or time range too large"; + const char* msg1 = "start(end) time of time range required or time range too large"; if (pQueryInfo->interval.interval == 0) { return TSDB_CODE_SUCCESS; } - bool initialWindows = TSWINDOW_IS_EQUAL(pQueryInfo->window, TSWINDOW_INITIALIZER); - if (initialWindows) { - return buildInvalidOperationMsg(pMsgBuf, msg3); - } + // TODO disable this check temporarily +// bool initialWindows = TSWINDOW_IS_EQUAL(pQueryInfo->window, TSWINDOW_INITIALIZER); +// if (initialWindows) { +// return buildInvalidOperationMsg(pMsgBuf, msg1); +// } int64_t timeRange = ABS(pQueryInfo->window.skey - pQueryInfo->window.ekey); @@ -1256,7 +1279,7 @@ static int32_t checkFillQueryRange(SQueryStmtInfo* pQueryInfo, SMsgBuf* pMsgBuf) // number of result is not greater than 10,000,000 if ((timeRange == 0) || (timeRange / intervalRange) >= MAX_INTERVAL_TIME_WINDOW) { - return buildInvalidOperationMsg(pMsgBuf, msg3); + return buildInvalidOperationMsg(pMsgBuf, msg1); } } @@ -1373,6 +1396,9 @@ int32_t validateFillNode(SQueryStmtInfo *pQueryInfo, SSqlNode* pSqlNode, SMsgBuf return TSDB_CODE_SUCCESS; } +static void pushDownAggFuncExprInfo(SQueryStmtInfo* pQueryInfo); +static void addColumnNodeFromLowerLevel(SQueryStmtInfo* pQueryInfo); + int32_t validateSqlNode(SSqlNode* pSqlNode, SQueryStmtInfo* pQueryInfo, SMsgBuf* pMsgBuf) { assert(pSqlNode != NULL && (pSqlNode->from == NULL || taosArrayGetSize(pSqlNode->from->list) > 0)); @@ -1524,11 +1550,6 @@ int32_t validateSqlNode(SSqlNode* pSqlNode, SQueryStmtInfo* pQueryInfo, SMsgBuf* return TSDB_CODE_TSC_INVALID_OPERATION; } - // set order by info - if (validateOrderbyNode(pQueryInfo, pSqlNode, pMsgBuf) != TSDB_CODE_SUCCESS) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } - // set interval value if (validateIntervalNode(pQueryInfo, pSqlNode, pMsgBuf) != TSDB_CODE_SUCCESS) { return TSDB_CODE_TSC_INVALID_OPERATION; @@ -1553,6 +1574,11 @@ int32_t validateSqlNode(SSqlNode* pSqlNode, SQueryStmtInfo* pQueryInfo, SMsgBuf* return TSDB_CODE_SUCCESS; } + // set order by info + if (validateOrderbyNode(pQueryInfo, pSqlNode, pMsgBuf) != TSDB_CODE_SUCCESS) { + return TSDB_CODE_TSC_INVALID_OPERATION; + } + if ((code = validateLimitNode(pQueryInfo, pSqlNode, pMsgBuf)) != TSDB_CODE_SUCCESS) { return code; } @@ -1562,9 +1588,159 @@ int32_t validateSqlNode(SSqlNode* pSqlNode, SQueryStmtInfo* pQueryInfo, SMsgBuf* } } + pushDownAggFuncExprInfo(pQueryInfo); +// addColumnNodeFromLowerLevel(pQueryInfo); + + for(int32_t i = 0; i < 1; ++i) { + SArray* functionList = extractFunctionList(pQueryInfo->exprList[i]); + extractFunctionDesc(functionList, &pQueryInfo->info); + + if ((code = checkForInvalidExpr(pQueryInfo, pMsgBuf)) != TSDB_CODE_SUCCESS) { + return code; + } + } + return TSDB_CODE_SUCCESS; // Does not build query message here } +static bool isTagOrPrimaryTs(SExprInfo* pExprInfo) { + if (pExprInfo->pExpr->nodeType != TEXPR_COL_NODE) { + return false; + } + + assert(pExprInfo->base.pColumns->info.colId == pExprInfo->pExpr->pSchema->colId); + return (TSDB_COL_IS_TAG(pExprInfo->base.pColumns->flag) || pExprInfo->pExpr->pSchema->colId == PRIMARYKEY_TIMESTAMP_COL_ID); +} + +// todo extract the table column in expression + +static bool isGroupbyCol(SExprInfo* pExprInfo, SGroupbyExpr* pGroupbyExpr) { + assert(pExprInfo != NULL && pGroupbyExpr != NULL); + + int32_t nodeType = pExprInfo->pExpr->nodeType; + assert(nodeType == TEXPR_COL_NODE || nodeType == TEXPR_BINARYEXPR_NODE); + + for(int32_t i = 0; i < taosArrayGetSize(pGroupbyExpr->columnInfo); ++i) { + SColumn* pCol = taosArrayGet(pGroupbyExpr->columnInfo, i); + if (pCol->info.colId == pExprInfo->pExpr->pSchema->colId) { + return true; + } + } + + return false; +} + +static bool isAllAggExpr(SArray* pList) { + assert(pList != NULL); + + for (int32_t k = 0; k < taosArrayGetSize(pList); ++k) { + SExprInfo* p = taosArrayGetP(pList, k); + if (p->pExpr->nodeType != TEXPR_FUNCTION_NODE || !qIsAggregateFunction(p->pExpr->_function.functionName)) { + return false; + } + } + + return true; +} + +static bool isAllProjectExpr(SArray *pList) { + assert(pList != NULL); + + for(int32_t i = 0; i < taosArrayGetSize(pList); ++i) { + SExprInfo* p = taosArrayGetP(pList, i); + if (p->pExpr->nodeType == TEXPR_FUNCTION_NODE && !qIsAggregateFunction(p->pExpr->_function.functionName)) { + return false; + } + } + + return true; +} + +static SExprInfo* createColumnNodeFromAggFunc(SSchema* pSchema); + +static void pushDownAggFuncExprInfo(SQueryStmtInfo* pQueryInfo) { + assert(pQueryInfo != NULL); + + size_t level = getExprFunctionLevel(pQueryInfo); + for(int32_t i = 0; i < level - 1; ++i) { + SArray* p = pQueryInfo->exprList[i]; + + // If direct lower level expressions are all aggregate function, check if current function can be push down or not + SArray* pNext = pQueryInfo->exprList[i + 1]; + if (!isAllAggExpr(pNext)) { + continue; + } + + for (int32_t j = 0; j < taosArrayGetSize(p); ++j) { + SExprInfo* pExpr = taosArrayGetP(p, j); + + if (pExpr->pExpr->nodeType == TEXPR_FUNCTION_NODE && qIsAggregateFunction(pExpr->pExpr->_function.functionName)) { + bool canPushDown = true; + for (int32_t k = 0; k < taosArrayGetSize(pNext); ++k) { + SExprInfo* pNextLevelExpr = taosArrayGetP(pNext, k); + // pExpr depends on the output of the down level, so it can not be push downwards + if (pExpr->base.pColumns->info.colId == pNextLevelExpr->base.resSchema.colId) { + canPushDown = false; + break; + } + } + + if (canPushDown) { + taosArrayInsert(pNext, j, &pExpr); + taosArrayRemove(p, j); + + // Add the project function of the current level, to output the calculated result + SExprInfo* pNew = createColumnNodeFromAggFunc(&pExpr->base.resSchema); + taosArrayInsert(p, j, &pNew); + } + } + } + } +} + +// todo change the logic plan data +static void addColumnNodeFromLowerLevel(SQueryStmtInfo* pQueryInfo) { + assert(pQueryInfo != NULL); + + size_t level = getExprFunctionLevel(pQueryInfo); + for (int32_t i = 0; i < level - 1; ++i) { + SArray* p = pQueryInfo->exprList[i]; + if (isAllAggExpr(p)) { + continue; + } + + // If direct lower level expressions are all aggregate function, check if current function can be push down or not + SArray* pNext = pQueryInfo->exprList[i + 1]; + if (isAllAggExpr(pNext)) { + continue; + } + + for (int32_t j = 0; j < taosArrayGetSize(pNext); ++j) { + SExprInfo* pExpr = taosArrayGetP(p, j); + + bool exists = false; + for (int32_t k = 0; k < taosArrayGetSize(p); ++k) { + SExprInfo* pNextLevelExpr = taosArrayGetP(pNext, k); + // pExpr depends on the output of the down level, so it can not be push downwards + if (pExpr->base.pColumns->info.colId == pNextLevelExpr->base.resSchema.colId) { + exists = true; + break; + } + } + + if (!exists) { + SExprInfo* pNew = calloc(1, sizeof(SExprInfo)); + pNew->pExpr = exprdup(pExpr->pExpr); + memcpy(&pNew->base, &pExpr->base, sizeof(SSqlExpr)); + + int32_t pos = taosArrayGetSize(p); + // Add the project function of the current level, to output the calculated result + taosArrayInsert(p, pos - 1, &pExpr); + } + } + } +} + int32_t checkForInvalidExpr(SQueryStmtInfo* pQueryInfo, SMsgBuf* pMsgBuf) { assert(pQueryInfo != NULL && pMsgBuf != NULL); @@ -1583,9 +1759,18 @@ int32_t checkForInvalidExpr(SQueryStmtInfo* pQueryInfo, SMsgBuf* pMsgBuf) { // 1. invalid sql: // select top(col, k) from table_name [interval(1d)|session(ts, 1d)|statewindow(col)] order by k asc // order by normal column is not supported - int32_t colId = pQueryInfo->order.orderColId; - if (pQueryInfo->info.timewindow && colId != PRIMARYKEY_TIMESTAMP_COL_ID) { - return buildInvalidOperationMsg(pMsgBuf, msg2); + if (pQueryInfo->order != NULL) { + size_t numOfOrder = taosArrayGetSize(pQueryInfo->order); + if (numOfOrder > 1) { + return buildInvalidOperationMsg(pMsgBuf, msg2); + } + + if (numOfOrder > 0) { + SColumn* pOrderCol = taosArrayGet(pQueryInfo->order, 0); + if (pQueryInfo->info.timewindow && pOrderCol->info.colId != PRIMARYKEY_TIMESTAMP_COL_ID) { + return buildInvalidOperationMsg(pMsgBuf, msg2); + } + } } // select top(col, k) from table_name interval(10s) fill(prev) @@ -1593,6 +1778,41 @@ int32_t checkForInvalidExpr(SQueryStmtInfo* pQueryInfo, SMsgBuf* pMsgBuf) { if (pQueryInfo->fillType != TSDB_FILL_NONE) { return buildInvalidOperationMsg(pMsgBuf, msg4); } + + // select top(col, k), count(*) from table_name + size_t size = getNumOfExprs(pQueryInfo); + for (int32_t i = 0; i < size; ++i) { + SExprInfo* pExpr = getExprInfo(pQueryInfo, i); + + if (pExpr->pExpr->nodeType == TEXPR_COL_NODE) { + if (!isTagOrPrimaryTs(pExpr) && !isGroupbyCol(pExpr, &pQueryInfo->groupbyExpr)) { + return buildInvalidOperationMsg(pMsgBuf, "invalid expression in select clause"); + } + + } else if (pExpr->pExpr->nodeType == TEXPR_BINARYEXPR_NODE) { + continue; + // todo extract all column node in tree, and check for each node + + continue; + } + + // dummy column is also the placeholder for primary timestamp column in the result. + const char* functionName = pExpr->pExpr->_function.functionName; + if (strcmp(functionName, "top") != 0 && strcmp(functionName, "bottom") != 0 && strcmp(functionName, "dummy") != 0) { + if (qIsAggregateFunction(functionName)) { + return buildInvalidOperationMsg(pMsgBuf, "invalid expression in select clause"); + } + + // the primary key is valid + if (pExpr->pExpr->nodeType == TEXPR_COL_NODE) { + if (pExpr->pExpr->pSchema->colId == PRIMARYKEY_TIMESTAMP_COL_ID) { + continue; + } + } + + continue; + } + } } /* @@ -1603,7 +1823,11 @@ int32_t checkForInvalidExpr(SQueryStmtInfo* pQueryInfo, SMsgBuf* pMsgBuf) { size_t size = getNumOfExprs(pQueryInfo); for (int32_t i = 0; i < size; ++i) { SExprInfo* pExpr = getExprInfo(pQueryInfo, i); - int32_t functionId = getExprFunctionId(pExpr); + if (pExpr->pExpr->nodeType != TEXPR_FUNCTION_NODE) { + continue; + } + + int32_t functionId = getExprFunctionId(pExpr); if (functionId == FUNCTION_COUNT && TSDB_COL_IS_TAG(pExpr->base.pColumns->flag)) { return buildInvalidOperationMsg(pMsgBuf, msg1); } @@ -1667,11 +1891,35 @@ int32_t checkForInvalidExpr(SQueryStmtInfo* pQueryInfo, SMsgBuf* pMsgBuf) { pQueryInfo->info.groupbyColumn) { return buildInvalidOperationMsg(pMsgBuf, msg9); } -} -static int32_t resColId = 5000; -int32_t getNewResColId() { - return resColId++; + /* + * 9. invalid sql: + * select count(*), col_name from table_name + */ + if (pQueryInfo->info.agg) { + bool isSelectivity = false; + + if (pQueryInfo->info.projectionQuery) { + size_t size = getNumOfExprs(pQueryInfo); + for (int32_t i = 0; i < size; ++i) { + SExprInfo* pExpr = getExprInfo(pQueryInfo, i); + if (pExpr->pExpr->nodeType == TEXPR_FUNCTION_NODE) { + if (!isSelectivity) { + isSelectivity = qIsSelectivityFunction(pExpr->pExpr->_function.functionName); + } + continue; + } + + if (isSelectivity && isTagOrPrimaryTs(pExpr)) { + continue; + } + + if (!isGroupbyCol(pExpr, &pQueryInfo->groupbyExpr)) { + return buildInvalidOperationMsg(pMsgBuf, "invalid expression in select"); + } + } + } + } } int32_t addResColumnInfo(SQueryStmtInfo* pQueryInfo, int32_t outputIndex, SSchema* pSchema, SExprInfo* pSqlExpr) { @@ -1787,7 +2035,6 @@ static int32_t checkForAliasName(SMsgBuf* pMsgBuf, char* aliasName) { return TSDB_CODE_SUCCESS; } -static int32_t validateComplexExpr(tSqlExpr* pExpr, SQueryStmtInfo* pQueryInfo, SArray* pColList, int32_t* type, SMsgBuf* pMsgBuf); static int32_t sqlExprToExprNode(tExprNode **pExpr, const tSqlExpr* pSqlExpr, SQueryStmtInfo* pQueryInfo, SArray* pCols, bool* keepTableCols, SMsgBuf* pMsgBuf); static int64_t getTickPerSecond(SVariant* pVariant, int32_t precision, int64_t* tickPerSec, SMsgBuf *pMsgBuf) { @@ -1820,7 +2067,7 @@ static void setTsOutputExprInfo(SQueryStmtInfo* pQueryInfo, STableMetaInfo* pTab SSourceParam param = {0}; addIntoSourceParam(¶m, NULL, &col); - SExprInfo* pExpr = createExprInfo(pTableMetaInfo, "ts_dummy", ¶m, &s, TSDB_KEYSIZE); + SExprInfo* pExpr = createExprInfo(pTableMetaInfo, "dummy", ¶m, &s, TSDB_KEYSIZE); strncpy(pExpr->base.token, "ts", tListLen(pExpr->base.token)); SArray* pExprList = getCurrentExprList(pQueryInfo); @@ -2600,15 +2847,15 @@ static int32_t validateExprLeafFunctionNode(SQueryStmtInfo* pQueryInfo, tSqlExpr return TSDB_CODE_SUCCESS; } -int32_t validateScalarFunctionParamNum(tSqlExprItem* pItem, SMsgBuf* pMsgBuf) { +static int32_t validateScalarFunctionParamNum(tSqlExpr* pSqlExpr, int32_t functionId, SMsgBuf* pMsgBuf) { int32_t code = TSDB_CODE_SUCCESS; - switch (pItem->functionId) { + switch (functionId) { case FUNCTION_CEIL: { - code = checkForkParam(pItem->pNode, 1, pMsgBuf); + code = checkForkParam(pSqlExpr, 1, pMsgBuf); break; } case FUNCTION_LENGTH: { - code = checkForkParam(pItem->pNode, 1, pMsgBuf); + code = checkForkParam(pSqlExpr, 1, pMsgBuf); break; } } @@ -2616,67 +2863,54 @@ int32_t validateScalarFunctionParamNum(tSqlExprItem* pItem, SMsgBuf* pMsgBuf) { return code; } -int32_t validateScalarFunctionParam(SQueryStmtInfo* pQueryInfo, tSqlExpr* pExpr, SArray* pList, int32_t* exprType, SMsgBuf* pMsgBuf) { - int32_t code = TSDB_CODE_SUCCESS; - - SArray* pParamList = pExpr->Expr.paramList; - *exprType = NORMAL_ARITHMETIC; - - for (int32_t i = 0; i < 1; ++i) { - tSqlExprItem* pParamElem = taosArrayGet(pParamList, i); - tSqlExpr* pSqlExpr = pParamElem->pNode; - - int32_t type = pSqlExpr->type; - if (type == SQL_NODE_VALUE) { - // do nothing for scalar function, or maybe the evaluation can be done here - } else if (type == SQL_NODE_SQLFUNCTION) { - code = validateExprLeafFunctionNode(pQueryInfo, pSqlExpr, pMsgBuf); - if (code != TSDB_CODE_SUCCESS) { - return code; - } - } else if (type == SQL_NODE_EXPR) { - code = validateComplexExpr(pSqlExpr, pQueryInfo, pList, exprType, pMsgBuf); - if (code != TSDB_CODE_SUCCESS) { - return code; - } - } else if (type == SQL_NODE_TABLE_COLUMN) { - code = validateExprLeafColumnNode(pQueryInfo, &pSqlExpr->columnName, pList, pMsgBuf); - if (code != TSDB_CODE_SUCCESS) { - return code; - } - } - } -} - -SExprInfo* doAddProjectCol(SQueryStmtInfo* pQueryInfo, int32_t outputColIndex, SColumnIndex* pColIndex, const char* aliasName, int32_t colId) { - STableMeta* pTableMeta = getMetaInfo(pQueryInfo, pColIndex->tableIndex)->pTableMeta; - - SSchema* pSchema = getOneColumnSchema(pTableMeta, pColIndex->columnIndex); - SColumnIndex index = *pColIndex; - - char* funcName = NULL; - if (TSDB_COL_IS_TAG(index.type)) { - int32_t numOfCols = getNumOfColumns(pTableMeta); - index.columnIndex = pColIndex->columnIndex - numOfCols; - funcName = "project_tag"; - } else { - index.columnIndex = pColIndex->columnIndex; - funcName = "project_col"; - } - +// todo merge with the addScalarExprAndResColumn +int32_t doAddOneProjectCol(SQueryStmtInfo* pQueryInfo, int32_t outputColIndex, SSchema* pSchema, const char* aliasName, + int32_t colId, SMsgBuf* pMsgBuf) { const char* name = (aliasName == NULL)? pSchema->name:aliasName; SSchema s = createSchema(pSchema->type, pSchema->bytes, colId, name); - STableMetaInfo* pTableMetaInfo = getMetaInfo(pQueryInfo, index.tableIndex); - SColumn c = createColumn(pTableMetaInfo->pTableMeta->uid, pTableMetaInfo->aliasName, index.type, pSchema); + SArray* pColumnList = taosArrayInit(4, sizeof(SColumn)); + SToken colNameToken = {.z = pSchema->name, .n = strlen(pSchema->name)}; - SSourceParam param = {0}; - addIntoSourceParam(¶m, NULL, &c); + tSqlExpr sqlNode = {0}; + sqlNode.type = SQL_NODE_TABLE_COLUMN; + sqlNode.columnName = colNameToken; - return doAddOneExprInfo(pQueryInfo, funcName, ¶m, outputColIndex, pTableMetaInfo, &s, 0, s.name, true); + tExprNode* pNode = NULL; + bool keepTableCols = true; + int32_t ret = sqlExprToExprNode(&pNode, &sqlNode, pQueryInfo, pColumnList, &keepTableCols, pMsgBuf); + if (ret != TSDB_CODE_SUCCESS) { + tExprTreeDestroy(pNode, NULL); + return buildInvalidOperationMsg(pMsgBuf, "invalid expression in select clause"); + } + + SExprInfo* pExpr = createBinaryExprInfo(pNode, &s); + tstrncpy(pExpr->base.resSchema.name, name, tListLen(pExpr->base.resSchema.name)); + tstrncpy(pExpr->base.token, name, tListLen(pExpr->base.token)); + + SArray* pExprList = getCurrentExprList(pQueryInfo); + addExprInfo(pExprList, outputColIndex, pExpr, pQueryInfo->exprListLevelIndex); + + // extract columns according to the tExprNode tree + size_t num = taosArrayGetSize(pColumnList); + pExpr->base.pColumns = calloc(num, sizeof(SColumn)); + for (int32_t i = 0; i < num; ++i) { + SColumn* pCol = taosArrayGet(pColumnList, i); + pExpr->base.pColumns[i] = *pCol; + } + + pExpr->base.numOfCols = num; + + if (pQueryInfo->exprListLevelIndex == 0) { + int32_t exists = getNumOfFields(&pQueryInfo->fieldsInfo); + addResColumnInfo(pQueryInfo, exists, &pExpr->base.resSchema, pExpr); + } + + pQueryInfo->info.projectionQuery = true; + return TSDB_CODE_SUCCESS; } -static int32_t doAddProjectionExprAndResColumn(SQueryStmtInfo* pQueryInfo, SColumnIndex* pIndex, int32_t startPos) { +static int32_t doAddMultipleProjectExprAndResColumns(SQueryStmtInfo* pQueryInfo, SColumnIndex* pIndex, int32_t startPos, SMsgBuf* pMsgBuf) { STableMetaInfo* pTableMetaInfo = getMetaInfo(pQueryInfo, pIndex->tableIndex); STableMeta* pTableMeta = pTableMetaInfo->pTableMeta; @@ -2688,8 +2922,8 @@ static int32_t doAddProjectionExprAndResColumn(SQueryStmtInfo* pQueryInfo, SColu } for (int32_t j = 0; j < numOfTotalColumns; ++j) { - pIndex->columnIndex = j; - doAddProjectCol(pQueryInfo, startPos + j, pIndex, NULL, getNewResColId()); + SSchema* pSchema = getOneColumnSchema(pTableMetaInfo->pTableMeta, j); + doAddOneProjectCol(pQueryInfo, startPos + j, pSchema, NULL, getNewResColId(), pMsgBuf); } return numOfTotalColumns; @@ -2728,11 +2962,9 @@ static SSchema createConstantColumnSchema(SVariant* pVal, const SToken* exprStr, } static int32_t handleTbnameProjection(SQueryStmtInfo* pQueryInfo, tSqlExprItem* pItem, SColumnIndex* pIndex, int32_t startPos, bool outerQuery, SMsgBuf* pMsgBuf) { - const char* msg3 = "tbname not allowed in outer query"; + const char* msg1 = "tbname not allowed in outer query"; SSchema colSchema = {0}; - char* funcName = NULL; - if (outerQuery) { // todo?? STableMetaInfo* pTableMetaInfo = getMetaInfo(pQueryInfo, pIndex->tableIndex); @@ -2749,36 +2981,20 @@ static int32_t handleTbnameProjection(SQueryStmtInfo* pQueryInfo, tSqlExprItem* } if (!existed) { - return buildInvalidOperationMsg(pMsgBuf, msg3); + return buildInvalidOperationMsg(pMsgBuf, msg1); } colSchema = pSchema[pIndex->columnIndex]; - funcName = "project_col"; } else { colSchema = *getTbnameColumnSchema(); - funcName = "project_tag"; } - SSchema resultSchema = colSchema; - resultSchema.colId = getNewResColId(); - - char rawName[TSDB_COL_NAME_LEN] = {0}; - setTokenAndResColumnName(pItem, resultSchema.name, rawName, sizeof(colSchema.name) - 1); - - STableMetaInfo* pTableMetaInfo = getMetaInfo(pQueryInfo, pIndex->tableIndex); - SColumn c = createColumn(pTableMetaInfo->pTableMeta->uid, pTableMetaInfo->aliasName, pIndex->type, &colSchema); - - SSourceParam param = {0}; - addIntoSourceParam(¶m, NULL, &c); - - doAddOneExprInfo(pQueryInfo, "project_tag", ¶m, startPos, pTableMetaInfo, &colSchema, 0, rawName, true); - return TSDB_CODE_SUCCESS; + return doAddOneProjectCol(pQueryInfo, startPos, &colSchema, pItem->aliasName, getNewResColId(), pMsgBuf); } int32_t addProjectionExprAndResColumn(SQueryStmtInfo* pQueryInfo, tSqlExprItem* pItem, bool outerQuery, SMsgBuf* pMsgBuf) { const char* msg1 = "tag for normal table query is not allowed"; const char* msg2 = "invalid column name"; - const char* msg3 = "tbname not allowed in outer query"; if (checkForAliasName(pMsgBuf, pItem->aliasName) != TSDB_CODE_SUCCESS) { return TSDB_CODE_TSC_INVALID_OPERATION; @@ -2798,11 +3014,11 @@ int32_t addProjectionExprAndResColumn(SQueryStmtInfo* pQueryInfo, tSqlExprItem* if (index.tableIndex == COLUMN_INDEX_INITIAL_VAL) { // all table columns are required. for (int32_t i = 0; i < pQueryInfo->numOfTables; ++i) { index.tableIndex = i; - int32_t inc = doAddProjectionExprAndResColumn(pQueryInfo, &index, startPos); + int32_t inc = doAddMultipleProjectExprAndResColumns(pQueryInfo, &index, startPos, pMsgBuf); startPos += inc; } } else { - doAddProjectionExprAndResColumn(pQueryInfo, &index, startPos); + doAddMultipleProjectExprAndResColumns(pQueryInfo, &index, startPos, pMsgBuf); } // add the primary timestamp column even though it is not required by user @@ -2841,7 +3057,8 @@ int32_t addProjectionExprAndResColumn(SQueryStmtInfo* pQueryInfo, tSqlExprItem* return buildInvalidOperationMsg(pMsgBuf, msg1); } - doAddProjectCol(pQueryInfo, startPos, &index, pItem->aliasName, getNewResColId()); + SSchema* pSchema = getOneColumnSchema(pTableMetaInfo->pTableMeta, index.columnIndex); + doAddOneProjectCol(pQueryInfo, startPos, pSchema, pItem->aliasName, getNewResColId(), pMsgBuf); } // add the primary timestamp column even though it is not required by user @@ -2888,57 +3105,6 @@ static int32_t validateExprLeafNode(tSqlExpr* pExpr, SQueryStmtInfo* pQueryInfo, return TSDB_CODE_SUCCESS; } -int32_t validateComplexExpr(tSqlExpr * pExpr, SQueryStmtInfo* pQueryInfo, SArray* pColList, int32_t* type, SMsgBuf* pMsgBuf) { - if (pExpr == NULL) { - return TSDB_CODE_SUCCESS; - } - - int32_t code = TSDB_CODE_SUCCESS; - if (pExpr->type == SQL_NODE_SQLFUNCTION) { - return validateScalarFunctionParam(pQueryInfo, pExpr, pColList, type, pMsgBuf); - } - - tSqlExpr* pLeft = pExpr->pLeft; - if (pLeft->type == SQL_NODE_EXPR) { - code = validateComplexExpr(pLeft, pQueryInfo, pColList, type, pMsgBuf); - if (code != TSDB_CODE_SUCCESS) { - return code; - } - } else { - code = validateExprLeafNode(pLeft, pQueryInfo, pColList, type, pMsgBuf); - if (code != TSDB_CODE_SUCCESS) { - return code; - } - } - - tSqlExpr* pRight = pExpr->pRight; - if (pRight->type == SQL_NODE_EXPR) { - code = validateComplexExpr(pRight, pQueryInfo, pColList, type, pMsgBuf); - if (code != TSDB_CODE_SUCCESS) { - return code; - } - } else { - code = validateExprLeafNode(pRight, pQueryInfo, pColList, type, pMsgBuf); - if (code != TSDB_CODE_SUCCESS) { - return code; - } - } - - // check divide by 0 - if (pExpr->tokenId == TK_DIVIDE && pRight->type == SQL_NODE_VALUE) { - int32_t type1 = pRight->value.nType; - const char* msg1 = "invalid expr (divide by 0)"; - - if (type1 == TSDB_DATA_TYPE_DOUBLE && pRight->value.d < DBL_EPSILON) { - return buildInvalidOperationMsg(pMsgBuf, msg1); - } else if (type1 == TSDB_DATA_TYPE_INT && pRight->value.i == 0) { - return buildInvalidOperationMsg(pMsgBuf, msg1); - } - } - - return TSDB_CODE_SUCCESS; -} - static uint64_t findTmpSourceColumnInNextLevel(SQueryStmtInfo* pQueryInfo, tExprNode *pExpr) { // This function must be a aggregate function, so it must be in the next level pQueryInfo->exprListLevelIndex += 1; @@ -2972,31 +3138,60 @@ static tExprNode* doCreateColumnNode(SQueryStmtInfo* pQueryInfo, SColumnIndex* p STableMeta* pTableMeta = pTableMetaInfo->pTableMeta; tExprNode* pExpr = calloc(1, sizeof(tExprNode)); - pExpr->nodeType = TEXPR_COL_NODE; - pExpr->pSchema = calloc(1, sizeof(SSchema)); - SSchema* pSchema = getOneColumnSchema(pTableMeta, pIndex->columnIndex); + pExpr->nodeType = TEXPR_COL_NODE; + pExpr->pSchema = calloc(1, sizeof(SSchema)); + + SSchema* pSchema = NULL; + if (pIndex->columnIndex == TSDB_TBNAME_COLUMN_INDEX) { + pSchema = getTbnameColumnSchema(); + } else { + pSchema = getOneColumnSchema(pTableMeta, pIndex->columnIndex); + } + *(SSchema*)(pExpr->pSchema) = *pSchema; - if (keepTableCols) { + if (keepTableCols && TSDB_COL_IS_NORMAL_COL(pIndex->type)) { SColumn c = createColumn(pTableMeta->uid, pTableMetaInfo->aliasName, pIndex->type, pExpr->pSchema); taosArrayPush(pCols, &c); } - columnListInsert(pQueryInfo->colList, pTableMeta->uid, pSchema, TSDB_COL_NORMAL); - SSchema* pTsSchema = getOneColumnSchema(pTableMeta, 0); - insertPrimaryTsColumn(pQueryInfo->colList, pTsSchema->name, pTableMeta->uid); + if (TSDB_COL_IS_NORMAL_COL(pIndex->type)) { + columnListInsert(pQueryInfo->colList, pTableMeta->uid, pSchema, TSDB_COL_NORMAL); + SSchema* pTsSchema = getOneColumnSchema(pTableMeta, 0); + insertPrimaryTsColumn(pQueryInfo->colList, pTsSchema->name, pTableMeta->uid); + } else { + columnListInsert(pTableMetaInfo->tagColList, pTableMeta->uid, pSchema, TSDB_COL_TAG); + } + + return pExpr; +} + +static SExprInfo* createColumnNodeFromAggFunc(SSchema* pSchema) { + tExprNode* pExprNode = calloc(1, sizeof(tExprNode)); + + pExprNode->nodeType = TEXPR_COL_NODE; + pExprNode->pSchema = calloc(1, sizeof(SSchema)); + *(SSchema*)(pExprNode->pSchema) = *pSchema; + + SExprInfo* pExpr = calloc(1, sizeof(SExprInfo)); + if (pExpr == NULL) { + return NULL; + } + + pExpr->pExpr = pExprNode; + memcpy(&pExpr->base.resSchema, pSchema, sizeof(SSchema)); return pExpr; } static int32_t validateSqlExpr(const tSqlExpr* pSqlExpr, SQueryStmtInfo *pQueryInfo, SMsgBuf* pMsgBuf); -static int32_t doProcessFunctionLeafNodeParam(SQueryStmtInfo* pQueryInfo, int32_t* num, tExprNode** p, SArray* pCols, +static int32_t doProcessFunctionLeafNodeParam(SQueryStmtInfo* pQueryInfo, int32_t* num, tExprNode*** p, SArray* pCols, bool* keepTableCols, const tSqlExpr* pSqlExpr, SMsgBuf* pMsgBuf) { SArray* pParamList = pSqlExpr->Expr.paramList; if (pParamList != NULL) { *num = taosArrayGetSize(pParamList); - p = calloc((*num), POINTER_BYTES); + (*p) = calloc((*num), POINTER_BYTES); for (int32_t i = 0; i < (*num); ++i) { tSqlExprItem* pItem = taosArrayGet(pParamList, i); @@ -3006,7 +3201,7 @@ static int32_t doProcessFunctionLeafNodeParam(SQueryStmtInfo* pQueryInfo, int32_ return ret; } - int32_t code = sqlExprToExprNode(&p[i], pItem->pNode, pQueryInfo, pCols, keepTableCols, pMsgBuf); + int32_t code = sqlExprToExprNode(&(*p)[i], pItem->pNode, pQueryInfo, pCols, keepTableCols, pMsgBuf); if (code != TSDB_CODE_SUCCESS) { return code; } @@ -3017,10 +3212,10 @@ static int32_t doProcessFunctionLeafNodeParam(SQueryStmtInfo* pQueryInfo, int32_ } *num = 1; - p = calloc(*num, POINTER_BYTES); + (*p) = calloc(*num, POINTER_BYTES); SColumnIndex index = {.type = TSDB_COL_NORMAL, .tableIndex = 0, .columnIndex = 0}; - p[0] = doCreateColumnNode(pQueryInfo, &index, *keepTableCols, pCols); + (*p)[0] = doCreateColumnNode(pQueryInfo, &index, *keepTableCols, pCols); } return TSDB_CODE_SUCCESS; @@ -3080,7 +3275,8 @@ int32_t validateSqlExpr(const tSqlExpr* pSqlExpr, SQueryStmtInfo *pQueryInfo, SM } int32_t tokenId = pSqlExpr->tokenId; - if (pRight->type == SQL_NODE_VALUE && pRight->value.nType == TSDB_DATA_TYPE_DOUBLE && pRight->value.d == 0 && tokenId == TK_DIVIDE) { + if (pRight->type == SQL_NODE_VALUE && (pRight->value.nType == TSDB_DATA_TYPE_DOUBLE || pRight->value.nType == TSDB_DATA_TYPE_INT) && + pRight->value.d == 0 && tokenId == TK_DIVIDE) { return buildInvalidOperationMsg(pMsgBuf, "invalid expression (divided by 0)"); } @@ -3098,6 +3294,20 @@ int32_t validateSqlExpr(const tSqlExpr* pSqlExpr, SQueryStmtInfo *pQueryInfo, SM if (ret != TSDB_CODE_SUCCESS) { return ret; } + } else if (pSqlExpr->type == SQL_NODE_SQLFUNCTION) { + bool scalar = false; + int32_t functionId = qIsBuiltinFunction(pSqlExpr->Expr.operand.z, pSqlExpr->Expr.operand.n, &scalar); + if (functionId < 0) { + return buildInvalidOperationMsg(pMsgBuf, "invalid function name"); + } + + // do check the parameter number for scalar function + if (scalar) { + int32_t ret = validateScalarFunctionParamNum((tSqlExpr*) pSqlExpr, functionId, pMsgBuf); + if (ret != TSDB_CODE_SUCCESS) { + return buildInvalidOperationMsg(pMsgBuf, "invalid number of function parameters"); + } + } } return TSDB_CODE_SUCCESS; @@ -3143,7 +3353,7 @@ int32_t sqlExprToExprNode(tExprNode **pExpr, const tSqlExpr* pSqlExpr, SQueryStm int32_t num = 0; tExprNode** p = NULL; - int32_t code = doProcessFunctionLeafNodeParam(pQueryInfo, &num, p, pCols, keepTableCols, pSqlExpr, pMsgBuf); + int32_t code = doProcessFunctionLeafNodeParam(pQueryInfo, &num, &p, pCols, keepTableCols, pSqlExpr, pMsgBuf); if (code != TSDB_CODE_SUCCESS) { return code; } @@ -3203,6 +3413,9 @@ int32_t sqlExprToExprNode(tExprNode **pExpr, const tSqlExpr* pSqlExpr, SQueryStm (*pExpr)->pSchema = calloc(1, sizeof(SSchema)); strncpy((*pExpr)->pSchema->name, pSqlExpr->exprToken.z, pSqlExpr->exprToken.n); + // it must be the aggregate function + assert(qIsAggregateFunction((*pExpr)->pSchema->name)); + uint64_t uid = findTmpSourceColumnInNextLevel(pQueryInfo, *pExpr); if (!(*keepTableCols)) { SColumn c = createColumn(uid, NULL, TSDB_COL_TMP, (*pExpr)->pSchema); @@ -3265,26 +3478,6 @@ int32_t sqlExprToExprNode(tExprNode **pExpr, const tSqlExpr* pSqlExpr, SQueryStm return TSDB_CODE_SUCCESS; } -static int32_t multiColumnListInsert(SQueryStmtInfo* pQueryInfo, SArray* pColumnList, SMsgBuf* pMsgBuf) { - const char* msg1 = "tag can not be used in expression"; - - SColumn* p1 = taosArrayGet(pColumnList, 0); - - size_t numOfNode = taosArrayGetSize(pColumnList); - for(int32_t k = 0; k < numOfNode; ++k) { - SColumn* p = taosArrayGet(pColumnList, k); - if (TSDB_COL_IS_TAG(p->flag)) { - return buildInvalidOperationMsg(pMsgBuf, msg1); - } - - SSchema s = createSchema(p->info.type, p->info.bytes, p->info.colId, p->name); - columnListInsert(pQueryInfo->colList, p->uid, &s, p->flag); - } - - insertPrimaryTsColumn(pQueryInfo->colList, NULL, p1->uid); - return TSDB_CODE_SUCCESS; -} - static int32_t addScalarExprAndResColumn(SQueryStmtInfo* pQueryInfo, int32_t exprIndex, tSqlExprItem* pItem, SMsgBuf* pMsgBuf) { SArray* pColumnList = taosArrayInit(4, sizeof(SColumn)); SSchema s = createSchema(TSDB_DATA_TYPE_DOUBLE, sizeof(double), getNewResColId(), ""); @@ -3379,14 +3572,14 @@ int32_t validateSelectNodeList(SQueryStmtInfo* pQueryInfo, SArray* pSelNodeList, if (type == SQL_NODE_SQLFUNCTION) { bool scalarFunc = false; pItem->functionId = qIsBuiltinFunction(pItem->pNode->Expr.operand.z, pItem->pNode->Expr.operand.n, &scalarFunc); - if (pItem->functionId == FUNCTION_INVALID_ID) { - int32_t functionId = FUNCTION_INVALID_ID; - bool valid = qIsValidUdf(pQueryInfo->pUdfInfo, pItem->pNode->Expr.operand.z, pItem->pNode->Expr.operand.n, &functionId); - if (!valid) { + if (pItem->functionId == FUNCTION_INVALID_ID) { // temporarily disable the udf +// int32_t functionId = FUNCTION_INVALID_ID; +// bool valid = qIsValidUdf(pQueryInfo->pUdfInfo, pItem->pNode->Expr.operand.z, pItem->pNode->Expr.operand.n, &functionId); +// if (!valid) { return buildInvalidOperationMsg(pMsgBuf, msg5); - } +// } - pItem->functionId = functionId; +// pItem->functionId = functionId; } if (scalarFunc) { // scalar function @@ -3401,7 +3594,7 @@ int32_t validateSelectNodeList(SQueryStmtInfo* pQueryInfo, SArray* pSelNodeList, } } else if (type == SQL_NODE_TABLE_COLUMN || type == SQL_NODE_VALUE) { // use the dynamic array list to decide if the function is valid or not - // select table_name1.field_name1, table_name2.field_name2 from table_name1, table_name2 + // select table_name1.field_name1, table_name2.field_name2 from table_name1, table_name2 if ((code = addProjectionExprAndResColumn(pQueryInfo, pItem, outerQuery, pMsgBuf)) != TSDB_CODE_SUCCESS) { return code; } @@ -3920,12 +4113,6 @@ int32_t qParserValidateSqlNode(struct SCatalog* pCatalog, SSqlInfo* pInfo, SQuer validateSqlNode(p, pQueryInfo, &buf); } - SArray* functionList = extractFunctionList(pQueryInfo->exprList[0]); - extractFunctionDesc(functionList, &pQueryInfo->info); - - if ((code = checkForInvalidExpr(pQueryInfo, &buf)) != TSDB_CODE_SUCCESS) { - return code; - } return code; } diff --git a/source/libs/parser/src/queryInfoUtil.c b/source/libs/parser/src/queryInfoUtil.c index 04922ce5ad..c548f1556a 100644 --- a/source/libs/parser/src/queryInfoUtil.c +++ b/source/libs/parser/src/queryInfoUtil.c @@ -223,7 +223,7 @@ void addExprInfoParam(SSqlExpr* pExpr, char* argument, int32_t type, int32_t byt } int32_t getExprFunctionId(SExprInfo *pExprInfo) { - assert(pExprInfo != NULL && pExprInfo->pExpr != NULL && pExprInfo->pExpr->nodeType == TEXPR_UNARYEXPR_NODE); + assert(pExprInfo != NULL && pExprInfo->pExpr != NULL && pExprInfo->pExpr->nodeType == TEXPR_FUNCTION_NODE); return 0; } @@ -324,10 +324,17 @@ SArray* extractFunctionList(SArray* pExprInfoList) { assert(pExprInfoList != NULL); size_t len = taosArrayGetSize(pExprInfoList); - SArray* p = taosArrayInit(len, sizeof(int32_t)); + SArray* p = taosArrayInit(len, POINTER_BYTES); + for(int32_t i = 0; i < len; ++i) { SExprInfo* pExprInfo = taosArrayGetP(pExprInfoList, i); - taosArrayPush(p, &pExprInfo->pExpr->_function.functionName); + if (pExprInfo->pExpr->nodeType == TEXPR_FUNCTION_NODE) { + char* name = strdup(pExprInfo->pExpr->_function.functionName); + taosArrayPush(p, &name); + } else { + char* name = strdup("project"); + taosArrayPush(p, &name); + } } return p; @@ -350,11 +357,16 @@ bool tscHasColumnFilter(SQueryStmtInfo* pQueryInfo) { return false; } -//void tscClearInterpInfo(SQueryStmtInfo* pQueryInfo) { -// if (!tscIsPointInterpQuery(pQueryInfo)) { -// return; -// } -// -// pQueryInfo->fillType = TSDB_FILL_NONE; -// tfree(pQueryInfo->fillVal); -//} \ No newline at end of file +int32_t getExprFunctionLevel(SQueryStmtInfo* pQueryInfo) { + int32_t n = 10; + + int32_t level = 0; + for(int32_t i = 0; i < n; ++i) { + SArray* pList = pQueryInfo->exprList[i]; + if (taosArrayGetSize(pList) > 0) { + level += 1; + } + } + + return level; +} \ No newline at end of file diff --git a/source/libs/parser/test/parserTests.cpp b/source/libs/parser/test/parserTests.cpp index 6e491cedb0..2193a44604 100644 --- a/source/libs/parser/test/parserTests.cpp +++ b/source/libs/parser/test/parserTests.cpp @@ -16,6 +16,7 @@ #include #include #include +#include "tglobal.h" #pragma GCC diagnostic ignored "-Wwrite-strings" #pragma GCC diagnostic ignored "-Wunused-function" @@ -398,6 +399,7 @@ TEST(testCase, function_Test5) { TEST(testCase, function_Test10) { sqlCheck("select c from `t.1abc`", true); sqlCheck("select length(c) from `t.1abc`", true); + sqlCheck("select length(sum(col)) from `t.1abc`", true); sqlCheck("select sum(length(a+b)) from `t.1abc`", true); sqlCheck("select sum(sum(a+b)) from `t.1abc`", false); sqlCheck("select sum(length(a) + length(b)) from `t.1abc`", true); @@ -406,12 +408,27 @@ TEST(testCase, function_Test10) { sqlCheck("select cov(a, b) from `t.1abc`", true); sqlCheck("select sum(length(a) + count(b)) from `t.1abc`", false); + sqlCheck("select concat(sum(a), count(b)) from `t.1abc`", true); + sqlCheck("select concat(concat(a,b), concat(a,b)) from `t.1abc`", true); sqlCheck("select length(length(length(a))) from `t.1abc`", true); sqlCheck("select count() from `t.1abc`", false); sqlCheck("select block_dist() from `t.1abc`", true); sqlCheck("select block_dist(a) from `t.1abc`", false); sqlCheck("select count(*) from `t.1abc` interval(1s) group by a", false); + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// + sqlCheck("select length119(a,b) from `t.1abc`", false); + sqlCheck("select length(a, b) from `t.1abc`", false); + sqlCheck("select block_dist() + 20 from `t.1abc`", true); + sqlCheck("select count(b), c from `t.1abc`", false); + sqlCheck("select top(a, 20), count(b) from `t.1abc`", false); + sqlCheck("select top(a, 20), b from `t.1abc`", false); + sqlCheck("select top(a, 20), a+20 from `t.1abc`", true); +// sqlCheck("select top(a, 20), bottom(a, 10) from `t.1abc`", false); +// sqlCheck("select last_row(*), count(b) from `t.1abc`", false); +// sqlCheck("select last_row(a, b) + 20 from `t.1abc`", false); +// sqlCheck("select last_row(count(*)) from `t.1abc`", false); } TEST(testCase, function_Test6) { @@ -441,9 +458,14 @@ TEST(testCase, function_Test6) { ASSERT_EQ(ret, 0); SArray* pExprList = pQueryInfo->exprList[0]; - ASSERT_EQ(taosArrayGetSize(pExprList), 5); + if (tsCompatibleModel) { + ASSERT_EQ(taosArrayGetSize(pExprList), 6); + } else { + ASSERT_EQ(taosArrayGetSize(pExprList), 5); + } - SExprInfo* p1 = (SExprInfo*)taosArrayGetP(pExprList, 0); + int32_t index = tsCompatibleModel? 1:0; + SExprInfo* p1 = (SExprInfo*)taosArrayGetP(pExprList, index); ASSERT_EQ(p1->base.pColumns->uid, 110); ASSERT_EQ(p1->base.numOfParams, 0); ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_DOUBLE); @@ -461,9 +483,12 @@ TEST(testCase, function_Test6) { ASSERT_STREQ(pParam->pSchema->name, "t.1abc.a+b"); ASSERT_EQ(taosArrayGetSize(pQueryInfo->colList), 3); - ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 5); - SExprInfo* p2 = (SExprInfo*)taosArrayGetP(pExprList, 1); + int32_t numOfResCol = tsCompatibleModel? 6:5; + ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, numOfResCol); + + index = tsCompatibleModel? 2:1; + SExprInfo* p2 = (SExprInfo*)taosArrayGetP(pExprList, index); ASSERT_EQ(p2->base.pColumns->uid, 110); ASSERT_EQ(p2->base.numOfParams, 0); ASSERT_EQ(p2->base.resSchema.type, TSDB_DATA_TYPE_DOUBLE); @@ -511,9 +536,10 @@ TEST(testCase, function_Test6) { ASSERT_EQ(ret, 0); SArray* pExprList = pQueryInfo->exprList[0]; - ASSERT_EQ(taosArrayGetSize(pExprList), 2); + ASSERT_EQ(taosArrayGetSize(pExprList), 3); - SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 0); + int32_t index = tsCompatibleModel? 1:0; + SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, index); ASSERT_EQ(p1->base.pColumns->uid, 110); ASSERT_EQ(p1->base.numOfParams, 0); ASSERT_EQ(p1->base.resSchema.type, TSDB_DATA_TYPE_BIGINT); @@ -537,7 +563,9 @@ TEST(testCase, function_Test6) { ASSERT_EQ(pParam->pSchema->colId, p2->base.resSchema.colId); ASSERT_EQ(taosArrayGetSize(pQueryInfo->colList), 3); - ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, 2); + + int32_t numOfCols = tsCompatibleModel? 3:2; + ASSERT_EQ(pQueryInfo->fieldsInfo.numOfOutput, numOfCols); destroyQueryInfo(pQueryInfo); qParserClearupMetaRequestInfo(&req); diff --git a/source/libs/parser/test/plannerTest.cpp b/source/libs/parser/test/plannerTest.cpp index ee2c01dc48..c86e687664 100644 --- a/source/libs/parser/test/plannerTest.cpp +++ b/source/libs/parser/test/plannerTest.cpp @@ -15,6 +15,7 @@ #include #include +#include #include #pragma GCC diagnostic ignored "-Wwrite-strings" @@ -63,7 +64,6 @@ void setTableMetaInfo(SQueryStmtInfo* pQueryInfo, SMetaReq *req) { setSchema(&pSchema[1], TSDB_DATA_TYPE_INT, 4, "a", 1); setSchema(&pSchema[2], TSDB_DATA_TYPE_DOUBLE, 8, "b", 2); setSchema(&pSchema[3], TSDB_DATA_TYPE_DOUBLE, 8, "col", 3); - } void generateLogicplan(const char* sql) { @@ -132,7 +132,9 @@ TEST(testCase, planner_test) { ASSERT_EQ(ret, 0); SArray* pExprList = pQueryInfo->exprList[0]; - ASSERT_EQ(taosArrayGetSize(pExprList), 2); + + int32_t num = tsCompatibleModel? 2:1; + ASSERT_EQ(taosArrayGetSize(pExprList), num); SExprInfo* p1 = (SExprInfo*) taosArrayGetP(pExprList, 1); ASSERT_EQ(p1->base.pColumns->uid, 110); @@ -172,6 +174,7 @@ TEST(testCase, displayPlan) { generateLogicplan("select count(A+B) from `t.1abc` group by a"); generateLogicplan("select count(length(a)+b) from `t.1abc` group by a"); generateLogicplan("select count(*) from `t.1abc` interval(10s, 5s) sliding(7s)"); + generateLogicplan("select count(*) from `t.1abc` interval(10s, 5s) sliding(7s) order by 1 desc "); generateLogicplan("select count(*),sum(a),avg(b),min(a+b)+99 from `t.1abc`"); generateLogicplan("select count(*), min(a) + 99 from `t.1abc`"); generateLogicplan("select count(length(count(*) + 22)) from `t.1abc`"); @@ -179,15 +182,18 @@ TEST(testCase, displayPlan) { generateLogicplan("select count(*), first(a), last(b) from `t.1abc` state_window(a)"); generateLogicplan("select count(*), first(a), last(b) from `t.1abc` session(ts, 20s)"); - // order by + group by column + limit offset + fill + // order by + group by column + limit offset + generateLogicplan("select top(a, 20) k from `t.1abc` order by k asc limit 3 offset 1"); + + // fill + generateLogicplan("select min(a) from `t.1abc` where ts>now and tsinfo.type = type; pNode->info.name = strdup(name); - if (pTableInfo->uid != 0 && pTableInfo->tableName) { // it is a true table - pNode->tableInfo.uid = pTableInfo->uid; - pNode->tableInfo.tableName = strdup(pTableInfo->tableName); - } - pNode->numOfExpr = numOfOutput; pNode->pExpr = taosArrayInit(numOfOutput, POINTER_BYTES); @@ -120,9 +114,10 @@ static SQueryPlanNode* createQueryNode(int32_t type, const char* name, SQueryPla switch(type) { case QNODE_TABLESCAN: { - STimeWindow* window = calloc(1, sizeof(STimeWindow)); - memcpy(window, pExtInfo, sizeof(STimeWindow)); - pNode->pExtInfo = window; + SQueryTableInfo* info = calloc(1, sizeof(SQueryTableInfo)); + memcpy(info, pExtInfo, sizeof(SQueryTableInfo)); + info->tableName = strdup(((SQueryTableInfo*) pExtInfo)->tableName); + pNode->pExtInfo = info; break; } @@ -168,6 +163,12 @@ static SQueryPlanNode* createQueryNode(int32_t type, const char* name, SQueryPla memcpy(pNode->pExtInfo, pExtInfo, sizeof(SLimit)); break; } + + case QNODE_SORT: { + pNode->pExtInfo = taosArrayDup(pExtInfo); + break; + } + default: break; } @@ -179,21 +180,20 @@ static SQueryPlanNode* doAddTableColumnNode(SQueryStmtInfo* pQueryInfo, STableMe SArray* pExprs, SArray* tableCols) { if (pQueryInfo->info.onlyTagQuery) { int32_t num = (int32_t) taosArrayGetSize(pExprs); - SQueryPlanNode* pNode = createQueryNode(QNODE_TAGSCAN, "TableTagScan", NULL, 0, pExprs->pData, num, info, NULL); + SQueryPlanNode* pNode = createQueryNode(QNODE_TAGSCAN, "TableTagScan", NULL, 0, pExprs->pData, num, NULL); if (pQueryInfo->info.distinct) { - pNode = createQueryNode(QNODE_DISTINCT, "Distinct", &pNode, 1, pExprs->pData, num, info, NULL); + pNode = createQueryNode(QNODE_DISTINCT, "Distinct", &pNode, 1, pExprs->pData, num, NULL); } return pNode; } - STimeWindow* window = &pQueryInfo->window; - SQueryPlanNode* pNode = createQueryNode(QNODE_TABLESCAN, "TableScan", NULL, 0, NULL, 0, info, window); + SQueryPlanNode* pNode = createQueryNode(QNODE_TABLESCAN, "TableScan", NULL, 0, NULL, 0, info); if (pQueryInfo->info.projectionQuery) { int32_t numOfOutput = (int32_t) taosArrayGetSize(pExprs); - pNode = createQueryNode(QNODE_PROJECT, "Projection", &pNode, 1, pExprs->pData, numOfOutput, info, NULL); + pNode = createQueryNode(QNODE_PROJECT, "Projection", &pNode, 1, pExprs->pData, numOfOutput, NULL); } else { STableMetaInfo* pTableMetaInfo1 = getMetaInfo(pQueryInfo, 0); @@ -210,54 +210,24 @@ static SQueryPlanNode* doAddTableColumnNode(SQueryStmtInfo* pQueryInfo, STableMe pExpr[i] = p; } - pNode = createQueryNode(QNODE_PROJECT, "Projection", &pNode, 1, pExpr, numOfCols, info, NULL); + pNode = createQueryNode(QNODE_PROJECT, "Projection", &pNode, 1, pExpr, numOfCols, NULL); tfree(pExpr); } return pNode; } -static int32_t getFunctionLevel(SQueryStmtInfo* pQueryInfo) { - int32_t n = 10; - - int32_t level = 0; - for(int32_t i = 0; i < n; ++i) { - SArray* pList = pQueryInfo->exprList[i]; - if (taosArrayGetSize(pList) > 0) { - level += 1; - } - } - - return level; -} - -static SQueryPlanNode* createOneQueryPlanNode(SArray* p, SQueryPlanNode* pNode, SExprInfo* pExpr, SQueryTableInfo* info) { - if (pExpr->pExpr->nodeType == TEXPR_FUNCTION_NODE) { - bool aggregateFunc = qIsAggregateFunction(pExpr->pExpr->_function.functionName); - if (aggregateFunc) { - int32_t numOfOutput = (int32_t)taosArrayGetSize(p); - return createQueryNode(QNODE_AGGREGATE, "Aggregate", &pNode, 1, p->pData, numOfOutput, info, NULL); - } else { - int32_t numOfOutput = (int32_t)taosArrayGetSize(p); - return createQueryNode(QNODE_PROJECT, "Projection", &pNode, 1, p->pData, numOfOutput, info, NULL); - } - } else { - int32_t numOfOutput = (int32_t)taosArrayGetSize(p); - return createQueryNode(QNODE_PROJECT, "Projection", &pNode, 1, p->pData, numOfOutput, info, NULL); - } -} - static SQueryPlanNode* doCreateQueryPlanForSingleTableImpl(SQueryStmtInfo* pQueryInfo, SQueryPlanNode* pNode, SQueryTableInfo* info) { // group by column not by tag size_t numOfGroupCols = taosArrayGetSize(pQueryInfo->groupbyExpr.columnInfo); // check for aggregation - int32_t level = getFunctionLevel(pQueryInfo); + int32_t level = getExprFunctionLevel(pQueryInfo); for(int32_t i = level - 1; i >= 0; --i) { SArray* p = pQueryInfo->exprList[i]; + size_t num = taosArrayGetSize(p); - size_t num = taosArrayGetSize(p); bool aggregateFunc = false; for(int32_t j = 0; j < num; ++j) { SExprInfo* pExpr = (SExprInfo*)taosArrayGetP(p, 0); @@ -273,37 +243,43 @@ static SQueryPlanNode* doCreateQueryPlanForSingleTableImpl(SQueryStmtInfo* pQuer if (aggregateFunc) { if (pQueryInfo->interval.interval > 0) { - pNode = createQueryNode(QNODE_TIMEWINDOW, "TimeWindowAgg", &pNode, 1, p->pData, num, info, &pQueryInfo->interval); + pNode = createQueryNode(QNODE_TIMEWINDOW, "TimeWindowAgg", &pNode, 1, p->pData, num, &pQueryInfo->interval); } else if (pQueryInfo->sessionWindow.gap > 0) { - pNode = createQueryNode(QNODE_SESSIONWINDOW, "SessionWindowAgg", &pNode, 1, p->pData, num, info, &pQueryInfo->sessionWindow); + pNode = createQueryNode(QNODE_SESSIONWINDOW, "SessionWindowAgg", &pNode, 1, p->pData, num, &pQueryInfo->sessionWindow); } else if (pQueryInfo->stateWindow.col.info.colId > 0) { - pNode = createQueryNode(QNODE_STATEWINDOW, "StateWindowAgg", &pNode, 1, p->pData, num, info, &pQueryInfo->stateWindow); + pNode = createQueryNode(QNODE_STATEWINDOW, "StateWindowAgg", &pNode, 1, p->pData, num, &pQueryInfo->stateWindow); } else if (numOfGroupCols != 0 && !pQueryInfo->groupbyExpr.groupbyTag) { - pNode = createQueryNode(QNODE_GROUPBY, "Groupby", &pNode, 1, p->pData, num, info, &pQueryInfo->groupbyExpr); + pNode = createQueryNode(QNODE_GROUPBY, "Groupby", &pNode, 1, p->pData, num, &pQueryInfo->groupbyExpr); } else { - pNode = createQueryNode(QNODE_AGGREGATE, "Aggregate", &pNode, 1, p->pData, num, info, NULL); + pNode = createQueryNode(QNODE_AGGREGATE, "Aggregate", &pNode, 1, p->pData, num, NULL); } } else { - pNode = createQueryNode(QNODE_PROJECT, "Projection", &pNode, 1, p->pData, num, info, NULL); + pNode = createQueryNode(QNODE_PROJECT, "Projection", &pNode, 1, p->pData, num, NULL); } } if (pQueryInfo->havingFieldNum > 0) { // int32_t numOfExpr = (int32_t)taosArrayGetSize(pQueryInfo->exprList1); -// pNode = createQueryNode(QNODE_PROJECT, "Projection", &pNode, 1, pQueryInfo->exprList1->pData, numOfExpr, info, NULL); +// pNode = createQueryNode(QNODE_PROJECT, "Projection", &pNode, 1, pQueryInfo->exprList1->pData, numOfExpr, NULL); } if (pQueryInfo->fillType != TSDB_FILL_NONE) { SFillEssInfo* pInfo = calloc(1, sizeof(SFillEssInfo)); pInfo->fillType = pQueryInfo->fillType; - pInfo->val = calloc(pNode->numOfExpr, sizeof(int64_t)); + pInfo->val = calloc(pNode->numOfExpr, sizeof(int64_t)); memcpy(pInfo->val, pQueryInfo->fillVal, pNode->numOfExpr); - pNode = createQueryNode(QNODE_FILL, "Fill", &pNode, 1, NULL, 0, info, pInfo); + SArray* p = pQueryInfo->exprList[0]; // top expression in select clause + pNode = createQueryNode(QNODE_FILL, "Fill", &pNode, 1, p, taosArrayGetSize(p), pInfo); + } + + if (pQueryInfo->order != NULL) { + SArray* pList = pQueryInfo->exprList[0]; + pNode = createQueryNode(QNODE_SORT, "Sort", &pNode, 1, pList->pData, taosArrayGetSize(pList), pQueryInfo->order); } if (pQueryInfo->limit.limit != -1 || pQueryInfo->limit.offset != 0) { - pNode = createQueryNode(QNODE_LIMIT, "Limit", &pNode, 1, NULL, 0, info, &pQueryInfo->limit); + pNode = createQueryNode(QNODE_LIMIT, "Limit", &pNode, 1, NULL, 0, &pQueryInfo->limit); } return pNode; @@ -341,44 +317,6 @@ static bool isAllAggExpr(SArray* pList) { return true; } -static void exprInfoPushDown(SQueryStmtInfo* pQueryInfo) { - assert(pQueryInfo != NULL); - - size_t level = getFunctionLevel(pQueryInfo); - for(int32_t i = 0; i < level - 1; ++i) { - SArray* p = pQueryInfo->exprList[i]; - - SArray* pNext = pQueryInfo->exprList[i + 1]; - if (!isAllAggExpr(pNext)) { - continue; - } - - for (int32_t j = 0; j < taosArrayGetSize(p); ++j) { - SExprInfo* pExpr = taosArrayGetP(p, j); - - if (pExpr->pExpr->nodeType == TEXPR_FUNCTION_NODE && qIsAggregateFunction(pExpr->pExpr->_function.functionName)) { - bool canPushDown = true; - for (int32_t k = 0; k < taosArrayGetSize(pNext); ++k) { - SExprInfo* pNextLevelExpr = taosArrayGetP(pNext, k); - if (pExpr->base.pColumns->info.colId == pNextLevelExpr->base.resSchema.colId) { - // pExpr is dependent on the output of the under layer, so it can not be push downwards - canPushDown = false; - break; - } - } - - if (canPushDown) { - taosArrayInsert(pNext, j, &pExpr); - taosArrayRemove(p, j); - - // todo add the project function in level of "i" - - } - } - } - } -} - SArray* createQueryPlanImpl(SQueryStmtInfo* pQueryInfo) { SArray* upstream = NULL; @@ -429,7 +367,7 @@ SArray* createQueryPlanImpl(SQueryStmtInfo* pQueryInfo) { SQueryTableInfo info = {0}; int32_t num = (int32_t) taosArrayGetSize(pQueryInfo->exprList[0]); SQueryPlanNode* pNode = createQueryNode(QNODE_JOIN, "Join", upstream->pData, pQueryInfo->numOfTables, - pQueryInfo->exprList[0]->pData, num, &info, NULL); + pQueryInfo->exprList[0]->pData, num, NULL); // 4. add the aggregation or projection execution node pNode = doCreateQueryPlanForSingleTableImpl(pQueryInfo, pNode, &info); @@ -449,8 +387,6 @@ static void doDestroyQueryNode(SQueryPlanNode* pQueryNode) { tfree(pQueryNode->pExtInfo); tfree(pQueryNode->pSchema); tfree(pQueryNode->info.name); - - tfree(pQueryNode->tableInfo.tableName); // dropAllExprInfo(pQueryNode->pExpr); if (pQueryNode->pPrevNodes != NULL) { @@ -477,13 +413,13 @@ static int32_t doPrintPlan(char* buf, SQueryPlanNode* pQueryNode, int32_t level, switch(pQueryNode->info.type) { case QNODE_TABLESCAN: { - STimeWindow* win = (STimeWindow*)pQueryNode->pExtInfo; - len1 = sprintf(buf + len, "%s #%" PRIu64 ") time_range: %" PRId64 " - %" PRId64 " cols: ", - pQueryNode->tableInfo.tableName, pQueryNode->tableInfo.uid, win->skey, win->ekey); + SQueryTableInfo* pInfo = (SQueryTableInfo*)pQueryNode->pExtInfo; + len1 = sprintf(buf + len, "%s #%" PRIu64 ") time_range: %" PRId64 " - %" PRId64, pInfo->tableName, pInfo->uid, + pInfo->window.skey, pInfo->window.ekey); assert(len1 > 0); len += len1; - for(int32_t i = 0; i < pQueryNode->numOfExpr; ++i) { + for (int32_t i = 0; i < pQueryNode->numOfExpr; ++i) { SColumn* pCol = taosArrayGetP(pQueryNode->pExpr, i); len1 = sprintf(buf + len, " [%s #%d] ", pCol->name, pCol->info.colId); @@ -499,90 +435,47 @@ static int32_t doPrintPlan(char* buf, SQueryPlanNode* pQueryNode, int32_t level, } case QNODE_PROJECT: { - len1 = sprintf(buf + len, "cols: "); + len1 = sprintf(buf + len, "cols:"); assert(len1 > 0); - len += len1; - for(int32_t i = 0; i < pQueryNode->numOfExpr; ++i) { - SExprInfo* pExprInfo = taosArrayGetP(pQueryNode->pExpr, i); - - SSqlExpr* p = &pExprInfo->base; - len1 = sprintf(buf + len, "[%s #%d]", p->resSchema.name, p->resSchema.colId); - assert(len1 > 0); - - len += len1; - - if (i < pQueryNode->numOfExpr - 1) { - len1 = sprintf(buf + len, ", "); - len += len1; - } - } - + len = printExprInfo(buf, pQueryNode, len); len1 = sprintf(buf + len, ")"); len += len1; - //todo print filter info + // todo print filter info len1 = sprintf(buf + len, " filters:(nil)\n"); len += len1; break; } case QNODE_AGGREGATE: { - for(int32_t i = 0; i < pQueryNode->numOfExpr; ++i) { - SExprInfo* pExprInfo = taosArrayGetP(pQueryNode->pExpr, i); - - SSqlExpr* pExpr = &pExprInfo->base; - len += sprintf(buf + len,"%s [%s #%d]", pExpr->token, pExpr->resSchema.name, pExpr->resSchema.colId); - if (i < pQueryNode->numOfExpr - 1) { - len1 = sprintf(buf + len, ", "); - len += len1; - } - } - + len = printExprInfo(buf, pQueryNode, len); len1 = sprintf(buf + len, ")\n"); len += len1; + break; } case QNODE_TIMEWINDOW: { - for(int32_t i = 0; i < pQueryNode->numOfExpr; ++i) { - SExprInfo* pExprInfo = taosArrayGetP(pQueryNode->pExpr, i); - - SSqlExpr* pExpr = &pExprInfo->base; - len += sprintf(buf + len,"%s [%s #%d]", pExpr->token, pExpr->resSchema.name, pExpr->resSchema.colId); - if (i < pQueryNode->numOfExpr - 1) { - len1 = sprintf(buf + len,", "); - len += len1; - } - } - - len1 = sprintf(buf + len,") "); + len = printExprInfo(buf, pQueryNode, len); + len1 = sprintf(buf + len, ") "); len += len1; SInterval* pInterval = pQueryNode->pExtInfo; // todo dynamic return the time precision len1 = sprintf(buf + len, "interval:%" PRId64 "(%s), sliding:%" PRId64 "(%s), offset:%" PRId64 "(%s)\n", - pInterval->interval, TSDB_TIME_PRECISION_MILLI_STR, pInterval->sliding, TSDB_TIME_PRECISION_MILLI_STR, - pInterval->offset, TSDB_TIME_PRECISION_MILLI_STR); + pInterval->interval, TSDB_TIME_PRECISION_MILLI_STR, pInterval->sliding, + TSDB_TIME_PRECISION_MILLI_STR, pInterval->offset, TSDB_TIME_PRECISION_MILLI_STR); len += len1; break; } case QNODE_STATEWINDOW: { - for(int32_t i = 0; i < pQueryNode->numOfExpr; ++i) { - SExprInfo* pExprInfo = taosArrayGetP(pQueryNode->pExpr, i); - SSqlExpr* pExpr = &pExprInfo->base; - len += sprintf(buf + len,"%s [%s #%d]", pExpr->token, pExpr->resSchema.name, pExpr->resSchema.colId); - if (i < pQueryNode->numOfExpr - 1) { - len1 = sprintf(buf + len,", "); - len += len1; - } - } - - len1 = sprintf(buf + len,") "); + len = printExprInfo(buf, pQueryNode, len); + len1 = sprintf(buf + len, ") "); len += len1; SColumn* pCol = pQueryNode->pExtInfo; @@ -592,44 +485,25 @@ static int32_t doPrintPlan(char* buf, SQueryPlanNode* pQueryNode, int32_t level, } case QNODE_SESSIONWINDOW: { - for(int32_t i = 0; i < pQueryNode->numOfExpr; ++i) { - SExprInfo* pExprInfo = taosArrayGetP(pQueryNode->pExpr, i); - SSqlExpr* pExpr = &pExprInfo->base; - len += sprintf(buf + len,"%s [%s #%d]", pExpr->token, pExpr->resSchema.name, pExpr->resSchema.colId); - if (i < pQueryNode->numOfExpr - 1) { - len1 = sprintf(buf + len,", "); - len += len1; - } - } + len = printExprInfo(buf, pQueryNode, len); - len1 = sprintf(buf + len,") "); + len1 = sprintf(buf + len, ") "); len += len1; struct SSessionWindow* ps = pQueryNode->pExtInfo; - len1 = sprintf(buf + len, "col:[%s #%d], gap:%"PRId64" (ms) \n", ps->col.name, ps->col.info.colId, ps->gap); + len1 = sprintf(buf + len, "col:[%s #%d], gap:%" PRId64 " (ms) \n", ps->col.name, ps->col.info.colId, ps->gap); len += len1; break; } - case QNODE_GROUPBY: { // todo hide the invisible column - for(int32_t i = 0; i < pQueryNode->numOfExpr; ++i) { - SExprInfo* pExprInfo = taosArrayGetP(pQueryNode->pExpr, i); - - SSqlExpr* pExpr = &pExprInfo->base; - len1 = sprintf(buf + len,"%s [%s #%d]", pExpr->token, pExpr->resSchema.name, pExpr->resSchema.colId); - - len += len1; - if (i < pQueryNode->numOfExpr - 1) { - len1 = sprintf(buf + len,", "); - len += len1; - } - } + case QNODE_GROUPBY: { + len = printExprInfo(buf, pQueryNode, len); SGroupbyExpr* pGroupbyExpr = pQueryNode->pExtInfo; - len1 = sprintf(buf + len,") groupby_col: "); + len1 = sprintf(buf + len, ") groupby_col: "); len += len1; - for(int32_t i = 0; i < taosArrayGetSize(pGroupbyExpr->columnInfo); ++i) { + for (int32_t i = 0; i < taosArrayGetSize(pGroupbyExpr->columnInfo); ++i) { SColumn* pCol = taosArrayGet(pGroupbyExpr->columnInfo, i); len1 = sprintf(buf + len, "[%s #%d] ", pCol->name, pCol->info.colId); len += len1; @@ -641,58 +515,64 @@ static int32_t doPrintPlan(char* buf, SQueryPlanNode* pQueryNode, int32_t level, case QNODE_FILL: { SFillEssInfo* pEssInfo = pQueryNode->pExtInfo; - len1 = sprintf(buf + len,"%d", pEssInfo->fillType); + len1 = sprintf(buf + len, "%d", pEssInfo->fillType); len += len1; if (pEssInfo->fillType == TSDB_FILL_SET_VALUE) { - len1 = sprintf(buf + len,", val:"); + len1 = sprintf(buf + len, ", val:"); len += len1; // todo get the correct fill data type - for(int32_t i = 0; i < pQueryNode->numOfExpr; ++i) { - len1 = sprintf(buf + len,"%"PRId64, pEssInfo->val[i]); + for (int32_t i = 0; i < pQueryNode->numOfExpr; ++i) { + len1 = sprintf(buf + len, "%" PRId64, pEssInfo->val[i]); len += len1; if (i < pQueryNode->numOfExpr - 1) { - len1 = sprintf(buf + len,", "); + len1 = sprintf(buf + len, ", "); len += len1; } } } - len1 = sprintf(buf + len,")\n"); + len1 = sprintf(buf + len, ")\n"); len += len1; break; } case QNODE_LIMIT: { SLimit* pVal = pQueryNode->pExtInfo; - len1 = sprintf(buf + len,"limit: %"PRId64", offset: %"PRId64")\n", pVal->limit, pVal->offset); + len1 = sprintf(buf + len, "limit: %" PRId64 ", offset: %" PRId64 ")\n", pVal->limit, pVal->offset); len += len1; break; } case QNODE_DISTINCT: case QNODE_TAGSCAN: { - len1 = sprintf(buf + len,"cols: "); + len1 = sprintf(buf + len, "cols: "); len += len1; - for(int32_t i = 0; i < pQueryNode->numOfExpr; ++i) { - SExprInfo* pExprInfo = taosArrayGetP(pQueryNode->pExpr, i); - SSchema* resSchema = &pExprInfo->base.resSchema; + len = printExprInfo(buf, pQueryNode, len); + + len1 = sprintf(buf + len, ")\n"); + len += len1; + + break; + } + + case QNODE_SORT: { + len1 = sprintf(buf + len, "cols:"); + len += len1; + + SArray* pSort = pQueryNode->pExtInfo; + for (int32_t i = 0; i < taosArrayGetSize(pSort); ++i) { + SOrder* p = taosArrayGet(pSort, i); + len1 = sprintf(buf + len, " [%s #%d %s]", p->col.name, p->col.info.colId, p->order == TSDB_ORDER_ASC? "ASC":"DESC"); - len1 = sprintf(buf + len,"[%s #%d]", resSchema->name, resSchema->colId); len += len1; - - if (i < pQueryNode->numOfExpr - 1) { - len1 = sprintf(buf + len,", "); - len += len1; - } } - len1 = sprintf(buf + len,")\n"); + len1 = sprintf(buf + len, ")\n"); len += len1; - break; } @@ -707,6 +587,26 @@ static int32_t doPrintPlan(char* buf, SQueryPlanNode* pQueryNode, int32_t level, return len; } +int32_t printExprInfo(const char* buf, const SQueryPlanNode* pQueryNode, int32_t len) { + int32_t len1 = 0; + + for (int32_t i = 0; i < pQueryNode->numOfExpr; ++i) { + SExprInfo* pExprInfo = taosArrayGetP(pQueryNode->pExpr, i); + + SSqlExpr* pExpr = &pExprInfo->base; + len1 = sprintf(buf + len, "%s [%s #%d]", pExpr->token, pExpr->resSchema.name, pExpr->resSchema.colId); + assert(len1 > 0); + + len += len1; + if (i < pQueryNode->numOfExpr - 1) { + len1 = sprintf(buf + len, ", "); + len += len1; + } + } + + return len; +} + int32_t queryPlanToStringImpl(char* buf, SQueryPlanNode* pQueryNode, int32_t level, int32_t totalLen) { int32_t len = doPrintPlan(buf, pQueryNode, level, totalLen); diff --git a/source/util/src/terror.c b/source/util/src/terror.c index 11b40f61f6..3a36ad9b42 100644 --- a/source/util/src/terror.c +++ b/source/util/src/terror.c @@ -86,6 +86,9 @@ TAOS_DEFINE_ERROR(TSDB_CODE_REF_INVALID_ID, "Invalid Ref ID") TAOS_DEFINE_ERROR(TSDB_CODE_REF_ALREADY_EXIST, "Ref is already there") TAOS_DEFINE_ERROR(TSDB_CODE_REF_NOT_EXIST, "Ref is not there") +TAOS_DEFINE_ERROR(TSDB_CODE_INVALID_VERSION_NUMBER, "Invalid version number") +TAOS_DEFINE_ERROR(TSDB_CODE_INVALID_VERSION_STRING, "Invalid version string") +TAOS_DEFINE_ERROR(TSDB_CODE_VERSION_NOT_COMPATIBLE, "Version not compatible") //client TAOS_DEFINE_ERROR(TSDB_CODE_TSC_INVALID_OPERATION, "Invalid operation") diff --git a/source/util/src/tversion.c b/source/util/src/tversion.c new file mode 100644 index 0000000000..3944bd5132 --- /dev/null +++ b/source/util/src/tversion.c @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * 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 . + */ + +#define _DEFAULT_SOURCE +#include "os.h" +#include "taoserror.h" +#include "tdef.h" +#include "ulog.h" + +int32_t taosVersionStrToInt(const char *vstr, int32_t *vint) { + if (vstr == NULL) { + terrno = TSDB_CODE_INVALID_VERSION_STRING; + return -1; + } + + int32_t vnum[4] = {0}; + int32_t len = strlen(vstr); + char tmp[16] = {0}; + + for (int32_t spos = 0, tpos = 0, vpos = 0; spos < len && vpos < 4; ++spos) { + if (vstr[spos] != '.') { + tmp[spos - tpos] = vstr[spos]; + } else { + vnum[vpos] = atoi(tmp); + memset(tmp, 0, sizeof(tmp)); + vpos++; + tpos = spos + 1; + } + } + + if (vnum[0] <= 0) { + terrno = TSDB_CODE_INVALID_VERSION_STRING; + return -1; + } + + *vint = vnum[0] * 1000000 + vnum[1] * 10000 + vnum[2] * 100 + vnum[3]; + return 0; +} + +int32_t taosVersionIntToStr(int32_t vint, char *vstr, int32_t len) { + int32_t s1 = (vint % 100000000) / 1000000; + int32_t s2 = (vint % 1000000) / 10000; + int32_t s3 = (vint % 10000) / 100; + int32_t s4 = vint % 100; + if (s1 <= 0) { + terrno = TSDB_CODE_INVALID_VERSION_NUMBER; + return -1; + } + + snprintf(vstr, len, "%02d.%02d.%02d.%02d", s1, s2, s3, s4); + return 0; +} + +int32_t taosCheckVersionCompatible(int32_t clientVer, int32_t serverVer, int32_t comparedSegments) { + switch (comparedSegments) { + case 4: + break; + case 3: + clientVer %= 100; + serverVer %= 100; + break; + case 2: + clientVer %= 10000; + serverVer %= 10000; + break; + case 1: + clientVer %= 1000000; + serverVer %= 1000000; + break; + default: + terrno = TSDB_CODE_INVALID_VERSION_NUMBER; + return -1; + } + + if (clientVer == serverVer) { + return 0; + } else { + terrno = TSDB_CODE_VERSION_NOT_COMPATIBLE; + return -1; + } +} diff --git a/src/client/src/tscSQLParser.c b/src/client/src/tscSQLParser.c index 05e4cbaa97..4fc78d73e4 100644 --- a/src/client/src/tscSQLParser.c +++ b/src/client/src/tscSQLParser.c @@ -63,7 +63,7 @@ typedef struct SConvertFunc { int32_t execFuncId; } SConvertFunc; -static SExprInfo* doAddProjectCol(SQueryInfo* pQueryInfo, int32_t colIndex, int32_t tableIndex, int32_t colId); +static SExprInfo* doAddOneProjectCol(SQueryInfo* pQueryInfo, int32_t colIndex, int32_t tableIndex, int32_t colId); static int32_t setShowInfo(SSqlObj* pSql, SSqlInfo* pInfo); static char* getAccountId(SSqlObj* pSql); @@ -1890,7 +1890,7 @@ static int32_t handleArithmeticExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32 } static void addProjectQueryCol(SQueryInfo* pQueryInfo, int32_t startPos, SColumnIndex* pIndex, tSqlExprItem* pItem, int32_t colId) { - SExprInfo* pExpr = doAddProjectCol(pQueryInfo, pIndex->columnIndex, pIndex->tableIndex, colId); + SExprInfo* pExpr = doAddOneProjectCol(pQueryInfo, pIndex->columnIndex, pIndex->tableIndex, colId); STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, pIndex->tableIndex); STableMeta* pTableMeta = pTableMetaInfo->pTableMeta; @@ -2157,7 +2157,7 @@ int32_t insertResultField(SQueryInfo* pQueryInfo, int32_t outputIndex, SColumnLi return TSDB_CODE_SUCCESS; } -SExprInfo* doAddProjectCol(SQueryInfo* pQueryInfo, int32_t colIndex, int32_t tableIndex, int32_t colId) { +SExprInfo* doAddOneProjectCol(SQueryInfo* pQueryInfo, int32_t colIndex, int32_t tableIndex, int32_t colId) { STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, tableIndex); STableMeta* pTableMeta = pTableMetaInfo->pTableMeta; int32_t numOfCols = tscGetNumOfColumns(pTableMeta); @@ -2218,7 +2218,7 @@ static int32_t doAddProjectionExprAndResultFields(SQueryInfo* pQueryInfo, SColum } for (int32_t j = 0; j < numOfTotalColumns; ++j) { - SExprInfo* pExpr = doAddProjectCol(pQueryInfo, j, pIndex->tableIndex, getNewResColId(pCmd)); + SExprInfo* pExpr = doAddOneProjectCol(pQueryInfo, j, pIndex->tableIndex, getNewResColId(pCmd)); tstrncpy(pExpr->base.aliasName, pSchema[j].name, sizeof(pExpr->base.aliasName)); pIndex->columnIndex = j;