feat: data analysis
This commit is contained in:
parent
b315b446e8
commit
3003e7286e
|
@ -144,6 +144,12 @@ option(
|
|||
OFF
|
||||
)
|
||||
|
||||
option(
|
||||
BUILD_WITH_ANALYSIS
|
||||
"If build with analysis"
|
||||
ON
|
||||
)
|
||||
|
||||
ENDIF ()
|
||||
|
||||
IF(NOT TD_ENTERPRISE)
|
||||
|
@ -151,8 +157,15 @@ MESSAGE("switch s3 off with community version")
|
|||
set(BUILD_S3 OFF)
|
||||
set(BUILD_WITH_S3 OFF)
|
||||
set(BUILD_WITH_COS OFF)
|
||||
set(BUILD_WITH_ANALYSIS OFF)
|
||||
ENDIF ()
|
||||
|
||||
IF(${BUILD_WITH_ANALYSIS})
|
||||
message("build with analysis")
|
||||
set(BUILD_S3 ON)
|
||||
set(BUILD_WITH_S3 ON)
|
||||
ENDIF()
|
||||
|
||||
IF(${BUILD_S3})
|
||||
|
||||
IF(${BUILD_WITH_S3})
|
||||
|
|
|
@ -29,6 +29,8 @@ extern "C" {
|
|||
#define TSDB_INS_TABLE_QNODES "ins_qnodes"
|
||||
#define TSDB_INS_TABLE_BNODES "ins_bnodes" // no longer used
|
||||
#define TSDB_INS_TABLE_SNODES "ins_snodes"
|
||||
#define TSDB_INS_TABLE_ANODES "ins_anodes"
|
||||
#define TSDB_INS_TABLE_ANODES_FULL "ins_anodes_full"
|
||||
#define TSDB_INS_TABLE_ARBGROUPS "ins_arbgroups"
|
||||
#define TSDB_INS_TABLE_CLUSTER "ins_cluster"
|
||||
#define TSDB_INS_TABLE_DATABASES "ins_databases"
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
||||
*
|
||||
* This program is free software: you can use, redistribute, and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3
|
||||
* or later ("AGPL"), as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _TD_UTIL_ANAL_H_
|
||||
#define _TD_UTIL_ANAL_H_
|
||||
|
||||
#include "os.h"
|
||||
#include "tdef.h"
|
||||
#include "thash.h"
|
||||
#include "tjson.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define ANAL_FORECAST_DEFAULT_PERIOD 10
|
||||
#define ANAL_FORECAST_DEFAULT_ROWS 10
|
||||
#define ANAL_FORECAST_DEFAULT_CONF 95
|
||||
#define ANAL_FORECAST_DEFAULT_ALPHA 0.05
|
||||
#define ANAL_FORECAST_DEFAULT_PARAM "diff"
|
||||
|
||||
typedef struct {
|
||||
EAnalAlgoType type;
|
||||
int32_t anode;
|
||||
int32_t urlLen;
|
||||
char *url;
|
||||
} SAnalUrl;
|
||||
|
||||
typedef enum {
|
||||
ANAL_BUF_TYPE_JSON = 0,
|
||||
ANAL_BUF_TYPE_JSON_COL = 1,
|
||||
ANAL_BUF_TYPE_OTHERS,
|
||||
} EAnalBufType;
|
||||
|
||||
typedef enum {
|
||||
ANAL_HTTP_TYPE_GET = 0,
|
||||
ANAL_HTTP_TYPE_POST,
|
||||
} EAnalHttpType;
|
||||
|
||||
typedef struct {
|
||||
TdFilePtr filePtr;
|
||||
char fileName[TSDB_FILENAME_LEN + 10];
|
||||
int64_t numOfRows;
|
||||
} SAnalColBuf;
|
||||
|
||||
typedef struct {
|
||||
EAnalBufType bufType;
|
||||
TdFilePtr filePtr;
|
||||
char fileName[TSDB_FILENAME_LEN];
|
||||
int32_t numOfCols;
|
||||
SAnalColBuf *pCols;
|
||||
} SAnalBuf;
|
||||
|
||||
int32_t taosAnalInit();
|
||||
void taosAnalCleanup();
|
||||
SJson *taosAnalSendReqRetJson(const char *url, EAnalHttpType type, SAnalBuf *pBuf);
|
||||
|
||||
int32_t taosAnalGetAlgoUrl(const char *algoName, EAnalAlgoType type, char *url, int32_t urlLen);
|
||||
bool taosAnalGetOptStr(const char *option, const char *optName, char *optValue, int32_t optMaxLen);
|
||||
bool taosAnalGetOptInt(const char *option, const char *optName, int32_t *optValue);
|
||||
int64_t taosAnalGetVersion();
|
||||
void taosAnalUpdate(int64_t newVer, SHashObj *pHash);
|
||||
|
||||
int32_t tsosAnalBufOpen(SAnalBuf *pBuf, int32_t numOfCols);
|
||||
int32_t taosAnalBufWriteOptStr(SAnalBuf *pBuf, const char *optName, const char *optVal);
|
||||
int32_t taosAnalBufWriteOptInt(SAnalBuf *pBuf, const char *optName, int64_t optVal);
|
||||
int32_t taosAnalBufWriteOptFloat(SAnalBuf *pBuf, const char *optName, float optVal);
|
||||
int32_t taosAnalBufWriteColMeta(SAnalBuf *pBuf, int32_t colIndex, int32_t colType, const char *colName);
|
||||
int32_t taosAnalBufWriteDataBegin(SAnalBuf *pBuf);
|
||||
int32_t taosAnalBufWriteColBegin(SAnalBuf *pBuf, int32_t colIndex);
|
||||
int32_t taosAnalBufWriteColData(SAnalBuf *pBuf, int32_t colIndex, int32_t colType, void *colValue);
|
||||
int32_t taosAnalBufWriteColEnd(SAnalBuf *pBuf, int32_t colIndex);
|
||||
int32_t taosAnalBufWriteDataEnd(SAnalBuf *pBuf);
|
||||
int32_t taosAnalBufClose(SAnalBuf *pBuf);
|
||||
void taosAnalBufDestroy(SAnalBuf *pBuf);
|
||||
|
||||
const char *taosAnalAlgoStr(EAnalAlgoType algoType);
|
||||
EAnalAlgoType taosAnalAlgoInt(const char *algoName);
|
||||
const char *taosAnalAlgoUrlStr(EAnalAlgoType algoType);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /*_TD_UTIL_ANAL_H_*/
|
|
@ -159,6 +159,8 @@ typedef enum _mgmt_table {
|
|||
TSDB_MGMT_TABLE_ARBGROUP,
|
||||
TSDB_MGMT_TABLE_ENCRYPTIONS,
|
||||
TSDB_MGMT_TABLE_USER_FULL,
|
||||
TSDB_MGMT_TABLE_ANODE,
|
||||
TSDB_MGMT_TABLE_ANODE_FULL,
|
||||
TSDB_MGMT_TABLE_MAX,
|
||||
} EShowType;
|
||||
|
||||
|
@ -260,6 +262,7 @@ typedef enum ENodeType {
|
|||
QUERY_NODE_COUNT_WINDOW,
|
||||
QUERY_NODE_COLUMN_OPTIONS,
|
||||
QUERY_NODE_TSMA_OPTIONS,
|
||||
QUERY_NODE_ANOMALY_WINDOW,
|
||||
|
||||
// Statement nodes are used in parser and planner module.
|
||||
QUERY_NODE_SET_OPERATOR = 100,
|
||||
|
@ -345,6 +348,9 @@ typedef enum ENodeType {
|
|||
QUERY_NODE_CREATE_VIEW_STMT,
|
||||
QUERY_NODE_DROP_VIEW_STMT,
|
||||
QUERY_NODE_CREATE_SUBTABLE_FROM_FILE_CLAUSE,
|
||||
QUERY_NODE_CREATE_ANODE_STMT,
|
||||
QUERY_NODE_DROP_ANODE_STMT,
|
||||
QUERY_NODE_UPDATE_ANODE_STMT,
|
||||
|
||||
// show statement nodes
|
||||
// see 'sysTableShowAdapter', 'SYSTABLE_SHOW_TYPE_OFFSET'
|
||||
|
@ -386,6 +392,8 @@ typedef enum ENodeType {
|
|||
QUERY_NODE_SHOW_CLUSTER_MACHINES_STMT,
|
||||
QUERY_NODE_SHOW_ENCRYPTIONS_STMT,
|
||||
QUERY_NODE_SHOW_TSMAS_STMT,
|
||||
QUERY_NODE_SHOW_ANODES_STMT,
|
||||
QUERY_NODE_SHOW_ANODES_FULL_STMT,
|
||||
QUERY_NODE_CREATE_TSMA_STMT,
|
||||
QUERY_NODE_SHOW_CREATE_TSMA_STMT,
|
||||
QUERY_NODE_DROP_TSMA_STMT,
|
||||
|
@ -408,6 +416,7 @@ typedef enum ENodeType {
|
|||
QUERY_NODE_LOGIC_PLAN,
|
||||
QUERY_NODE_LOGIC_PLAN_GROUP_CACHE,
|
||||
QUERY_NODE_LOGIC_PLAN_DYN_QUERY_CTRL,
|
||||
QUERY_NODE_LOGIC_PLAN_FORECAST_FUNC,
|
||||
|
||||
// physical plan node
|
||||
QUERY_NODE_PHYSICAL_PLAN_TAG_SCAN = 1100,
|
||||
|
@ -458,6 +467,9 @@ typedef enum ENodeType {
|
|||
QUERY_NODE_PHYSICAL_PLAN_MERGE_COUNT,
|
||||
QUERY_NODE_PHYSICAL_PLAN_STREAM_COUNT,
|
||||
QUERY_NODE_PHYSICAL_PLAN_STREAM_MID_INTERVAL,
|
||||
QUERY_NODE_PHYSICAL_PLAN_MERGE_ANOMALY,
|
||||
QUERY_NODE_PHYSICAL_PLAN_STREAM_ANOMALY,
|
||||
QUERY_NODE_PHYSICAL_PLAN_FORECAST_FUNC,
|
||||
} ENodeType;
|
||||
|
||||
typedef struct {
|
||||
|
@ -1092,6 +1104,22 @@ typedef struct {
|
|||
int32_t tSerializeRetrieveIpWhite(void* buf, int32_t bufLen, SRetrieveIpWhiteReq* pReq);
|
||||
int32_t tDeserializeRetrieveIpWhite(void* buf, int32_t bufLen, SRetrieveIpWhiteReq* pReq);
|
||||
|
||||
typedef struct {
|
||||
int32_t dnodeId;
|
||||
int64_t analVer;
|
||||
} SRetrieveAnalAlgoReq;
|
||||
|
||||
typedef struct {
|
||||
int64_t ver;
|
||||
SHashObj* hash; // algoname:algotype -> SAnalUrl
|
||||
} SRetrieveAnalAlgoRsp;
|
||||
|
||||
int32_t tSerializeRetrieveAnalAlgoReq(void* buf, int32_t bufLen, SRetrieveAnalAlgoReq* pReq);
|
||||
int32_t tDeserializeRetrieveAnalAlgoReq(void* buf, int32_t bufLen, SRetrieveAnalAlgoReq* pReq);
|
||||
int32_t tSerializeRetrieveAnalAlgoRsp(void* buf, int32_t bufLen, SRetrieveAnalAlgoRsp* pRsp);
|
||||
int32_t tDeserializeRetrieveAnalAlgoRsp(void* buf, int32_t bufLen, SRetrieveAnalAlgoRsp* pRsp);
|
||||
void tFreeRetrieveAnalAlgoRsp(SRetrieveAnalAlgoRsp* pRsp);
|
||||
|
||||
typedef struct {
|
||||
int8_t alterType;
|
||||
int8_t superUser;
|
||||
|
@ -1766,6 +1794,7 @@ typedef struct {
|
|||
SArray* pVloads; // array of SVnodeLoad
|
||||
int32_t statusSeq;
|
||||
int64_t ipWhiteVer;
|
||||
int64_t analVer;
|
||||
} SStatusReq;
|
||||
|
||||
int32_t tSerializeSStatusReq(void* buf, int32_t bufLen, SStatusReq* pReq);
|
||||
|
@ -1831,6 +1860,7 @@ typedef struct {
|
|||
SArray* pDnodeEps; // Array of SDnodeEp
|
||||
int32_t statusSeq;
|
||||
int64_t ipWhiteVer;
|
||||
int64_t analVer;
|
||||
} SStatusRsp;
|
||||
|
||||
int32_t tSerializeSStatusRsp(void* buf, int32_t bufLen, SStatusRsp* pRsp);
|
||||
|
@ -2377,6 +2407,30 @@ typedef struct {
|
|||
int32_t tSerializeSDCreateMnodeReq(void* buf, int32_t bufLen, SDCreateMnodeReq* pReq);
|
||||
int32_t tDeserializeSDCreateMnodeReq(void* buf, int32_t bufLen, SDCreateMnodeReq* pReq);
|
||||
|
||||
typedef struct {
|
||||
int32_t urlLen;
|
||||
int32_t sqlLen;
|
||||
char* url;
|
||||
char* sql;
|
||||
} SMCreateAnodeReq;
|
||||
|
||||
int32_t tSerializeSMCreateAnodeReq(void* buf, int32_t bufLen, SMCreateAnodeReq* pReq);
|
||||
int32_t tDeserializeSMCreateAnodeReq(void* buf, int32_t bufLen, SMCreateAnodeReq* pReq);
|
||||
void tFreeSMCreateAnodeReq(SMCreateAnodeReq* pReq);
|
||||
|
||||
typedef struct {
|
||||
int32_t anodeId;
|
||||
int32_t sqlLen;
|
||||
char* sql;
|
||||
} SMDropAnodeReq, SMUpdateAnodeReq;
|
||||
|
||||
int32_t tSerializeSMDropAnodeReq(void* buf, int32_t bufLen, SMDropAnodeReq* pReq);
|
||||
int32_t tDeserializeSMDropAnodeReq(void* buf, int32_t bufLen, SMDropAnodeReq* pReq);
|
||||
void tFreeSMDropAnodeReq(SMDropAnodeReq* pReq);
|
||||
int32_t tSerializeSMUpdateAnodeReq(void* buf, int32_t bufLen, SMUpdateAnodeReq* pReq);
|
||||
int32_t tDeserializeSMUpdateAnodeReq(void* buf, int32_t bufLen, SMUpdateAnodeReq* pReq);
|
||||
void tFreeSMUpdateAnodeReq(SMUpdateAnodeReq* pReq);
|
||||
|
||||
typedef struct {
|
||||
int32_t vgId;
|
||||
int32_t hbSeq;
|
||||
|
|
|
@ -125,6 +125,11 @@
|
|||
TD_DEF_MSG_TYPE(TDMT_DND_ALTER_VNODE_TYPE, "dnode-alter-vnode-type", NULL, NULL)
|
||||
TD_DEF_MSG_TYPE(TDMT_DND_CHECK_VNODE_LEARNER_CATCHUP, "dnode-check-vnode-learner-catchup", NULL, NULL)
|
||||
TD_DEF_MSG_TYPE(TDMT_DND_CREATE_ENCRYPT_KEY, "create-encrypt-key", NULL, NULL)
|
||||
// mnode msg overload
|
||||
TD_DEF_MSG_TYPE(TDMT_MND_CREATE_ANODE, "create-anode", NULL, NULL)
|
||||
TD_DEF_MSG_TYPE(TDMT_MND_UPDATE_ANODE, "update-anode", NULL, NULL)
|
||||
TD_DEF_MSG_TYPE(TDMT_MND_DROP_ANODE, "drop-anode", NULL, NULL)
|
||||
TD_DEF_MSG_TYPE(TDMT_MND_RETRIEVE_ANAL_ALGO, "retrieve-anal-algo", NULL, NULL)
|
||||
TD_CLOSE_MSG_SEG(TDMT_DND_MSG)
|
||||
|
||||
TD_NEW_MSG_SEG(TDMT_MND_MSG) // 1<<8
|
||||
|
|
|
@ -69,335 +69,341 @@
|
|||
#define TK_NK_DOT 51
|
||||
#define TK_WITH 52
|
||||
#define TK_ENCRYPT_KEY 53
|
||||
#define TK_DNODE 54
|
||||
#define TK_PORT 55
|
||||
#define TK_DNODES 56
|
||||
#define TK_RESTORE 57
|
||||
#define TK_NK_IPTOKEN 58
|
||||
#define TK_FORCE 59
|
||||
#define TK_UNSAFE 60
|
||||
#define TK_CLUSTER 61
|
||||
#define TK_LOCAL 62
|
||||
#define TK_QNODE 63
|
||||
#define TK_BNODE 64
|
||||
#define TK_SNODE 65
|
||||
#define TK_MNODE 66
|
||||
#define TK_VNODE 67
|
||||
#define TK_DATABASE 68
|
||||
#define TK_USE 69
|
||||
#define TK_FLUSH 70
|
||||
#define TK_TRIM 71
|
||||
#define TK_S3MIGRATE 72
|
||||
#define TK_COMPACT 73
|
||||
#define TK_IF 74
|
||||
#define TK_NOT 75
|
||||
#define TK_EXISTS 76
|
||||
#define TK_BUFFER 77
|
||||
#define TK_CACHEMODEL 78
|
||||
#define TK_CACHESIZE 79
|
||||
#define TK_COMP 80
|
||||
#define TK_DURATION 81
|
||||
#define TK_NK_VARIABLE 82
|
||||
#define TK_MAXROWS 83
|
||||
#define TK_MINROWS 84
|
||||
#define TK_KEEP 85
|
||||
#define TK_PAGES 86
|
||||
#define TK_PAGESIZE 87
|
||||
#define TK_TSDB_PAGESIZE 88
|
||||
#define TK_PRECISION 89
|
||||
#define TK_REPLICA 90
|
||||
#define TK_VGROUPS 91
|
||||
#define TK_SINGLE_STABLE 92
|
||||
#define TK_RETENTIONS 93
|
||||
#define TK_SCHEMALESS 94
|
||||
#define TK_WAL_LEVEL 95
|
||||
#define TK_WAL_FSYNC_PERIOD 96
|
||||
#define TK_WAL_RETENTION_PERIOD 97
|
||||
#define TK_WAL_RETENTION_SIZE 98
|
||||
#define TK_WAL_ROLL_PERIOD 99
|
||||
#define TK_WAL_SEGMENT_SIZE 100
|
||||
#define TK_STT_TRIGGER 101
|
||||
#define TK_TABLE_PREFIX 102
|
||||
#define TK_TABLE_SUFFIX 103
|
||||
#define TK_S3_CHUNKSIZE 104
|
||||
#define TK_S3_KEEPLOCAL 105
|
||||
#define TK_S3_COMPACT 106
|
||||
#define TK_KEEP_TIME_OFFSET 107
|
||||
#define TK_ENCRYPT_ALGORITHM 108
|
||||
#define TK_NK_COLON 109
|
||||
#define TK_BWLIMIT 110
|
||||
#define TK_START 111
|
||||
#define TK_TIMESTAMP 112
|
||||
#define TK_END 113
|
||||
#define TK_TABLE 114
|
||||
#define TK_NK_LP 115
|
||||
#define TK_NK_RP 116
|
||||
#define TK_USING 117
|
||||
#define TK_FILE 118
|
||||
#define TK_STABLE 119
|
||||
#define TK_COLUMN 120
|
||||
#define TK_MODIFY 121
|
||||
#define TK_RENAME 122
|
||||
#define TK_TAG 123
|
||||
#define TK_SET 124
|
||||
#define TK_NK_EQ 125
|
||||
#define TK_TAGS 126
|
||||
#define TK_BOOL 127
|
||||
#define TK_TINYINT 128
|
||||
#define TK_SMALLINT 129
|
||||
#define TK_INT 130
|
||||
#define TK_INTEGER 131
|
||||
#define TK_BIGINT 132
|
||||
#define TK_FLOAT 133
|
||||
#define TK_DOUBLE 134
|
||||
#define TK_BINARY 135
|
||||
#define TK_NCHAR 136
|
||||
#define TK_UNSIGNED 137
|
||||
#define TK_JSON 138
|
||||
#define TK_VARCHAR 139
|
||||
#define TK_MEDIUMBLOB 140
|
||||
#define TK_BLOB 141
|
||||
#define TK_VARBINARY 142
|
||||
#define TK_GEOMETRY 143
|
||||
#define TK_DECIMAL 144
|
||||
#define TK_COMMENT 145
|
||||
#define TK_MAX_DELAY 146
|
||||
#define TK_WATERMARK 147
|
||||
#define TK_ROLLUP 148
|
||||
#define TK_TTL 149
|
||||
#define TK_SMA 150
|
||||
#define TK_DELETE_MARK 151
|
||||
#define TK_FIRST 152
|
||||
#define TK_LAST 153
|
||||
#define TK_SHOW 154
|
||||
#define TK_FULL 155
|
||||
#define TK_PRIVILEGES 156
|
||||
#define TK_DATABASES 157
|
||||
#define TK_TABLES 158
|
||||
#define TK_STABLES 159
|
||||
#define TK_MNODES 160
|
||||
#define TK_QNODES 161
|
||||
#define TK_ARBGROUPS 162
|
||||
#define TK_FUNCTIONS 163
|
||||
#define TK_INDEXES 164
|
||||
#define TK_ACCOUNTS 165
|
||||
#define TK_APPS 166
|
||||
#define TK_CONNECTIONS 167
|
||||
#define TK_LICENCES 168
|
||||
#define TK_GRANTS 169
|
||||
#define TK_LOGS 170
|
||||
#define TK_MACHINES 171
|
||||
#define TK_ENCRYPTIONS 172
|
||||
#define TK_QUERIES 173
|
||||
#define TK_SCORES 174
|
||||
#define TK_TOPICS 175
|
||||
#define TK_VARIABLES 176
|
||||
#define TK_BNODES 177
|
||||
#define TK_SNODES 178
|
||||
#define TK_TRANSACTIONS 179
|
||||
#define TK_DISTRIBUTED 180
|
||||
#define TK_CONSUMERS 181
|
||||
#define TK_SUBSCRIPTIONS 182
|
||||
#define TK_VNODES 183
|
||||
#define TK_ALIVE 184
|
||||
#define TK_VIEWS 185
|
||||
#define TK_VIEW 186
|
||||
#define TK_COMPACTS 187
|
||||
#define TK_NORMAL 188
|
||||
#define TK_CHILD 189
|
||||
#define TK_LIKE 190
|
||||
#define TK_TBNAME 191
|
||||
#define TK_QTAGS 192
|
||||
#define TK_AS 193
|
||||
#define TK_SYSTEM 194
|
||||
#define TK_TSMA 195
|
||||
#define TK_INTERVAL 196
|
||||
#define TK_RECURSIVE 197
|
||||
#define TK_TSMAS 198
|
||||
#define TK_FUNCTION 199
|
||||
#define TK_INDEX 200
|
||||
#define TK_COUNT 201
|
||||
#define TK_LAST_ROW 202
|
||||
#define TK_META 203
|
||||
#define TK_ONLY 204
|
||||
#define TK_TOPIC 205
|
||||
#define TK_CONSUMER 206
|
||||
#define TK_GROUP 207
|
||||
#define TK_DESC 208
|
||||
#define TK_DESCRIBE 209
|
||||
#define TK_RESET 210
|
||||
#define TK_QUERY 211
|
||||
#define TK_CACHE 212
|
||||
#define TK_EXPLAIN 213
|
||||
#define TK_ANALYZE 214
|
||||
#define TK_VERBOSE 215
|
||||
#define TK_NK_BOOL 216
|
||||
#define TK_RATIO 217
|
||||
#define TK_NK_FLOAT 218
|
||||
#define TK_OUTPUTTYPE 219
|
||||
#define TK_AGGREGATE 220
|
||||
#define TK_BUFSIZE 221
|
||||
#define TK_LANGUAGE 222
|
||||
#define TK_REPLACE 223
|
||||
#define TK_STREAM 224
|
||||
#define TK_INTO 225
|
||||
#define TK_PAUSE 226
|
||||
#define TK_RESUME 227
|
||||
#define TK_PRIMARY 228
|
||||
#define TK_KEY 229
|
||||
#define TK_TRIGGER 230
|
||||
#define TK_AT_ONCE 231
|
||||
#define TK_WINDOW_CLOSE 232
|
||||
#define TK_IGNORE 233
|
||||
#define TK_EXPIRED 234
|
||||
#define TK_FILL_HISTORY 235
|
||||
#define TK_UPDATE 236
|
||||
#define TK_SUBTABLE 237
|
||||
#define TK_UNTREATED 238
|
||||
#define TK_KILL 239
|
||||
#define TK_CONNECTION 240
|
||||
#define TK_TRANSACTION 241
|
||||
#define TK_BALANCE 242
|
||||
#define TK_VGROUP 243
|
||||
#define TK_LEADER 244
|
||||
#define TK_MERGE 245
|
||||
#define TK_REDISTRIBUTE 246
|
||||
#define TK_SPLIT 247
|
||||
#define TK_DELETE 248
|
||||
#define TK_INSERT 249
|
||||
#define TK_NK_BIN 250
|
||||
#define TK_NK_HEX 251
|
||||
#define TK_NULL 252
|
||||
#define TK_NK_QUESTION 253
|
||||
#define TK_NK_ALIAS 254
|
||||
#define TK_NK_ARROW 255
|
||||
#define TK_ROWTS 256
|
||||
#define TK_QSTART 257
|
||||
#define TK_QEND 258
|
||||
#define TK_QDURATION 259
|
||||
#define TK_WSTART 260
|
||||
#define TK_WEND 261
|
||||
#define TK_WDURATION 262
|
||||
#define TK_IROWTS 263
|
||||
#define TK_ISFILLED 264
|
||||
#define TK_CAST 265
|
||||
#define TK_POSITION 266
|
||||
#define TK_IN 267
|
||||
#define TK_FOR 268
|
||||
#define TK_NOW 269
|
||||
#define TK_TODAY 270
|
||||
#define TK_RAND 271
|
||||
#define TK_SUBSTR 272
|
||||
#define TK_SUBSTRING 273
|
||||
#define TK_BOTH 274
|
||||
#define TK_TRAILING 275
|
||||
#define TK_LEADING 276
|
||||
#define TK_TIMEZONE 277
|
||||
#define TK_CLIENT_VERSION 278
|
||||
#define TK_SERVER_VERSION 279
|
||||
#define TK_SERVER_STATUS 280
|
||||
#define TK_CURRENT_USER 281
|
||||
#define TK_PI 282
|
||||
#define TK_CASE 283
|
||||
#define TK_WHEN 284
|
||||
#define TK_THEN 285
|
||||
#define TK_ELSE 286
|
||||
#define TK_BETWEEN 287
|
||||
#define TK_IS 288
|
||||
#define TK_NK_LT 289
|
||||
#define TK_NK_GT 290
|
||||
#define TK_NK_LE 291
|
||||
#define TK_NK_GE 292
|
||||
#define TK_NK_NE 293
|
||||
#define TK_MATCH 294
|
||||
#define TK_NMATCH 295
|
||||
#define TK_CONTAINS 296
|
||||
#define TK_JOIN 297
|
||||
#define TK_INNER 298
|
||||
#define TK_LEFT 299
|
||||
#define TK_RIGHT 300
|
||||
#define TK_OUTER 301
|
||||
#define TK_SEMI 302
|
||||
#define TK_ANTI 303
|
||||
#define TK_ASOF 304
|
||||
#define TK_WINDOW 305
|
||||
#define TK_WINDOW_OFFSET 306
|
||||
#define TK_JLIMIT 307
|
||||
#define TK_SELECT 308
|
||||
#define TK_NK_HINT 309
|
||||
#define TK_DISTINCT 310
|
||||
#define TK_WHERE 311
|
||||
#define TK_PARTITION 312
|
||||
#define TK_BY 313
|
||||
#define TK_SESSION 314
|
||||
#define TK_STATE_WINDOW 315
|
||||
#define TK_EVENT_WINDOW 316
|
||||
#define TK_COUNT_WINDOW 317
|
||||
#define TK_SLIDING 318
|
||||
#define TK_FILL 319
|
||||
#define TK_VALUE 320
|
||||
#define TK_VALUE_F 321
|
||||
#define TK_NONE 322
|
||||
#define TK_PREV 323
|
||||
#define TK_NULL_F 324
|
||||
#define TK_LINEAR 325
|
||||
#define TK_NEXT 326
|
||||
#define TK_HAVING 327
|
||||
#define TK_RANGE 328
|
||||
#define TK_EVERY 329
|
||||
#define TK_ORDER 330
|
||||
#define TK_SLIMIT 331
|
||||
#define TK_SOFFSET 332
|
||||
#define TK_LIMIT 333
|
||||
#define TK_OFFSET 334
|
||||
#define TK_ASC 335
|
||||
#define TK_NULLS 336
|
||||
#define TK_ABORT 337
|
||||
#define TK_AFTER 338
|
||||
#define TK_ATTACH 339
|
||||
#define TK_BEFORE 340
|
||||
#define TK_BEGIN 341
|
||||
#define TK_BITAND 342
|
||||
#define TK_BITNOT 343
|
||||
#define TK_BITOR 344
|
||||
#define TK_BLOCKS 345
|
||||
#define TK_CHANGE 346
|
||||
#define TK_COMMA 347
|
||||
#define TK_CONCAT 348
|
||||
#define TK_CONFLICT 349
|
||||
#define TK_COPY 350
|
||||
#define TK_DEFERRED 351
|
||||
#define TK_DELIMITERS 352
|
||||
#define TK_DETACH 353
|
||||
#define TK_DIVIDE 354
|
||||
#define TK_DOT 355
|
||||
#define TK_EACH 356
|
||||
#define TK_FAIL 357
|
||||
#define TK_GLOB 358
|
||||
#define TK_ID 359
|
||||
#define TK_IMMEDIATE 360
|
||||
#define TK_IMPORT 361
|
||||
#define TK_INITIALLY 362
|
||||
#define TK_INSTEAD 363
|
||||
#define TK_ISNULL 364
|
||||
#define TK_MODULES 365
|
||||
#define TK_NK_BITNOT 366
|
||||
#define TK_NK_SEMI 367
|
||||
#define TK_NOTNULL 368
|
||||
#define TK_OF 369
|
||||
#define TK_PLUS 370
|
||||
#define TK_PRIVILEGE 371
|
||||
#define TK_RAISE 372
|
||||
#define TK_RESTRICT 373
|
||||
#define TK_ROW 374
|
||||
#define TK_STAR 375
|
||||
#define TK_STATEMENT 376
|
||||
#define TK_STRICT 377
|
||||
#define TK_STRING 378
|
||||
#define TK_TIMES 379
|
||||
#define TK_VALUES 380
|
||||
#define TK_VARIABLE 381
|
||||
#define TK_WAL 382
|
||||
#define TK_ANODE 54
|
||||
#define TK_UPDATE 55
|
||||
#define TK_ANODES 56
|
||||
#define TK_DNODE 57
|
||||
#define TK_PORT 58
|
||||
#define TK_DNODES 59
|
||||
#define TK_RESTORE 60
|
||||
#define TK_NK_IPTOKEN 61
|
||||
#define TK_FORCE 62
|
||||
#define TK_UNSAFE 63
|
||||
#define TK_CLUSTER 64
|
||||
#define TK_LOCAL 65
|
||||
#define TK_QNODE 66
|
||||
#define TK_BNODE 67
|
||||
#define TK_SNODE 68
|
||||
#define TK_MNODE 69
|
||||
#define TK_VNODE 70
|
||||
#define TK_DATABASE 71
|
||||
#define TK_USE 72
|
||||
#define TK_FLUSH 73
|
||||
#define TK_TRIM 74
|
||||
#define TK_S3MIGRATE 75
|
||||
#define TK_COMPACT 76
|
||||
#define TK_IF 77
|
||||
#define TK_NOT 78
|
||||
#define TK_EXISTS 79
|
||||
#define TK_BUFFER 80
|
||||
#define TK_CACHEMODEL 81
|
||||
#define TK_CACHESIZE 82
|
||||
#define TK_COMP 83
|
||||
#define TK_DURATION 84
|
||||
#define TK_NK_VARIABLE 85
|
||||
#define TK_MAXROWS 86
|
||||
#define TK_MINROWS 87
|
||||
#define TK_KEEP 88
|
||||
#define TK_PAGES 89
|
||||
#define TK_PAGESIZE 90
|
||||
#define TK_TSDB_PAGESIZE 91
|
||||
#define TK_PRECISION 92
|
||||
#define TK_REPLICA 93
|
||||
#define TK_VGROUPS 94
|
||||
#define TK_SINGLE_STABLE 95
|
||||
#define TK_RETENTIONS 96
|
||||
#define TK_SCHEMALESS 97
|
||||
#define TK_WAL_LEVEL 98
|
||||
#define TK_WAL_FSYNC_PERIOD 99
|
||||
#define TK_WAL_RETENTION_PERIOD 100
|
||||
#define TK_WAL_RETENTION_SIZE 101
|
||||
#define TK_WAL_ROLL_PERIOD 102
|
||||
#define TK_WAL_SEGMENT_SIZE 103
|
||||
#define TK_STT_TRIGGER 104
|
||||
#define TK_TABLE_PREFIX 105
|
||||
#define TK_TABLE_SUFFIX 106
|
||||
#define TK_S3_CHUNKSIZE 107
|
||||
#define TK_S3_KEEPLOCAL 108
|
||||
#define TK_S3_COMPACT 109
|
||||
#define TK_KEEP_TIME_OFFSET 110
|
||||
#define TK_ENCRYPT_ALGORITHM 111
|
||||
#define TK_NK_COLON 112
|
||||
#define TK_BWLIMIT 113
|
||||
#define TK_START 114
|
||||
#define TK_TIMESTAMP 115
|
||||
#define TK_END 116
|
||||
#define TK_TABLE 117
|
||||
#define TK_NK_LP 118
|
||||
#define TK_NK_RP 119
|
||||
#define TK_USING 120
|
||||
#define TK_FILE 121
|
||||
#define TK_STABLE 122
|
||||
#define TK_COLUMN 123
|
||||
#define TK_MODIFY 124
|
||||
#define TK_RENAME 125
|
||||
#define TK_TAG 126
|
||||
#define TK_SET 127
|
||||
#define TK_NK_EQ 128
|
||||
#define TK_TAGS 129
|
||||
#define TK_BOOL 130
|
||||
#define TK_TINYINT 131
|
||||
#define TK_SMALLINT 132
|
||||
#define TK_INT 133
|
||||
#define TK_INTEGER 134
|
||||
#define TK_BIGINT 135
|
||||
#define TK_FLOAT 136
|
||||
#define TK_DOUBLE 137
|
||||
#define TK_BINARY 138
|
||||
#define TK_NCHAR 139
|
||||
#define TK_UNSIGNED 140
|
||||
#define TK_JSON 141
|
||||
#define TK_VARCHAR 142
|
||||
#define TK_MEDIUMBLOB 143
|
||||
#define TK_BLOB 144
|
||||
#define TK_VARBINARY 145
|
||||
#define TK_GEOMETRY 146
|
||||
#define TK_DECIMAL 147
|
||||
#define TK_COMMENT 148
|
||||
#define TK_MAX_DELAY 149
|
||||
#define TK_WATERMARK 150
|
||||
#define TK_ROLLUP 151
|
||||
#define TK_TTL 152
|
||||
#define TK_SMA 153
|
||||
#define TK_DELETE_MARK 154
|
||||
#define TK_FIRST 155
|
||||
#define TK_LAST 156
|
||||
#define TK_SHOW 157
|
||||
#define TK_FULL 158
|
||||
#define TK_PRIVILEGES 159
|
||||
#define TK_DATABASES 160
|
||||
#define TK_TABLES 161
|
||||
#define TK_STABLES 162
|
||||
#define TK_MNODES 163
|
||||
#define TK_QNODES 164
|
||||
#define TK_ARBGROUPS 165
|
||||
#define TK_FUNCTIONS 166
|
||||
#define TK_INDEXES 167
|
||||
#define TK_ACCOUNTS 168
|
||||
#define TK_APPS 169
|
||||
#define TK_CONNECTIONS 170
|
||||
#define TK_LICENCES 171
|
||||
#define TK_GRANTS 172
|
||||
#define TK_LOGS 173
|
||||
#define TK_MACHINES 174
|
||||
#define TK_ENCRYPTIONS 175
|
||||
#define TK_QUERIES 176
|
||||
#define TK_SCORES 177
|
||||
#define TK_TOPICS 178
|
||||
#define TK_VARIABLES 179
|
||||
#define TK_BNODES 180
|
||||
#define TK_SNODES 181
|
||||
#define TK_TRANSACTIONS 182
|
||||
#define TK_DISTRIBUTED 183
|
||||
#define TK_CONSUMERS 184
|
||||
#define TK_SUBSCRIPTIONS 185
|
||||
#define TK_VNODES 186
|
||||
#define TK_ALIVE 187
|
||||
#define TK_VIEWS 188
|
||||
#define TK_VIEW 189
|
||||
#define TK_COMPACTS 190
|
||||
#define TK_NORMAL 191
|
||||
#define TK_CHILD 192
|
||||
#define TK_LIKE 193
|
||||
#define TK_TBNAME 194
|
||||
#define TK_QTAGS 195
|
||||
#define TK_AS 196
|
||||
#define TK_SYSTEM 197
|
||||
#define TK_TSMA 198
|
||||
#define TK_INTERVAL 199
|
||||
#define TK_RECURSIVE 200
|
||||
#define TK_TSMAS 201
|
||||
#define TK_FUNCTION 202
|
||||
#define TK_INDEX 203
|
||||
#define TK_COUNT 204
|
||||
#define TK_LAST_ROW 205
|
||||
#define TK_META 206
|
||||
#define TK_ONLY 207
|
||||
#define TK_TOPIC 208
|
||||
#define TK_CONSUMER 209
|
||||
#define TK_GROUP 210
|
||||
#define TK_DESC 211
|
||||
#define TK_DESCRIBE 212
|
||||
#define TK_RESET 213
|
||||
#define TK_QUERY 214
|
||||
#define TK_CACHE 215
|
||||
#define TK_EXPLAIN 216
|
||||
#define TK_ANALYZE 217
|
||||
#define TK_VERBOSE 218
|
||||
#define TK_NK_BOOL 219
|
||||
#define TK_RATIO 220
|
||||
#define TK_NK_FLOAT 221
|
||||
#define TK_OUTPUTTYPE 222
|
||||
#define TK_AGGREGATE 223
|
||||
#define TK_BUFSIZE 224
|
||||
#define TK_LANGUAGE 225
|
||||
#define TK_REPLACE 226
|
||||
#define TK_STREAM 227
|
||||
#define TK_INTO 228
|
||||
#define TK_PAUSE 229
|
||||
#define TK_RESUME 230
|
||||
#define TK_PRIMARY 231
|
||||
#define TK_KEY 232
|
||||
#define TK_TRIGGER 233
|
||||
#define TK_AT_ONCE 234
|
||||
#define TK_WINDOW_CLOSE 235
|
||||
#define TK_IGNORE 236
|
||||
#define TK_EXPIRED 237
|
||||
#define TK_FILL_HISTORY 238
|
||||
#define TK_SUBTABLE 239
|
||||
#define TK_UNTREATED 240
|
||||
#define TK_KILL 241
|
||||
#define TK_CONNECTION 242
|
||||
#define TK_TRANSACTION 243
|
||||
#define TK_BALANCE 244
|
||||
#define TK_VGROUP 245
|
||||
#define TK_LEADER 246
|
||||
#define TK_MERGE 247
|
||||
#define TK_REDISTRIBUTE 248
|
||||
#define TK_SPLIT 249
|
||||
#define TK_DELETE 250
|
||||
#define TK_INSERT 251
|
||||
#define TK_NK_BIN 252
|
||||
#define TK_NK_HEX 253
|
||||
#define TK_NULL 254
|
||||
#define TK_NK_QUESTION 255
|
||||
#define TK_NK_ALIAS 256
|
||||
#define TK_NK_ARROW 257
|
||||
#define TK_ROWTS 258
|
||||
#define TK_QSTART 259
|
||||
#define TK_QEND 260
|
||||
#define TK_QDURATION 261
|
||||
#define TK_WSTART 262
|
||||
#define TK_WEND 263
|
||||
#define TK_WDURATION 264
|
||||
#define TK_IROWTS 265
|
||||
#define TK_ISFILLED 266
|
||||
#define TK_FLOW 267
|
||||
#define TK_FHIGH 268
|
||||
#define TK_FROWTS 269
|
||||
#define TK_CAST 270
|
||||
#define TK_POSITION 271
|
||||
#define TK_IN 272
|
||||
#define TK_FOR 273
|
||||
#define TK_NOW 274
|
||||
#define TK_TODAY 275
|
||||
#define TK_RAND 276
|
||||
#define TK_SUBSTR 277
|
||||
#define TK_SUBSTRING 278
|
||||
#define TK_BOTH 279
|
||||
#define TK_TRAILING 280
|
||||
#define TK_LEADING 281
|
||||
#define TK_TIMEZONE 282
|
||||
#define TK_CLIENT_VERSION 283
|
||||
#define TK_SERVER_VERSION 284
|
||||
#define TK_SERVER_STATUS 285
|
||||
#define TK_CURRENT_USER 286
|
||||
#define TK_PI 287
|
||||
#define TK_CASE 288
|
||||
#define TK_WHEN 289
|
||||
#define TK_THEN 290
|
||||
#define TK_ELSE 291
|
||||
#define TK_BETWEEN 292
|
||||
#define TK_IS 293
|
||||
#define TK_NK_LT 294
|
||||
#define TK_NK_GT 295
|
||||
#define TK_NK_LE 296
|
||||
#define TK_NK_GE 297
|
||||
#define TK_NK_NE 298
|
||||
#define TK_MATCH 299
|
||||
#define TK_NMATCH 300
|
||||
#define TK_CONTAINS 301
|
||||
#define TK_JOIN 302
|
||||
#define TK_INNER 303
|
||||
#define TK_LEFT 304
|
||||
#define TK_RIGHT 305
|
||||
#define TK_OUTER 306
|
||||
#define TK_SEMI 307
|
||||
#define TK_ANTI 308
|
||||
#define TK_ASOF 309
|
||||
#define TK_WINDOW 310
|
||||
#define TK_WINDOW_OFFSET 311
|
||||
#define TK_JLIMIT 312
|
||||
#define TK_SELECT 313
|
||||
#define TK_NK_HINT 314
|
||||
#define TK_DISTINCT 315
|
||||
#define TK_WHERE 316
|
||||
#define TK_PARTITION 317
|
||||
#define TK_BY 318
|
||||
#define TK_SESSION 319
|
||||
#define TK_STATE_WINDOW 320
|
||||
#define TK_EVENT_WINDOW 321
|
||||
#define TK_COUNT_WINDOW 322
|
||||
#define TK_ANOMALY_WINDOW 323
|
||||
#define TK_SLIDING 324
|
||||
#define TK_FILL 325
|
||||
#define TK_VALUE 326
|
||||
#define TK_VALUE_F 327
|
||||
#define TK_NONE 328
|
||||
#define TK_PREV 329
|
||||
#define TK_NULL_F 330
|
||||
#define TK_LINEAR 331
|
||||
#define TK_NEXT 332
|
||||
#define TK_HAVING 333
|
||||
#define TK_RANGE 334
|
||||
#define TK_EVERY 335
|
||||
#define TK_ORDER 336
|
||||
#define TK_SLIMIT 337
|
||||
#define TK_SOFFSET 338
|
||||
#define TK_LIMIT 339
|
||||
#define TK_OFFSET 340
|
||||
#define TK_ASC 341
|
||||
#define TK_NULLS 342
|
||||
#define TK_ABORT 343
|
||||
#define TK_AFTER 344
|
||||
#define TK_ATTACH 345
|
||||
#define TK_BEFORE 346
|
||||
#define TK_BEGIN 347
|
||||
#define TK_BITAND 348
|
||||
#define TK_BITNOT 349
|
||||
#define TK_BITOR 350
|
||||
#define TK_BLOCKS 351
|
||||
#define TK_CHANGE 352
|
||||
#define TK_COMMA 353
|
||||
#define TK_CONCAT 354
|
||||
#define TK_CONFLICT 355
|
||||
#define TK_COPY 356
|
||||
#define TK_DEFERRED 357
|
||||
#define TK_DELIMITERS 358
|
||||
#define TK_DETACH 359
|
||||
#define TK_DIVIDE 360
|
||||
#define TK_DOT 361
|
||||
#define TK_EACH 362
|
||||
#define TK_FAIL 363
|
||||
#define TK_GLOB 364
|
||||
#define TK_ID 365
|
||||
#define TK_IMMEDIATE 366
|
||||
#define TK_IMPORT 367
|
||||
#define TK_INITIALLY 368
|
||||
#define TK_INSTEAD 369
|
||||
#define TK_ISNULL 370
|
||||
#define TK_MODULES 371
|
||||
#define TK_NK_BITNOT 372
|
||||
#define TK_NK_SEMI 373
|
||||
#define TK_NOTNULL 374
|
||||
#define TK_OF 375
|
||||
#define TK_PLUS 376
|
||||
#define TK_PRIVILEGE 377
|
||||
#define TK_RAISE 378
|
||||
#define TK_RESTRICT 379
|
||||
#define TK_ROW 380
|
||||
#define TK_STAR 381
|
||||
#define TK_STATEMENT 382
|
||||
#define TK_STRICT 383
|
||||
#define TK_STRING 384
|
||||
#define TK_TIMES 385
|
||||
#define TK_VALUES 386
|
||||
#define TK_VARIABLE 387
|
||||
#define TK_WAL 388
|
||||
|
||||
#define TK_NK_SPACE 600
|
||||
#define TK_NK_COMMENT 601
|
||||
|
|
|
@ -62,6 +62,7 @@ typedef enum EFunctionType {
|
|||
FUNCTION_TYPE_UNIQUE,
|
||||
FUNCTION_TYPE_STATE_COUNT,
|
||||
FUNCTION_TYPE_STATE_DURATION,
|
||||
FUNCTION_TYPE_FORECAST,
|
||||
|
||||
// math function
|
||||
FUNCTION_TYPE_ABS = 1000,
|
||||
|
@ -149,6 +150,9 @@ typedef enum EFunctionType {
|
|||
FUNCTION_TYPE_TBUID,
|
||||
FUNCTION_TYPE_VGID,
|
||||
FUNCTION_TYPE_VGVER,
|
||||
FUNCTION_TYPE_FORECAST_LOW,
|
||||
FUNCTION_TYPE_FORECAST_HIGH,
|
||||
FUNCTION_TYPE_FORECAST_ROWTS,
|
||||
|
||||
// internal function
|
||||
FUNCTION_TYPE_SELECT_VALUE = 3750,
|
||||
|
@ -263,6 +267,7 @@ bool fmIsForbidSysTableFunc(int32_t funcId);
|
|||
bool fmIsIntervalInterpoFunc(int32_t funcId);
|
||||
bool fmIsInterpFunc(int32_t funcId);
|
||||
bool fmIsLastRowFunc(int32_t funcId);
|
||||
bool fmIsForecastFunc(int32_t funcId);
|
||||
bool fmIsNotNullOutputFunc(int32_t funcId);
|
||||
bool fmIsSelectValueFunc(int32_t funcId);
|
||||
bool fmIsSystemInfoFunc(int32_t funcId);
|
||||
|
@ -272,6 +277,7 @@ bool fmIsMultiRowsFunc(int32_t funcId);
|
|||
bool fmIsKeepOrderFunc(int32_t funcId);
|
||||
bool fmIsCumulativeFunc(int32_t funcId);
|
||||
bool fmIsInterpPseudoColumnFunc(int32_t funcId);
|
||||
bool fmIsForecastPseudoColumnFunc(int32_t funcId);
|
||||
bool fmIsGroupKeyFunc(int32_t funcId);
|
||||
bool fmIsBlockDistFunc(int32_t funcId);
|
||||
bool fmIsIgnoreNullFunc(int32_t funcId);
|
||||
|
|
|
@ -318,6 +318,21 @@ typedef struct SAlterDnodeStmt {
|
|||
char value[TSDB_DNODE_VALUE_LEN];
|
||||
} SAlterDnodeStmt;
|
||||
|
||||
typedef struct {
|
||||
ENodeType type;
|
||||
char url[TSDB_ANAL_ANODE_URL_LEN + 3];
|
||||
} SCreateAnodeStmt;
|
||||
|
||||
typedef struct {
|
||||
ENodeType type;
|
||||
int32_t anodeId;
|
||||
} SDropAnodeStmt;
|
||||
|
||||
typedef struct {
|
||||
ENodeType type;
|
||||
int32_t anodeId;
|
||||
} SUpdateAnodeStmt;
|
||||
|
||||
typedef struct SShowStmt {
|
||||
ENodeType type;
|
||||
SNode* pDbName; // SValueNode
|
||||
|
|
|
@ -204,6 +204,11 @@ typedef struct SInterpFuncLogicNode {
|
|||
SNode* pTimeSeries; // SColumnNode
|
||||
} SInterpFuncLogicNode;
|
||||
|
||||
typedef struct SForecastFuncLogicNode {
|
||||
SLogicNode node;
|
||||
SNodeList* pFuncs;
|
||||
} SForecastFuncLogicNode;
|
||||
|
||||
typedef struct SGroupCacheLogicNode {
|
||||
SLogicNode node;
|
||||
bool grpColsMayBeNull;
|
||||
|
@ -275,6 +280,7 @@ typedef enum EWindowType {
|
|||
WINDOW_TYPE_STATE,
|
||||
WINDOW_TYPE_EVENT,
|
||||
WINDOW_TYPE_COUNT,
|
||||
WINDOW_TYPE_ANOMALY
|
||||
} EWindowType;
|
||||
|
||||
typedef enum EWindowAlgorithm {
|
||||
|
@ -315,6 +321,8 @@ typedef struct SWindowLogicNode {
|
|||
int64_t windowCount;
|
||||
int64_t windowSliding;
|
||||
SNodeList* pTsmaSubplans;
|
||||
SNode* pAnomalyExpr;
|
||||
char anomalyOpt[TSDB_ANAL_ALGO_OPTION_LEN];
|
||||
} SWindowLogicNode;
|
||||
|
||||
typedef struct SFillLogicNode {
|
||||
|
@ -507,6 +515,12 @@ typedef struct SInterpFuncPhysiNode {
|
|||
SNode* pTimeSeries; // SColumnNode
|
||||
} SInterpFuncPhysiNode;
|
||||
|
||||
typedef struct SForecastFuncPhysiNode {
|
||||
SPhysiNode node;
|
||||
SNodeList* pExprs;
|
||||
SNodeList* pFuncs;
|
||||
} SForecastFuncPhysiNode;
|
||||
|
||||
typedef struct SSortMergeJoinPhysiNode {
|
||||
SPhysiNode node;
|
||||
EJoinType joinType;
|
||||
|
@ -704,6 +718,12 @@ typedef struct SCountWinodwPhysiNode {
|
|||
|
||||
typedef SCountWinodwPhysiNode SStreamCountWinodwPhysiNode;
|
||||
|
||||
typedef struct SAnomalyWindowPhysiNode {
|
||||
SWindowPhysiNode window;
|
||||
SNode* pAnomalyKey;
|
||||
char anomalyOpt[TSDB_ANAL_ALGO_OPTION_LEN];
|
||||
} SAnomalyWindowPhysiNode;
|
||||
|
||||
typedef struct SSortPhysiNode {
|
||||
SPhysiNode node;
|
||||
SNodeList* pExprs; // these are expression list of order_by_clause and parameter expression of aggregate function
|
||||
|
|
|
@ -347,6 +347,13 @@ typedef struct SCountWindowNode {
|
|||
int64_t windowSliding;
|
||||
} SCountWindowNode;
|
||||
|
||||
typedef struct SAnomalyWindowNode {
|
||||
ENodeType type; // QUERY_NODE_ANOMALY_WINDOW
|
||||
SNode* pCol; // timestamp primary key
|
||||
SNode* pExpr;
|
||||
char anomalyOpt[TSDB_ANAL_ALGO_OPTION_LEN];
|
||||
} SAnomalyWindowNode;
|
||||
|
||||
typedef enum EFillMode {
|
||||
FILL_MODE_NONE = 1,
|
||||
FILL_MODE_VALUE,
|
||||
|
@ -442,6 +449,8 @@ typedef struct SSelectStmt {
|
|||
bool hasTailFunc;
|
||||
bool hasInterpFunc;
|
||||
bool hasInterpPseudoColFunc;
|
||||
bool hasForecastFunc;
|
||||
bool hasForecastPseudoColFunc;
|
||||
bool hasLastRowFunc;
|
||||
bool hasLastFunc;
|
||||
bool hasTimeLineFunc;
|
||||
|
|
|
@ -139,6 +139,7 @@ int32_t mavgScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam
|
|||
int32_t hllScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput);
|
||||
int32_t csumScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput);
|
||||
int32_t diffScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput);
|
||||
int32_t forecastScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput);
|
||||
int32_t stateCountScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput);
|
||||
int32_t stateDurationScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput);
|
||||
int32_t histogramScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput);
|
||||
|
|
|
@ -476,6 +476,24 @@ int32_t taosGetErrSize();
|
|||
#define TSDB_CODE_DNODE_INVALID_MONITOR_PARAS TAOS_DEF_ERROR_CODE(0, 0x0429)
|
||||
#define TSDB_CODE_MNODE_STOPPED TAOS_DEF_ERROR_CODE(0, 0x042A)
|
||||
|
||||
// anode
|
||||
#define TSDB_CODE_MND_ANODE_ALREADY_EXIST TAOS_DEF_ERROR_CODE(0, 0x0430)
|
||||
#define TSDB_CODE_MND_ANODE_NOT_EXIST TAOS_DEF_ERROR_CODE(0, 0x0431)
|
||||
#define TSDB_CODE_MND_ANODE_TOO_LONG_URL TAOS_DEF_ERROR_CODE(0, 0x0432)
|
||||
#define TSDB_CODE_MND_ANODE_INVALID_PROTOCOL TAOS_DEF_ERROR_CODE(0, 0x0433)
|
||||
#define TSDB_CODE_MND_ANODE_INVALID_VERSION TAOS_DEF_ERROR_CODE(0, 0x0434)
|
||||
#define TSDB_CODE_MND_ANODE_INVALID_ALGO_TYPE TAOS_DEF_ERROR_CODE(0, 0x0435)
|
||||
#define TSDB_CODE_MND_ANODE_TOO_MANY_ALGO TAOS_DEF_ERROR_CODE(0, 0x0436)
|
||||
#define TSDB_CODE_MND_ANODE_TOO_LONG_ALGO_NAME TAOS_DEF_ERROR_CODE(0, 0x0437)
|
||||
#define TSDB_CODE_MND_ANODE_TOO_MANY_ALGO_TYPE TAOS_DEF_ERROR_CODE(0, 0x0438)
|
||||
|
||||
// analysis
|
||||
#define TSDB_CODE_ANAL_URL_RSP_IS_NULL TAOS_DEF_ERROR_CODE(0, 0x0440)
|
||||
#define TSDB_CODE_ANAL_URL_CANT_ACCESS TAOS_DEF_ERROR_CODE(0, 0x0441)
|
||||
#define TSDB_CODE_ANAL_ALGO_NOT_FOUND TAOS_DEF_ERROR_CODE(0, 0x0442)
|
||||
#define TSDB_CODE_ANAL_ALGO_NOT_LOAD TAOS_DEF_ERROR_CODE(0, 0x0443)
|
||||
#define TSDB_CODE_ANAL_BUF_INVALID_TYPE TAOS_DEF_ERROR_CODE(0, 0x0444)
|
||||
|
||||
// mnode-sma
|
||||
#define TSDB_CODE_MND_SMA_ALREADY_EXIST TAOS_DEF_ERROR_CODE(0, 0x0480)
|
||||
#define TSDB_CODE_MND_SMA_NOT_EXIST TAOS_DEF_ERROR_CODE(0, 0x0481)
|
||||
|
@ -867,6 +885,10 @@ int32_t taosGetErrSize();
|
|||
#define TSDB_CODE_PAR_TAG_NAME_DUPLICATED TAOS_DEF_ERROR_CODE(0, 0x267F)
|
||||
#define TSDB_CODE_PAR_NOT_ALLOWED_DIFFERENT_BY_ROW_FUNC TAOS_DEF_ERROR_CODE(0, 0x2680)
|
||||
#define TSDB_CODE_PAR_REGULAR_EXPRESSION_ERROR TAOS_DEF_ERROR_CODE(0, 0x2681)
|
||||
#define TSDB_CODE_PAR_INVALID_ANOMALY_WIN_TYPE TAOS_DEF_ERROR_CODE(0, 0x2682)
|
||||
#define TSDB_CODE_PAR_INVALID_ANOMALY_WIN_COL TAOS_DEF_ERROR_CODE(0, 0x2683)
|
||||
#define TSDB_CODE_PAR_INVALID_ANOMALY_WIN_OPT TAOS_DEF_ERROR_CODE(0, 0x2684)
|
||||
#define TSDB_CODE_PAR_INVALID_FORECAST_CLAUSE TAOS_DEF_ERROR_CODE(0, 0x2685)
|
||||
#define TSDB_CODE_PAR_INTERNAL_ERROR TAOS_DEF_ERROR_CODE(0, 0x26FF)
|
||||
|
||||
//planner
|
||||
|
|
|
@ -293,6 +293,12 @@ typedef enum ELogicConditionType {
|
|||
#define TSDB_SLOW_QUERY_SQL_LEN 512
|
||||
#define TSDB_SHOW_SUBQUERY_LEN 1000
|
||||
#define TSDB_LOG_VAR_LEN 32
|
||||
#define TSDB_ANAL_ANODE_URL_LEN 128
|
||||
#define TSDB_ANAL_ALGO_NAME_LEN 64
|
||||
#define TSDB_ANAL_ALGO_TYPE_LEN 24
|
||||
#define TSDB_ANAL_ALGO_KEY_LEN (TSDB_ANAL_ALGO_NAME_LEN + 9)
|
||||
#define TSDB_ANAL_ALGO_URL_LEN (TSDB_ANAL_ANODE_URL_LEN + TSDB_ANAL_ALGO_TYPE_LEN + 1)
|
||||
#define TSDB_ANAL_ALGO_OPTION_LEN 256
|
||||
|
||||
#define TSDB_MAX_EP_NUM 10
|
||||
|
||||
|
@ -604,6 +610,12 @@ enum { RAND_ERR_MEMORY = 1, RAND_ERR_FILE = 2, RAND_ERR_NETWORK = 4 };
|
|||
#define MONITOR_TAG_VALUE_LEN 300
|
||||
#define MONITOR_METRIC_NAME_LEN 100
|
||||
|
||||
typedef enum {
|
||||
ANAL_ALGO_TYPE_ANOMALY_DETECT = 0,
|
||||
ANAL_ALGO_TYPE_FORECAST = 1,
|
||||
ANAL_ALGO_TYPE_END,
|
||||
} EAnalAlgoType;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -68,7 +68,10 @@ int32_t tjsonAddItemToArray(SJson* pJson, SJson* pItem);
|
|||
SJson* tjsonGetObjectItem(const SJson* pJson, const char* pName);
|
||||
int32_t tjsonGetObjectName(const SJson* pJson, char** pName);
|
||||
int32_t tjsonGetObjectValueString(const SJson* pJson, char** pStringValue);
|
||||
void tjsonGetObjectValueBigInt(const SJson* pJson, int64_t* pVal);
|
||||
void tjsonGetObjectValueDouble(const SJson* pJson, double* pVal);
|
||||
int32_t tjsonGetStringValue(const SJson* pJson, const char* pName, char* pVal);
|
||||
int32_t tjsonGetStringValue2(const SJson* pJson, const char* pName, char* pVal, int32_t maxLen);
|
||||
int32_t tjsonDupStringValue(const SJson* pJson, const char* pName, char** pVal);
|
||||
int32_t tjsonGetBigIntValue(const SJson* pJson, const char* pName, int64_t* pVal);
|
||||
int32_t tjsonGetIntValue(const SJson* pJson, const char* pName, int32_t* pVal);
|
||||
|
|
|
@ -399,6 +399,20 @@ static const SSysDbTableSchema userCompactsDetailSchema[] = {
|
|||
{.name = "start_time", .bytes = 8, .type = TSDB_DATA_TYPE_TIMESTAMP, .sysInfo = false},
|
||||
};
|
||||
|
||||
static const SSysDbTableSchema anodesSchema[] = {
|
||||
{.name = "id", .bytes = 4, .type = TSDB_DATA_TYPE_INT, .sysInfo = false},
|
||||
{.name = "url", .bytes = TSDB_ANAL_ANODE_URL_LEN + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = true},
|
||||
{.name = "status", .bytes = 10 + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = true},
|
||||
{.name = "create_time", .bytes = 8, .type = TSDB_DATA_TYPE_TIMESTAMP, .sysInfo = true},
|
||||
{.name = "update_time", .bytes = 8, .type = TSDB_DATA_TYPE_TIMESTAMP, .sysInfo = true},
|
||||
};
|
||||
|
||||
static const SSysDbTableSchema anodesFullSchema[] = {
|
||||
{.name = "id", .bytes = 4, .type = TSDB_DATA_TYPE_INT, .sysInfo = false},
|
||||
{.name = "type", .bytes = TSDB_ANAL_ALGO_TYPE_LEN + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = true},
|
||||
{.name = "algo", .bytes = TSDB_ANAL_ALGO_NAME_LEN + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = true},
|
||||
};
|
||||
|
||||
static const SSysDbTableSchema tsmaSchema[] = {
|
||||
{.name = "tsma_name", .bytes = SYSTABLE_SCH_TABLE_NAME_LEN, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = false},
|
||||
{.name = "db_name", .bytes = SYSTABLE_SCH_DB_NAME_LEN, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = false},
|
||||
|
@ -473,6 +487,8 @@ static const SSysTableMeta infosMeta[] = {
|
|||
{TSDB_INS_TABLE_ARBGROUPS, arbGroupsSchema, tListLen(arbGroupsSchema), true},
|
||||
{TSDB_INS_TABLE_ENCRYPTIONS, encryptionsSchema, tListLen(encryptionsSchema), true},
|
||||
{TSDB_INS_TABLE_TSMAS, tsmaSchema, tListLen(tsmaSchema), false},
|
||||
{TSDB_INS_TABLE_ANODES, anodesSchema, tListLen(anodesSchema), true},
|
||||
{TSDB_INS_TABLE_ANODES_FULL, anodesFullSchema, tListLen(anodesFullSchema), true},
|
||||
};
|
||||
|
||||
static const SSysDbTableSchema connectionsSchema[] = {
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#define TD_MSG_RANGE_CODE_
|
||||
#include "tmsgdef.h"
|
||||
|
||||
#include "tanal.h"
|
||||
#include "tcol.h"
|
||||
#include "tlog.h"
|
||||
|
||||
|
@ -1453,6 +1454,7 @@ int32_t tSerializeSStatusReq(void *buf, int32_t bufLen, SStatusReq *pReq) {
|
|||
}
|
||||
|
||||
TAOS_CHECK_EXIT(tEncodeI64(&encoder, pReq->ipWhiteVer));
|
||||
TAOS_CHECK_EXIT(tEncodeI64(&encoder, pReq->analVer));
|
||||
TAOS_CHECK_EXIT(tSerializeSMonitorParas(&encoder, &pReq->clusterCfg.monitorParas));
|
||||
|
||||
tEndEncode(&encoder);
|
||||
|
@ -1576,6 +1578,10 @@ int32_t tDeserializeSStatusReq(void *buf, int32_t bufLen, SStatusReq *pReq) {
|
|||
TAOS_CHECK_EXIT(tDecodeI64(&decoder, &pReq->ipWhiteVer));
|
||||
}
|
||||
|
||||
if (!tDecodeIsEnd(&decoder)) {
|
||||
TAOS_CHECK_EXIT(tDecodeI64(&decoder, &pReq->analVer));
|
||||
}
|
||||
|
||||
if (!tDecodeIsEnd(&decoder)) {
|
||||
TAOS_CHECK_EXIT(tDeserializeSMonitorParas(&decoder, &pReq->clusterCfg.monitorParas));
|
||||
}
|
||||
|
@ -1652,6 +1658,7 @@ int32_t tSerializeSStatusRsp(void *buf, int32_t bufLen, SStatusRsp *pRsp) {
|
|||
TAOS_CHECK_EXIT(tEncodeI32(&encoder, pRsp->statusSeq));
|
||||
|
||||
TAOS_CHECK_EXIT(tEncodeI64(&encoder, pRsp->ipWhiteVer));
|
||||
TAOS_CHECK_EXIT(tEncodeI64(&encoder, pRsp->analVer));
|
||||
tEndEncode(&encoder);
|
||||
|
||||
_exit:
|
||||
|
@ -1704,6 +1711,10 @@ int32_t tDeserializeSStatusRsp(void *buf, int32_t bufLen, SStatusRsp *pRsp) {
|
|||
TAOS_CHECK_EXIT(tDecodeI64(&decoder, &pRsp->ipWhiteVer));
|
||||
}
|
||||
|
||||
if (!tDecodeIsEnd(&decoder)) {
|
||||
TAOS_CHECK_EXIT(tDecodeI64(&decoder, &pRsp->analVer));
|
||||
}
|
||||
|
||||
tEndDecode(&decoder);
|
||||
_exit:
|
||||
tDecoderClear(&decoder);
|
||||
|
@ -2045,6 +2056,156 @@ _exit:
|
|||
return code;
|
||||
}
|
||||
|
||||
int32_t tSerializeRetrieveAnalAlgoReq(void *buf, int32_t bufLen, SRetrieveAnalAlgoReq *pReq) {
|
||||
SEncoder encoder = {0};
|
||||
int32_t code = 0;
|
||||
int32_t lino;
|
||||
int32_t tlen;
|
||||
tEncoderInit(&encoder, buf, bufLen);
|
||||
|
||||
TAOS_CHECK_EXIT(tStartEncode(&encoder));
|
||||
TAOS_CHECK_EXIT(tEncodeI32(&encoder, pReq->dnodeId));
|
||||
TAOS_CHECK_EXIT(tEncodeI64(&encoder, pReq->analVer));
|
||||
tEndEncode(&encoder);
|
||||
|
||||
_exit:
|
||||
if (code) {
|
||||
tlen = code;
|
||||
} else {
|
||||
tlen = encoder.pos;
|
||||
}
|
||||
tEncoderClear(&encoder);
|
||||
return tlen;
|
||||
}
|
||||
|
||||
int32_t tDeserializeRetrieveAnalAlgoReq(void *buf, int32_t bufLen, SRetrieveAnalAlgoReq *pReq) {
|
||||
SDecoder decoder = {0};
|
||||
int32_t code = 0;
|
||||
int32_t lino;
|
||||
|
||||
tDecoderInit(&decoder, buf, bufLen);
|
||||
|
||||
TAOS_CHECK_EXIT(tStartDecode(&decoder));
|
||||
TAOS_CHECK_EXIT(tDecodeI32(&decoder, &pReq->dnodeId));
|
||||
TAOS_CHECK_EXIT(tDecodeI64(&decoder, &pReq->analVer));
|
||||
tEndDecode(&decoder);
|
||||
|
||||
_exit:
|
||||
tDecoderClear(&decoder);
|
||||
return code;
|
||||
}
|
||||
|
||||
int32_t tSerializeRetrieveAnalAlgoRsp(void *buf, int32_t bufLen, SRetrieveAnalAlgoRsp *pRsp) {
|
||||
SEncoder encoder = {0};
|
||||
int32_t code = 0;
|
||||
int32_t lino;
|
||||
int32_t tlen;
|
||||
tEncoderInit(&encoder, buf, bufLen);
|
||||
|
||||
int32_t numOfAlgos = 0;
|
||||
void *pIter = taosHashIterate(pRsp->hash, NULL);
|
||||
while (pIter != NULL) {
|
||||
SAnalUrl *pUrl = pIter;
|
||||
size_t nameLen = 0;
|
||||
const char *name = taosHashGetKey(pIter, &nameLen);
|
||||
if (nameLen > 0 && nameLen <= TSDB_ANAL_ALGO_KEY_LEN && pUrl->urlLen > 0) {
|
||||
numOfAlgos++;
|
||||
}
|
||||
pIter = taosHashIterate(pRsp->hash, pIter);
|
||||
}
|
||||
|
||||
TAOS_CHECK_EXIT(tStartEncode(&encoder));
|
||||
TAOS_CHECK_EXIT(tEncodeI64(&encoder, pRsp->ver));
|
||||
TAOS_CHECK_EXIT(tEncodeI32(&encoder, numOfAlgos));
|
||||
|
||||
pIter = taosHashIterate(pRsp->hash, NULL);
|
||||
while (pIter != NULL) {
|
||||
SAnalUrl *pUrl = pIter;
|
||||
size_t nameLen = 0;
|
||||
const char *name = taosHashGetKey(pIter, &nameLen);
|
||||
if (nameLen > 0 && pUrl->urlLen > 0) {
|
||||
TAOS_CHECK_EXIT(tEncodeI32(&encoder, nameLen));
|
||||
TAOS_CHECK_EXIT(tEncodeBinary(&encoder, (const uint8_t *)name, nameLen));
|
||||
TAOS_CHECK_EXIT(tEncodeI32(&encoder, pUrl->anode));
|
||||
TAOS_CHECK_EXIT(tEncodeI32(&encoder, pUrl->type));
|
||||
TAOS_CHECK_EXIT(tEncodeI32(&encoder, pUrl->urlLen));
|
||||
TAOS_CHECK_EXIT(tEncodeBinary(&encoder, (const uint8_t *)pUrl->url, pUrl->urlLen));
|
||||
}
|
||||
pIter = taosHashIterate(pRsp->hash, pIter);
|
||||
}
|
||||
|
||||
tEndEncode(&encoder);
|
||||
|
||||
_exit:
|
||||
if (code) {
|
||||
tlen = code;
|
||||
} else {
|
||||
tlen = encoder.pos;
|
||||
}
|
||||
tEncoderClear(&encoder);
|
||||
return tlen;
|
||||
}
|
||||
|
||||
int32_t tDeserializeRetrieveAnalAlgoRsp(void *buf, int32_t bufLen, SRetrieveAnalAlgoRsp *pRsp) {
|
||||
if (pRsp->hash == NULL) {
|
||||
pRsp->hash = taosHashInit(64, MurmurHash3_32, true, HASH_ENTRY_LOCK);
|
||||
if (pRsp->hash == NULL) {
|
||||
terrno = TSDB_CODE_OUT_OF_BUFFER;
|
||||
return terrno;
|
||||
}
|
||||
}
|
||||
|
||||
SDecoder decoder = {0};
|
||||
int32_t code = 0;
|
||||
int32_t lino;
|
||||
tDecoderInit(&decoder, buf, bufLen);
|
||||
|
||||
int32_t numOfAlgos = 0;
|
||||
int32_t nameLen;
|
||||
int32_t type;
|
||||
char name[TSDB_ANAL_ALGO_KEY_LEN];
|
||||
SAnalUrl url = {0};
|
||||
|
||||
TAOS_CHECK_EXIT(tStartDecode(&decoder));
|
||||
TAOS_CHECK_EXIT(tDecodeI64(&decoder, &pRsp->ver));
|
||||
TAOS_CHECK_EXIT(tDecodeI32(&decoder, &numOfAlgos));
|
||||
|
||||
for (int32_t f = 0; f < numOfAlgos; ++f) {
|
||||
TAOS_CHECK_EXIT(tDecodeI32(&decoder, &nameLen));
|
||||
if (nameLen > 0 && nameLen <= TSDB_ANAL_ALGO_NAME_LEN) {
|
||||
TAOS_CHECK_EXIT(tDecodeCStrTo(&decoder, name));
|
||||
}
|
||||
|
||||
TAOS_CHECK_EXIT(tDecodeI32(&decoder, &url.anode));
|
||||
TAOS_CHECK_EXIT(tDecodeI32(&decoder, &type));
|
||||
url.type = (EAnalAlgoType)type;
|
||||
TAOS_CHECK_EXIT(tDecodeI32(&decoder, &url.urlLen));
|
||||
if (url.urlLen > 0) {
|
||||
TAOS_CHECK_EXIT(tDecodeBinaryAlloc(&decoder, (void **)&url.url, NULL) < 0);
|
||||
}
|
||||
|
||||
TAOS_CHECK_EXIT(taosHashPut(pRsp->hash, name, nameLen, &url, sizeof(SAnalUrl)));
|
||||
}
|
||||
|
||||
tEndDecode(&decoder);
|
||||
|
||||
_exit:
|
||||
tDecoderClear(&decoder);
|
||||
return code;
|
||||
}
|
||||
|
||||
void tFreeRetrieveAnalAlgoRsp(SRetrieveAnalAlgoRsp *pRsp) {
|
||||
void *pIter = taosHashIterate(pRsp->hash, NULL);
|
||||
while (pIter != NULL) {
|
||||
SAnalUrl *pUrl = (SAnalUrl *)pIter;
|
||||
taosMemoryFree(pUrl->url);
|
||||
pIter = taosHashIterate(pRsp->hash, pIter);
|
||||
}
|
||||
taosHashCleanup(pRsp->hash);
|
||||
|
||||
pRsp->hash = NULL;
|
||||
}
|
||||
|
||||
void tFreeSCreateUserReq(SCreateUserReq *pReq) {
|
||||
FREESQL();
|
||||
taosMemoryFreeClear(pReq->pIpRanges);
|
||||
|
@ -2962,6 +3123,108 @@ _exit:
|
|||
return code;
|
||||
}
|
||||
|
||||
int32_t tSerializeSMCreateAnodeReq(void *buf, int32_t bufLen, SMCreateAnodeReq *pReq) {
|
||||
SEncoder encoder = {0};
|
||||
int32_t code = 0;
|
||||
int32_t lino;
|
||||
int32_t tlen;
|
||||
tEncoderInit(&encoder, buf, bufLen);
|
||||
|
||||
TAOS_CHECK_EXIT(tStartEncode(&encoder));
|
||||
TAOS_CHECK_EXIT(tEncodeI32(&encoder, pReq->urlLen));
|
||||
if (pReq->urlLen > 0) {
|
||||
TAOS_CHECK_EXIT(tEncodeBinary(&encoder, (const uint8_t *)pReq->url, pReq->urlLen));
|
||||
}
|
||||
ENCODESQL();
|
||||
tEndEncode(&encoder);
|
||||
|
||||
_exit:
|
||||
if (code) {
|
||||
tlen = code;
|
||||
} else {
|
||||
tlen = encoder.pos;
|
||||
}
|
||||
tEncoderClear(&encoder);
|
||||
return tlen;
|
||||
}
|
||||
|
||||
int32_t tDeserializeSMCreateAnodeReq(void *buf, int32_t bufLen, SMCreateAnodeReq *pReq) {
|
||||
SDecoder decoder = {0};
|
||||
int32_t code = 0;
|
||||
int32_t lino;
|
||||
|
||||
tDecoderInit(&decoder, buf, bufLen);
|
||||
|
||||
TAOS_CHECK_EXIT(tStartDecode(&decoder));
|
||||
TAOS_CHECK_EXIT(tDecodeI32(&decoder, &pReq->urlLen));
|
||||
if (pReq->urlLen > 0) {
|
||||
TAOS_CHECK_EXIT(tDecodeBinaryAlloc(&decoder, (void **)&pReq->url, NULL));
|
||||
}
|
||||
|
||||
DECODESQL();
|
||||
tEndDecode(&decoder);
|
||||
|
||||
_exit:
|
||||
tDecoderClear(&decoder);
|
||||
return code;
|
||||
}
|
||||
|
||||
void tFreeSMCreateAnodeReq(SMCreateAnodeReq *pReq) {
|
||||
taosMemoryFreeClear(pReq->url);
|
||||
FREESQL();
|
||||
}
|
||||
|
||||
int32_t tSerializeSMDropAnodeReq(void *buf, int32_t bufLen, SMDropAnodeReq *pReq) {
|
||||
SEncoder encoder = {0};
|
||||
int32_t code = 0;
|
||||
int32_t lino;
|
||||
int32_t tlen;
|
||||
tEncoderInit(&encoder, buf, bufLen);
|
||||
|
||||
TAOS_CHECK_EXIT(tStartEncode(&encoder));
|
||||
TAOS_CHECK_EXIT(tEncodeI32(&encoder, pReq->anodeId));
|
||||
ENCODESQL();
|
||||
tEndEncode(&encoder);
|
||||
|
||||
_exit:
|
||||
if (code) {
|
||||
tlen = code;
|
||||
} else {
|
||||
tlen = encoder.pos;
|
||||
}
|
||||
tEncoderClear(&encoder);
|
||||
return tlen;
|
||||
}
|
||||
|
||||
int32_t tDeserializeSMDropAnodeReq(void *buf, int32_t bufLen, SMDropAnodeReq *pReq) {
|
||||
SDecoder decoder = {0};
|
||||
int32_t code = 0;
|
||||
int32_t lino;
|
||||
|
||||
tDecoderInit(&decoder, buf, bufLen);
|
||||
|
||||
TAOS_CHECK_EXIT(tStartDecode(&decoder));
|
||||
TAOS_CHECK_EXIT(tDecodeI32(&decoder, &pReq->anodeId));
|
||||
DECODESQL();
|
||||
tEndDecode(&decoder);
|
||||
|
||||
_exit:
|
||||
tDecoderClear(&decoder);
|
||||
return code;
|
||||
}
|
||||
|
||||
void tFreeSMDropAnodeReq(SMDropAnodeReq *pReq) { FREESQL(); }
|
||||
|
||||
int32_t tSerializeSMUpdateAnodeReq(void *buf, int32_t bufLen, SMUpdateAnodeReq *pReq) {
|
||||
return tSerializeSMDropAnodeReq(buf, bufLen, pReq);
|
||||
}
|
||||
|
||||
int32_t tDeserializeSMUpdateAnodeReq(void *buf, int32_t bufLen, SMUpdateAnodeReq *pReq) {
|
||||
return tDeserializeSMDropAnodeReq(buf, bufLen, pReq);
|
||||
}
|
||||
|
||||
void tFreeSMUpdateAnodeReq(SMUpdateAnodeReq *pReq) { tFreeSMDropAnodeReq(pReq); }
|
||||
|
||||
int32_t tSerializeSCreateDnodeReq(void *buf, int32_t bufLen, SCreateDnodeReq *pReq) {
|
||||
SEncoder encoder = {0};
|
||||
int32_t code = 0;
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "dmInt.h"
|
||||
#include "monitor.h"
|
||||
#include "systable.h"
|
||||
#include "tanal.h"
|
||||
#include "tchecksum.h"
|
||||
|
||||
extern SConfig *tsCfg;
|
||||
|
@ -86,6 +87,46 @@ static void dmMayShouldUpdateIpWhiteList(SDnodeMgmt *pMgmt, int64_t ver) {
|
|||
}
|
||||
}
|
||||
|
||||
static void dmMayShouldUpdateAnalFunc(SDnodeMgmt *pMgmt, int64_t newVer) {
|
||||
int32_t code = 0;
|
||||
int64_t oldVer = taosAnalGetVersion();
|
||||
if (oldVer == newVer) return;
|
||||
dDebug("analysis on dnode ver:%" PRId64 ", status ver:%" PRId64, oldVer, newVer);
|
||||
|
||||
SRetrieveAnalAlgoReq req = {.dnodeId = pMgmt->pData->dnodeId, .analVer = oldVer};
|
||||
int32_t contLen = tSerializeRetrieveAnalAlgoReq(NULL, 0, &req);
|
||||
if (contLen < 0) {
|
||||
dError("failed to serialize analysis function ver request since %s", tstrerror(contLen));
|
||||
return;
|
||||
}
|
||||
|
||||
void *pHead = rpcMallocCont(contLen);
|
||||
contLen = tSerializeRetrieveAnalAlgoReq(pHead, contLen, &req);
|
||||
if (contLen < 0) {
|
||||
rpcFreeCont(pHead);
|
||||
dError("failed to serialize analysis function ver request since %s", tstrerror(contLen));
|
||||
return;
|
||||
}
|
||||
|
||||
SRpcMsg rpcMsg = {
|
||||
.pCont = pHead,
|
||||
.contLen = contLen,
|
||||
.msgType = TDMT_MND_RETRIEVE_ANAL_ALGO,
|
||||
.info.ahandle = (void *)0x9527,
|
||||
.info.refId = 0,
|
||||
.info.noResp = 0,
|
||||
.info.handle = 0,
|
||||
};
|
||||
SEpSet epset = {0};
|
||||
|
||||
(void)dmGetMnodeEpSet(pMgmt->pData, &epset);
|
||||
|
||||
code = rpcSendRequest(pMgmt->msgCb.clientRpc, &epset, &rpcMsg, NULL);
|
||||
if (code != 0) {
|
||||
dError("failed to send retrieve analysis func ver request since %s", tstrerror(code));
|
||||
}
|
||||
}
|
||||
|
||||
static void dmProcessStatusRsp(SDnodeMgmt *pMgmt, SRpcMsg *pRsp) {
|
||||
const STraceId *trace = &pRsp->info.traceId;
|
||||
dGTrace("status rsp received from mnode, statusSeq:%d code:0x%x", pMgmt->statusSeq, pRsp->code);
|
||||
|
@ -113,6 +154,7 @@ static void dmProcessStatusRsp(SDnodeMgmt *pMgmt, SRpcMsg *pRsp) {
|
|||
dmUpdateEps(pMgmt->pData, statusRsp.pDnodeEps);
|
||||
}
|
||||
dmMayShouldUpdateIpWhiteList(pMgmt, statusRsp.ipWhiteVer);
|
||||
dmMayShouldUpdateAnalFunc(pMgmt, statusRsp.analVer);
|
||||
}
|
||||
tFreeSStatusRsp(&statusRsp);
|
||||
}
|
||||
|
@ -174,6 +216,7 @@ void dmSendStatusReq(SDnodeMgmt *pMgmt) {
|
|||
pMgmt->statusSeq++;
|
||||
req.statusSeq = pMgmt->statusSeq;
|
||||
req.ipWhiteVer = pMgmt->pData->ipWhiteVer;
|
||||
req.analVer = taosAnalGetVersion();
|
||||
|
||||
int32_t contLen = tSerializeSStatusReq(NULL, 0, &req);
|
||||
if (contLen < 0) {
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#define _DEFAULT_SOURCE
|
||||
#include "dmInt.h"
|
||||
#include "libs/function/tudf.h"
|
||||
#include "tanal.h"
|
||||
|
||||
static int32_t dmStartMgmt(SDnodeMgmt *pMgmt) {
|
||||
int32_t code = 0;
|
||||
|
@ -80,6 +81,10 @@ static int32_t dmOpenMgmt(SMgmtInputOpt *pInput, SMgmtOutputOpt *pOutput) {
|
|||
dError("failed to start udfd since %s", tstrerror(code));
|
||||
}
|
||||
|
||||
if ((code = taosAnalInit()) != 0) {
|
||||
dError("failed to init analysis env since %s", tstrerror(code));
|
||||
}
|
||||
|
||||
pOutput->pMgmt = pMgmt;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -141,6 +141,9 @@ SArray *mmGetMsgHandles() {
|
|||
if (dmSetMgmtHandle(pArray, TDMT_MND_DNODE_LIST, mmPutMsgToReadQueue, 0) == NULL) goto _OVER;
|
||||
if (dmSetMgmtHandle(pArray, TDMT_MND_CREATE_SNODE, mmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
|
||||
if (dmSetMgmtHandle(pArray, TDMT_MND_DROP_SNODE, mmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
|
||||
if (dmSetMgmtHandle(pArray, TDMT_MND_CREATE_ANODE, mmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
|
||||
if (dmSetMgmtHandle(pArray, TDMT_MND_UPDATE_ANODE, mmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
|
||||
if (dmSetMgmtHandle(pArray, TDMT_MND_DROP_ANODE, mmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
|
||||
if (dmSetMgmtHandle(pArray, TDMT_MND_CREATE_DB, mmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
|
||||
if (dmSetMgmtHandle(pArray, TDMT_MND_DROP_DB, mmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
|
||||
if (dmSetMgmtHandle(pArray, TDMT_MND_USE_DB, mmPutMsgToReadQueue, 0) == NULL) goto _OVER;
|
||||
|
@ -180,6 +183,7 @@ SArray *mmGetMsgHandles() {
|
|||
if (dmSetMgmtHandle(pArray, TDMT_VND_FETCH_TTL_EXPIRED_TBS_RSP, mmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
|
||||
if (dmSetMgmtHandle(pArray, TDMT_VND_DROP_TABLE_RSP, mmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
|
||||
|
||||
if (dmSetMgmtHandle(pArray, TDMT_MND_RETRIEVE_ANAL_ALGO, mmPutMsgToReadQueue, 0) == NULL) goto _OVER;
|
||||
if (dmSetMgmtHandle(pArray, TDMT_MND_RETRIEVE_IP_WHITE, mmPutMsgToReadQueue, 0) == NULL) goto _OVER;
|
||||
if (dmSetMgmtHandle(pArray, TDMT_MND_GET_USER_WHITELIST, mmPutMsgToReadQueue, 0) == NULL) goto _OVER;
|
||||
if (dmSetMgmtHandle(pArray, TDMT_MND_GET_INDEX, mmPutMsgToReadQueue, 0) == NULL) goto _OVER;
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "libs/function/tudf.h"
|
||||
#include "tgrant.h"
|
||||
#include "tcompare.h"
|
||||
#include "tanal.h"
|
||||
// clang-format on
|
||||
|
||||
#define DM_INIT_AUDIT() \
|
||||
|
@ -214,6 +215,7 @@ void dmCleanup() {
|
|||
dError("failed to close udfc");
|
||||
}
|
||||
udfStopUdfd();
|
||||
taosAnalCleanup();
|
||||
taosStopCacheRefreshWorker();
|
||||
(void)dmDiskClose();
|
||||
DestroyRegexCache();
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "dmMgmt.h"
|
||||
#include "qworker.h"
|
||||
#include "tversion.h"
|
||||
#include "tanal.h"
|
||||
|
||||
static inline void dmSendRsp(SRpcMsg *pMsg) {
|
||||
if (rpcSendResponse(pMsg) != 0) {
|
||||
|
@ -106,6 +107,16 @@ static bool dmIsForbiddenIp(int8_t forbidden, char *user, uint32_t clientIp) {
|
|||
}
|
||||
}
|
||||
|
||||
static void dmUpdateAnalFunc(SDnodeData *pData, void *pTrans, SRpcMsg *pRpc) {
|
||||
SRetrieveAnalAlgoRsp rsp = {0};
|
||||
if (tDeserializeRetrieveAnalAlgoRsp(pRpc->pCont, pRpc->contLen, &rsp) == 0) {
|
||||
taosAnalUpdate(rsp.ver, rsp.hash);
|
||||
rsp.hash = NULL;
|
||||
}
|
||||
tFreeRetrieveAnalAlgoRsp(&rsp);
|
||||
rpcFreeCont(pRpc->pCont);
|
||||
}
|
||||
|
||||
static void dmProcessRpcMsg(SDnode *pDnode, SRpcMsg *pRpc, SEpSet *pEpSet) {
|
||||
SDnodeTrans *pTrans = &pDnode->trans;
|
||||
int32_t code = -1;
|
||||
|
@ -154,6 +165,9 @@ static void dmProcessRpcMsg(SDnode *pDnode, SRpcMsg *pRpc, SEpSet *pEpSet) {
|
|||
case TDMT_MND_RETRIEVE_IP_WHITE_RSP:
|
||||
dmUpdateRpcIpWhite(&pDnode->data, pTrans->serverRpc, pRpc);
|
||||
return;
|
||||
case TDMT_MND_RETRIEVE_ANAL_ALGO_RSP:
|
||||
dmUpdateAnalFunc(&pDnode->data, pTrans->serverRpc, pRpc);
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -15,6 +15,9 @@ IF (TD_ENTERPRISE)
|
|||
add_definitions(-DUSE_COS)
|
||||
ENDIF()
|
||||
|
||||
IF(${BUILD_WITH_ANALYSIS})
|
||||
add_definitions(-DUSE_ANAL)
|
||||
ENDIF()
|
||||
ENDIF ()
|
||||
|
||||
add_library(mnode STATIC ${MNODE_SRC})
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
||||
*
|
||||
* This program is free software: you can use, redistribute, and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3
|
||||
* or later ("AGPL"), as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _TD_MND_ANODE_H_
|
||||
#define _TD_MND_ANODE_H_
|
||||
|
||||
#include "mndInt.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int32_t mndInitAnode(SMnode *pMnode);
|
||||
void mndCleanupAnode(SMnode *pMnode);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*_TD_MND_ANODE_H_*/
|
|
@ -78,6 +78,9 @@ typedef enum {
|
|||
MND_OPER_DROP_VIEW,
|
||||
MND_OPER_CONFIG_CLUSTER,
|
||||
MND_OPER_BALANCE_VGROUP_LEADER,
|
||||
MND_OPER_CREATE_ANODE,
|
||||
MND_OPER_UPDATE_ANODE,
|
||||
MND_OPER_DROP_ANODE
|
||||
} EOperType;
|
||||
|
||||
typedef enum {
|
||||
|
@ -232,6 +235,24 @@ typedef struct {
|
|||
char machineId[TSDB_MACHINE_ID_LEN + 1];
|
||||
} SDnodeObj;
|
||||
|
||||
typedef struct {
|
||||
int32_t nameLen;
|
||||
char* name;
|
||||
} SAnodeAlgo;
|
||||
|
||||
typedef struct {
|
||||
int32_t id;
|
||||
int64_t createdTime;
|
||||
int64_t updateTime;
|
||||
int32_t version;
|
||||
int32_t urlLen;
|
||||
int32_t numOfAlgos;
|
||||
int32_t status;
|
||||
SRWLatch lock;
|
||||
char* url;
|
||||
SArray** algos;
|
||||
} SAnodeObj;
|
||||
|
||||
typedef struct {
|
||||
int32_t id;
|
||||
int64_t createdTime;
|
||||
|
|
|
@ -0,0 +1,901 @@
|
|||
/*
|
||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
||||
*
|
||||
* This program is free software: you can use, redistribute, and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3
|
||||
* or later ("AGPL"), as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#define _DEFAULT_SOURCE
|
||||
#include "mndAnode.h"
|
||||
#include "audit.h"
|
||||
#include "mndDnode.h"
|
||||
#include "mndPrivilege.h"
|
||||
#include "mndShow.h"
|
||||
#include "mndTrans.h"
|
||||
#include "mndUser.h"
|
||||
#include "tanal.h"
|
||||
#include "tjson.h"
|
||||
|
||||
#ifdef USE_ANAL
|
||||
|
||||
#define TSDB_ANODE_VER_NUMBER 1
|
||||
#define TSDB_ANODE_RESERVE_SIZE 64
|
||||
|
||||
static SSdbRaw *mndAnodeActionEncode(SAnodeObj *pObj);
|
||||
static SSdbRow *mndAnodeActionDecode(SSdbRaw *pRaw);
|
||||
static int32_t mndAnodeActionInsert(SSdb *pSdb, SAnodeObj *pObj);
|
||||
static int32_t mndAnodeActionUpdate(SSdb *pSdb, SAnodeObj *pOld, SAnodeObj *pNew);
|
||||
static int32_t mndAnodeActionDelete(SSdb *pSdb, SAnodeObj *pObj);
|
||||
static int32_t mndProcessCreateAnodeReq(SRpcMsg *pReq);
|
||||
static int32_t mndProcessUpdateAnodeReq(SRpcMsg *pReq);
|
||||
static int32_t mndProcessDropAnodeReq(SRpcMsg *pReq);
|
||||
static int32_t mndProcessAnalAlgoReq(SRpcMsg *pReq);
|
||||
static int32_t mndRetrieveAnodes(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows);
|
||||
static void mndCancelGetNextAnode(SMnode *pMnode, void *pIter);
|
||||
static int32_t mndRetrieveAnodesFull(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows);
|
||||
static void mndCancelGetNextAnodeFull(SMnode *pMnode, void *pIter);
|
||||
static int32_t mndGetAnodeAlgoList(const char *url, SAnodeObj *pObj);
|
||||
static int32_t mndGetAnodeStatus(SAnodeObj *pObj, char *status, int32_t statusLen);
|
||||
|
||||
int32_t mndInitAnode(SMnode *pMnode) {
|
||||
SSdbTable table = {
|
||||
.sdbType = SDB_ANODE,
|
||||
.keyType = SDB_KEY_INT32,
|
||||
.encodeFp = (SdbEncodeFp)mndAnodeActionEncode,
|
||||
.decodeFp = (SdbDecodeFp)mndAnodeActionDecode,
|
||||
.insertFp = (SdbInsertFp)mndAnodeActionInsert,
|
||||
.updateFp = (SdbUpdateFp)mndAnodeActionUpdate,
|
||||
.deleteFp = (SdbDeleteFp)mndAnodeActionDelete,
|
||||
};
|
||||
|
||||
mndSetMsgHandle(pMnode, TDMT_MND_CREATE_ANODE, mndProcessCreateAnodeReq);
|
||||
mndSetMsgHandle(pMnode, TDMT_MND_UPDATE_ANODE, mndProcessUpdateAnodeReq);
|
||||
mndSetMsgHandle(pMnode, TDMT_MND_DROP_ANODE, mndProcessDropAnodeReq);
|
||||
mndSetMsgHandle(pMnode, TDMT_MND_RETRIEVE_ANAL_ALGO, mndProcessAnalAlgoReq);
|
||||
|
||||
mndAddShowRetrieveHandle(pMnode, TSDB_MGMT_TABLE_ANODE, mndRetrieveAnodes);
|
||||
mndAddShowFreeIterHandle(pMnode, TSDB_MGMT_TABLE_ANODE, mndCancelGetNextAnode);
|
||||
mndAddShowRetrieveHandle(pMnode, TSDB_MGMT_TABLE_ANODE_FULL, mndRetrieveAnodesFull);
|
||||
mndAddShowFreeIterHandle(pMnode, TSDB_MGMT_TABLE_ANODE_FULL, mndCancelGetNextAnodeFull);
|
||||
|
||||
return sdbSetTable(pMnode->pSdb, table);
|
||||
}
|
||||
|
||||
void mndCleanupAnode(SMnode *pMnode) {}
|
||||
|
||||
SAnodeObj *mndAcquireAnode(SMnode *pMnode, int32_t anodeId) {
|
||||
SAnodeObj *pObj = sdbAcquire(pMnode->pSdb, SDB_ANODE, &anodeId);
|
||||
if (pObj == NULL && terrno == TSDB_CODE_SDB_OBJ_NOT_THERE) {
|
||||
terrno = TSDB_CODE_MND_ANODE_NOT_EXIST;
|
||||
}
|
||||
return pObj;
|
||||
}
|
||||
|
||||
void mndReleaseAnode(SMnode *pMnode, SAnodeObj *pObj) {
|
||||
SSdb *pSdb = pMnode->pSdb;
|
||||
sdbRelease(pSdb, pObj);
|
||||
}
|
||||
|
||||
static SSdbRaw *mndAnodeActionEncode(SAnodeObj *pObj) {
|
||||
int32_t code = 0;
|
||||
int32_t lino = 0;
|
||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||
|
||||
int32_t rawDataLen = sizeof(SAnodeObj) + TSDB_ANODE_RESERVE_SIZE + pObj->urlLen;
|
||||
for (int32_t t = 0; t < pObj->numOfAlgos; ++t) {
|
||||
SArray *algos = pObj->algos[t];
|
||||
for (int32_t a = 0; a < (int32_t)taosArrayGetSize(algos); ++a) {
|
||||
SAnodeAlgo *algo = taosArrayGet(algos, a);
|
||||
rawDataLen += (2 * sizeof(int32_t) + algo->nameLen);
|
||||
}
|
||||
rawDataLen += sizeof(int32_t);
|
||||
}
|
||||
|
||||
SSdbRaw *pRaw = sdbAllocRaw(SDB_ANODE, TSDB_ANODE_VER_NUMBER, rawDataLen);
|
||||
if (pRaw == NULL) goto _OVER;
|
||||
|
||||
int32_t dataPos = 0;
|
||||
SDB_SET_INT32(pRaw, dataPos, pObj->id, _OVER)
|
||||
SDB_SET_INT64(pRaw, dataPos, pObj->createdTime, _OVER)
|
||||
SDB_SET_INT64(pRaw, dataPos, pObj->updateTime, _OVER)
|
||||
SDB_SET_INT32(pRaw, dataPos, pObj->version, _OVER)
|
||||
SDB_SET_INT32(pRaw, dataPos, pObj->urlLen, _OVER)
|
||||
SDB_SET_BINARY(pRaw, dataPos, pObj->url, pObj->urlLen, _OVER)
|
||||
SDB_SET_INT32(pRaw, dataPos, pObj->numOfAlgos, _OVER)
|
||||
for (int32_t i = 0; i < pObj->numOfAlgos; ++i) {
|
||||
SArray *algos = pObj->algos[i];
|
||||
SDB_SET_INT32(pRaw, dataPos, (int32_t)taosArrayGetSize(algos), _OVER)
|
||||
for (int32_t j = 0; j < (int32_t)taosArrayGetSize(algos); ++j) {
|
||||
SAnodeAlgo *algo = taosArrayGet(algos, j);
|
||||
SDB_SET_INT32(pRaw, dataPos, algo->nameLen, _OVER)
|
||||
SDB_SET_BINARY(pRaw, dataPos, algo->name, algo->nameLen, _OVER)
|
||||
SDB_SET_INT32(pRaw, dataPos, 0, _OVER) // reserved
|
||||
}
|
||||
}
|
||||
|
||||
SDB_SET_RESERVE(pRaw, dataPos, TSDB_ANODE_RESERVE_SIZE, _OVER)
|
||||
|
||||
terrno = 0;
|
||||
|
||||
_OVER:
|
||||
if (terrno != 0) {
|
||||
mError("anode:%d, failed to encode to raw:%p since %s", pObj->id, pRaw, terrstr());
|
||||
sdbFreeRaw(pRaw);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mTrace("anode:%d, encode to raw:%p, row:%p", pObj->id, pRaw, pObj);
|
||||
return pRaw;
|
||||
}
|
||||
|
||||
static SSdbRow *mndAnodeActionDecode(SSdbRaw *pRaw) {
|
||||
int32_t code = 0;
|
||||
int32_t lino = 0;
|
||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||
SSdbRow *pRow = NULL;
|
||||
SAnodeObj *pObj = NULL;
|
||||
|
||||
int8_t sver = 0;
|
||||
if (sdbGetRawSoftVer(pRaw, &sver) != 0) goto _OVER;
|
||||
|
||||
if (sver != TSDB_ANODE_VER_NUMBER) {
|
||||
terrno = TSDB_CODE_SDB_INVALID_DATA_VER;
|
||||
goto _OVER;
|
||||
}
|
||||
|
||||
pRow = sdbAllocRow(sizeof(SAnodeObj));
|
||||
if (pRow == NULL) goto _OVER;
|
||||
|
||||
pObj = sdbGetRowObj(pRow);
|
||||
if (pObj == NULL) goto _OVER;
|
||||
|
||||
int32_t dataPos = 0;
|
||||
SDB_GET_INT32(pRaw, dataPos, &pObj->id, _OVER)
|
||||
SDB_GET_INT64(pRaw, dataPos, &pObj->createdTime, _OVER)
|
||||
SDB_GET_INT64(pRaw, dataPos, &pObj->updateTime, _OVER)
|
||||
SDB_GET_INT32(pRaw, dataPos, &pObj->version, _OVER)
|
||||
SDB_GET_INT32(pRaw, dataPos, &pObj->urlLen, _OVER)
|
||||
|
||||
if (pObj->urlLen > 0) {
|
||||
pObj->url = taosMemoryCalloc(pObj->urlLen, 1);
|
||||
if (pObj->url == NULL) goto _OVER;
|
||||
SDB_GET_BINARY(pRaw, dataPos, pObj->url, pObj->urlLen, _OVER)
|
||||
}
|
||||
|
||||
SDB_GET_INT32(pRaw, dataPos, &pObj->numOfAlgos, _OVER)
|
||||
if (pObj->numOfAlgos > 0) {
|
||||
pObj->algos = taosMemoryCalloc(pObj->numOfAlgos, sizeof(SArray *));
|
||||
if (pObj->algos == NULL) {
|
||||
goto _OVER;
|
||||
}
|
||||
}
|
||||
|
||||
for (int32_t i = 0; i < pObj->numOfAlgos; ++i) {
|
||||
int32_t numOfAlgos = 0;
|
||||
SDB_GET_INT32(pRaw, dataPos, &numOfAlgos, _OVER)
|
||||
|
||||
pObj->algos[i] = taosArrayInit(2, sizeof(SAnodeAlgo));
|
||||
if (pObj->algos[i] == NULL) goto _OVER;
|
||||
|
||||
for (int32_t j = 0; j < numOfAlgos; ++j) {
|
||||
SAnodeAlgo algoObj = {0};
|
||||
int32_t reserved = 0;
|
||||
|
||||
SDB_GET_INT32(pRaw, dataPos, &algoObj.nameLen, _OVER)
|
||||
if (algoObj.nameLen > 0) {
|
||||
algoObj.name = taosMemoryCalloc(algoObj.nameLen, 1);
|
||||
if (algoObj.name == NULL) goto _OVER;
|
||||
}
|
||||
|
||||
SDB_GET_BINARY(pRaw, dataPos, algoObj.name, algoObj.nameLen, _OVER)
|
||||
SDB_GET_INT32(pRaw, dataPos, &reserved, _OVER);
|
||||
|
||||
if (taosArrayPush(pObj->algos[i], &algoObj) == NULL) goto _OVER;
|
||||
}
|
||||
}
|
||||
|
||||
SDB_GET_RESERVE(pRaw, dataPos, TSDB_ANODE_RESERVE_SIZE, _OVER)
|
||||
|
||||
terrno = 0;
|
||||
|
||||
_OVER:
|
||||
if (terrno != 0) {
|
||||
mError("anode:%d, failed to decode from raw:%p since %s", pObj == NULL ? 0 : pObj->id, pRaw, terrstr());
|
||||
if (pObj != NULL) {
|
||||
taosMemoryFreeClear(pObj->url);
|
||||
}
|
||||
taosMemoryFreeClear(pRow);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mTrace("anode:%d, decode from raw:%p, row:%p", pObj->id, pRaw, pObj);
|
||||
return pRow;
|
||||
}
|
||||
|
||||
static void mndFreeAnode(SAnodeObj *pObj) {
|
||||
taosMemoryFreeClear(pObj->url);
|
||||
for (int32_t i = 0; i < pObj->numOfAlgos; ++i) {
|
||||
SArray *algos = pObj->algos[i];
|
||||
for (int32_t j = 0; j < (int32_t)taosArrayGetSize(algos); ++j) {
|
||||
SAnodeAlgo *algo = taosArrayGet(algos, j);
|
||||
taosMemoryFreeClear(algo->name);
|
||||
}
|
||||
taosArrayDestroy(algos);
|
||||
}
|
||||
taosMemoryFreeClear(pObj->algos);
|
||||
}
|
||||
|
||||
static int32_t mndAnodeActionInsert(SSdb *pSdb, SAnodeObj *pObj) {
|
||||
mTrace("anode:%d, perform insert action, row:%p", pObj->id, pObj);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t mndAnodeActionDelete(SSdb *pSdb, SAnodeObj *pObj) {
|
||||
mTrace("anode:%d, perform delete action, row:%p", pObj->id, pObj);
|
||||
mndFreeAnode(pObj);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t mndAnodeActionUpdate(SSdb *pSdb, SAnodeObj *pOld, SAnodeObj *pNew) {
|
||||
mTrace("anode:%d, perform update action, old row:%p new row:%p", pOld->id, pOld, pNew);
|
||||
|
||||
taosWLockLatch(&pOld->lock);
|
||||
int32_t numOfAlgos = pNew->numOfAlgos;
|
||||
void *algos = pNew->algos;
|
||||
pNew->numOfAlgos = pOld->numOfAlgos;
|
||||
pNew->algos = pOld->algos;
|
||||
pOld->numOfAlgos = numOfAlgos;
|
||||
pOld->algos = algos;
|
||||
pOld->updateTime = pNew->updateTime;
|
||||
pOld->version = pNew->version;
|
||||
taosWUnLockLatch(&pOld->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t mndSetCreateAnodeRedoLogs(STrans *pTrans, SAnodeObj *pObj) {
|
||||
int32_t code = 0;
|
||||
SSdbRaw *pRedoRaw = mndAnodeActionEncode(pObj);
|
||||
if (pRedoRaw == NULL) {
|
||||
code = TSDB_CODE_MND_RETURN_VALUE_NULL;
|
||||
if (terrno != 0) code = terrno;
|
||||
TAOS_RETURN(code);
|
||||
}
|
||||
TAOS_CHECK_RETURN(mndTransAppendRedolog(pTrans, pRedoRaw));
|
||||
TAOS_CHECK_RETURN(sdbSetRawStatus(pRedoRaw, SDB_STATUS_CREATING));
|
||||
TAOS_RETURN(code);
|
||||
}
|
||||
|
||||
static int32_t mndSetCreateAnodeUndoLogs(STrans *pTrans, SAnodeObj *pObj) {
|
||||
int32_t code = 0;
|
||||
SSdbRaw *pUndoRaw = mndAnodeActionEncode(pObj);
|
||||
if (pUndoRaw == NULL) {
|
||||
code = TSDB_CODE_MND_RETURN_VALUE_NULL;
|
||||
if (terrno != 0) code = terrno;
|
||||
TAOS_RETURN(code);
|
||||
}
|
||||
TAOS_CHECK_RETURN(mndTransAppendUndolog(pTrans, pUndoRaw));
|
||||
TAOS_CHECK_RETURN(sdbSetRawStatus(pUndoRaw, SDB_STATUS_DROPPED));
|
||||
TAOS_RETURN(code);
|
||||
}
|
||||
|
||||
static int32_t mndSetCreateAnodeCommitLogs(STrans *pTrans, SAnodeObj *pObj) {
|
||||
int32_t code = 0;
|
||||
SSdbRaw *pCommitRaw = mndAnodeActionEncode(pObj);
|
||||
if (pCommitRaw == NULL) {
|
||||
code = TSDB_CODE_MND_RETURN_VALUE_NULL;
|
||||
if (terrno != 0) code = terrno;
|
||||
TAOS_RETURN(code);
|
||||
}
|
||||
TAOS_CHECK_RETURN(mndTransAppendCommitlog(pTrans, pCommitRaw));
|
||||
TAOS_CHECK_RETURN(sdbSetRawStatus(pCommitRaw, SDB_STATUS_READY));
|
||||
TAOS_RETURN(code);
|
||||
}
|
||||
|
||||
static int32_t mndCreateAnode(SMnode *pMnode, SRpcMsg *pReq, SMCreateAnodeReq *pCreate) {
|
||||
int32_t code = -1;
|
||||
STrans *pTrans = NULL;
|
||||
|
||||
SAnodeObj anodeObj = {0};
|
||||
anodeObj.id = sdbGetMaxId(pMnode->pSdb, SDB_ANODE);
|
||||
anodeObj.createdTime = taosGetTimestampMs();
|
||||
anodeObj.updateTime = anodeObj.createdTime;
|
||||
anodeObj.version = 0;
|
||||
anodeObj.urlLen = pCreate->urlLen;
|
||||
if (anodeObj.urlLen > TSDB_ANAL_ANODE_URL_LEN) {
|
||||
code = TSDB_CODE_MND_ANODE_TOO_LONG_URL;
|
||||
goto _OVER;
|
||||
}
|
||||
|
||||
anodeObj.url = taosMemoryCalloc(1, pCreate->urlLen);
|
||||
if (anodeObj.url == NULL) goto _OVER;
|
||||
(void)memcpy(anodeObj.url, pCreate->url, pCreate->urlLen);
|
||||
|
||||
code = mndGetAnodeAlgoList(anodeObj.url, &anodeObj);
|
||||
if (code != 0) goto _OVER;
|
||||
|
||||
pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_CONFLICT_NOTHING, pReq, "create-anode");
|
||||
if (pTrans == NULL) {
|
||||
code = TSDB_CODE_MND_RETURN_VALUE_NULL;
|
||||
if (terrno != 0) code = terrno;
|
||||
goto _OVER;
|
||||
}
|
||||
mndTransSetSerial(pTrans);
|
||||
|
||||
mInfo("trans:%d, used to create anode:%s as anode:%d", pTrans->id, pCreate->url, anodeObj.id);
|
||||
|
||||
TAOS_CHECK_GOTO(mndSetCreateAnodeRedoLogs(pTrans, &anodeObj), NULL, _OVER);
|
||||
TAOS_CHECK_GOTO(mndSetCreateAnodeUndoLogs(pTrans, &anodeObj), NULL, _OVER);
|
||||
TAOS_CHECK_GOTO(mndSetCreateAnodeCommitLogs(pTrans, &anodeObj), NULL, _OVER);
|
||||
TAOS_CHECK_GOTO(mndTransPrepare(pMnode, pTrans), NULL, _OVER);
|
||||
|
||||
code = 0;
|
||||
|
||||
_OVER:
|
||||
mndFreeAnode(&anodeObj);
|
||||
mndTransDrop(pTrans);
|
||||
TAOS_RETURN(code);
|
||||
}
|
||||
|
||||
static SAnodeObj *mndAcquireAnodeByURL(SMnode *pMnode, char *url) {
|
||||
SSdb *pSdb = pMnode->pSdb;
|
||||
|
||||
void *pIter = NULL;
|
||||
while (1) {
|
||||
SAnodeObj *pAnode = NULL;
|
||||
pIter = sdbFetch(pSdb, SDB_ANODE, pIter, (void **)&pAnode);
|
||||
if (pIter == NULL) break;
|
||||
|
||||
if (strcasecmp(url, pAnode->url) == 0) {
|
||||
sdbCancelFetch(pSdb, pIter);
|
||||
return pAnode;
|
||||
}
|
||||
|
||||
sdbRelease(pSdb, pAnode);
|
||||
}
|
||||
|
||||
terrno = TSDB_CODE_MND_ANODE_NOT_EXIST;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int32_t mndProcessCreateAnodeReq(SRpcMsg *pReq) {
|
||||
SMnode *pMnode = pReq->info.node;
|
||||
int32_t code = -1;
|
||||
SAnodeObj *pObj = NULL;
|
||||
SMCreateAnodeReq createReq = {0};
|
||||
|
||||
TAOS_CHECK_GOTO(tDeserializeSMCreateAnodeReq(pReq->pCont, pReq->contLen, &createReq), NULL, _OVER);
|
||||
|
||||
mInfo("anode:%s, start to create", createReq.url);
|
||||
TAOS_CHECK_GOTO(mndCheckOperPrivilege(pMnode, pReq->info.conn.user, MND_OPER_CREATE_ANODE), NULL, _OVER);
|
||||
|
||||
pObj = mndAcquireAnodeByURL(pMnode, createReq.url);
|
||||
if (pObj != NULL) {
|
||||
code = TSDB_CODE_MND_ANODE_ALREADY_EXIST;
|
||||
goto _OVER;
|
||||
}
|
||||
|
||||
code = mndCreateAnode(pMnode, pReq, &createReq);
|
||||
if (code == 0) code = TSDB_CODE_ACTION_IN_PROGRESS;
|
||||
|
||||
_OVER:
|
||||
if (code != 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) {
|
||||
mError("anode:%s, failed to create since %s", createReq.url, tstrerror(code));
|
||||
}
|
||||
|
||||
mndReleaseAnode(pMnode, pObj);
|
||||
tFreeSMCreateAnodeReq(&createReq);
|
||||
TAOS_RETURN(code);
|
||||
}
|
||||
|
||||
static int32_t mndUpdateAnode(SMnode *pMnode, SAnodeObj *pAnode, SRpcMsg *pReq) {
|
||||
mInfo("anode:%d, start to update", pAnode->id);
|
||||
int32_t code = -1;
|
||||
STrans *pTrans = NULL;
|
||||
SAnodeObj anodeObj = {0};
|
||||
anodeObj.id = pAnode->id;
|
||||
anodeObj.updateTime = taosGetTimestampMs();
|
||||
|
||||
code = mndGetAnodeAlgoList(pAnode->url, &anodeObj);
|
||||
if (code != 0) goto _OVER;
|
||||
|
||||
pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_CONFLICT_NOTHING, pReq, "update-anode");
|
||||
if (pTrans == NULL) {
|
||||
code = TSDB_CODE_MND_RETURN_VALUE_NULL;
|
||||
if (terrno != 0) code = terrno;
|
||||
goto _OVER;
|
||||
}
|
||||
mInfo("trans:%d, used to update anode:%d", pTrans->id, anodeObj.id);
|
||||
|
||||
TAOS_CHECK_GOTO(mndSetCreateAnodeCommitLogs(pTrans, &anodeObj), NULL, _OVER);
|
||||
TAOS_CHECK_GOTO(mndTransPrepare(pMnode, pTrans), NULL, _OVER);
|
||||
code = 0;
|
||||
|
||||
_OVER:
|
||||
mndFreeAnode(&anodeObj);
|
||||
mndTransDrop(pTrans);
|
||||
TAOS_RETURN(code);
|
||||
}
|
||||
|
||||
static int32_t mndUpdateAllAnodes(SMnode *pMnode, SRpcMsg *pReq) {
|
||||
mInfo("update all anodes");
|
||||
SSdb *pSdb = pMnode->pSdb;
|
||||
int32_t code = 0;
|
||||
int32_t rows = 0;
|
||||
int32_t numOfRows = sdbGetSize(pSdb, SDB_ANODE);
|
||||
|
||||
void *pIter = NULL;
|
||||
while (1) {
|
||||
SAnodeObj *pObj = NULL;
|
||||
ESdbStatus objStatus = 0;
|
||||
pIter = sdbFetchAll(pSdb, SDB_ANODE, pIter, (void **)&pObj, &objStatus, true);
|
||||
if (pIter == NULL) break;
|
||||
|
||||
rows++;
|
||||
void *transReq = NULL;
|
||||
if (rows == numOfRows) transReq = pReq;
|
||||
code = mndUpdateAnode(pMnode, pObj, transReq);
|
||||
sdbRelease(pSdb, pObj);
|
||||
|
||||
if (code != 0) break;
|
||||
}
|
||||
|
||||
if (code == 0 && rows == numOfRows) {
|
||||
code = TSDB_CODE_ACTION_IN_PROGRESS;
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t mndProcessUpdateAnodeReq(SRpcMsg *pReq) {
|
||||
SMnode *pMnode = pReq->info.node;
|
||||
int32_t code = -1;
|
||||
SAnodeObj *pObj = NULL;
|
||||
SMUpdateAnodeReq updateReq = {0};
|
||||
|
||||
TAOS_CHECK_GOTO(tDeserializeSMUpdateAnodeReq(pReq->pCont, pReq->contLen, &updateReq), NULL, _OVER);
|
||||
TAOS_CHECK_GOTO(mndCheckOperPrivilege(pMnode, pReq->info.conn.user, MND_OPER_UPDATE_ANODE), NULL, _OVER);
|
||||
|
||||
if (updateReq.anodeId == -1) {
|
||||
code = mndUpdateAllAnodes(pMnode, pReq);
|
||||
} else {
|
||||
pObj = mndAcquireAnode(pMnode, updateReq.anodeId);
|
||||
if (pObj == NULL) {
|
||||
code = TSDB_CODE_MND_ANODE_NOT_EXIST;
|
||||
goto _OVER;
|
||||
}
|
||||
code = mndUpdateAnode(pMnode, pObj, pReq);
|
||||
if (code == 0) code = TSDB_CODE_ACTION_IN_PROGRESS;
|
||||
}
|
||||
|
||||
_OVER:
|
||||
if (code != 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) {
|
||||
if (updateReq.anodeId != -1) {
|
||||
mError("anode:%d, failed to update since %s", updateReq.anodeId, tstrerror(code));
|
||||
}
|
||||
}
|
||||
|
||||
mndReleaseAnode(pMnode, pObj);
|
||||
tFreeSMUpdateAnodeReq(&updateReq);
|
||||
TAOS_RETURN(code);
|
||||
}
|
||||
|
||||
static int32_t mndSetDropAnodeRedoLogs(STrans *pTrans, SAnodeObj *pObj) {
|
||||
int32_t code = 0;
|
||||
SSdbRaw *pRedoRaw = mndAnodeActionEncode(pObj);
|
||||
if (pRedoRaw == NULL) {
|
||||
code = TSDB_CODE_MND_RETURN_VALUE_NULL;
|
||||
if (terrno != 0) code = terrno;
|
||||
TAOS_RETURN(code);
|
||||
}
|
||||
TAOS_CHECK_RETURN(mndTransAppendRedolog(pTrans, pRedoRaw));
|
||||
TAOS_CHECK_RETURN(sdbSetRawStatus(pRedoRaw, SDB_STATUS_DROPPING));
|
||||
TAOS_RETURN(code);
|
||||
}
|
||||
|
||||
static int32_t mndSetDropAnodeCommitLogs(STrans *pTrans, SAnodeObj *pObj) {
|
||||
int32_t code = 0;
|
||||
SSdbRaw *pCommitRaw = mndAnodeActionEncode(pObj);
|
||||
if (pCommitRaw == NULL) {
|
||||
code = TSDB_CODE_MND_RETURN_VALUE_NULL;
|
||||
if (terrno != 0) code = terrno;
|
||||
TAOS_RETURN(code);
|
||||
}
|
||||
TAOS_CHECK_RETURN(mndTransAppendCommitlog(pTrans, pCommitRaw));
|
||||
TAOS_CHECK_RETURN(sdbSetRawStatus(pCommitRaw, SDB_STATUS_DROPPED));
|
||||
TAOS_RETURN(code);
|
||||
}
|
||||
|
||||
static int32_t mndSetDropAnodeInfoToTrans(SMnode *pMnode, STrans *pTrans, SAnodeObj *pObj, bool force) {
|
||||
if (pObj == NULL) return 0;
|
||||
TAOS_CHECK_RETURN(mndSetDropAnodeRedoLogs(pTrans, pObj));
|
||||
TAOS_CHECK_RETURN(mndSetDropAnodeCommitLogs(pTrans, pObj));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t mndDropAnode(SMnode *pMnode, SRpcMsg *pReq, SAnodeObj *pObj) {
|
||||
int32_t code = -1;
|
||||
|
||||
STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_NOTHING, pReq, "drop-anode");
|
||||
if (pTrans == NULL) {
|
||||
code = TSDB_CODE_MND_RETURN_VALUE_NULL;
|
||||
if (terrno != 0) code = terrno;
|
||||
goto _OVER;
|
||||
}
|
||||
mndTransSetSerial(pTrans);
|
||||
|
||||
mInfo("trans:%d, used to drop anode:%d", pTrans->id, pObj->id);
|
||||
TAOS_CHECK_GOTO(mndSetDropAnodeInfoToTrans(pMnode, pTrans, pObj, false), NULL, _OVER);
|
||||
TAOS_CHECK_GOTO(mndTransPrepare(pMnode, pTrans), NULL, _OVER);
|
||||
|
||||
code = 0;
|
||||
|
||||
_OVER:
|
||||
mndTransDrop(pTrans);
|
||||
TAOS_RETURN(code);
|
||||
}
|
||||
|
||||
static int32_t mndProcessDropAnodeReq(SRpcMsg *pReq) {
|
||||
SMnode *pMnode = pReq->info.node;
|
||||
int32_t code = -1;
|
||||
SAnodeObj *pObj = NULL;
|
||||
SMDropAnodeReq dropReq = {0};
|
||||
|
||||
TAOS_CHECK_GOTO(tDeserializeSMDropAnodeReq(pReq->pCont, pReq->contLen, &dropReq), NULL, _OVER);
|
||||
|
||||
mInfo("anode:%d, start to drop", dropReq.anodeId);
|
||||
TAOS_CHECK_GOTO(mndCheckOperPrivilege(pMnode, pReq->info.conn.user, MND_OPER_DROP_ANODE), NULL, _OVER);
|
||||
|
||||
if (dropReq.anodeId <= 0) {
|
||||
code = TSDB_CODE_INVALID_MSG;
|
||||
goto _OVER;
|
||||
}
|
||||
|
||||
pObj = mndAcquireAnode(pMnode, dropReq.anodeId);
|
||||
if (pObj == NULL) {
|
||||
code = TSDB_CODE_MND_RETURN_VALUE_NULL;
|
||||
if (terrno != 0) code = terrno;
|
||||
goto _OVER;
|
||||
}
|
||||
|
||||
code = mndDropAnode(pMnode, pReq, pObj);
|
||||
if (code == 0) code = TSDB_CODE_ACTION_IN_PROGRESS;
|
||||
|
||||
_OVER:
|
||||
if (code != 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) {
|
||||
mError("anode:%d, failed to drop since %s", dropReq.anodeId, tstrerror(code));
|
||||
}
|
||||
|
||||
mndReleaseAnode(pMnode, pObj);
|
||||
tFreeSMDropAnodeReq(&dropReq);
|
||||
TAOS_RETURN(code);
|
||||
}
|
||||
|
||||
static int32_t mndRetrieveAnodes(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows) {
|
||||
SMnode *pMnode = pReq->info.node;
|
||||
SSdb *pSdb = pMnode->pSdb;
|
||||
int32_t numOfRows = 0;
|
||||
int32_t cols = 0;
|
||||
SAnodeObj *pObj = NULL;
|
||||
char buf[TSDB_ANAL_ANODE_URL_LEN + VARSTR_HEADER_SIZE];
|
||||
char status[64];
|
||||
int32_t code = 0;
|
||||
|
||||
while (numOfRows < rows) {
|
||||
pShow->pIter = sdbFetch(pSdb, SDB_ANODE, pShow->pIter, (void **)&pObj);
|
||||
if (pShow->pIter == NULL) break;
|
||||
|
||||
cols = 0;
|
||||
SColumnInfoData *pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
|
||||
code = colDataSetVal(pColInfo, numOfRows, (const char *)&pObj->id, false);
|
||||
if (code != 0) goto _end;
|
||||
|
||||
STR_WITH_MAXSIZE_TO_VARSTR(buf, pObj->url, pShow->pMeta->pSchemas[cols].bytes);
|
||||
pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
|
||||
code = colDataSetVal(pColInfo, numOfRows, (const char *)buf, false);
|
||||
if (code != 0) goto _end;
|
||||
|
||||
status[0] = 0;
|
||||
if (mndGetAnodeStatus(pObj, status, 64) == 0) {
|
||||
STR_TO_VARSTR(buf, status);
|
||||
} else {
|
||||
STR_TO_VARSTR(buf, "offline");
|
||||
}
|
||||
pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
|
||||
code = colDataSetVal(pColInfo, numOfRows, buf, false);
|
||||
if (code != 0) goto _end;
|
||||
|
||||
pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
|
||||
code = colDataSetVal(pColInfo, numOfRows, (const char *)&pObj->createdTime, false);
|
||||
if (code != 0) goto _end;
|
||||
|
||||
pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
|
||||
code = colDataSetVal(pColInfo, numOfRows, (const char *)&pObj->updateTime, false);
|
||||
if (code != 0) goto _end;
|
||||
|
||||
numOfRows++;
|
||||
sdbRelease(pSdb, pObj);
|
||||
}
|
||||
|
||||
_end:
|
||||
if (code != 0) sdbRelease(pSdb, pObj);
|
||||
|
||||
pShow->numOfRows += numOfRows;
|
||||
return numOfRows;
|
||||
}
|
||||
|
||||
static void mndCancelGetNextAnode(SMnode *pMnode, void *pIter) {
|
||||
SSdb *pSdb = pMnode->pSdb;
|
||||
sdbCancelFetchByType(pSdb, pIter, SDB_ANODE);
|
||||
}
|
||||
|
||||
static int32_t mndRetrieveAnodesFull(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows) {
|
||||
SMnode *pMnode = pReq->info.node;
|
||||
SSdb *pSdb = pMnode->pSdb;
|
||||
int32_t numOfRows = 0;
|
||||
int32_t cols = 0;
|
||||
SAnodeObj *pObj = NULL;
|
||||
char buf[TSDB_ANAL_ALGO_NAME_LEN + VARSTR_HEADER_SIZE];
|
||||
int32_t code = 0;
|
||||
|
||||
while (numOfRows < rows) {
|
||||
pShow->pIter = sdbFetch(pSdb, SDB_ANODE, pShow->pIter, (void **)&pObj);
|
||||
if (pShow->pIter == NULL) break;
|
||||
|
||||
for (int32_t t = 0; t < pObj->numOfAlgos; ++t) {
|
||||
SArray *algos = pObj->algos[t];
|
||||
|
||||
for (int32_t a = 0; a < taosArrayGetSize(algos); ++a) {
|
||||
SAnodeAlgo *algo = taosArrayGet(algos, a);
|
||||
|
||||
cols = 0;
|
||||
SColumnInfoData *pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
|
||||
code = colDataSetVal(pColInfo, numOfRows, (const char *)&pObj->id, false);
|
||||
if (code != 0) goto _end;
|
||||
|
||||
STR_TO_VARSTR(buf, taosAnalAlgoStr(t));
|
||||
pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
|
||||
code = colDataSetVal(pColInfo, numOfRows, buf, false);
|
||||
if (code != 0) goto _end;
|
||||
|
||||
STR_TO_VARSTR(buf, algo->name);
|
||||
pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
|
||||
code = colDataSetVal(pColInfo, numOfRows, buf, false);
|
||||
if (code != 0) goto _end;
|
||||
|
||||
numOfRows++;
|
||||
}
|
||||
}
|
||||
|
||||
sdbRelease(pSdb, pObj);
|
||||
}
|
||||
|
||||
_end:
|
||||
if (code != 0) sdbRelease(pSdb, pObj);
|
||||
|
||||
pShow->numOfRows += numOfRows;
|
||||
return numOfRows;
|
||||
}
|
||||
|
||||
static void mndCancelGetNextAnodeFull(SMnode *pMnode, void *pIter) {
|
||||
SSdb *pSdb = pMnode->pSdb;
|
||||
sdbCancelFetchByType(pSdb, pIter, SDB_ANODE);
|
||||
}
|
||||
|
||||
static int32_t mndDecodeAlgoList(SJson *pJson, SAnodeObj *pObj) {
|
||||
int32_t code = 0;
|
||||
int32_t protocol = 0;
|
||||
double tmp = 0;
|
||||
char buf[TSDB_ANAL_ALGO_NAME_LEN + 1] = {0};
|
||||
|
||||
code = tjsonGetDoubleValue(pJson, "protocol", &tmp);
|
||||
if (code < 0) return TSDB_CODE_INVALID_JSON_FORMAT;
|
||||
protocol = (int32_t)(tmp * 1000);
|
||||
if (protocol != 100 && protocol != 1000) return TSDB_CODE_MND_ANODE_INVALID_PROTOCOL;
|
||||
|
||||
code = tjsonGetDoubleValue(pJson, "version", &tmp);
|
||||
pObj->version = (int32_t)(tmp * 1000);
|
||||
if (code < 0) return TSDB_CODE_INVALID_JSON_FORMAT;
|
||||
if (pObj->version <= 0) return TSDB_CODE_MND_ANODE_INVALID_VERSION;
|
||||
|
||||
SJson *details = tjsonGetObjectItem(pJson, "details");
|
||||
if (details == NULL) return TSDB_CODE_INVALID_JSON_FORMAT;
|
||||
int32_t numOfDetails = tjsonGetArraySize(details);
|
||||
|
||||
pObj->algos = taosMemoryCalloc(ANAL_ALGO_TYPE_END, sizeof(SArray *));
|
||||
if (pObj->algos == NULL) return TSDB_CODE_OUT_OF_MEMORY;
|
||||
|
||||
pObj->numOfAlgos = ANAL_ALGO_TYPE_END;
|
||||
for (int32_t i = 0; i < ANAL_ALGO_TYPE_END; ++i) {
|
||||
pObj->algos[i] = taosArrayInit(4, sizeof(SAnodeAlgo));
|
||||
if (pObj->algos[i] == NULL) return TSDB_CODE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
for (int32_t d = 0; d < numOfDetails; ++d) {
|
||||
SJson *detail = tjsonGetArrayItem(details, d);
|
||||
if (detail == NULL) return TSDB_CODE_INVALID_JSON_FORMAT;
|
||||
|
||||
code = tjsonGetStringValue2(detail, "type", buf, sizeof(buf));
|
||||
if (code < 0) return TSDB_CODE_INVALID_JSON_FORMAT;
|
||||
EAnalAlgoType type = taosAnalAlgoInt(buf);
|
||||
if (type < 0 || type >= ANAL_ALGO_TYPE_END) return TSDB_CODE_MND_ANODE_INVALID_ALGO_TYPE;
|
||||
|
||||
SJson *algos = tjsonGetObjectItem(detail, "algo");
|
||||
if (algos == NULL) return TSDB_CODE_INVALID_JSON_FORMAT;
|
||||
int32_t numOfAlgos = tjsonGetArraySize(algos);
|
||||
for (int32_t a = 0; a < numOfAlgos; ++a) {
|
||||
SJson *algo = tjsonGetArrayItem(algos, a);
|
||||
if (algo == NULL) return TSDB_CODE_INVALID_JSON_FORMAT;
|
||||
|
||||
code = tjsonGetStringValue2(algo, "name", buf, sizeof(buf));
|
||||
if (code < 0) return TSDB_CODE_MND_ANODE_TOO_LONG_ALGO_NAME;
|
||||
|
||||
SAnodeAlgo algoObj = {0};
|
||||
algoObj.nameLen = strlen(buf) + 1;
|
||||
if (algoObj.nameLen <= 1) return TSDB_CODE_INVALID_JSON_FORMAT;
|
||||
algoObj.name = taosMemoryCalloc(algoObj.nameLen, 1);
|
||||
tstrncpy(algoObj.name, buf, algoObj.nameLen);
|
||||
|
||||
if (taosArrayPush(pObj->algos[type], &algoObj) == NULL) return TSDB_CODE_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t mndGetAnodeAlgoList(const char *url, SAnodeObj *pObj) {
|
||||
char anodeUrl[TSDB_ANAL_ANODE_URL_LEN + 1] = {0};
|
||||
snprintf(anodeUrl, TSDB_ANAL_ANODE_URL_LEN, "%s/%s", url, "list");
|
||||
|
||||
SJson *pJson = taosAnalSendReqRetJson(anodeUrl, ANAL_HTTP_TYPE_GET, NULL);
|
||||
if (pJson == NULL) return terrno;
|
||||
|
||||
int32_t code = mndDecodeAlgoList(pJson, pObj);
|
||||
if (pJson != NULL) tjsonDelete(pJson);
|
||||
|
||||
TAOS_RETURN(code);
|
||||
}
|
||||
|
||||
static int32_t mndGetAnodeStatus(SAnodeObj *pObj, char *status, int32_t statusLen) {
|
||||
int32_t code = 0;
|
||||
int32_t protocol = 0;
|
||||
double tmp = 0;
|
||||
char anodeUrl[TSDB_ANAL_ANODE_URL_LEN + 1] = {0};
|
||||
snprintf(anodeUrl, TSDB_ANAL_ANODE_URL_LEN, "%s/%s", pObj->url, "status");
|
||||
|
||||
SJson *pJson = taosAnalSendReqRetJson(anodeUrl, ANAL_HTTP_TYPE_GET, NULL);
|
||||
if (pJson == NULL) return terrno;
|
||||
|
||||
code = tjsonGetDoubleValue(pJson, "protocol", &tmp);
|
||||
if (code < 0) {
|
||||
code = TSDB_CODE_INVALID_JSON_FORMAT;
|
||||
goto _OVER;
|
||||
}
|
||||
protocol = (int32_t)(tmp * 1000);
|
||||
if (protocol != 100 && protocol != 1000) {
|
||||
code = TSDB_CODE_MND_ANODE_INVALID_PROTOCOL;
|
||||
goto _OVER;
|
||||
}
|
||||
|
||||
code = tjsonGetStringValue2(pJson, "status", status, statusLen);
|
||||
if (code < 0) {
|
||||
code = TSDB_CODE_INVALID_JSON_FORMAT;
|
||||
goto _OVER;
|
||||
}
|
||||
if (strlen(status) == 0) {
|
||||
code = TSDB_CODE_MND_ANODE_INVALID_PROTOCOL;
|
||||
goto _OVER;
|
||||
}
|
||||
|
||||
_OVER:
|
||||
if (pJson != NULL) tjsonDelete(pJson);
|
||||
TAOS_RETURN(code);
|
||||
}
|
||||
|
||||
static int32_t mndProcessAnalAlgoReq(SRpcMsg *pReq) {
|
||||
SMnode *pMnode = pReq->info.node;
|
||||
SSdb *pSdb = pMnode->pSdb;
|
||||
int32_t code = -1;
|
||||
SAnodeObj *pObj = NULL;
|
||||
SAnalUrl url;
|
||||
int32_t nameLen;
|
||||
char name[TSDB_ANAL_ALGO_KEY_LEN];
|
||||
SRetrieveAnalAlgoReq req = {0};
|
||||
SRetrieveAnalAlgoRsp rsp = {0};
|
||||
|
||||
TAOS_CHECK_GOTO(tDeserializeRetrieveAnalAlgoReq(pReq->pCont, pReq->contLen, &req), NULL, _OVER);
|
||||
|
||||
rsp.ver = sdbGetTableVer(pSdb, SDB_ANODE);
|
||||
if (req.analVer != rsp.ver) {
|
||||
mInfo("dnode:%d, update analysis old ver:%" PRId64 " to new ver:%" PRId64, req.dnodeId, req.analVer, rsp.ver);
|
||||
rsp.hash = taosHashInit(64, MurmurHash3_32, true, HASH_ENTRY_LOCK);
|
||||
if (rsp.hash == NULL) {
|
||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||
goto _OVER;
|
||||
}
|
||||
|
||||
void *pIter = NULL;
|
||||
while (1) {
|
||||
SAnodeObj *pAnode = NULL;
|
||||
pIter = sdbFetch(pSdb, SDB_ANODE, pIter, (void **)&pAnode);
|
||||
if (pIter == NULL) break;
|
||||
|
||||
url.anode = pAnode->id;
|
||||
for (int32_t t = 0; t < pAnode->numOfAlgos; ++t) {
|
||||
SArray *algos = pAnode->algos[t];
|
||||
url.type = t;
|
||||
|
||||
for (int32_t a = 0; a < taosArrayGetSize(algos); ++a) {
|
||||
SAnodeAlgo *algo = taosArrayGet(algos, a);
|
||||
nameLen = 1 + tsnprintf(name, sizeof(name) - 1, "%d:%s", url.type, algo->name);
|
||||
|
||||
SAnalUrl *pOldUrl = taosHashAcquire(rsp.hash, name, nameLen);
|
||||
if (pOldUrl == NULL || (pOldUrl != NULL && pOldUrl->anode < url.anode)) {
|
||||
if (pOldUrl != NULL) {
|
||||
taosMemoryFreeClear(pOldUrl->url);
|
||||
if (taosHashRemove(rsp.hash, name, nameLen) != 0) {
|
||||
sdbRelease(pSdb, pAnode);
|
||||
goto _OVER;
|
||||
}
|
||||
}
|
||||
url.url = taosMemoryMalloc(TSDB_ANAL_ANODE_URL_LEN + TSDB_ANAL_ALGO_TYPE_LEN + 1);
|
||||
if (url.url == NULL) {
|
||||
sdbRelease(pSdb, pAnode);
|
||||
goto _OVER;
|
||||
}
|
||||
|
||||
url.urlLen = 1 + tsnprintf(url.url, TSDB_ANAL_ANODE_URL_LEN + TSDB_ANAL_ALGO_TYPE_LEN, "%s/%s", pAnode->url,
|
||||
taosAnalAlgoUrlStr(url.type));
|
||||
if (taosHashPut(rsp.hash, name, nameLen, &url, sizeof(SAnalUrl)) != 0) {
|
||||
taosMemoryFree(url.url);
|
||||
sdbRelease(pSdb, pAnode);
|
||||
goto _OVER;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sdbRelease(pSdb, pAnode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int32_t contLen = tSerializeRetrieveAnalAlgoRsp(NULL, 0, &rsp);
|
||||
void *pHead = rpcMallocCont(contLen);
|
||||
(void)tSerializeRetrieveAnalAlgoRsp(pHead, contLen, &rsp);
|
||||
|
||||
pReq->info.rspLen = contLen;
|
||||
pReq->info.rsp = pHead;
|
||||
|
||||
_OVER:
|
||||
tFreeRetrieveAnalAlgoRsp(&rsp);
|
||||
TAOS_RETURN(code);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static int32_t mndProcessUnsupportReq(SRpcMsg *pReq) { return TSDB_CODE_OPS_NOT_SUPPORT; }
|
||||
static int32_t mndRetrieveUnsupport(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows) {
|
||||
return TSDB_CODE_OPS_NOT_SUPPORT;
|
||||
}
|
||||
|
||||
int32_t mndInitAnode(SMnode *pMnode) {
|
||||
mndSetMsgHandle(pMnode, TDMT_MND_CREATE_ANODE, mndProcessUnsupportReq);
|
||||
mndSetMsgHandle(pMnode, TDMT_MND_UPDATE_ANODE, mndProcessUnsupportReq);
|
||||
mndSetMsgHandle(pMnode, TDMT_MND_DROP_ANODE, mndProcessUnsupportReq);
|
||||
mndSetMsgHandle(pMnode, TDMT_MND_RETRIEVE_ANAL_ALGO, mndProcessUnsupportReq);
|
||||
|
||||
mndAddShowRetrieveHandle(pMnode, TSDB_MGMT_TABLE_ANODE, mndRetrieveUnsupport);
|
||||
mndAddShowRetrieveHandle(pMnode, TSDB_MGMT_TABLE_ANODE_FULL, mndRetrieveUnsupport);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mndCleanupAnode(SMnode *pMnode) {}
|
||||
|
||||
#endif
|
|
@ -730,6 +730,7 @@ static int32_t mndProcessStatusReq(SRpcMsg *pReq) {
|
|||
|
||||
pMnode->ipWhiteVer = mndGetIpWhiteVer(pMnode);
|
||||
|
||||
int64_t analVer = sdbGetTableVer(pMnode->pSdb, SDB_ANODE);
|
||||
int64_t dnodeVer = sdbGetTableVer(pMnode->pSdb, SDB_DNODE) + sdbGetTableVer(pMnode->pSdb, SDB_MNODE);
|
||||
int64_t curMs = taosGetTimestampMs();
|
||||
bool online = mndIsDnodeOnline(pDnode, curMs);
|
||||
|
@ -738,7 +739,8 @@ static int32_t mndProcessStatusReq(SRpcMsg *pReq) {
|
|||
bool supportVnodesChanged = pDnode->numOfSupportVnodes != statusReq.numOfSupportVnodes;
|
||||
bool encryptKeyChanged = pDnode->encryptionKeyChksum != statusReq.clusterCfg.encryptionKeyChksum;
|
||||
bool enableWhiteListChanged = statusReq.clusterCfg.enableWhiteList != (tsEnableWhiteList ? 1 : 0);
|
||||
bool needCheck = !online || dnodeChanged || reboot || supportVnodesChanged ||
|
||||
bool analVerChanged = (analVer != statusReq.analVer);
|
||||
bool needCheck = !online || dnodeChanged || reboot || supportVnodesChanged || analVerChanged ||
|
||||
pMnode->ipWhiteVer != statusReq.ipWhiteVer || encryptKeyChanged || enableWhiteListChanged;
|
||||
const STraceId *trace = &pReq->info.traceId;
|
||||
mGTrace("dnode:%d, status received, accessTimes:%d check:%d online:%d reboot:%d changed:%d statusSeq:%d", pDnode->id,
|
||||
|
@ -862,6 +864,7 @@ static int32_t mndProcessStatusReq(SRpcMsg *pReq) {
|
|||
|
||||
SStatusRsp statusRsp = {0};
|
||||
statusRsp.statusSeq++;
|
||||
statusRsp.analVer = analVer;
|
||||
statusRsp.dnodeVer = dnodeVer;
|
||||
statusRsp.dnodeCfg.dnodeId = pDnode->id;
|
||||
statusRsp.dnodeCfg.clusterId = pMnode->clusterId;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#define _DEFAULT_SOURCE
|
||||
#include "mndAcct.h"
|
||||
#include "mndArbGroup.h"
|
||||
#include "mndAnode.h"
|
||||
#include "mndCluster.h"
|
||||
#include "mndCompact.h"
|
||||
#include "mndCompactDetail.h"
|
||||
|
@ -607,6 +608,7 @@ static int32_t mndInitSteps(SMnode *pMnode) {
|
|||
TAOS_CHECK_RETURN(mndAllocStep(pMnode, "mnode-mnode", mndInitMnode, mndCleanupMnode));
|
||||
TAOS_CHECK_RETURN(mndAllocStep(pMnode, "mnode-qnode", mndInitQnode, mndCleanupQnode));
|
||||
TAOS_CHECK_RETURN(mndAllocStep(pMnode, "mnode-snode", mndInitSnode, mndCleanupSnode));
|
||||
TAOS_CHECK_RETURN(mndAllocStep(pMnode, "mnode-anode", mndInitAnode, mndCleanupAnode));
|
||||
TAOS_CHECK_RETURN(mndAllocStep(pMnode, "mnode-arbgroup", mndInitArbGroup, mndCleanupArbGroup));
|
||||
TAOS_CHECK_RETURN(mndAllocStep(pMnode, "mnode-dnode", mndInitDnode, mndCleanupDnode));
|
||||
TAOS_CHECK_RETURN(mndAllocStep(pMnode, "mnode-user", mndInitUser, mndCleanupUser));
|
||||
|
|
|
@ -68,6 +68,10 @@ static int32_t convertToRetrieveType(char *name, int32_t len) {
|
|||
type = TSDB_MGMT_TABLE_QNODE;
|
||||
} else if (strncasecmp(name, TSDB_INS_TABLE_SNODES, len) == 0) {
|
||||
type = TSDB_MGMT_TABLE_SNODE;
|
||||
} else if (strncasecmp(name, TSDB_INS_TABLE_ANODES, len) == 0) {
|
||||
type = TSDB_MGMT_TABLE_ANODE;
|
||||
} else if (strncasecmp(name, TSDB_INS_TABLE_ANODES_FULL, len) == 0) {
|
||||
type = TSDB_MGMT_TABLE_ANODE_FULL;
|
||||
} else if (strncasecmp(name, TSDB_INS_TABLE_ARBGROUPS, len) == 0) {
|
||||
type = TSDB_MGMT_TABLE_ARBGROUP;
|
||||
} else if (strncasecmp(name, TSDB_INS_TABLE_CLUSTER, len) == 0) {
|
||||
|
|
|
@ -161,7 +161,8 @@ typedef enum {
|
|||
SDB_COMPACT_DETAIL = 25,
|
||||
SDB_GRANT = 26, // grant log
|
||||
SDB_ARBGROUP = 27,
|
||||
SDB_MAX = 28
|
||||
SDB_ANODE = 28,
|
||||
SDB_MAX = 29
|
||||
} ESdbType;
|
||||
|
||||
typedef struct SSdbRaw {
|
||||
|
|
|
@ -25,6 +25,9 @@
|
|||
#define SDB_RESERVE_SIZE 512
|
||||
#define SDB_FILE_VER 1
|
||||
|
||||
#define SDB_TABLE_SIZE_EXTRA SDB_MAX
|
||||
#define SDB_RESERVE_SIZE_EXTRA (512 - (SDB_TABLE_SIZE_EXTRA - SDB_TABLE_SIZE) * 2 * sizeof(int64_t))
|
||||
|
||||
static int32_t sdbDeployData(SSdb *pSdb) {
|
||||
int32_t code = 0;
|
||||
mInfo("start to deploy sdb");
|
||||
|
@ -154,7 +157,38 @@ static int32_t sdbReadFileHead(SSdb *pSdb, TdFilePtr pFile) {
|
|||
}
|
||||
}
|
||||
|
||||
char reserve[SDB_RESERVE_SIZE] = {0};
|
||||
// for sdb compatibility
|
||||
for (int32_t i = SDB_TABLE_SIZE; i < SDB_TABLE_SIZE_EXTRA; ++i) {
|
||||
int64_t maxId = 0;
|
||||
ret = taosReadFile(pFile, &maxId, sizeof(int64_t));
|
||||
if (ret < 0) {
|
||||
code = TAOS_SYSTEM_ERROR(errno);
|
||||
TAOS_RETURN(code);
|
||||
}
|
||||
if (ret != sizeof(int64_t)) {
|
||||
code = TSDB_CODE_FILE_CORRUPTED;
|
||||
TAOS_RETURN(code);
|
||||
}
|
||||
if (i < SDB_MAX) {
|
||||
pSdb->maxId[i] = maxId;
|
||||
}
|
||||
|
||||
int64_t ver = 0;
|
||||
ret = taosReadFile(pFile, &ver, sizeof(int64_t));
|
||||
if (ret < 0) {
|
||||
code = TAOS_SYSTEM_ERROR(errno);
|
||||
TAOS_RETURN(code);
|
||||
}
|
||||
if (ret != sizeof(int64_t)) {
|
||||
code = TSDB_CODE_FILE_CORRUPTED;
|
||||
TAOS_RETURN(code);
|
||||
}
|
||||
if (i < SDB_MAX) {
|
||||
pSdb->tableVer[i] = ver;
|
||||
}
|
||||
}
|
||||
|
||||
char reserve[SDB_RESERVE_SIZE_EXTRA] = {0};
|
||||
ret = taosReadFile(pFile, reserve, sizeof(reserve));
|
||||
if (ret < 0) {
|
||||
return terrno;
|
||||
|
@ -207,7 +241,26 @@ static int32_t sdbWriteFileHead(SSdb *pSdb, TdFilePtr pFile) {
|
|||
}
|
||||
}
|
||||
|
||||
char reserve[SDB_RESERVE_SIZE] = {0};
|
||||
// for sdb compatibility
|
||||
for (int32_t i = SDB_TABLE_SIZE; i < SDB_TABLE_SIZE_EXTRA; ++i) {
|
||||
int64_t maxId = 0;
|
||||
if (i < SDB_MAX) {
|
||||
maxId = pSdb->maxId[i];
|
||||
}
|
||||
if (taosWriteFile(pFile, &maxId, sizeof(int64_t)) != sizeof(int64_t)) {
|
||||
return terrno;
|
||||
}
|
||||
|
||||
int64_t ver = 0;
|
||||
if (i < SDB_MAX) {
|
||||
ver = pSdb->tableVer[i];
|
||||
}
|
||||
if (taosWriteFile(pFile, &ver, sizeof(int64_t)) != sizeof(int64_t)) {
|
||||
return terrno;
|
||||
}
|
||||
}
|
||||
|
||||
char reserve[SDB_RESERVE_SIZE_EXTRA] = {0};
|
||||
if (taosWriteFile(pFile, reserve, sizeof(reserve)) != sizeof(reserve)) {
|
||||
return terrno;
|
||||
}
|
||||
|
|
|
@ -74,6 +74,8 @@ const char *sdbTableName(ESdbType type) {
|
|||
return "grant";
|
||||
case SDB_ARBGROUP:
|
||||
return "arb_group";
|
||||
case SDB_ANODE:
|
||||
return "anode";
|
||||
default:
|
||||
return "undefine";
|
||||
}
|
||||
|
|
|
@ -5,6 +5,10 @@ if(${TD_DARWIN})
|
|||
target_compile_options(executor PRIVATE -Wno-error=deprecated-non-prototype)
|
||||
endif(${TD_DARWIN})
|
||||
|
||||
IF(${BUILD_WITH_ANALYSIS})
|
||||
add_definitions(-DUSE_ANAL)
|
||||
ENDIF()
|
||||
|
||||
target_link_libraries(executor
|
||||
PRIVATE os util common function parser planner qcom scalar nodes index wal tdb geometry
|
||||
)
|
||||
|
|
|
@ -133,6 +133,8 @@ int32_t createStreamPartitionOperatorInfo(SOperatorInfo* downstream, SStreamPart
|
|||
|
||||
int32_t createTimeSliceOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pNode, SExecTaskInfo* pTaskInfo, SOperatorInfo** pInfo);
|
||||
|
||||
int32_t createForecastOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pNode, SExecTaskInfo* pTaskInfo, SOperatorInfo** pInfo);
|
||||
|
||||
int32_t createMergeJoinOperatorInfo(SOperatorInfo** pDownstream, int32_t numOfDownstream, SSortMergeJoinPhysiNode* pJoinNode, SExecTaskInfo* pTaskInfo, SOperatorInfo** pInfo);
|
||||
|
||||
int32_t createHashJoinOperatorInfo(SOperatorInfo** pDownstream, int32_t numOfDownstream, SHashJoinPhysiNode* pJoinNode, SExecTaskInfo* pTaskInfo, SOperatorInfo** pInfo);
|
||||
|
@ -159,6 +161,8 @@ int32_t createCountwindowOperatorInfo(SOperatorInfo* downstream, SPhysiNode* phy
|
|||
|
||||
int32_t createGroupCacheOperatorInfo(SOperatorInfo** pDownstream, int32_t numOfDownstream, SGroupCachePhysiNode* pPhyciNode, SExecTaskInfo* pTaskInfo, SOperatorInfo** pInfo);
|
||||
|
||||
int32_t createAnomalywindowOperatorInfo(SOperatorInfo* downstream, SPhysiNode* physiNode, SExecTaskInfo* pTaskInfo, SOperatorInfo** pInfo);
|
||||
|
||||
int32_t createDynQueryCtrlOperatorInfo(SOperatorInfo** pDownstream, int32_t numOfDownstream, SDynQueryCtrlPhysiNode* pPhyciNode, SExecTaskInfo* pTaskInfo, SOperatorInfo** pInfo);
|
||||
|
||||
// clang-format on
|
||||
|
|
|
@ -0,0 +1,609 @@
|
|||
/*
|
||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
||||
*
|
||||
* This program is free software: you can use, redistribute, and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3
|
||||
* or later ("AGPL"), as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "executorInt.h"
|
||||
#include "filter.h"
|
||||
#include "function.h"
|
||||
#include "functionMgt.h"
|
||||
#include "operator.h"
|
||||
#include "querytask.h"
|
||||
#include "tanal.h"
|
||||
#include "tcommon.h"
|
||||
#include "tcompare.h"
|
||||
#include "tdatablock.h"
|
||||
#include "tjson.h"
|
||||
#include "ttime.h"
|
||||
|
||||
#ifdef USE_ANAL
|
||||
|
||||
typedef struct {
|
||||
SArray* blocks; // SSDataBlock*
|
||||
SArray* windows; // STimeWindow
|
||||
uint64_t groupId;
|
||||
int64_t numOfRows;
|
||||
int32_t curWinIndex;
|
||||
STimeWindow curWin;
|
||||
SResultRow* pResultRow;
|
||||
} SAnomalyWindowSupp;
|
||||
|
||||
typedef struct {
|
||||
SOptrBasicInfo binfo;
|
||||
SAggSupporter aggSup;
|
||||
SExprSupp scalarSup;
|
||||
int32_t tsSlotId;
|
||||
STimeWindowAggSupp twAggSup;
|
||||
char algoName[TSDB_ANAL_ALGO_NAME_LEN];
|
||||
char algoUrl[TSDB_ANAL_ALGO_URL_LEN];
|
||||
char anomalyOpt[TSDB_ANAL_ALGO_OPTION_LEN];
|
||||
SAnomalyWindowSupp anomalySup;
|
||||
SWindowRowsSup anomalyWinRowSup;
|
||||
SColumn anomalyCol;
|
||||
SStateKeys anomalyKey;
|
||||
} SAnomalyWindowOperatorInfo;
|
||||
|
||||
static void anomalyDestroyOperatorInfo(void* param);
|
||||
static int32_t anomalyAggregateNext(SOperatorInfo* pOperator, SSDataBlock** ppRes);
|
||||
static void anomalyAggregateBlocks(SOperatorInfo* pOperator);
|
||||
static int32_t anomalyCacheBlock(SAnomalyWindowOperatorInfo* pInfo, SSDataBlock* pBlock);
|
||||
|
||||
int32_t createAnomalywindowOperatorInfo(SOperatorInfo* downstream, SPhysiNode* physiNode, SExecTaskInfo* pTaskInfo,
|
||||
SOperatorInfo** pOptrInfo) {
|
||||
QRY_PARAM_CHECK(pOptrInfo);
|
||||
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
int32_t lino = 0;
|
||||
SAnomalyWindowOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SAnomalyWindowOperatorInfo));
|
||||
SOperatorInfo* pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
|
||||
SAnomalyWindowPhysiNode* pAnomalyNode = (SAnomalyWindowPhysiNode*)physiNode;
|
||||
SColumnNode* pColNode = (SColumnNode*)(pAnomalyNode->pAnomalyKey);
|
||||
if (pInfo == NULL || pOperator == NULL) {
|
||||
code = terrno;
|
||||
goto _error;
|
||||
}
|
||||
|
||||
if (!taosAnalGetOptStr(pAnomalyNode->anomalyOpt, "algo", pInfo->algoName, sizeof(pInfo->algoName))) {
|
||||
qError("failed to get anomaly_window algorithm name from %s", pAnomalyNode->anomalyOpt);
|
||||
code = TSDB_CODE_ANAL_ALGO_NOT_FOUND;
|
||||
goto _error;
|
||||
}
|
||||
if (taosAnalGetAlgoUrl(pInfo->algoName, ANAL_ALGO_TYPE_ANOMALY_DETECT, pInfo->algoUrl, sizeof(pInfo->algoUrl)) != 0) {
|
||||
qError("failed to get anomaly_window algorithm url from %s", pInfo->algoName);
|
||||
code = TSDB_CODE_ANAL_ALGO_NOT_LOAD;
|
||||
goto _error;
|
||||
}
|
||||
|
||||
pOperator->exprSupp.hasWindowOrGroup = true;
|
||||
pInfo->tsSlotId = ((SColumnNode*)pAnomalyNode->window.pTspk)->slotId;
|
||||
strncpy(pInfo->anomalyOpt, pAnomalyNode->anomalyOpt, sizeof(pInfo->anomalyOpt));
|
||||
|
||||
if (pAnomalyNode->window.pExprs != NULL) {
|
||||
int32_t numOfScalarExpr = 0;
|
||||
SExprInfo* pScalarExprInfo = NULL;
|
||||
code = createExprInfo(pAnomalyNode->window.pExprs, NULL, &pScalarExprInfo, &numOfScalarExpr);
|
||||
QUERY_CHECK_CODE(code, lino, _error);
|
||||
code = initExprSupp(&pInfo->scalarSup, pScalarExprInfo, numOfScalarExpr, &pTaskInfo->storageAPI.functionStore);
|
||||
QUERY_CHECK_CODE(code, lino, _error);
|
||||
}
|
||||
|
||||
size_t keyBufSize = 0;
|
||||
int32_t num = 0;
|
||||
SExprInfo* pExprInfo = NULL;
|
||||
code = createExprInfo(pAnomalyNode->window.pFuncs, NULL, &pExprInfo, &num);
|
||||
QUERY_CHECK_CODE(code, lino, _error);
|
||||
|
||||
initResultSizeInfo(&pOperator->resultInfo, 4096);
|
||||
|
||||
code = initAggSup(&pOperator->exprSupp, &pInfo->aggSup, pExprInfo, num, keyBufSize, pTaskInfo->id.str,
|
||||
pTaskInfo->streamInfo.pState, &pTaskInfo->storageAPI.functionStore);
|
||||
QUERY_CHECK_CODE(code, lino, _error);
|
||||
|
||||
SSDataBlock* pResBlock = createDataBlockFromDescNode(pAnomalyNode->window.node.pOutputDataBlockDesc);
|
||||
QUERY_CHECK_NULL(pResBlock, code, lino, _error, terrno);
|
||||
initBasicInfo(&pInfo->binfo, pResBlock);
|
||||
|
||||
code = blockDataEnsureCapacity(pResBlock, pOperator->resultInfo.capacity);
|
||||
QUERY_CHECK_CODE(code, lino, _error);
|
||||
|
||||
initResultRowInfo(&pInfo->binfo.resultRowInfo);
|
||||
pInfo->binfo.inputTsOrder = pAnomalyNode->window.node.inputTsOrder;
|
||||
pInfo->binfo.outputTsOrder = pAnomalyNode->window.node.outputTsOrder;
|
||||
|
||||
pInfo->anomalyCol = extractColumnFromColumnNode(pColNode);
|
||||
pInfo->anomalyKey.type = pInfo->anomalyCol.type;
|
||||
pInfo->anomalyKey.bytes = pInfo->anomalyCol.bytes;
|
||||
pInfo->anomalyKey.pData = taosMemoryCalloc(1, pInfo->anomalyCol.bytes);
|
||||
if (pInfo->anomalyKey.pData == NULL) {
|
||||
goto _error;
|
||||
}
|
||||
|
||||
int32_t itemSize = sizeof(int32_t) + pInfo->aggSup.resultRowSize + pInfo->anomalyKey.bytes;
|
||||
pInfo->anomalySup.pResultRow = taosMemoryCalloc(1, itemSize);
|
||||
pInfo->anomalySup.blocks = taosArrayInit(16, sizeof(SSDataBlock*));
|
||||
pInfo->anomalySup.windows = taosArrayInit(16, sizeof(STimeWindow));
|
||||
|
||||
if (pInfo->anomalySup.windows == NULL || pInfo->anomalySup.blocks == NULL || pInfo->anomalySup.pResultRow == NULL) {
|
||||
code = TSDB_CODE_OUT_OF_MEMORY;
|
||||
goto _error;
|
||||
}
|
||||
|
||||
code = filterInitFromNode((SNode*)pAnomalyNode->window.node.pConditions, &pOperator->exprSupp.pFilterInfo, 0);
|
||||
QUERY_CHECK_CODE(code, lino, _error);
|
||||
|
||||
code = initExecTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &pTaskInfo->window);
|
||||
QUERY_CHECK_CODE(code, lino, _error);
|
||||
|
||||
setOperatorInfo(pOperator, "AnomalyWindowOperator", QUERY_NODE_PHYSICAL_PLAN_MERGE_ANOMALY, true, OP_NOT_OPENED,
|
||||
pInfo, pTaskInfo);
|
||||
pOperator->fpSet = createOperatorFpSet(optrDummyOpenFn, anomalyAggregateNext, NULL, anomalyDestroyOperatorInfo,
|
||||
optrDefaultBufFn, NULL, optrDefaultGetNextExtFn, NULL);
|
||||
|
||||
code = appendDownstream(pOperator, &downstream, 1);
|
||||
QUERY_CHECK_CODE(code, lino, _error);
|
||||
|
||||
*pOptrInfo = pOperator;
|
||||
|
||||
qDebug("anomaly_window operator is created, algo:%s url:%s opt:%s", pInfo->algoName, pInfo->algoUrl,
|
||||
pInfo->anomalyOpt);
|
||||
return TSDB_CODE_SUCCESS;
|
||||
|
||||
_error:
|
||||
if (pInfo != NULL) {
|
||||
anomalyDestroyOperatorInfo(pInfo);
|
||||
}
|
||||
|
||||
destroyOperatorAndDownstreams(pOperator, &downstream, 1);
|
||||
pTaskInfo->code = code;
|
||||
qError("failed to create anomaly_window operator, algo:%s code:0x%x", pInfo->algoName, code);
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t anomalyAggregateNext(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
int32_t lino = 0;
|
||||
SAnomalyWindowOperatorInfo* pInfo = pOperator->info;
|
||||
SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
|
||||
SOptrBasicInfo* pBInfo = &pInfo->binfo;
|
||||
SAnomalyWindowSupp* pSupp = &pInfo->anomalySup;
|
||||
SSDataBlock* pRes = pInfo->binfo.pRes;
|
||||
int64_t st = taosGetTimestampUs();
|
||||
int32_t numOfBlocks = taosArrayGetSize(pSupp->blocks);
|
||||
|
||||
blockDataCleanup(pRes);
|
||||
|
||||
while (1) {
|
||||
SSDataBlock* pBlock = getNextBlockFromDownstream(pOperator, 0);
|
||||
if (pBlock == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (pSupp->groupId == 0 || pSupp->groupId == pBlock->info.id.groupId) {
|
||||
pSupp->groupId = pBlock->info.id.groupId;
|
||||
numOfBlocks++;
|
||||
qDebug("group:%" PRId64 ", blocks:%d, cache block rows:%" PRId64, pSupp->groupId, numOfBlocks, pBlock->info.rows);
|
||||
code = anomalyCacheBlock(pInfo, pBlock);
|
||||
QUERY_CHECK_CODE(code, lino, _end);
|
||||
} else {
|
||||
qDebug("group:%" PRId64 ", read finish for new group coming, blocks:%d", pSupp->groupId, numOfBlocks);
|
||||
anomalyAggregateBlocks(pOperator);
|
||||
pSupp->groupId = pBlock->info.id.groupId;
|
||||
numOfBlocks = 1;
|
||||
qDebug("group:%" PRId64 ", new group, cache block rows:%" PRId64, pSupp->groupId, pBlock->info.rows);
|
||||
code = anomalyCacheBlock(pInfo, pBlock);
|
||||
QUERY_CHECK_CODE(code, lino, _end);
|
||||
}
|
||||
|
||||
if (pRes->info.rows > 0) {
|
||||
(*ppRes) = pRes;
|
||||
qDebug("group:%" PRId64 ", return to upstream, blocks:%d", pRes->info.id.groupId, numOfBlocks);
|
||||
return code;
|
||||
}
|
||||
}
|
||||
|
||||
if (numOfBlocks > 0) {
|
||||
qDebug("group:%" PRId64 ", read finish, blocks:%d", pInfo->anomalySup.groupId, numOfBlocks);
|
||||
anomalyAggregateBlocks(pOperator);
|
||||
}
|
||||
|
||||
int64_t cost = taosGetTimestampUs() - st;
|
||||
qDebug("all groups finished, cost:%" PRId64 "us", cost);
|
||||
|
||||
_end:
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
|
||||
pTaskInfo->code = code;
|
||||
T_LONG_JMP(pTaskInfo->env, code);
|
||||
}
|
||||
(*ppRes) = (pBInfo->pRes->info.rows == 0) ? NULL : pBInfo->pRes;
|
||||
return code;
|
||||
}
|
||||
|
||||
static void anomalyDestroyOperatorInfo(void* param) {
|
||||
SAnomalyWindowOperatorInfo* pInfo = (SAnomalyWindowOperatorInfo*)param;
|
||||
if (pInfo == NULL) return;
|
||||
|
||||
qDebug("anomaly_window operator is destroyed, algo:%s", pInfo->algoName);
|
||||
|
||||
cleanupBasicInfo(&pInfo->binfo);
|
||||
cleanupAggSup(&pInfo->aggSup);
|
||||
cleanupExprSupp(&pInfo->scalarSup);
|
||||
colDataDestroy(&pInfo->twAggSup.timeWindowData);
|
||||
|
||||
for (int32_t i = 0; i < taosArrayGetSize(pInfo->anomalySup.blocks); ++i) {
|
||||
SSDataBlock* pBlock = taosArrayGetP(pInfo->anomalySup.blocks, i);
|
||||
blockDataDestroy(pBlock);
|
||||
}
|
||||
taosArrayDestroy(pInfo->anomalySup.blocks);
|
||||
taosArrayDestroy(pInfo->anomalySup.windows);
|
||||
taosMemoryFreeClear(pInfo->anomalySup.pResultRow);
|
||||
taosMemoryFreeClear(pInfo->anomalyKey.pData);
|
||||
|
||||
taosMemoryFreeClear(param);
|
||||
}
|
||||
|
||||
static int32_t anomalyCacheBlock(SAnomalyWindowOperatorInfo* pInfo, SSDataBlock* pSrc) {
|
||||
SSDataBlock* pDst = NULL;
|
||||
int32_t code = createOneDataBlock(pSrc, true, &pDst);
|
||||
|
||||
if (code != 0) return code;
|
||||
if (pDst == NULL) return TSDB_CODE_OUT_OF_MEMORY;
|
||||
if (taosArrayPush(pInfo->anomalySup.blocks, &pDst) == NULL) return TSDB_CODE_OUT_OF_MEMORY;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t anomalyFindWindow(SAnomalyWindowSupp* pSupp, TSKEY key) {
|
||||
for (int32_t i = pSupp->curWinIndex; i < taosArrayGetSize(pSupp->windows); ++i) {
|
||||
STimeWindow* pWindow = taosArrayGet(pSupp->windows, i);
|
||||
if (key >= pWindow->skey && key < pWindow->ekey) {
|
||||
pSupp->curWin = *pWindow;
|
||||
pSupp->curWinIndex = i;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int32_t anomalyParseJson(SJson* pJson, SArray* pWindows) {
|
||||
int32_t code = 0;
|
||||
int32_t rows = 0;
|
||||
STimeWindow win = {0};
|
||||
|
||||
taosArrayClear(pWindows);
|
||||
|
||||
tjsonGetInt32ValueFromDouble(pJson, "rows", rows, code);
|
||||
if (code < 0) return TSDB_CODE_INVALID_JSON_FORMAT;
|
||||
if (rows <= 0) return 0;
|
||||
|
||||
SJson* res = tjsonGetObjectItem(pJson, "res");
|
||||
if (res == NULL) return TSDB_CODE_INVALID_JSON_FORMAT;
|
||||
|
||||
int32_t ressize = tjsonGetArraySize(res);
|
||||
if (ressize != rows) return TSDB_CODE_INVALID_JSON_FORMAT;
|
||||
|
||||
for (int32_t i = 0; i < rows; ++i) {
|
||||
SJson* row = tjsonGetArrayItem(res, i);
|
||||
if (row == NULL) return TSDB_CODE_INVALID_JSON_FORMAT;
|
||||
|
||||
int32_t colsize = tjsonGetArraySize(row);
|
||||
if (colsize != 2) return TSDB_CODE_INVALID_JSON_FORMAT;
|
||||
|
||||
SJson* start = tjsonGetArrayItem(row, 0);
|
||||
SJson* end = tjsonGetArrayItem(row, 1);
|
||||
if (start == NULL || end == NULL) return TSDB_CODE_INVALID_JSON_FORMAT;
|
||||
|
||||
tjsonGetObjectValueBigInt(start, &win.skey);
|
||||
tjsonGetObjectValueBigInt(end, &win.ekey);
|
||||
|
||||
if (win.skey >= win.ekey) {
|
||||
win.ekey = win.skey + 1;
|
||||
}
|
||||
|
||||
if (taosArrayPush(pWindows, &win) == NULL) return TSDB_CODE_OUT_OF_BUFFER;
|
||||
}
|
||||
|
||||
int32_t numOfWins = taosArrayGetSize(pWindows);
|
||||
qDebug("anomaly window recevied, total:%d", numOfWins);
|
||||
for (int32_t i = 0; i < numOfWins; ++i) {
|
||||
STimeWindow* pWindow = taosArrayGet(pWindows, i);
|
||||
qDebug("anomaly win:%d [%" PRId64 ", %" PRId64 ")", i, pWindow->skey, pWindow->ekey);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t anomalyAnalysisWindow(SOperatorInfo* pOperator) {
|
||||
SAnomalyWindowOperatorInfo* pInfo = pOperator->info;
|
||||
SAnomalyWindowSupp* pSupp = &pInfo->anomalySup;
|
||||
SJson* pJson = NULL;
|
||||
SAnalBuf analBuf = {.bufType = ANAL_BUF_TYPE_JSON};
|
||||
char dataBuf[64] = {0};
|
||||
int32_t code = 0;
|
||||
|
||||
int64_t ts = 0;
|
||||
// int64_t ts = taosGetTimestampMs();
|
||||
snprintf(analBuf.fileName, sizeof(analBuf.fileName), "%s/tdengine-anomaly-%" PRId64 "-%" PRId64, tsTempDir, ts,
|
||||
pSupp->groupId);
|
||||
code = tsosAnalBufOpen(&analBuf, 2);
|
||||
if (code != 0) goto _OVER;
|
||||
|
||||
const char* prec = TSDB_TIME_PRECISION_MILLI_STR;
|
||||
if (pInfo->anomalyCol.precision == TSDB_TIME_PRECISION_MICRO) prec = TSDB_TIME_PRECISION_MICRO_STR;
|
||||
if (pInfo->anomalyCol.precision == TSDB_TIME_PRECISION_NANO) prec = TSDB_TIME_PRECISION_NANO_STR;
|
||||
|
||||
code = taosAnalBufWriteOptStr(&analBuf, "algo", pInfo->algoName);
|
||||
if (code != 0) goto _OVER;
|
||||
|
||||
code = taosAnalBufWriteOptStr(&analBuf, "prec", prec);
|
||||
if (code != 0) goto _OVER;
|
||||
|
||||
code = taosAnalBufWriteColMeta(&analBuf, 0, TSDB_DATA_TYPE_TIMESTAMP, "ts");
|
||||
if (code != 0) goto _OVER;
|
||||
|
||||
code = taosAnalBufWriteColMeta(&analBuf, 1, pInfo->anomalyCol.type, "val");
|
||||
if (code != 0) goto _OVER;
|
||||
|
||||
code = taosAnalBufWriteDataBegin(&analBuf);
|
||||
if (code != 0) goto _OVER;
|
||||
|
||||
int32_t numOfBlocks = (int32_t)taosArrayGetSize(pSupp->blocks);
|
||||
|
||||
// timestamp
|
||||
code = taosAnalBufWriteColBegin(&analBuf, 0);
|
||||
if (code != 0) goto _OVER;
|
||||
for (int32_t i = 0; i < numOfBlocks; ++i) {
|
||||
SSDataBlock* pBlock = taosArrayGetP(pSupp->blocks, i);
|
||||
if (pBlock == NULL) break;
|
||||
SColumnInfoData* pTsCol = taosArrayGet(pBlock->pDataBlock, pInfo->tsSlotId);
|
||||
if (pTsCol == NULL) break;
|
||||
for (int32_t j = 0; j < pBlock->info.rows; ++j) {
|
||||
code = taosAnalBufWriteColData(&analBuf, 0, TSDB_DATA_TYPE_TIMESTAMP, &((TSKEY*)pTsCol->pData)[j]);
|
||||
if (code != 0) goto _OVER;
|
||||
}
|
||||
}
|
||||
code = taosAnalBufWriteColEnd(&analBuf, 0);
|
||||
if (code != 0) goto _OVER;
|
||||
|
||||
// data
|
||||
code = taosAnalBufWriteColBegin(&analBuf, 1);
|
||||
if (code != 0) goto _OVER;
|
||||
for (int32_t i = 0; i < numOfBlocks; ++i) {
|
||||
SSDataBlock* pBlock = taosArrayGetP(pSupp->blocks, i);
|
||||
if (pBlock == NULL) break;
|
||||
SColumnInfoData* pValCol = taosArrayGet(pBlock->pDataBlock, pInfo->anomalyCol.slotId);
|
||||
if (pValCol == NULL) break;
|
||||
|
||||
for (int32_t j = 0; j < pBlock->info.rows; ++j) {
|
||||
code = taosAnalBufWriteColData(&analBuf, 1, pValCol->info.type, colDataGetData(pValCol, j));
|
||||
if (code != 0) goto _OVER;
|
||||
if (code != 0) goto _OVER;
|
||||
}
|
||||
}
|
||||
code = taosAnalBufWriteColEnd(&analBuf, 1);
|
||||
if (code != 0) goto _OVER;
|
||||
|
||||
code = taosAnalBufWriteDataEnd(&analBuf);
|
||||
if (code != 0) goto _OVER;
|
||||
|
||||
code = taosAnalBufWriteOptStr(&analBuf, "option", pInfo->anomalyOpt);
|
||||
if (code != 0) goto _OVER;
|
||||
|
||||
code = taosAnalBufClose(&analBuf);
|
||||
if (code != 0) goto _OVER;
|
||||
|
||||
pJson = taosAnalSendReqRetJson(pInfo->algoUrl, ANAL_HTTP_TYPE_POST, &analBuf);
|
||||
if (pJson == NULL) {
|
||||
code = terrno;
|
||||
goto _OVER;
|
||||
}
|
||||
|
||||
code = anomalyParseJson(pJson, pSupp->windows);
|
||||
if (code != 0) goto _OVER;
|
||||
|
||||
_OVER:
|
||||
if (code != 0) {
|
||||
qError("failed to analysis window since %s", tstrerror(code));
|
||||
}
|
||||
taosAnalBufDestroy(&analBuf);
|
||||
if (pJson != NULL) tjsonDelete(pJson);
|
||||
return code;
|
||||
}
|
||||
|
||||
static void anomalyAggregateRows(SOperatorInfo* pOperator, SSDataBlock* pBlock) {
|
||||
SAnomalyWindowOperatorInfo* pInfo = pOperator->info;
|
||||
SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
|
||||
SExprSupp* pExprSup = &pOperator->exprSupp;
|
||||
SAnomalyWindowSupp* pSupp = &pInfo->anomalySup;
|
||||
SWindowRowsSup* pRowSup = &pInfo->anomalyWinRowSup;
|
||||
SResultRow* pResRow = pSupp->pResultRow;
|
||||
int32_t numOfOutput = pOperator->exprSupp.numOfExprs;
|
||||
|
||||
if (setResultRowInitCtx(pResRow, pExprSup->pCtx, pExprSup->numOfExprs, pExprSup->rowEntryInfoOffset) == 0) {
|
||||
updateTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &pSupp->curWin, 0);
|
||||
applyAggFunctionOnPartialTuples(pTaskInfo, pExprSup->pCtx, &pInfo->twAggSup.timeWindowData, pRowSup->startRowIndex,
|
||||
pRowSup->numOfRows, pBlock->info.rows, numOfOutput);
|
||||
}
|
||||
}
|
||||
|
||||
static void anomalyBuildResult(SOperatorInfo* pOperator) {
|
||||
SAnomalyWindowOperatorInfo* pInfo = pOperator->info;
|
||||
SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
|
||||
SExprSupp* pExprSup = &pOperator->exprSupp;
|
||||
SSDataBlock* pRes = pInfo->binfo.pRes;
|
||||
SResultRow* pResRow = pInfo->anomalySup.pResultRow;
|
||||
|
||||
doUpdateNumOfRows(pExprSup->pCtx, pResRow, pExprSup->numOfExprs, pExprSup->rowEntryInfoOffset);
|
||||
copyResultrowToDataBlock(pExprSup->pExprInfo, pExprSup->numOfExprs, pResRow, pExprSup->pCtx, pRes,
|
||||
pExprSup->rowEntryInfoOffset, pTaskInfo);
|
||||
pRes->info.rows += pResRow->numOfRows;
|
||||
clearResultRowInitFlag(pExprSup->pCtx, pExprSup->numOfExprs);
|
||||
}
|
||||
|
||||
static void anomalyAggregateBlocks(SOperatorInfo* pOperator) {
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
int32_t lino = 0;
|
||||
SAnomalyWindowOperatorInfo* pInfo = pOperator->info;
|
||||
SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
|
||||
SExprSupp* pExprSup = &pOperator->exprSupp;
|
||||
SSDataBlock* pRes = pInfo->binfo.pRes;
|
||||
SAnomalyWindowSupp* pSupp = &pInfo->anomalySup;
|
||||
SWindowRowsSup* pRowSup = &pInfo->anomalyWinRowSup;
|
||||
SResultRow* pResRow = pSupp->pResultRow;
|
||||
int32_t numOfOutput = pOperator->exprSupp.numOfExprs;
|
||||
int32_t rowsInWin = 0;
|
||||
int32_t rowsInBlock = 0;
|
||||
const int64_t gid = pSupp->groupId;
|
||||
const int32_t order = pInfo->binfo.inputTsOrder;
|
||||
|
||||
int32_t numOfBlocks = (int32_t)taosArrayGetSize(pSupp->blocks);
|
||||
if (numOfBlocks == 0) goto _OVER;
|
||||
|
||||
qDebug("group:%" PRId64 ", aggregate blocks, blocks:%d", pSupp->groupId, numOfBlocks);
|
||||
pRes->info.id.groupId = pSupp->groupId;
|
||||
|
||||
code = anomalyAnalysisWindow(pOperator);
|
||||
QUERY_CHECK_CODE(code, lino, _OVER);
|
||||
|
||||
int32_t numOfWins = taosArrayGetSize(pSupp->windows);
|
||||
qDebug("group:%" PRId64 ", wins:%d, rows:%" PRId64, pSupp->groupId, numOfWins, pSupp->numOfRows);
|
||||
for (int32_t w = 0; w < numOfWins; ++w) {
|
||||
STimeWindow* pWindow = taosArrayGet(pSupp->windows, w);
|
||||
if (w == 0) {
|
||||
pSupp->curWin = *pWindow;
|
||||
pRowSup->win.skey = pSupp->curWin.skey;
|
||||
}
|
||||
qDebug("group:%" PRId64 ", win:%d [%" PRId64 ", %" PRId64 ")", pSupp->groupId, w, pWindow->skey, pWindow->ekey);
|
||||
}
|
||||
|
||||
if (numOfWins <= 0) goto _OVER;
|
||||
if (numOfWins > pRes->info.capacity) {
|
||||
code = blockDataEnsureCapacity(pRes, numOfWins);
|
||||
QUERY_CHECK_CODE(code, lino, _OVER);
|
||||
}
|
||||
|
||||
for (int32_t b = 0; b < numOfBlocks; ++b) {
|
||||
SSDataBlock* pBlock = taosArrayGetP(pSupp->blocks, b);
|
||||
if (pBlock == NULL) break;
|
||||
|
||||
pRes->info.scanFlag = pBlock->info.scanFlag;
|
||||
code = setInputDataBlock(pExprSup, pBlock, order, MAIN_SCAN, true);
|
||||
if (code != 0) break;
|
||||
|
||||
code = blockDataUpdateTsWindow(pBlock, pInfo->tsSlotId);
|
||||
if (code != 0) break;
|
||||
|
||||
// there is an scalar expression that needs to be calculated right before apply the group aggregation.
|
||||
if (pInfo->scalarSup.pExprInfo != NULL) {
|
||||
code = projectApplyFunctions(pInfo->scalarSup.pExprInfo, pBlock, pBlock, pInfo->scalarSup.pCtx,
|
||||
pInfo->scalarSup.numOfExprs, NULL);
|
||||
if (code != 0) break;
|
||||
}
|
||||
|
||||
SColumnInfoData* pValCol = taosArrayGet(pBlock->pDataBlock, pInfo->anomalyCol.slotId);
|
||||
if (pValCol == NULL) break;
|
||||
SColumnInfoData* pTsCol = taosArrayGet(pBlock->pDataBlock, pInfo->tsSlotId);
|
||||
if (pTsCol == NULL) break;
|
||||
TSKEY* tsList = (TSKEY*)pTsCol->pData;
|
||||
bool lastBlock = (b == numOfBlocks - 1);
|
||||
|
||||
qTrace("group:%" PRId64 ", block:%d win:%d, riwin:%d riblock:%d, rows:%" PRId64, pSupp->groupId, b,
|
||||
pSupp->curWinIndex, rowsInWin, rowsInBlock, pBlock->info.rows);
|
||||
|
||||
for (int32_t r = 0; r < pBlock->info.rows; ++r) {
|
||||
TSKEY key = tsList[r];
|
||||
bool keyInWin = (key >= pSupp->curWin.skey && key < pSupp->curWin.ekey);
|
||||
bool lastRow = (r == pBlock->info.rows - 1);
|
||||
|
||||
if (keyInWin) {
|
||||
if (r < 5) {
|
||||
qTrace("group:%" PRId64 ", block:%d win:%d, row:%d ts:%" PRId64 ", riwin:%d riblock:%d", pSupp->groupId, b,
|
||||
pSupp->curWinIndex, r, key, rowsInWin, rowsInBlock);
|
||||
}
|
||||
if (rowsInBlock == 0) {
|
||||
doKeepNewWindowStartInfo(pRowSup, tsList, r, gid);
|
||||
}
|
||||
doKeepTuple(pRowSup, tsList[r], gid);
|
||||
rowsInBlock++;
|
||||
rowsInWin++;
|
||||
} else {
|
||||
if (rowsInBlock > 0) {
|
||||
qTrace("group:%" PRId64 ", block:%d win:%d, row:%d ts:%" PRId64 ", riwin:%d riblock:%d, agg", pSupp->groupId,
|
||||
b, pSupp->curWinIndex, r, key, rowsInWin, rowsInBlock);
|
||||
anomalyAggregateRows(pOperator, pBlock);
|
||||
rowsInBlock = 0;
|
||||
}
|
||||
if (rowsInWin > 0) {
|
||||
qTrace("group:%" PRId64 ", block:%d win:%d, row:%d ts:%" PRId64 ", riwin:%d riblock:%d, build result",
|
||||
pSupp->groupId, b, pSupp->curWinIndex, r, key, rowsInWin, rowsInBlock);
|
||||
anomalyBuildResult(pOperator);
|
||||
rowsInWin = 0;
|
||||
}
|
||||
if (anomalyFindWindow(pSupp, tsList[r]) == 0) {
|
||||
qTrace("group:%" PRId64 ", block:%d win:%d, row:%d ts:%" PRId64 ", riwin:%d riblock:%d, new window detect",
|
||||
pSupp->groupId, b, pSupp->curWinIndex, r, key, rowsInWin, rowsInBlock);
|
||||
doKeepNewWindowStartInfo(pRowSup, tsList, r, gid);
|
||||
doKeepTuple(pRowSup, tsList[r], gid);
|
||||
rowsInBlock = 1;
|
||||
rowsInWin = 1;
|
||||
} else {
|
||||
qTrace("group:%" PRId64 ", block:%d win:%d, row:%d ts:%" PRId64 ", riwin:%d riblock:%d, window not found",
|
||||
pSupp->groupId, b, pSupp->curWinIndex, r, key, rowsInWin, rowsInBlock);
|
||||
rowsInBlock = 0;
|
||||
rowsInWin = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (lastRow && rowsInBlock > 0) {
|
||||
qTrace("group:%" PRId64 ", block:%d win:%d, row:%d ts:%" PRId64 ", riwin:%d riblock:%d, agg since lastrow",
|
||||
pSupp->groupId, b, pSupp->curWinIndex, r, key, rowsInWin, rowsInBlock);
|
||||
anomalyAggregateRows(pOperator, pBlock);
|
||||
rowsInBlock = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (lastBlock && rowsInWin > 0) {
|
||||
qTrace("group:%" PRId64 ", block:%d win:%d, riwin:%d riblock:%d, build result since lastblock", pSupp->groupId, b,
|
||||
pSupp->curWinIndex, rowsInWin, rowsInBlock);
|
||||
anomalyBuildResult(pOperator);
|
||||
rowsInWin = 0;
|
||||
}
|
||||
}
|
||||
|
||||
code = doFilter(pRes, pOperator->exprSupp.pFilterInfo, NULL);
|
||||
QUERY_CHECK_CODE(code, lino, _OVER);
|
||||
|
||||
_OVER:
|
||||
for (int32_t i = 0; i < numOfBlocks; ++i) {
|
||||
SSDataBlock* pBlock = taosArrayGetP(pSupp->blocks, i);
|
||||
qDebug("%s, clear block, pBlock:%p pBlock->pDataBlock:%p", __func__, pBlock, pBlock->pDataBlock);
|
||||
blockDataDestroy(pBlock);
|
||||
}
|
||||
|
||||
taosArrayClear(pSupp->blocks);
|
||||
taosArrayClear(pSupp->windows);
|
||||
pSupp->numOfRows = 0;
|
||||
pSupp->curWin.ekey = 0;
|
||||
pSupp->curWin.skey = 0;
|
||||
pSupp->curWinIndex = 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int32_t createAnomalywindowOperatorInfo(SOperatorInfo* downstream, SPhysiNode* physiNode, SExecTaskInfo* pTaskInfo,
|
||||
SOperatorInfo** pOptrInfo) {
|
||||
return TSDB_CODE_OPS_NOT_SUPPORT;
|
||||
}
|
||||
void destroyForecastInfo(void* param) {}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,663 @@
|
|||
/*
|
||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
||||
*
|
||||
* This program is free software: you can use, redistribute, and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3
|
||||
* or later ("AGPL"), as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "executorInt.h"
|
||||
#include "filter.h"
|
||||
#include "function.h"
|
||||
#include "functionMgt.h"
|
||||
#include "operator.h"
|
||||
#include "querytask.h"
|
||||
#include "storageapi.h"
|
||||
#include "tanal.h"
|
||||
#include "tcommon.h"
|
||||
#include "tcompare.h"
|
||||
#include "tdatablock.h"
|
||||
#include "tfill.h"
|
||||
#include "ttime.h"
|
||||
|
||||
#ifdef USE_ANAL
|
||||
|
||||
typedef struct {
|
||||
char algoName[TSDB_ANAL_ALGO_NAME_LEN];
|
||||
char algoUrl[TSDB_ANAL_ALGO_URL_LEN];
|
||||
char algoOpt[TSDB_ANAL_ALGO_OPTION_LEN];
|
||||
int64_t maxTs;
|
||||
int64_t minTs;
|
||||
int64_t numOfRows;
|
||||
uint64_t groupId;
|
||||
int32_t numOfBlocks;
|
||||
int32_t optRows;
|
||||
int16_t resTsSlot;
|
||||
int16_t resValSlot;
|
||||
int16_t resLowSlot;
|
||||
int16_t resHighSlot;
|
||||
int16_t inputTsSlot;
|
||||
int16_t inputValSlot;
|
||||
int8_t inputValType;
|
||||
int8_t inputPrecision;
|
||||
SAnalBuf analBuf;
|
||||
} SForecastSupp;
|
||||
|
||||
typedef struct SForecastOperatorInfo {
|
||||
SSDataBlock* pRes;
|
||||
SExprSupp scalarSup; // scalar calculation
|
||||
SForecastSupp forecastSupp;
|
||||
} SForecastOperatorInfo;
|
||||
|
||||
static void destroyForecastInfo(void* param);
|
||||
|
||||
static FORCE_INLINE int32_t forecastEnsureBlockCapacity(SSDataBlock* pBlock, int32_t newRowsNum) {
|
||||
if (pBlock->info.rows < pBlock->info.capacity) {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t code = blockDataEnsureCapacity(pBlock, newRowsNum);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code));
|
||||
return code;
|
||||
}
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t forecastCacheBlock(SForecastSupp* pSupp, SSDataBlock* pBlock) {
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
int32_t lino = 0;
|
||||
SAnalBuf* pBuf = &pSupp->analBuf;
|
||||
|
||||
qDebug("block:%d, %p rows:%" PRId64, pSupp->numOfBlocks, pBlock, pBlock->info.rows);
|
||||
pSupp->numOfBlocks++;
|
||||
|
||||
for (int32_t j = 0; j < pBlock->info.rows; ++j) {
|
||||
SColumnInfoData* pValCol = taosArrayGet(pBlock->pDataBlock, pSupp->inputValSlot);
|
||||
SColumnInfoData* pTsCol = taosArrayGet(pBlock->pDataBlock, pSupp->inputTsSlot);
|
||||
if (pTsCol == NULL || pValCol == NULL) break;
|
||||
|
||||
int64_t ts = ((TSKEY*)pTsCol->pData)[j];
|
||||
char* val = colDataGetData(pValCol, j);
|
||||
int16_t valType = pValCol->info.type;
|
||||
|
||||
pSupp->minTs = MIN(pSupp->minTs, ts);
|
||||
pSupp->maxTs = MAX(pSupp->maxTs, ts);
|
||||
pSupp->numOfRows++;
|
||||
|
||||
code = taosAnalBufWriteColData(pBuf, 0, TSDB_DATA_TYPE_TIMESTAMP, &ts);
|
||||
if (TSDB_CODE_SUCCESS != code) return code;
|
||||
|
||||
code = taosAnalBufWriteColData(pBuf, 1, valType, val);
|
||||
if (TSDB_CODE_SUCCESS != code) return code;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t forecastCloseBuf(SForecastSupp* pSupp) {
|
||||
SAnalBuf* pBuf = &pSupp->analBuf;
|
||||
int32_t code = 0;
|
||||
|
||||
for (int32_t i = 0; i < 2; ++i) {
|
||||
code = taosAnalBufWriteColEnd(pBuf, i);
|
||||
if (code != 0) return code;
|
||||
}
|
||||
|
||||
code = taosAnalBufWriteDataEnd(pBuf);
|
||||
if (code != 0) return code;
|
||||
|
||||
int32_t len = strlen(pSupp->algoOpt);
|
||||
int64_t every = (pSupp->maxTs - pSupp->minTs) / (pSupp->numOfRows + 1);
|
||||
int64_t start = pSupp->maxTs + every;
|
||||
bool hasStart = taosAnalGetOptStr(pSupp->algoOpt, "start", NULL, 0);
|
||||
if (!hasStart) {
|
||||
qDebug("forecast start not found from %s, use %" PRId64, pSupp->algoOpt, start);
|
||||
code = taosAnalBufWriteOptInt(pBuf, "start", start);
|
||||
if (code != 0) return code;
|
||||
}
|
||||
|
||||
bool hasEvery = taosAnalGetOptStr(pSupp->algoOpt, "every", NULL, 0);
|
||||
if (!hasEvery) {
|
||||
qDebug("forecast every not found from %s, use %" PRId64, pSupp->algoOpt, every);
|
||||
code = taosAnalBufWriteOptInt(pBuf, "every", every);
|
||||
if (code != 0) return code;
|
||||
}
|
||||
|
||||
code = taosAnalBufWriteOptStr(pBuf, "option", pSupp->algoOpt);
|
||||
if (code != 0) return code;
|
||||
|
||||
code = taosAnalBufClose(pBuf);
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t forecastAnalysis(SForecastSupp* pSupp, SSDataBlock* pBlock) {
|
||||
SAnalBuf* pBuf = &pSupp->analBuf;
|
||||
int32_t resCurRow = pBlock->info.rows;
|
||||
int8_t tmpI8;
|
||||
int16_t tmpI16;
|
||||
int32_t tmpI32;
|
||||
int64_t tmpI64;
|
||||
float tmpFloat;
|
||||
double tmpDouble;
|
||||
int32_t code = 0;
|
||||
|
||||
SColumnInfoData* pResValCol = taosArrayGet(pBlock->pDataBlock, pSupp->resValSlot);
|
||||
if (NULL == pResValCol) return TSDB_CODE_OUT_OF_RANGE;
|
||||
|
||||
SColumnInfoData* pResTsCol = (pSupp->resTsSlot != -1 ? taosArrayGet(pBlock->pDataBlock, pSupp->resTsSlot) : NULL);
|
||||
SColumnInfoData* pResLowCol = (pSupp->resLowSlot != -1 ? taosArrayGet(pBlock->pDataBlock, pSupp->resLowSlot) : NULL);
|
||||
SColumnInfoData* pResHighCol =
|
||||
(pSupp->resHighSlot != -1 ? taosArrayGet(pBlock->pDataBlock, pSupp->resHighSlot) : NULL);
|
||||
|
||||
SJson* pJson = taosAnalSendReqRetJson(pSupp->algoUrl, ANAL_HTTP_TYPE_POST, pBuf);
|
||||
if (pJson == NULL) return terrno;
|
||||
|
||||
int32_t rows = 0;
|
||||
tjsonGetInt32ValueFromDouble(pJson, "rows", rows, code);
|
||||
if (code < 0) goto _OVER;
|
||||
if (rows <= 0) goto _OVER;
|
||||
|
||||
SJson* res = tjsonGetObjectItem(pJson, "res");
|
||||
if (res == NULL) goto _OVER;
|
||||
int32_t ressize = tjsonGetArraySize(res);
|
||||
bool returnConf = (pSupp->resHighSlot != -1 || pSupp->resLowSlot != -1);
|
||||
if (returnConf) {
|
||||
if (ressize != 4) goto _OVER;
|
||||
} else if (ressize != 2) {
|
||||
goto _OVER;
|
||||
}
|
||||
|
||||
if (pResTsCol != NULL) {
|
||||
resCurRow = pBlock->info.rows;
|
||||
SJson* tsJsonArray = tjsonGetArrayItem(res, 0);
|
||||
if (tsJsonArray == NULL) goto _OVER;
|
||||
int32_t tsSize = tjsonGetArraySize(tsJsonArray);
|
||||
if (tsSize != rows) goto _OVER;
|
||||
for (int32_t i = 0; i < tsSize; ++i) {
|
||||
SJson* tsJson = tjsonGetArrayItem(tsJsonArray, i);
|
||||
tjsonGetObjectValueBigInt(tsJson, &tmpI64);
|
||||
colDataSetInt64(pResTsCol, resCurRow, &tmpI64);
|
||||
resCurRow++;
|
||||
}
|
||||
}
|
||||
|
||||
if (pResLowCol != NULL) {
|
||||
resCurRow = pBlock->info.rows;
|
||||
SJson* lowJsonArray = tjsonGetArrayItem(res, 2);
|
||||
if (lowJsonArray == NULL) goto _OVER;
|
||||
int32_t lowSize = tjsonGetArraySize(lowJsonArray);
|
||||
if (lowSize != rows) goto _OVER;
|
||||
for (int32_t i = 0; i < lowSize; ++i) {
|
||||
SJson* lowJson = tjsonGetArrayItem(lowJsonArray, i);
|
||||
tjsonGetObjectValueDouble(lowJson, &tmpDouble);
|
||||
tmpFloat = (float)tmpDouble;
|
||||
colDataSetFloat(pResLowCol, resCurRow, &tmpFloat);
|
||||
resCurRow++;
|
||||
}
|
||||
}
|
||||
|
||||
if (pResHighCol != NULL) {
|
||||
resCurRow = pBlock->info.rows;
|
||||
SJson* highJsonArray = tjsonGetArrayItem(res, 3);
|
||||
if (highJsonArray == NULL) goto _OVER;
|
||||
int32_t highSize = tjsonGetArraySize(highJsonArray);
|
||||
if (highSize != rows) goto _OVER;
|
||||
for (int32_t i = 0; i < highSize; ++i) {
|
||||
SJson* highJson = tjsonGetArrayItem(highJsonArray, i);
|
||||
tjsonGetObjectValueDouble(highJson, &tmpDouble);
|
||||
tmpFloat = (float)tmpDouble;
|
||||
colDataSetFloat(pResHighCol, resCurRow, &tmpFloat);
|
||||
resCurRow++;
|
||||
}
|
||||
}
|
||||
|
||||
resCurRow = pBlock->info.rows;
|
||||
SJson* valJsonArray = tjsonGetArrayItem(res, 1);
|
||||
if (valJsonArray == NULL) goto _OVER;
|
||||
int32_t valSize = tjsonGetArraySize(valJsonArray);
|
||||
if (valSize != rows) goto _OVER;
|
||||
for (int32_t i = 0; i < valSize; ++i) {
|
||||
SJson* valJson = tjsonGetArrayItem(valJsonArray, i);
|
||||
tjsonGetObjectValueDouble(valJson, &tmpDouble);
|
||||
|
||||
switch (pSupp->inputValType) {
|
||||
case TSDB_DATA_TYPE_BOOL:
|
||||
case TSDB_DATA_TYPE_UTINYINT:
|
||||
case TSDB_DATA_TYPE_TINYINT: {
|
||||
tmpI8 = (int8_t)tmpDouble;
|
||||
colDataSetInt8(pResValCol, resCurRow, &tmpI8);
|
||||
break;
|
||||
}
|
||||
case TSDB_DATA_TYPE_USMALLINT:
|
||||
case TSDB_DATA_TYPE_SMALLINT: {
|
||||
tmpI16 = (int16_t)tmpDouble;
|
||||
colDataSetInt16(pResValCol, resCurRow, &tmpI16);
|
||||
break;
|
||||
}
|
||||
case TSDB_DATA_TYPE_INT:
|
||||
case TSDB_DATA_TYPE_UINT: {
|
||||
tmpI32 = (int32_t)tmpDouble;
|
||||
colDataSetInt32(pResValCol, resCurRow, &tmpI32);
|
||||
break;
|
||||
}
|
||||
case TSDB_DATA_TYPE_TIMESTAMP:
|
||||
case TSDB_DATA_TYPE_UBIGINT:
|
||||
case TSDB_DATA_TYPE_BIGINT: {
|
||||
tmpI64 = (int64_t)tmpDouble;
|
||||
colDataSetInt64(pResValCol, resCurRow, &tmpI64);
|
||||
break;
|
||||
}
|
||||
case TSDB_DATA_TYPE_FLOAT: {
|
||||
tmpFloat = (float)tmpDouble;
|
||||
colDataSetFloat(pResValCol, resCurRow, &tmpFloat);
|
||||
break;
|
||||
}
|
||||
case TSDB_DATA_TYPE_DOUBLE: {
|
||||
colDataSetDouble(pResValCol, resCurRow, &tmpDouble);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
code = TSDB_CODE_FUNC_FUNTION_PARA_TYPE;
|
||||
goto _OVER;
|
||||
}
|
||||
resCurRow++;
|
||||
}
|
||||
|
||||
// for (int32_t i = rows; i < pSupp->optRows; ++i) {
|
||||
// colDataSetNNULL(pResValCol, rows, (pSupp->optRows - rows));
|
||||
// if (pResTsCol != NULL) {
|
||||
// colDataSetNNULL(pResTsCol, rows, (pSupp->optRows - rows));
|
||||
// }
|
||||
// if (pResLowCol != NULL) {
|
||||
// colDataSetNNULL(pResLowCol, rows, (pSupp->optRows - rows));
|
||||
// }
|
||||
// if (pResHighCol != NULL) {
|
||||
// colDataSetNNULL(pResHighCol, rows, (pSupp->optRows - rows));
|
||||
// }
|
||||
// }
|
||||
|
||||
// if (rows == pSupp->optRows) {
|
||||
// pResValCol->hasNull = false;
|
||||
// }
|
||||
|
||||
pBlock->info.rows += rows;
|
||||
|
||||
if (pJson != NULL) tjsonDelete(pJson);
|
||||
return 0;
|
||||
|
||||
_OVER:
|
||||
if (pJson != NULL) tjsonDelete(pJson);
|
||||
if (code == 0) {
|
||||
code = TSDB_CODE_INVALID_JSON_FORMAT;
|
||||
}
|
||||
qError("failed to perform forecast finalize since %s", tstrerror(code));
|
||||
return TSDB_CODE_INVALID_JSON_FORMAT;
|
||||
}
|
||||
|
||||
static int32_t forecastAggregateBlocks(SForecastSupp* pSupp, SSDataBlock* pResBlock) {
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
int32_t lino = 0;
|
||||
SAnalBuf* pBuf = &pSupp->analBuf;
|
||||
|
||||
code = forecastCloseBuf(pSupp);
|
||||
QUERY_CHECK_CODE(code, lino, _end);
|
||||
|
||||
code = forecastEnsureBlockCapacity(pResBlock, 1);
|
||||
QUERY_CHECK_CODE(code, lino, _end);
|
||||
|
||||
code = forecastAnalysis(pSupp, pResBlock);
|
||||
QUERY_CHECK_CODE(code, lino, _end);
|
||||
|
||||
uInfo("block:%d, forecast finalize", pSupp->numOfBlocks);
|
||||
|
||||
_end:
|
||||
pSupp->numOfBlocks = 0;
|
||||
taosAnalBufDestroy(&pSupp->analBuf);
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t forecastNext(SOperatorInfo* pOperator, SSDataBlock** ppRes) {
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
int32_t lino = 0;
|
||||
SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
|
||||
SForecastOperatorInfo* pInfo = pOperator->info;
|
||||
SSDataBlock* pResBlock = pInfo->pRes;
|
||||
SForecastSupp* pSupp = &pInfo->forecastSupp;
|
||||
SAnalBuf* pBuf = &pSupp->analBuf;
|
||||
int64_t st = taosGetTimestampUs();
|
||||
int32_t numOfBlocks = pSupp->numOfBlocks;
|
||||
|
||||
blockDataCleanup(pResBlock);
|
||||
|
||||
while (1) {
|
||||
SSDataBlock* pBlock = getNextBlockFromDownstream(pOperator, 0);
|
||||
if (pBlock == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (pSupp->groupId == 0 || pSupp->groupId == pBlock->info.id.groupId) {
|
||||
pSupp->groupId = pBlock->info.id.groupId;
|
||||
numOfBlocks++;
|
||||
qDebug("group:%" PRId64 ", blocks:%d, cache block rows:%" PRId64, pSupp->groupId, numOfBlocks, pBlock->info.rows);
|
||||
code = forecastCacheBlock(pSupp, pBlock);
|
||||
QUERY_CHECK_CODE(code, lino, _end);
|
||||
} else {
|
||||
qDebug("group:%" PRId64 ", read finish for new group coming, blocks:%d", pSupp->groupId, numOfBlocks);
|
||||
forecastAggregateBlocks(pSupp, pResBlock);
|
||||
pSupp->groupId = pBlock->info.id.groupId;
|
||||
numOfBlocks = 1;
|
||||
qDebug("group:%" PRId64 ", new group, cache block rows:%" PRId64, pSupp->groupId, pBlock->info.rows);
|
||||
code = forecastCacheBlock(pSupp, pBlock);
|
||||
QUERY_CHECK_CODE(code, lino, _end);
|
||||
}
|
||||
|
||||
if (pResBlock->info.rows > 0) {
|
||||
(*ppRes) = pResBlock;
|
||||
qDebug("group:%" PRId64 ", return to upstream, blocks:%d", pResBlock->info.id.groupId, numOfBlocks);
|
||||
return code;
|
||||
}
|
||||
}
|
||||
|
||||
if (numOfBlocks > 0) {
|
||||
qDebug("group:%" PRId64 ", read finish, blocks:%d", pSupp->groupId, numOfBlocks);
|
||||
forecastAggregateBlocks(pSupp, pResBlock);
|
||||
}
|
||||
|
||||
int64_t cost = taosGetTimestampUs() - st;
|
||||
qDebug("all groups finished, cost:%" PRId64 "us", cost);
|
||||
|
||||
_end:
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
|
||||
pTaskInfo->code = code;
|
||||
T_LONG_JMP(pTaskInfo->env, code);
|
||||
}
|
||||
(*ppRes) = (pResBlock->info.rows == 0) ? NULL : pResBlock;
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t forecastParseOutput(SForecastSupp* pSupp, SExprSupp* pExprSup) {
|
||||
pSupp->resLowSlot = -1;
|
||||
pSupp->resHighSlot = -1;
|
||||
pSupp->resTsSlot = -1;
|
||||
pSupp->resValSlot = -1;
|
||||
|
||||
for (int32_t j = 0; j < pExprSup->numOfExprs; ++j) {
|
||||
SExprInfo* pExprInfo = &pExprSup->pExprInfo[j];
|
||||
int32_t dstSlot = pExprInfo->base.resSchema.slotId;
|
||||
if (pExprInfo->pExpr->_function.functionType == FUNCTION_TYPE_FORECAST) {
|
||||
pSupp->resValSlot = dstSlot;
|
||||
} else if (pExprInfo->pExpr->_function.functionType == FUNCTION_TYPE_FORECAST_ROWTS) {
|
||||
pSupp->resTsSlot = dstSlot;
|
||||
} else if (pExprInfo->pExpr->_function.functionType == FUNCTION_TYPE_FORECAST_LOW) {
|
||||
pSupp->resLowSlot = dstSlot;
|
||||
} else if (pExprInfo->pExpr->_function.functionType == FUNCTION_TYPE_FORECAST_HIGH) {
|
||||
pSupp->resHighSlot = dstSlot;
|
||||
} else {
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t forecastParseInput(SForecastSupp* pSupp, SNodeList* pFuncs) {
|
||||
SNode* pNode = NULL;
|
||||
|
||||
pSupp->inputTsSlot = -1;
|
||||
pSupp->inputValSlot = -1;
|
||||
pSupp->inputValType = -1;
|
||||
pSupp->inputPrecision = -1;
|
||||
|
||||
FOREACH(pNode, pFuncs) {
|
||||
if ((nodeType(pNode) == QUERY_NODE_TARGET) && (nodeType(((STargetNode*)pNode)->pExpr) == QUERY_NODE_FUNCTION)) {
|
||||
SFunctionNode* pFunc = (SFunctionNode*)((STargetNode*)pNode)->pExpr;
|
||||
int32_t numOfParam = LIST_LENGTH(pFunc->pParameterList);
|
||||
|
||||
if (pFunc->funcType == FUNCTION_TYPE_FORECAST) {
|
||||
if (numOfParam == 3) {
|
||||
SNode* p1 = nodesListGetNode(pFunc->pParameterList, 0);
|
||||
SNode* p2 = nodesListGetNode(pFunc->pParameterList, 1);
|
||||
SNode* p3 = nodesListGetNode(pFunc->pParameterList, 2);
|
||||
if (p1 == NULL || p2 == NULL || p3 == NULL) return TSDB_CODE_PLAN_INTERNAL_ERROR;
|
||||
if (p1->type != QUERY_NODE_COLUMN) return TSDB_CODE_PLAN_INTERNAL_ERROR;
|
||||
if (p2->type != QUERY_NODE_VALUE) return TSDB_CODE_PLAN_INTERNAL_ERROR;
|
||||
if (p3->type != QUERY_NODE_COLUMN) return TSDB_CODE_PLAN_INTERNAL_ERROR;
|
||||
SColumnNode* pValNode = (SColumnNode*)p1;
|
||||
SValueNode* pOptNode = (SValueNode*)p2;
|
||||
SColumnNode* pTsNode = (SColumnNode*)p3;
|
||||
pSupp->inputTsSlot = pTsNode->slotId;
|
||||
pSupp->inputPrecision = pTsNode->node.resType.precision;
|
||||
pSupp->inputValSlot = pValNode->slotId;
|
||||
pSupp->inputValType = pValNode->node.resType.type;
|
||||
tstrncpy(pSupp->algoOpt, pOptNode->literal, sizeof(pSupp->algoOpt));
|
||||
} else if (numOfParam == 2) {
|
||||
SNode* p1 = nodesListGetNode(pFunc->pParameterList, 0);
|
||||
SNode* p2 = nodesListGetNode(pFunc->pParameterList, 1);
|
||||
if (p1 == NULL || p2 == NULL) return TSDB_CODE_PLAN_INTERNAL_ERROR;
|
||||
if (p1->type != QUERY_NODE_COLUMN) return TSDB_CODE_PLAN_INTERNAL_ERROR;
|
||||
if (p2->type != QUERY_NODE_COLUMN) return TSDB_CODE_PLAN_INTERNAL_ERROR;
|
||||
SColumnNode* pValNode = (SColumnNode*)p1;
|
||||
SColumnNode* pTsNode = (SColumnNode*)p2;
|
||||
pSupp->inputTsSlot = pTsNode->slotId;
|
||||
pSupp->inputPrecision = pTsNode->node.resType.precision;
|
||||
pSupp->inputValSlot = pValNode->slotId;
|
||||
pSupp->inputValType = pValNode->node.resType.type;
|
||||
tstrncpy(pSupp->algoOpt, "algo=arima", TSDB_ANAL_ALGO_OPTION_LEN);
|
||||
} else {
|
||||
return TSDB_CODE_PLAN_INTERNAL_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t forecastParseAlgo(SForecastSupp* pSupp) {
|
||||
pSupp->maxTs = 0;
|
||||
pSupp->minTs = INT64_MAX;
|
||||
pSupp->numOfRows = 0;
|
||||
|
||||
if (!taosAnalGetOptStr(pSupp->algoOpt, "algo", pSupp->algoName, sizeof(pSupp->algoName))) {
|
||||
qError("failed to get forecast algorithm name from %s", pSupp->algoOpt);
|
||||
return TSDB_CODE_ANAL_ALGO_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (taosAnalGetAlgoUrl(pSupp->algoName, ANAL_ALGO_TYPE_FORECAST, pSupp->algoUrl, sizeof(pSupp->algoUrl)) != 0) {
|
||||
qError("failed to get forecast algorithm url from %s", pSupp->algoName);
|
||||
return TSDB_CODE_ANAL_ALGO_NOT_LOAD;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t forecastCreateBuf(SForecastSupp* pSupp) {
|
||||
SAnalBuf* pBuf = &pSupp->analBuf;
|
||||
int64_t ts = 0; // taosGetTimestampMs();
|
||||
|
||||
pBuf->bufType = ANAL_BUF_TYPE_JSON_COL;
|
||||
snprintf(pBuf->fileName, sizeof(pBuf->fileName), "%s/tdengine-forecast-%" PRId64, tsTempDir, ts);
|
||||
int32_t code = tsosAnalBufOpen(pBuf, 2);
|
||||
if (code != 0) goto _OVER;
|
||||
|
||||
code = taosAnalBufWriteOptStr(pBuf, "algo", pSupp->algoName);
|
||||
if (code != 0) goto _OVER;
|
||||
|
||||
bool returnConf = (pSupp->resHighSlot == -1 || pSupp->resLowSlot == -1);
|
||||
code = taosAnalBufWriteOptStr(pBuf, "return_conf", returnConf ? "true" : "false");
|
||||
if (code != 0) goto _OVER;
|
||||
|
||||
bool hasAlpha = taosAnalGetOptStr(pSupp->algoOpt, "alpha", NULL, 0);
|
||||
if (!hasAlpha) {
|
||||
qDebug("forecast alpha not found from %s, use default:%f", pSupp->algoOpt, ANAL_FORECAST_DEFAULT_ALPHA);
|
||||
code = taosAnalBufWriteOptFloat(pBuf, "alpha", ANAL_FORECAST_DEFAULT_ALPHA);
|
||||
if (code != 0) goto _OVER;
|
||||
}
|
||||
|
||||
char tmpOpt[32] = {0};
|
||||
bool hasParam = taosAnalGetOptStr(pSupp->algoOpt, "param", tmpOpt, sizeof(tmpOpt));
|
||||
if (!hasParam) {
|
||||
qDebug("forecast param not found from %s, use default:%s", pSupp->algoOpt, ANAL_FORECAST_DEFAULT_PARAM);
|
||||
code = taosAnalBufWriteOptStr(pBuf, "param", ANAL_FORECAST_DEFAULT_PARAM);
|
||||
if (code != 0) goto _OVER;
|
||||
}
|
||||
|
||||
bool hasPeriod = taosAnalGetOptInt(pSupp->algoOpt, "period", NULL);
|
||||
if (!hasPeriod) {
|
||||
qDebug("forecast period not found from %s, use default:%d", pSupp->algoOpt, ANAL_FORECAST_DEFAULT_PERIOD);
|
||||
code = taosAnalBufWriteOptInt(pBuf, "period", ANAL_FORECAST_DEFAULT_PERIOD);
|
||||
if (code != 0) goto _OVER;
|
||||
}
|
||||
|
||||
bool hasRows = taosAnalGetOptInt(pSupp->algoOpt, "rows", &pSupp->optRows);
|
||||
if (!hasRows) {
|
||||
pSupp->optRows = ANAL_FORECAST_DEFAULT_ROWS;
|
||||
qDebug("forecast rows not found from %s, use default:%d", pSupp->algoOpt, pSupp->optRows);
|
||||
code = taosAnalBufWriteOptInt(pBuf, "forecast_rows", pSupp->optRows);
|
||||
if (code != 0) goto _OVER;
|
||||
}
|
||||
|
||||
const char* prec = TSDB_TIME_PRECISION_MILLI_STR;
|
||||
if (pSupp->inputPrecision == TSDB_TIME_PRECISION_MICRO) prec = TSDB_TIME_PRECISION_MICRO_STR;
|
||||
if (pSupp->inputPrecision == TSDB_TIME_PRECISION_NANO) prec = TSDB_TIME_PRECISION_NANO_STR;
|
||||
code = taosAnalBufWriteOptStr(pBuf, "prec", prec);
|
||||
if (code != 0) goto _OVER;
|
||||
|
||||
if (returnConf) {
|
||||
bool hasConf = taosAnalGetOptStr(pSupp->algoOpt, "conf", NULL, 0);
|
||||
if (!hasConf) {
|
||||
qDebug("forecast conf not found from %s, use default:%d", pSupp->algoOpt, ANAL_FORECAST_DEFAULT_CONF);
|
||||
code = taosAnalBufWriteOptInt(pBuf, "conf", ANAL_FORECAST_DEFAULT_CONF);
|
||||
if (code != 0) goto _OVER;
|
||||
}
|
||||
}
|
||||
|
||||
code = taosAnalBufWriteColMeta(pBuf, 0, TSDB_DATA_TYPE_TIMESTAMP, "ts");
|
||||
if (code != 0) goto _OVER;
|
||||
|
||||
code = taosAnalBufWriteColMeta(pBuf, 1, pSupp->inputValType, "val");
|
||||
if (code != 0) goto _OVER;
|
||||
|
||||
code = taosAnalBufWriteDataBegin(pBuf);
|
||||
if (code != 0) goto _OVER;
|
||||
|
||||
for (int32_t i = 0; i < 2; ++i) {
|
||||
code = taosAnalBufWriteColBegin(pBuf, i);
|
||||
if (code != 0) goto _OVER;
|
||||
}
|
||||
|
||||
_OVER:
|
||||
if (code != 0) {
|
||||
taosAnalBufClose(pBuf);
|
||||
taosAnalBufDestroy(pBuf);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
int32_t createForecastOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo,
|
||||
SOperatorInfo** pOptrInfo) {
|
||||
QRY_PARAM_CHECK(pOptrInfo);
|
||||
|
||||
int32_t code = 0;
|
||||
int32_t lino = 0;
|
||||
SForecastOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SForecastOperatorInfo));
|
||||
SOperatorInfo* pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
|
||||
if (pOperator == NULL || pInfo == NULL) {
|
||||
code = terrno;
|
||||
goto _error;
|
||||
}
|
||||
|
||||
SForecastSupp* pSupp = &pInfo->forecastSupp;
|
||||
SForecastFuncPhysiNode* pForecastPhyNode = (SForecastFuncPhysiNode*)pPhyNode;
|
||||
SExprSupp* pExprSup = &pOperator->exprSupp;
|
||||
int32_t numOfExprs = 0;
|
||||
SExprInfo* pExprInfo = NULL;
|
||||
|
||||
code = createExprInfo(pForecastPhyNode->pFuncs, NULL, &pExprInfo, &numOfExprs);
|
||||
QUERY_CHECK_CODE(code, lino, _error);
|
||||
|
||||
code = initExprSupp(pExprSup, pExprInfo, numOfExprs, &pTaskInfo->storageAPI.functionStore);
|
||||
QUERY_CHECK_CODE(code, lino, _error);
|
||||
|
||||
if (pForecastPhyNode->pExprs != NULL) {
|
||||
int32_t num = 0;
|
||||
SExprInfo* pScalarExprInfo = NULL;
|
||||
code = createExprInfo(pForecastPhyNode->pExprs, NULL, &pScalarExprInfo, &num);
|
||||
QUERY_CHECK_CODE(code, lino, _error);
|
||||
|
||||
code = initExprSupp(&pInfo->scalarSup, pScalarExprInfo, num, &pTaskInfo->storageAPI.functionStore);
|
||||
QUERY_CHECK_CODE(code, lino, _error);
|
||||
}
|
||||
|
||||
code = filterInitFromNode((SNode*)pForecastPhyNode->node.pConditions, &pOperator->exprSupp.pFilterInfo, 0);
|
||||
QUERY_CHECK_CODE(code, lino, _error);
|
||||
|
||||
code = forecastParseInput(pSupp, pForecastPhyNode->pFuncs);
|
||||
QUERY_CHECK_CODE(code, lino, _error);
|
||||
|
||||
code = forecastParseOutput(pSupp, pExprSup);
|
||||
QUERY_CHECK_CODE(code, lino, _error);
|
||||
|
||||
code = forecastParseAlgo(pSupp);
|
||||
QUERY_CHECK_CODE(code, lino, _error);
|
||||
|
||||
code = forecastCreateBuf(pSupp);
|
||||
QUERY_CHECK_CODE(code, lino, _error);
|
||||
|
||||
initResultSizeInfo(&pOperator->resultInfo, 4096);
|
||||
|
||||
pInfo->pRes = createDataBlockFromDescNode(pPhyNode->pOutputDataBlockDesc);
|
||||
QUERY_CHECK_NULL(pInfo->pRes, code, lino, _error, terrno);
|
||||
|
||||
setOperatorInfo(pOperator, "ForecastOperator", QUERY_NODE_PHYSICAL_PLAN_FORECAST_FUNC, false, OP_NOT_OPENED, pInfo,
|
||||
pTaskInfo);
|
||||
pOperator->fpSet = createOperatorFpSet(optrDummyOpenFn, forecastNext, NULL, destroyForecastInfo, optrDefaultBufFn,
|
||||
NULL, optrDefaultGetNextExtFn, NULL);
|
||||
|
||||
code = blockDataEnsureCapacity(pInfo->pRes, pOperator->resultInfo.capacity);
|
||||
QUERY_CHECK_CODE(code, lino, _error);
|
||||
|
||||
code = appendDownstream(pOperator, &downstream, 1);
|
||||
QUERY_CHECK_CODE(code, lino, _error);
|
||||
|
||||
*pOptrInfo = pOperator;
|
||||
|
||||
qDebug("forecast env is initialized, option:%s", pSupp->algoOpt);
|
||||
return TSDB_CODE_SUCCESS;
|
||||
|
||||
_error:
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
|
||||
}
|
||||
if (pInfo != NULL) destroyForecastInfo(pInfo);
|
||||
destroyOperatorAndDownstreams(pOperator, &downstream, 1);
|
||||
pTaskInfo->code = code;
|
||||
return code;
|
||||
}
|
||||
|
||||
static void destroyForecastInfo(void* param) {
|
||||
SForecastOperatorInfo* pInfo = (SForecastOperatorInfo*)param;
|
||||
|
||||
blockDataDestroy(pInfo->pRes);
|
||||
pInfo->pRes = NULL;
|
||||
cleanupExprSupp(&pInfo->scalarSup);
|
||||
taosAnalBufDestroy(&pInfo->forecastSupp.analBuf);
|
||||
taosMemoryFreeClear(param);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int32_t createForecastOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo,
|
||||
SOperatorInfo** pOptrInfo) {
|
||||
return TSDB_CODE_OPS_NOT_SUPPORT;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -619,6 +619,8 @@ int32_t createOperator(SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo, SReadHand
|
|||
code = createIndefinitOutputOperatorInfo(ops[0], pPhyNode, pTaskInfo, &pOptr);
|
||||
} else if (QUERY_NODE_PHYSICAL_PLAN_INTERP_FUNC == type) {
|
||||
code = createTimeSliceOperatorInfo(ops[0], pPhyNode, pTaskInfo, &pOptr);
|
||||
} else if (QUERY_NODE_PHYSICAL_PLAN_FORECAST_FUNC == type) {
|
||||
code = createForecastOperatorInfo(ops[0], pPhyNode, pTaskInfo, &pOptr);
|
||||
} else if (QUERY_NODE_PHYSICAL_PLAN_MERGE_EVENT == type) {
|
||||
code = createEventwindowOperatorInfo(ops[0], pPhyNode, pTaskInfo, &pOptr);
|
||||
} else if (QUERY_NODE_PHYSICAL_PLAN_GROUP_CACHE == type) {
|
||||
|
@ -629,6 +631,8 @@ int32_t createOperator(SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo, SReadHand
|
|||
code = createStreamCountAggOperatorInfo(ops[0], pPhyNode, pTaskInfo, pHandle, &pOptr);
|
||||
} else if (QUERY_NODE_PHYSICAL_PLAN_MERGE_COUNT == type) {
|
||||
code = createCountwindowOperatorInfo(ops[0], pPhyNode, pTaskInfo, &pOptr);
|
||||
} else if (QUERY_NODE_PHYSICAL_PLAN_MERGE_ANOMALY == type) {
|
||||
code = createAnomalywindowOperatorInfo(ops[0], pPhyNode, pTaskInfo, &pOptr);
|
||||
} else {
|
||||
code = TSDB_CODE_INVALID_PARA;
|
||||
pTaskInfo->code = code;
|
||||
|
|
|
@ -116,6 +116,8 @@ int32_t diffFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo);
|
|||
int32_t diffFunction(SqlFunctionCtx* pCtx);
|
||||
int32_t diffFunctionByRow(SArray* pCtx);
|
||||
|
||||
bool getForecastConfEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv);
|
||||
|
||||
bool getDerivativeFuncEnv(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv);
|
||||
int32_t derivativeFuncSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo);
|
||||
int32_t derivativeFunction(SqlFunctionCtx* pCtx);
|
||||
|
|
|
@ -58,6 +58,7 @@ extern "C" {
|
|||
#define FUNC_MGT_TSMA_FUNC FUNC_MGT_FUNC_CLASSIFICATION_MASK(29)
|
||||
#define FUNC_MGT_COUNT_LIKE_FUNC FUNC_MGT_FUNC_CLASSIFICATION_MASK(30) // funcs that should also return 0 when no rows found
|
||||
#define FUNC_MGT_PROCESS_BY_ROW FUNC_MGT_FUNC_CLASSIFICATION_MASK(31)
|
||||
#define FUNC_MGT_FORECAST_PC_FUNC FUNC_MGT_FUNC_CLASSIFICATION_MASK(32)
|
||||
|
||||
#define FUNC_MGT_TEST_MASK(val, mask) (((val) & (mask)) != 0)
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "geomFunc.h"
|
||||
#include "querynodes.h"
|
||||
#include "scalar.h"
|
||||
#include "tanal.h"
|
||||
#include "taoserror.h"
|
||||
#include "ttime.h"
|
||||
|
||||
|
@ -2078,6 +2079,47 @@ static int32_t translateMode(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
|
|||
return translateUniqueMode(pFunc, pErrBuf, len, false);
|
||||
}
|
||||
|
||||
static int32_t translateForecast(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
|
||||
int32_t numOfParams = LIST_LENGTH(pFunc->pParameterList);
|
||||
if (2 != numOfParams && 1 != numOfParams) {
|
||||
return invaildFuncParaNumErrMsg(pErrBuf, len, "FORECAST require 1 or 2 parameters");
|
||||
}
|
||||
|
||||
uint8_t valType = getSDataTypeFromNode(nodesListGetNode(pFunc->pParameterList, 0))->type;
|
||||
if (!IS_MATHABLE_TYPE(valType)) {
|
||||
return invaildFuncParaTypeErrMsg(pErrBuf, len, "FORECAST only support mathable column");
|
||||
}
|
||||
|
||||
if (numOfParams == 2) {
|
||||
uint8_t optionType = getSDataTypeFromNode(nodesListGetNode(pFunc->pParameterList, 1))->type;
|
||||
if (TSDB_DATA_TYPE_BINARY != optionType) {
|
||||
return invaildFuncParaTypeErrMsg(pErrBuf, len, "FORECAST option should be varchar");
|
||||
}
|
||||
|
||||
SNode* pOption = nodesListGetNode(pFunc->pParameterList, 1);
|
||||
if (QUERY_NODE_VALUE != nodeType(pOption)) {
|
||||
return invaildFuncParaTypeErrMsg(pErrBuf, len, "FORECAST option should be value");
|
||||
}
|
||||
|
||||
SValueNode* pValue = (SValueNode*)pOption;
|
||||
if (!taosAnalGetOptStr(pValue->literal, "algo", NULL, 0) != 0) {
|
||||
return invaildFuncParaValueErrMsg(pErrBuf, len, "FORECAST option should include algo field");
|
||||
}
|
||||
|
||||
pValue->notReserved = true;
|
||||
}
|
||||
|
||||
pFunc->node.resType = (SDataType){.bytes = tDataTypes[valType].bytes, .type = valType};
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t translateForecastConf(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
|
||||
pFunc->node.resType = (SDataType){.bytes = tDataTypes[TSDB_DATA_TYPE_FLOAT].bytes, .type = TSDB_DATA_TYPE_FLOAT};
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static EFuncReturnRows forecastEstReturnRows(SFunctionNode* pFunc) { return FUNC_RETURN_ROWS_N; }
|
||||
|
||||
static int32_t translateDiff(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
|
||||
int32_t numOfParams = LIST_LENGTH(pFunc->pParameterList);
|
||||
if (numOfParams > 2) {
|
||||
|
@ -4797,6 +4839,48 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
|||
.sprocessFunc = randFunction,
|
||||
.finalizeFunc = NULL
|
||||
},
|
||||
{
|
||||
.name = "forecast",
|
||||
.type = FUNCTION_TYPE_FORECAST,
|
||||
.classification = FUNC_MGT_TIMELINE_FUNC | FUNC_MGT_IMPLICIT_TS_FUNC |
|
||||
FUNC_MGT_FORBID_STREAM_FUNC | FUNC_MGT_FORBID_SYSTABLE_FUNC | FUNC_MGT_KEEP_ORDER_FUNC | FUNC_MGT_PRIMARY_KEY_FUNC,
|
||||
.translateFunc = translateForecast,
|
||||
.getEnvFunc = getSelectivityFuncEnv,
|
||||
.initFunc = functionSetup,
|
||||
.processFunc = NULL,
|
||||
.finalizeFunc = NULL,
|
||||
.estimateReturnRowsFunc = forecastEstReturnRows,
|
||||
},
|
||||
{
|
||||
.name = "_frowts",
|
||||
.type = FUNCTION_TYPE_FORECAST_ROWTS,
|
||||
.classification = FUNC_MGT_PSEUDO_COLUMN_FUNC | FUNC_MGT_FORECAST_PC_FUNC | FUNC_MGT_KEEP_ORDER_FUNC,
|
||||
.translateFunc = translateTimePseudoColumn,
|
||||
.getEnvFunc = getTimePseudoFuncEnv,
|
||||
.initFunc = NULL,
|
||||
.sprocessFunc = NULL,
|
||||
.finalizeFunc = NULL
|
||||
},
|
||||
{
|
||||
.name = "_flow",
|
||||
.type = FUNCTION_TYPE_FORECAST_LOW,
|
||||
.classification = FUNC_MGT_PSEUDO_COLUMN_FUNC | FUNC_MGT_FORECAST_PC_FUNC | FUNC_MGT_KEEP_ORDER_FUNC,
|
||||
.translateFunc = translateForecastConf,
|
||||
.getEnvFunc = getForecastConfEnv,
|
||||
.initFunc = NULL,
|
||||
.sprocessFunc = NULL,
|
||||
.finalizeFunc = NULL
|
||||
},
|
||||
{
|
||||
.name = "_fhigh",
|
||||
.type = FUNCTION_TYPE_FORECAST_HIGH,
|
||||
.classification = FUNC_MGT_PSEUDO_COLUMN_FUNC | FUNC_MGT_FORECAST_PC_FUNC | FUNC_MGT_KEEP_ORDER_FUNC,
|
||||
.translateFunc = translateForecastConf,
|
||||
.getEnvFunc = getForecastConfEnv,
|
||||
.initFunc = NULL,
|
||||
.sprocessFunc = NULL,
|
||||
.finalizeFunc = NULL
|
||||
},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "functionResInfoInt.h"
|
||||
#include "query.h"
|
||||
#include "querynodes.h"
|
||||
#include "tanal.h"
|
||||
#include "tcompare.h"
|
||||
#include "tdatablock.h"
|
||||
#include "tdigest.h"
|
||||
|
@ -3342,6 +3343,11 @@ bool funcInputGetNextRowIndex(SInputColumnInfoData* pInput, int32_t from, bool f
|
|||
}
|
||||
}
|
||||
|
||||
bool getForecastConfEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) {
|
||||
pEnv->calcMemSize = sizeof(float);
|
||||
return true;
|
||||
}
|
||||
|
||||
int32_t diffResultIsNull(SqlFunctionCtx* pCtx, SFuncInputRow* pRow){
|
||||
SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx);
|
||||
SDiffInfo* pDiffInfo = GET_ROWCELL_INTERBUF(pResInfo);
|
||||
|
|
|
@ -232,6 +232,15 @@ bool fmIsInterpFunc(int32_t funcId) {
|
|||
|
||||
bool fmIsInterpPseudoColumnFunc(int32_t funcId) { return isSpecificClassifyFunc(funcId, FUNC_MGT_INTERP_PC_FUNC); }
|
||||
|
||||
bool fmIsForecastFunc(int32_t funcId) {
|
||||
if (funcId < 0 || funcId >= funcMgtBuiltinsNum) {
|
||||
return false;
|
||||
}
|
||||
return FUNCTION_TYPE_FORECAST == funcMgtBuiltins[funcId].type;
|
||||
}
|
||||
|
||||
bool fmIsForecastPseudoColumnFunc(int32_t funcId) { return isSpecificClassifyFunc(funcId, FUNC_MGT_FORECAST_PC_FUNC); }
|
||||
|
||||
bool fmIsLastRowFunc(int32_t funcId) {
|
||||
if (funcId < 0 || funcId >= funcMgtBuiltinsNum) {
|
||||
return false;
|
||||
|
|
|
@ -368,6 +368,13 @@ static int32_t countWindowNodeCopy(const SCountWindowNode* pSrc, SCountWindowNod
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t anomalyWindowNodeCopy(const SAnomalyWindowNode* pSrc, SAnomalyWindowNode* pDst) {
|
||||
CLONE_NODE_FIELD(pCol);
|
||||
CLONE_NODE_FIELD(pExpr);
|
||||
COPY_CHAR_ARRAY_FIELD(anomalyOpt);
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t sessionWindowNodeCopy(const SSessionWindowNode* pSrc, SSessionWindowNode* pDst) {
|
||||
CLONE_NODE_FIELD_EX(pCol, SColumnNode*);
|
||||
CLONE_NODE_FIELD_EX(pGap, SValueNode*);
|
||||
|
@ -622,6 +629,8 @@ static int32_t logicWindowCopy(const SWindowLogicNode* pSrc, SWindowLogicNode* p
|
|||
COPY_SCALAR_FIELD(windowAlgo);
|
||||
COPY_SCALAR_FIELD(windowCount);
|
||||
COPY_SCALAR_FIELD(windowSliding);
|
||||
CLONE_NODE_FIELD(pAnomalyExpr);
|
||||
COPY_CHAR_ARRAY_FIELD(anomalyOpt);
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -674,6 +683,12 @@ static int32_t logicInterpFuncCopy(const SInterpFuncLogicNode* pSrc, SInterpFunc
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t logicForecastFuncCopy(const SForecastFuncLogicNode* pSrc, SForecastFuncLogicNode* pDst) {
|
||||
COPY_BASE_OBJECT_FIELD(node, logicNodeCopy);
|
||||
CLONE_NODE_LIST_FIELD(pFuncs);
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t logicGroupCacheCopy(const SGroupCacheLogicNode* pSrc, SGroupCacheLogicNode* pDst) {
|
||||
COPY_BASE_OBJECT_FIELD(node, logicNodeCopy);
|
||||
COPY_SCALAR_FIELD(grpColsMayBeNull);
|
||||
|
@ -937,6 +952,9 @@ int32_t nodesCloneNode(const SNode* pNode, SNode** ppNode) {
|
|||
case QUERY_NODE_COUNT_WINDOW:
|
||||
code = countWindowNodeCopy((const SCountWindowNode*)pNode, (SCountWindowNode*)pDst);
|
||||
break;
|
||||
case QUERY_NODE_ANOMALY_WINDOW:
|
||||
code = anomalyWindowNodeCopy((const SAnomalyWindowNode*)pNode, (SAnomalyWindowNode*)pDst);
|
||||
break;
|
||||
case QUERY_NODE_SESSION_WINDOW:
|
||||
code = sessionWindowNodeCopy((const SSessionWindowNode*)pNode, (SSessionWindowNode*)pDst);
|
||||
break;
|
||||
|
@ -1021,6 +1039,9 @@ int32_t nodesCloneNode(const SNode* pNode, SNode** ppNode) {
|
|||
case QUERY_NODE_LOGIC_PLAN_INTERP_FUNC:
|
||||
code = logicInterpFuncCopy((const SInterpFuncLogicNode*)pNode, (SInterpFuncLogicNode*)pDst);
|
||||
break;
|
||||
case QUERY_NODE_LOGIC_PLAN_FORECAST_FUNC:
|
||||
code = logicForecastFuncCopy((const SForecastFuncLogicNode*)pNode, (SForecastFuncLogicNode*)pDst);
|
||||
break;
|
||||
case QUERY_NODE_LOGIC_PLAN_GROUP_CACHE:
|
||||
code = logicGroupCacheCopy((const SGroupCacheLogicNode*)pNode, (SGroupCacheLogicNode*)pDst);
|
||||
break;
|
||||
|
|
|
@ -97,6 +97,8 @@ const char* nodesNodeName(ENodeType type) {
|
|||
return "WindowOffset";
|
||||
case QUERY_NODE_COUNT_WINDOW:
|
||||
return "CountWindow";
|
||||
case QUERY_NODE_ANOMALY_WINDOW:
|
||||
return "AnomalyWindow";
|
||||
case QUERY_NODE_SET_OPERATOR:
|
||||
return "SetOperator";
|
||||
case QUERY_NODE_SELECT_STMT:
|
||||
|
@ -153,6 +155,12 @@ const char* nodesNodeName(ENodeType type) {
|
|||
return "CreateQnodeStmt";
|
||||
case QUERY_NODE_DROP_QNODE_STMT:
|
||||
return "DropQnodeStmt";
|
||||
case QUERY_NODE_CREATE_ANODE_STMT:
|
||||
return "CreateAnodeStmt";
|
||||
case QUERY_NODE_DROP_ANODE_STMT:
|
||||
return "DropAnodeStmt";
|
||||
case QUERY_NODE_UPDATE_ANODE_STMT:
|
||||
return "UpdateAnodeStmt";
|
||||
case QUERY_NODE_CREATE_SNODE_STMT:
|
||||
return "CreateSnodeStmt";
|
||||
case QUERY_NODE_DROP_SNODE_STMT:
|
||||
|
@ -213,6 +221,10 @@ const char* nodesNodeName(ENodeType type) {
|
|||
return "ShowModulesStmt";
|
||||
case QUERY_NODE_SHOW_QNODES_STMT:
|
||||
return "ShowQnodesStmt";
|
||||
case QUERY_NODE_SHOW_ANODES_STMT:
|
||||
return "ShowAnodesStmt";
|
||||
case QUERY_NODE_SHOW_ANODES_FULL_STMT:
|
||||
return "ShowAnodesFullStmt";
|
||||
case QUERY_NODE_SHOW_SNODES_STMT:
|
||||
return "ShowSnodesStmt";
|
||||
case QUERY_NODE_SHOW_BNODES_STMT:
|
||||
|
@ -328,6 +340,8 @@ const char* nodesNodeName(ENodeType type) {
|
|||
return "LogicIndefRowsFunc";
|
||||
case QUERY_NODE_LOGIC_PLAN_INTERP_FUNC:
|
||||
return "LogicInterpFunc";
|
||||
case QUERY_NODE_LOGIC_PLAN_FORECAST_FUNC:
|
||||
return "LogicForecastFunc";
|
||||
case QUERY_NODE_LOGIC_PLAN_GROUP_CACHE:
|
||||
return "LogicGroupCache";
|
||||
case QUERY_NODE_LOGIC_PLAN_DYN_QUERY_CTRL:
|
||||
|
@ -362,6 +376,10 @@ const char* nodesNodeName(ENodeType type) {
|
|||
return "PhysiMergeCountWindow";
|
||||
case QUERY_NODE_PHYSICAL_PLAN_STREAM_COUNT:
|
||||
return "PhysiStreamCountWindow";
|
||||
case QUERY_NODE_PHYSICAL_PLAN_MERGE_ANOMALY:
|
||||
return "PhysiMergeAnomalyWindow";
|
||||
case QUERY_NODE_PHYSICAL_PLAN_STREAM_ANOMALY:
|
||||
return "PhysiStreamAnomalyWindow";
|
||||
case QUERY_NODE_PHYSICAL_PLAN_PROJECT:
|
||||
return "PhysiProject";
|
||||
case QUERY_NODE_PHYSICAL_PLAN_MERGE_JOIN:
|
||||
|
@ -413,6 +431,8 @@ const char* nodesNodeName(ENodeType type) {
|
|||
return "PhysiIndefRowsFunc";
|
||||
case QUERY_NODE_PHYSICAL_PLAN_INTERP_FUNC:
|
||||
return "PhysiInterpFunc";
|
||||
case QUERY_NODE_PHYSICAL_PLAN_FORECAST_FUNC:
|
||||
return "PhysiForecastFunc";
|
||||
case QUERY_NODE_PHYSICAL_PLAN_DISPATCH:
|
||||
return "PhysiDispatch";
|
||||
case QUERY_NODE_PHYSICAL_PLAN_INSERT:
|
||||
|
@ -1260,6 +1280,30 @@ static int32_t jsonToLogicInterpFuncNode(const SJson* pJson, void* pObj) {
|
|||
return code;
|
||||
}
|
||||
|
||||
static const char* jkForecastFuncLogicPlanFuncs = "Funcs";
|
||||
|
||||
static int32_t logicForecastFuncNodeToJson(const void* pObj, SJson* pJson) {
|
||||
const SForecastFuncLogicNode* pNode = (const SForecastFuncLogicNode*)pObj;
|
||||
|
||||
int32_t code = logicPlanNodeToJson(pObj, pJson);
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = nodeListToJson(pJson, jkForecastFuncLogicPlanFuncs, pNode->pFuncs);
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t jsonToLogicForecastFuncNode(const SJson* pJson, void* pObj) {
|
||||
SForecastFuncLogicNode* pNode = (SForecastFuncLogicNode*)pObj;
|
||||
|
||||
int32_t code = jsonToLogicPlanNode(pJson, pObj);
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = jsonToNodeList(pJson, jkForecastFuncLogicPlanFuncs, &pNode->pFuncs);
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
static const char* jkGroupCacheLogicPlanGrpColsMayBeNull = "GroupColsMayBeNull";
|
||||
static const char* jkGroupCacheLogicPlanGroupByUid = "GroupByUid";
|
||||
static const char* jkGroupCacheLogicPlanGlobalGroup = "GlobalGroup";
|
||||
|
@ -3011,6 +3055,36 @@ static int32_t jsonToPhysiCountWindowNode(const SJson* pJson, void* pObj) {
|
|||
return code;
|
||||
}
|
||||
|
||||
static const char* jkAnomalyWindowPhysiPlanAnomalyKey = "AnomalyKey";
|
||||
static const char* jkAnomalyWindowPhysiPlanAnomalyOption = "AnomalyOpt";
|
||||
|
||||
static int32_t physiAnomalyWindowNodeToJson(const void* pObj, SJson* pJson) {
|
||||
const SAnomalyWindowPhysiNode* pNode = (const SAnomalyWindowPhysiNode*)pObj;
|
||||
|
||||
int32_t code = physiWindowNodeToJson(pObj, pJson);
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = tjsonAddObject(pJson, jkAnomalyWindowPhysiPlanAnomalyKey, nodeToJson, pNode->pAnomalyKey);
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = tjsonAddStringToObject(pJson, jkAnomalyWindowPhysiPlanAnomalyOption, pNode->anomalyOpt);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t jsonToPhysiAnomalyWindowNode(const SJson* pJson, void* pObj) {
|
||||
SAnomalyWindowPhysiNode* pNode = (SAnomalyWindowPhysiNode*)pObj;
|
||||
|
||||
int32_t code = jsonToPhysiWindowNode(pJson, pObj);
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = jsonToNodeObject(pJson, jkAnomalyWindowPhysiPlanAnomalyKey, &pNode->pAnomalyKey);
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = tjsonGetStringValue(pJson, jkAnomalyWindowPhysiPlanAnomalyOption, pNode->anomalyOpt);
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
static const char* jkPartitionPhysiPlanExprs = "Exprs";
|
||||
static const char* jkPartitionPhysiPlanPartitionKeys = "PartitionKeys";
|
||||
static const char* jkPartitionPhysiPlanTargets = "Targets";
|
||||
|
@ -3198,6 +3272,37 @@ static int32_t jsonToPhysiInterpFuncNode(const SJson* pJson, void* pObj) {
|
|||
return code;
|
||||
}
|
||||
|
||||
static const char* jkForecastFuncPhysiPlanExprs = "Exprs";
|
||||
static const char* jkForecastFuncPhysiPlanFuncs = "Funcs";
|
||||
|
||||
static int32_t physiForecastFuncNodeToJson(const void* pObj, SJson* pJson) {
|
||||
const SForecastFuncPhysiNode* pNode = (const SForecastFuncPhysiNode*)pObj;
|
||||
|
||||
int32_t code = physicPlanNodeToJson(pObj, pJson);
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = nodeListToJson(pJson, jkForecastFuncPhysiPlanExprs, pNode->pExprs);
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = nodeListToJson(pJson, jkForecastFuncPhysiPlanFuncs, pNode->pFuncs);
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t jsonToPhysiForecastFuncNode(const SJson* pJson, void* pObj) {
|
||||
SForecastFuncPhysiNode* pNode = (SForecastFuncPhysiNode*)pObj;
|
||||
|
||||
int32_t code = jsonToPhysicPlanNode(pJson, pObj);
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = jsonToNodeList(pJson, jkForecastFuncPhysiPlanExprs, &pNode->pExprs);
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = jsonToNodeList(pJson, jkForecastFuncPhysiPlanFuncs, &pNode->pFuncs);
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
static const char* jkDataSinkInputDataBlockDesc = "InputDataBlockDesc";
|
||||
|
||||
static int32_t physicDataSinkNodeToJson(const void* pObj, SJson* pJson) {
|
||||
|
@ -4765,6 +4870,36 @@ static int32_t jsonToCountWindowNode(const SJson* pJson, void* pObj) {
|
|||
return code;
|
||||
}
|
||||
|
||||
static const char* jkAnomalyWindowTsPrimaryKey = "AnomalyTsPrimaryKey";
|
||||
static const char* jkAnomalyWindowExpr = "AnomalyWindowExpr";
|
||||
static const char* jkAnomalyWindowOption = "AnomalyWindowOpt";
|
||||
|
||||
static int32_t anomalyWindowNodeToJson(const void* pObj, SJson* pJson) {
|
||||
const SAnomalyWindowNode* pNode = (const SAnomalyWindowNode*)pObj;
|
||||
|
||||
int32_t code = tjsonAddObject(pJson, jkAnomalyWindowTsPrimaryKey, nodeToJson, pNode->pCol);
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = tjsonAddObject(pJson, jkAnomalyWindowExpr, nodeToJson, pNode->pExpr);
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = tjsonAddStringToObject(pJson, jkAnomalyWindowOption, pNode->anomalyOpt);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t jsonToAnomalyWindowNode(const SJson* pJson, void* pObj) {
|
||||
SAnomalyWindowNode* pNode = (SAnomalyWindowNode*)pObj;
|
||||
|
||||
int32_t code = jsonToNodeObject(pJson, jkAnomalyWindowTsPrimaryKey, &pNode->pCol);
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = jsonToNodeObject(pJson, jkAnomalyWindowExpr, (SNode**)&pNode->pExpr);
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = tjsonGetStringValue(pJson, jkAnomalyWindowOption, pNode->anomalyOpt);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
static const char* jkIntervalWindowInterval = "Interval";
|
||||
static const char* jkIntervalWindowOffset = "Offset";
|
||||
static const char* jkIntervalWindowSliding = "Sliding";
|
||||
|
@ -6451,6 +6586,39 @@ static int32_t dropQnodeStmtToJson(const void* pObj, SJson* pJson) { return drop
|
|||
|
||||
static int32_t jsonToDropQnodeStmt(const SJson* pJson, void* pObj) { return jsonToDropComponentNodeStmt(pJson, pObj); }
|
||||
|
||||
static const char* jkCreateAnodeStmtUrl = "Url";
|
||||
static const char* jkUpdateDropANodeStmtId = "AnodeId";
|
||||
|
||||
static int32_t createAnodeStmtToJson(const void* pObj, SJson* pJson) {
|
||||
const SCreateAnodeStmt* pNode = (const SCreateAnodeStmt*)pObj;
|
||||
return tjsonAddStringToObject(pJson, jkCreateAnodeStmtUrl, pNode->url);
|
||||
}
|
||||
|
||||
static int32_t jsonToCreateAnodeStmt(const SJson* pJson, void* pObj) {
|
||||
SCreateAnodeStmt* pNode = (SCreateAnodeStmt*)pObj;
|
||||
return tjsonGetStringValue(pJson, jkCreateAnodeStmtUrl, pNode->url);
|
||||
}
|
||||
|
||||
static int32_t updateAnodeStmtToJson(const void* pObj, SJson* pJson) {
|
||||
const SUpdateAnodeStmt* pNode = (const SUpdateAnodeStmt*)pObj;
|
||||
return tjsonAddIntegerToObject(pJson, jkUpdateDropANodeStmtId, pNode->anodeId);
|
||||
}
|
||||
|
||||
static int32_t jsonToUpdateAnodeStmt(const SJson* pJson, void* pObj) {
|
||||
SUpdateAnodeStmt* pNode = (SUpdateAnodeStmt*)pObj;
|
||||
return tjsonGetIntValue(pJson, jkUpdateDropANodeStmtId, &pNode->anodeId);
|
||||
}
|
||||
|
||||
static int32_t dropAnodeStmtToJson(const void* pObj, SJson* pJson) {
|
||||
const SDropAnodeStmt* pNode = (const SDropAnodeStmt*)pObj;
|
||||
return tjsonAddIntegerToObject(pJson, jkUpdateDropANodeStmtId, pNode->anodeId);
|
||||
}
|
||||
|
||||
static int32_t jsonToDropAnodeStmt(const SJson* pJson, void* pObj) {
|
||||
SDropAnodeStmt* pNode = (SDropAnodeStmt*)pObj;
|
||||
return tjsonGetIntValue(pJson, jkUpdateDropANodeStmtId, &pNode->anodeId);
|
||||
}
|
||||
|
||||
static int32_t createSnodeStmtToJson(const void* pObj, SJson* pJson) {
|
||||
return createComponentNodeStmtToJson(pObj, pJson);
|
||||
}
|
||||
|
@ -7016,6 +7184,14 @@ static int32_t showQnodesStmtToJson(const void* pObj, SJson* pJson) { return sho
|
|||
|
||||
static int32_t jsonToShowQnodesStmt(const SJson* pJson, void* pObj) { return jsonToShowStmt(pJson, pObj); }
|
||||
|
||||
static int32_t showAnodesStmtToJson(const void* pObj, SJson* pJson) { return showStmtToJson(pObj, pJson); }
|
||||
|
||||
static int32_t jsonToShowAnodesStmt(const SJson* pJson, void* pObj) { return jsonToShowStmt(pJson, pObj); }
|
||||
|
||||
static int32_t showAnodesFullStmtToJson(const void* pObj, SJson* pJson) { return showStmtToJson(pObj, pJson); }
|
||||
|
||||
static int32_t jsonToShowAnodesFullStmt(const SJson* pJson, void* pObj) { return jsonToShowStmt(pJson, pObj); }
|
||||
|
||||
static int32_t showArbGroupsStmtToJson(const void* pObj, SJson* pJson) { return showStmtToJson(pObj, pJson); }
|
||||
|
||||
static int32_t jsonToShowArbGroupsStmt(const SJson* pJson, void* pObj) { return jsonToShowStmt(pJson, pObj); }
|
||||
|
@ -7552,6 +7728,8 @@ static int32_t specificNodeToJson(const void* pObj, SJson* pJson) {
|
|||
return windowOffsetNodeToJson(pObj, pJson);
|
||||
case QUERY_NODE_COUNT_WINDOW:
|
||||
return countWindowNodeToJson(pObj, pJson);
|
||||
case QUERY_NODE_ANOMALY_WINDOW:
|
||||
return anomalyWindowNodeToJson(pObj, pJson);
|
||||
case QUERY_NODE_SET_OPERATOR:
|
||||
return setOperatorToJson(pObj, pJson);
|
||||
case QUERY_NODE_SELECT_STMT:
|
||||
|
@ -7604,6 +7782,12 @@ static int32_t specificNodeToJson(const void* pObj, SJson* pJson) {
|
|||
return createQnodeStmtToJson(pObj, pJson);
|
||||
case QUERY_NODE_DROP_QNODE_STMT:
|
||||
return dropQnodeStmtToJson(pObj, pJson);
|
||||
case QUERY_NODE_CREATE_ANODE_STMT:
|
||||
return createAnodeStmtToJson(pObj, pJson);
|
||||
case QUERY_NODE_DROP_ANODE_STMT:
|
||||
return dropAnodeStmtToJson(pObj, pJson);
|
||||
case QUERY_NODE_UPDATE_ANODE_STMT:
|
||||
return updateAnodeStmtToJson(pObj, pJson);
|
||||
case QUERY_NODE_CREATE_SNODE_STMT:
|
||||
return createSnodeStmtToJson(pObj, pJson);
|
||||
case QUERY_NODE_DROP_SNODE_STMT:
|
||||
|
@ -7654,6 +7838,10 @@ static int32_t specificNodeToJson(const void* pObj, SJson* pJson) {
|
|||
return showMnodesStmtToJson(pObj, pJson);
|
||||
case QUERY_NODE_SHOW_QNODES_STMT:
|
||||
return showQnodesStmtToJson(pObj, pJson);
|
||||
case QUERY_NODE_SHOW_ANODES_STMT:
|
||||
return showAnodesStmtToJson(pObj, pJson);
|
||||
case QUERY_NODE_SHOW_ANODES_FULL_STMT:
|
||||
return showAnodesFullStmtToJson(pObj, pJson);
|
||||
case QUERY_NODE_SHOW_ARBGROUPS_STMT:
|
||||
return showArbGroupsStmtToJson(pObj, pJson);
|
||||
case QUERY_NODE_SHOW_CLUSTER_STMT:
|
||||
|
@ -7743,6 +7931,8 @@ static int32_t specificNodeToJson(const void* pObj, SJson* pJson) {
|
|||
return logicIndefRowsFuncNodeToJson(pObj, pJson);
|
||||
case QUERY_NODE_LOGIC_PLAN_INTERP_FUNC:
|
||||
return logicInterpFuncNodeToJson(pObj, pJson);
|
||||
case QUERY_NODE_LOGIC_PLAN_FORECAST_FUNC:
|
||||
return logicForecastFuncNodeToJson(pObj, pJson);
|
||||
case QUERY_NODE_LOGIC_PLAN_GROUP_CACHE:
|
||||
return logicGroupCacheNodeToJson(pObj, pJson);
|
||||
case QUERY_NODE_LOGIC_PLAN_DYN_QUERY_CTRL:
|
||||
|
@ -7803,6 +7993,8 @@ static int32_t specificNodeToJson(const void* pObj, SJson* pJson) {
|
|||
case QUERY_NODE_PHYSICAL_PLAN_MERGE_COUNT:
|
||||
case QUERY_NODE_PHYSICAL_PLAN_STREAM_COUNT:
|
||||
return physiCountWindowNodeToJson(pObj, pJson);
|
||||
case QUERY_NODE_PHYSICAL_PLAN_MERGE_ANOMALY:
|
||||
return physiAnomalyWindowNodeToJson(pObj, pJson);
|
||||
case QUERY_NODE_PHYSICAL_PLAN_PARTITION:
|
||||
return physiPartitionNodeToJson(pObj, pJson);
|
||||
case QUERY_NODE_PHYSICAL_PLAN_STREAM_PARTITION:
|
||||
|
@ -7811,6 +8003,8 @@ static int32_t specificNodeToJson(const void* pObj, SJson* pJson) {
|
|||
return physiIndefRowsFuncNodeToJson(pObj, pJson);
|
||||
case QUERY_NODE_PHYSICAL_PLAN_INTERP_FUNC:
|
||||
return physiInterpFuncNodeToJson(pObj, pJson);
|
||||
case QUERY_NODE_PHYSICAL_PLAN_FORECAST_FUNC:
|
||||
return physiForecastFuncNodeToJson(pObj, pJson);
|
||||
case QUERY_NODE_PHYSICAL_PLAN_DISPATCH:
|
||||
return physiDispatchNodeToJson(pObj, pJson);
|
||||
case QUERY_NODE_PHYSICAL_PLAN_INSERT:
|
||||
|
@ -7902,6 +8096,8 @@ static int32_t jsonToSpecificNode(const SJson* pJson, void* pObj) {
|
|||
return jsonToWindowOffsetNode(pJson, pObj);
|
||||
case QUERY_NODE_COUNT_WINDOW:
|
||||
return jsonToCountWindowNode(pJson, pObj);
|
||||
case QUERY_NODE_ANOMALY_WINDOW:
|
||||
return jsonToAnomalyWindowNode(pJson, pObj);
|
||||
case QUERY_NODE_SET_OPERATOR:
|
||||
return jsonToSetOperator(pJson, pObj);
|
||||
case QUERY_NODE_SELECT_STMT:
|
||||
|
@ -8004,6 +8200,10 @@ static int32_t jsonToSpecificNode(const SJson* pJson, void* pObj) {
|
|||
return jsonToShowMnodesStmt(pJson, pObj);
|
||||
case QUERY_NODE_SHOW_QNODES_STMT:
|
||||
return jsonToShowQnodesStmt(pJson, pObj);
|
||||
case QUERY_NODE_SHOW_ANODES_STMT:
|
||||
return jsonToShowAnodesStmt(pJson, pObj);
|
||||
case QUERY_NODE_SHOW_ANODES_FULL_STMT:
|
||||
return jsonToShowAnodesFullStmt(pJson, pObj);
|
||||
case QUERY_NODE_SHOW_ARBGROUPS_STMT:
|
||||
return jsonToShowArbGroupsStmt(pJson, pObj);
|
||||
case QUERY_NODE_SHOW_CLUSTER_STMT:
|
||||
|
@ -8101,6 +8301,8 @@ static int32_t jsonToSpecificNode(const SJson* pJson, void* pObj) {
|
|||
return jsonToLogicIndefRowsFuncNode(pJson, pObj);
|
||||
case QUERY_NODE_LOGIC_PLAN_INTERP_FUNC:
|
||||
return jsonToLogicInterpFuncNode(pJson, pObj);
|
||||
case QUERY_NODE_LOGIC_PLAN_FORECAST_FUNC:
|
||||
return jsonToLogicForecastFuncNode(pJson, pObj);
|
||||
case QUERY_NODE_LOGIC_PLAN_GROUP_CACHE:
|
||||
return jsonToLogicGroupCacheNode(pJson, pObj);
|
||||
case QUERY_NODE_LOGIC_PLAN_DYN_QUERY_CTRL:
|
||||
|
@ -8161,6 +8363,8 @@ static int32_t jsonToSpecificNode(const SJson* pJson, void* pObj) {
|
|||
case QUERY_NODE_PHYSICAL_PLAN_MERGE_COUNT:
|
||||
case QUERY_NODE_PHYSICAL_PLAN_STREAM_COUNT:
|
||||
return jsonToPhysiCountWindowNode(pJson, pObj);
|
||||
case QUERY_NODE_PHYSICAL_PLAN_MERGE_ANOMALY:
|
||||
return jsonToPhysiAnomalyWindowNode(pJson, pObj);
|
||||
case QUERY_NODE_PHYSICAL_PLAN_PARTITION:
|
||||
return jsonToPhysiPartitionNode(pJson, pObj);
|
||||
case QUERY_NODE_PHYSICAL_PLAN_STREAM_PARTITION:
|
||||
|
@ -8169,6 +8373,8 @@ static int32_t jsonToSpecificNode(const SJson* pJson, void* pObj) {
|
|||
return jsonToPhysiIndefRowsFuncNode(pJson, pObj);
|
||||
case QUERY_NODE_PHYSICAL_PLAN_INTERP_FUNC:
|
||||
return jsonToPhysiInterpFuncNode(pJson, pObj);
|
||||
case QUERY_NODE_PHYSICAL_PLAN_FORECAST_FUNC:
|
||||
return jsonToPhysiForecastFuncNode(pJson, pObj);
|
||||
case QUERY_NODE_PHYSICAL_PLAN_DISPATCH:
|
||||
return jsonToPhysiDispatchNode(pJson, pObj);
|
||||
case QUERY_NODE_PHYSICAL_PLAN_QUERY_INSERT:
|
||||
|
|
|
@ -3539,6 +3539,46 @@ static int32_t msgToPhysiCountWindowNode(STlvDecoder* pDecoder, void* pObj) {
|
|||
return code;
|
||||
}
|
||||
|
||||
enum { PHY_ANOMALY_CODE_WINDOW = 1, PHY_ANOMALY_CODE_KEY, PHY_ANOMALY_CODE_WINDOW_OPTION };
|
||||
|
||||
static int32_t physiAnomalyWindowNodeToMsg(const void* pObj, STlvEncoder* pEncoder) {
|
||||
const SAnomalyWindowPhysiNode* pNode = (const SAnomalyWindowPhysiNode*)pObj;
|
||||
|
||||
int32_t code = tlvEncodeObj(pEncoder, PHY_ANOMALY_CODE_WINDOW, physiWindowNodeToMsg, &pNode->window);
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = tlvEncodeObj(pEncoder, PHY_ANOMALY_CODE_KEY, nodeToMsg, pNode->pAnomalyKey);
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = tlvEncodeCStr(pEncoder, PHY_ANOMALY_CODE_WINDOW_OPTION, pNode->anomalyOpt);
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t msgToPhysiAnomalyWindowNode(STlvDecoder* pDecoder, void* pObj) {
|
||||
SAnomalyWindowPhysiNode* pNode = (SAnomalyWindowPhysiNode*)pObj;
|
||||
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
STlv* pTlv = NULL;
|
||||
tlvForEach(pDecoder, pTlv, code) {
|
||||
switch (pTlv->type) {
|
||||
case PHY_ANOMALY_CODE_WINDOW:
|
||||
code = tlvDecodeObjFromTlv(pTlv, msgToPhysiWindowNode, &pNode->window);
|
||||
break;
|
||||
case PHY_ANOMALY_CODE_KEY:
|
||||
code = msgToNodeFromTlv(pTlv, (void**)&pNode->pAnomalyKey);
|
||||
break;
|
||||
case PHY_ANOMALY_CODE_WINDOW_OPTION:
|
||||
code = tlvDecodeCStr(pTlv, pNode->anomalyOpt, sizeof(pNode->anomalyOpt));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
enum {
|
||||
PHY_PARTITION_CODE_BASE_NODE = 1,
|
||||
PHY_PARTITION_CODE_EXPR,
|
||||
|
@ -3770,6 +3810,50 @@ static int32_t msgToPhysiInterpFuncNode(STlvDecoder* pDecoder, void* pObj) {
|
|||
return code;
|
||||
}
|
||||
|
||||
enum {
|
||||
PHY_FORECAST_FUNC_CODE_BASE_NODE = 1,
|
||||
PHY_FORECAST_FUNC_CODE_EXPR,
|
||||
PHY_FORECAST_FUNC_CODE_FUNCS,
|
||||
};
|
||||
|
||||
static int32_t physiForecastFuncNodeToMsg(const void* pObj, STlvEncoder* pEncoder) {
|
||||
const SForecastFuncPhysiNode* pNode = (const SForecastFuncPhysiNode*)pObj;
|
||||
|
||||
int32_t code = tlvEncodeObj(pEncoder, PHY_FORECAST_FUNC_CODE_BASE_NODE, physiNodeToMsg, &pNode->node);
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = tlvEncodeObj(pEncoder, PHY_FORECAST_FUNC_CODE_EXPR, nodeListToMsg, pNode->pExprs);
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = tlvEncodeObj(pEncoder, PHY_FORECAST_FUNC_CODE_FUNCS, nodeListToMsg, pNode->pFuncs);
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t msgToPhysiForecastFuncNode(STlvDecoder* pDecoder, void* pObj) {
|
||||
SForecastFuncPhysiNode* pNode = (SForecastFuncPhysiNode*)pObj;
|
||||
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
STlv* pTlv = NULL;
|
||||
tlvForEach(pDecoder, pTlv, code) {
|
||||
switch (pTlv->type) {
|
||||
case PHY_FORECAST_FUNC_CODE_BASE_NODE:
|
||||
code = tlvDecodeObjFromTlv(pTlv, msgToPhysiNode, &pNode->node);
|
||||
break;
|
||||
case PHY_FORECAST_FUNC_CODE_EXPR:
|
||||
code = msgToNodeListFromTlv(pTlv, (void**)&pNode->pExprs);
|
||||
break;
|
||||
case PHY_FORECAST_FUNC_CODE_FUNCS:
|
||||
code = msgToNodeListFromTlv(pTlv, (void**)&pNode->pFuncs);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
enum { PHY_DATA_SINK_CODE_INPUT_DESC = 1 };
|
||||
|
||||
static int32_t physicDataSinkNodeToMsg(const void* pObj, STlvEncoder* pEncoder) {
|
||||
|
@ -4536,6 +4620,9 @@ static int32_t specificNodeToMsg(const void* pObj, STlvEncoder* pEncoder) {
|
|||
case QUERY_NODE_PHYSICAL_PLAN_STREAM_COUNT:
|
||||
code = physiCountWindowNodeToMsg(pObj, pEncoder);
|
||||
break;
|
||||
case QUERY_NODE_PHYSICAL_PLAN_MERGE_ANOMALY:
|
||||
code = physiAnomalyWindowNodeToMsg(pObj, pEncoder);
|
||||
break;
|
||||
case QUERY_NODE_PHYSICAL_PLAN_PARTITION:
|
||||
code = physiPartitionNodeToMsg(pObj, pEncoder);
|
||||
break;
|
||||
|
@ -4548,6 +4635,9 @@ static int32_t specificNodeToMsg(const void* pObj, STlvEncoder* pEncoder) {
|
|||
case QUERY_NODE_PHYSICAL_PLAN_INTERP_FUNC:
|
||||
code = physiInterpFuncNodeToMsg(pObj, pEncoder);
|
||||
break;
|
||||
case QUERY_NODE_PHYSICAL_PLAN_FORECAST_FUNC:
|
||||
code = physiForecastFuncNodeToMsg(pObj, pEncoder);
|
||||
break;
|
||||
case QUERY_NODE_PHYSICAL_PLAN_DISPATCH:
|
||||
code = physiDispatchNodeToMsg(pObj, pEncoder);
|
||||
break;
|
||||
|
@ -4698,6 +4788,9 @@ static int32_t msgToSpecificNode(STlvDecoder* pDecoder, void* pObj) {
|
|||
case QUERY_NODE_PHYSICAL_PLAN_STREAM_COUNT:
|
||||
code = msgToPhysiCountWindowNode(pDecoder, pObj);
|
||||
break;
|
||||
case QUERY_NODE_PHYSICAL_PLAN_MERGE_ANOMALY:
|
||||
code = msgToPhysiAnomalyWindowNode(pDecoder, pObj);
|
||||
break;
|
||||
case QUERY_NODE_PHYSICAL_PLAN_PARTITION:
|
||||
code = msgToPhysiPartitionNode(pDecoder, pObj);
|
||||
break;
|
||||
|
@ -4710,6 +4803,9 @@ static int32_t msgToSpecificNode(STlvDecoder* pDecoder, void* pObj) {
|
|||
case QUERY_NODE_PHYSICAL_PLAN_INTERP_FUNC:
|
||||
code = msgToPhysiInterpFuncNode(pDecoder, pObj);
|
||||
break;
|
||||
case QUERY_NODE_PHYSICAL_PLAN_FORECAST_FUNC:
|
||||
code = msgToPhysiForecastFuncNode(pDecoder, pObj);
|
||||
break;
|
||||
case QUERY_NODE_PHYSICAL_PLAN_DISPATCH:
|
||||
code = msgToPhysiDispatchNode(pDecoder, pObj);
|
||||
break;
|
||||
|
|
|
@ -181,6 +181,14 @@ static EDealRes dispatchExpr(SNode* pNode, ETraversalOrder order, FNodeWalker wa
|
|||
res = walkExpr(pEvent->pCol, order, walker, pContext);
|
||||
break;
|
||||
}
|
||||
case QUERY_NODE_ANOMALY_WINDOW: {
|
||||
SAnomalyWindowNode* pAnomaly = (SAnomalyWindowNode*)pNode;
|
||||
res = walkExpr(pAnomaly->pExpr, order, walker, pContext);
|
||||
if (DEAL_RES_ERROR != res && DEAL_RES_END != res) {
|
||||
res = walkExpr(pAnomaly->pCol, order, walker, pContext);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -392,6 +400,14 @@ static EDealRes rewriteExpr(SNode** pRawNode, ETraversalOrder order, FNodeRewrit
|
|||
res = rewriteExpr(&pEvent->pCol, order, rewriter, pContext);
|
||||
break;
|
||||
}
|
||||
case QUERY_NODE_ANOMALY_WINDOW: {
|
||||
SAnomalyWindowNode* pAnomaly = (SAnomalyWindowNode*)pNode;
|
||||
res = rewriteExpr(&pAnomaly->pExpr, order, rewriter, pContext);
|
||||
if (DEAL_RES_ERROR != res && DEAL_RES_END != res) {
|
||||
res = rewriteExpr(&pAnomaly->pCol, order, rewriter, pContext);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -419,6 +419,8 @@ int32_t nodesMakeNode(ENodeType type, SNode** ppNodeOut) {
|
|||
code = makeNode(type, sizeof(SEventWindowNode), &pNode); break;
|
||||
case QUERY_NODE_COUNT_WINDOW:
|
||||
code = makeNode(type, sizeof(SCountWindowNode), &pNode); break;
|
||||
case QUERY_NODE_ANOMALY_WINDOW:
|
||||
code = makeNode(type, sizeof(SAnomalyWindowNode), &pNode); break;
|
||||
case QUERY_NODE_HINT:
|
||||
code = makeNode(type, sizeof(SHintNode), &pNode); break;
|
||||
case QUERY_NODE_VIEW:
|
||||
|
@ -474,6 +476,12 @@ int32_t nodesMakeNode(ENodeType type, SNode** ppNodeOut) {
|
|||
code = makeNode(type, sizeof(SDropDnodeStmt), &pNode); break;
|
||||
case QUERY_NODE_ALTER_DNODE_STMT:
|
||||
code = makeNode(type, sizeof(SAlterDnodeStmt), &pNode); break;
|
||||
case QUERY_NODE_CREATE_ANODE_STMT:
|
||||
code = makeNode(type, sizeof(SCreateAnodeStmt), &pNode); break;
|
||||
case QUERY_NODE_DROP_ANODE_STMT:
|
||||
code = makeNode(type, sizeof(SDropAnodeStmt), &pNode); break;
|
||||
case QUERY_NODE_UPDATE_ANODE_STMT:
|
||||
code = makeNode(type, sizeof(SUpdateAnodeStmt), &pNode); break;
|
||||
case QUERY_NODE_CREATE_INDEX_STMT:
|
||||
code = makeNode(type, sizeof(SCreateIndexStmt), &pNode); break;
|
||||
case QUERY_NODE_DROP_INDEX_STMT:
|
||||
|
@ -540,6 +548,8 @@ int32_t nodesMakeNode(ENodeType type, SNode** ppNodeOut) {
|
|||
case QUERY_NODE_SHOW_MNODES_STMT:
|
||||
case QUERY_NODE_SHOW_MODULES_STMT:
|
||||
case QUERY_NODE_SHOW_QNODES_STMT:
|
||||
case QUERY_NODE_SHOW_ANODES_STMT:
|
||||
case QUERY_NODE_SHOW_ANODES_FULL_STMT:
|
||||
case QUERY_NODE_SHOW_SNODES_STMT:
|
||||
case QUERY_NODE_SHOW_BNODES_STMT:
|
||||
case QUERY_NODE_SHOW_ARBGROUPS_STMT:
|
||||
|
@ -647,6 +657,8 @@ int32_t nodesMakeNode(ENodeType type, SNode** ppNodeOut) {
|
|||
code = makeNode(type, sizeof(SIndefRowsFuncLogicNode), &pNode); break;
|
||||
case QUERY_NODE_LOGIC_PLAN_INTERP_FUNC:
|
||||
code = makeNode(type, sizeof(SInterpFuncLogicNode), &pNode); break;
|
||||
case QUERY_NODE_LOGIC_PLAN_FORECAST_FUNC:
|
||||
code = makeNode(type, sizeof(SForecastFuncLogicNode), &pNode); break;
|
||||
case QUERY_NODE_LOGIC_PLAN_GROUP_CACHE:
|
||||
code = makeNode(type, sizeof(SGroupCacheLogicNode), &pNode); break;
|
||||
case QUERY_NODE_LOGIC_PLAN_DYN_QUERY_CTRL:
|
||||
|
@ -722,6 +734,8 @@ int32_t nodesMakeNode(ENodeType type, SNode** ppNodeOut) {
|
|||
code = makeNode(type, sizeof(SStreamEventWinodwPhysiNode), &pNode); break;
|
||||
case QUERY_NODE_PHYSICAL_PLAN_MERGE_COUNT:
|
||||
code = makeNode(type, sizeof(SCountWinodwPhysiNode), &pNode); break;
|
||||
case QUERY_NODE_PHYSICAL_PLAN_MERGE_ANOMALY:
|
||||
code = makeNode(type, sizeof(SAnomalyWindowPhysiNode), &pNode); break;
|
||||
case QUERY_NODE_PHYSICAL_PLAN_STREAM_COUNT:
|
||||
code = makeNode(type, sizeof(SStreamCountWinodwPhysiNode), &pNode); break;
|
||||
case QUERY_NODE_PHYSICAL_PLAN_PARTITION:
|
||||
|
@ -732,6 +746,8 @@ int32_t nodesMakeNode(ENodeType type, SNode** ppNodeOut) {
|
|||
code = makeNode(type, sizeof(SIndefRowsFuncPhysiNode), &pNode); break;
|
||||
case QUERY_NODE_PHYSICAL_PLAN_INTERP_FUNC:
|
||||
code = makeNode(type, sizeof(SInterpFuncLogicNode), &pNode); break;
|
||||
case QUERY_NODE_PHYSICAL_PLAN_FORECAST_FUNC:
|
||||
code = makeNode(type, sizeof(SForecastFuncLogicNode), &pNode); break;
|
||||
case QUERY_NODE_PHYSICAL_PLAN_DISPATCH:
|
||||
code = makeNode(type, sizeof(SDataDispatcherNode), &pNode); break;
|
||||
case QUERY_NODE_PHYSICAL_PLAN_INSERT:
|
||||
|
@ -1019,6 +1035,11 @@ void nodesDestroyNode(SNode* pNode) {
|
|||
nodesDestroyNode(pEvent->pCol);
|
||||
break;
|
||||
}
|
||||
case QUERY_NODE_ANOMALY_WINDOW: {
|
||||
SAnomalyWindowNode* pAnomaly = (SAnomalyWindowNode*)pNode;
|
||||
nodesDestroyNode(pAnomaly->pCol);
|
||||
break;
|
||||
}
|
||||
case QUERY_NODE_HINT: {
|
||||
SHintNode* pHint = (SHintNode*)pNode;
|
||||
destroyHintValue(pHint->option, pHint->value);
|
||||
|
@ -1167,6 +1188,9 @@ void nodesDestroyNode(SNode* pNode) {
|
|||
case QUERY_NODE_CREATE_DNODE_STMT: // no pointer field
|
||||
case QUERY_NODE_DROP_DNODE_STMT: // no pointer field
|
||||
case QUERY_NODE_ALTER_DNODE_STMT: // no pointer field
|
||||
case QUERY_NODE_CREATE_ANODE_STMT: // no pointer field
|
||||
case QUERY_NODE_UPDATE_ANODE_STMT: // no pointer field
|
||||
case QUERY_NODE_DROP_ANODE_STMT: // no pointer field
|
||||
break;
|
||||
case QUERY_NODE_CREATE_INDEX_STMT: {
|
||||
SCreateIndexStmt* pStmt = (SCreateIndexStmt*)pNode;
|
||||
|
@ -1252,6 +1276,8 @@ void nodesDestroyNode(SNode* pNode) {
|
|||
case QUERY_NODE_SHOW_MNODES_STMT:
|
||||
case QUERY_NODE_SHOW_MODULES_STMT:
|
||||
case QUERY_NODE_SHOW_QNODES_STMT:
|
||||
case QUERY_NODE_SHOW_ANODES_STMT:
|
||||
case QUERY_NODE_SHOW_ANODES_FULL_STMT:
|
||||
case QUERY_NODE_SHOW_SNODES_STMT:
|
||||
case QUERY_NODE_SHOW_BNODES_STMT:
|
||||
case QUERY_NODE_SHOW_ARBGROUPS_STMT:
|
||||
|
@ -1500,6 +1526,12 @@ void nodesDestroyNode(SNode* pNode) {
|
|||
nodesDestroyNode(pLogicNode->pTimeSeries);
|
||||
break;
|
||||
}
|
||||
case QUERY_NODE_LOGIC_PLAN_FORECAST_FUNC: {
|
||||
SForecastFuncLogicNode* pLogicNode = (SForecastFuncLogicNode*)pNode;
|
||||
destroyLogicNode((SLogicNode*)pLogicNode);
|
||||
nodesDestroyList(pLogicNode->pFuncs);
|
||||
break;
|
||||
}
|
||||
case QUERY_NODE_LOGIC_PLAN_GROUP_CACHE: {
|
||||
SGroupCacheLogicNode* pLogicNode = (SGroupCacheLogicNode*)pNode;
|
||||
destroyLogicNode((SLogicNode*)pLogicNode);
|
||||
|
@ -1663,6 +1695,11 @@ void nodesDestroyNode(SNode* pNode) {
|
|||
destroyWinodwPhysiNode((SWindowPhysiNode*)pPhyNode);
|
||||
break;
|
||||
}
|
||||
case QUERY_NODE_PHYSICAL_PLAN_MERGE_ANOMALY: {
|
||||
SAnomalyWindowPhysiNode* pPhyNode = (SAnomalyWindowPhysiNode*)pNode;
|
||||
destroyWinodwPhysiNode((SWindowPhysiNode*)pPhyNode);
|
||||
break;
|
||||
}
|
||||
case QUERY_NODE_PHYSICAL_PLAN_PARTITION: {
|
||||
destroyPartitionPhysiNode((SPartitionPhysiNode*)pNode);
|
||||
break;
|
||||
|
@ -1690,6 +1727,13 @@ void nodesDestroyNode(SNode* pNode) {
|
|||
nodesDestroyNode(pPhyNode->pTimeSeries);
|
||||
break;
|
||||
}
|
||||
case QUERY_NODE_PHYSICAL_PLAN_FORECAST_FUNC: {
|
||||
SForecastFuncPhysiNode* pPhyNode = (SForecastFuncPhysiNode*)pNode;
|
||||
destroyPhysiNode((SPhysiNode*)pPhyNode);
|
||||
nodesDestroyList(pPhyNode->pExprs);
|
||||
nodesDestroyList(pPhyNode->pFuncs);
|
||||
break;
|
||||
}
|
||||
case QUERY_NODE_PHYSICAL_PLAN_DISPATCH:
|
||||
destroyDataSinkNode((SDataSinkNode*)pNode);
|
||||
break;
|
||||
|
|
|
@ -154,6 +154,7 @@ SNode* createSessionWindowNode(SAstCreateContext* pCxt, SNode* pCol, SNode*
|
|||
SNode* createStateWindowNode(SAstCreateContext* pCxt, SNode* pExpr);
|
||||
SNode* createEventWindowNode(SAstCreateContext* pCxt, SNode* pStartCond, SNode* pEndCond);
|
||||
SNode* createCountWindowNode(SAstCreateContext* pCxt, const SToken* pCountToken, const SToken* pSlidingToken);
|
||||
SNode* createAnomalyWindowNode(SAstCreateContext* pCxt, SNode* pExpr, const SToken* pFuncOpt);
|
||||
SNode* createIntervalWindowNode(SAstCreateContext* pCxt, SNode* pInterval, SNode* pOffset, SNode* pSliding,
|
||||
SNode* pFill);
|
||||
SNode* createWindowOffsetNode(SAstCreateContext* pCxt, SNode* pStartOffset, SNode* pEndOffset);
|
||||
|
@ -251,6 +252,9 @@ SNode* createDropUserStmt(SAstCreateContext* pCxt, SToken* pUserName);
|
|||
SNode* createCreateDnodeStmt(SAstCreateContext* pCxt, const SToken* pFqdn, const SToken* pPort);
|
||||
SNode* createDropDnodeStmt(SAstCreateContext* pCxt, const SToken* pDnode, bool force, bool unsafe);
|
||||
SNode* createAlterDnodeStmt(SAstCreateContext* pCxt, const SToken* pDnode, const SToken* pConfig, const SToken* pValue);
|
||||
SNode* createCreateAnodeStmt(SAstCreateContext* pCxt, const SToken* pUrl);
|
||||
SNode* createDropAnodeStmt(SAstCreateContext* pCxt, const SToken* pAnode);
|
||||
SNode* createUpdateAnodeStmt(SAstCreateContext* pCxt, const SToken* pAnode, bool updateAll);
|
||||
SNode* createEncryptKeyStmt(SAstCreateContext* pCxt, const SToken* pValue);
|
||||
SNode* createRealTableNodeForIndexName(SAstCreateContext* pCxt, SToken* pDbName, SToken* pIndexName);
|
||||
SNode* createCreateIndexStmt(SAstCreateContext* pCxt, EIndexType type, bool ignoreExists, SNode* pIndexName,
|
||||
|
|
|
@ -157,6 +157,12 @@ with_clause_opt(A) ::= WITH search_condition(B).
|
|||
/************************************************ create encrypt_key *********************************************/
|
||||
cmd ::= CREATE ENCRYPT_KEY NK_STRING(A). { pCxt->pRootNode = createEncryptKeyStmt(pCxt, &A); }
|
||||
|
||||
/************************************************ create drop update anode ***************************************/
|
||||
cmd ::= CREATE ANODE NK_STRING(A). { pCxt->pRootNode = createCreateAnodeStmt(pCxt, &A); }
|
||||
cmd ::= UPDATE ANODE NK_INTEGER(A). { pCxt->pRootNode = createUpdateAnodeStmt(pCxt, &A, false); }
|
||||
cmd ::= UPDATE ALL ANODES. { pCxt->pRootNode = createUpdateAnodeStmt(pCxt, NULL, true); }
|
||||
cmd ::= DROP ANODE NK_INTEGER(A). { pCxt->pRootNode = createDropAnodeStmt(pCxt, &A); }
|
||||
|
||||
/************************************************ create/drop/alter/restore dnode *********************************************/
|
||||
cmd ::= CREATE DNODE dnode_endpoint(A). { pCxt->pRootNode = createCreateDnodeStmt(pCxt, &A, NULL); }
|
||||
cmd ::= CREATE DNODE dnode_endpoint(A) PORT NK_INTEGER(B). { pCxt->pRootNode = createCreateDnodeStmt(pCxt, &A, &B); }
|
||||
|
@ -524,6 +530,8 @@ cmd ::= SHOW db_name_cond_opt(A) VGROUPS.
|
|||
cmd ::= SHOW MNODES. { pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_MNODES_STMT); }
|
||||
//cmd ::= SHOW MODULES. { pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_MODULES_STMT); }
|
||||
cmd ::= SHOW QNODES. { pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_QNODES_STMT); }
|
||||
cmd ::= SHOW ANODES. { pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_ANODES_STMT); }
|
||||
cmd ::= SHOW ANODES FULL. { pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_ANODES_FULL_STMT); }
|
||||
cmd ::= SHOW ARBGROUPS. { pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_ARBGROUPS_STMT); }
|
||||
cmd ::= SHOW FUNCTIONS. { pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_FUNCTIONS_STMT); }
|
||||
cmd ::= SHOW INDEXES FROM table_name_cond(A) from_db_opt(B). { pCxt->pRootNode = createShowStmtWithCond(pCxt, QUERY_NODE_SHOW_INDEXES_STMT, B, A, OP_TYPE_EQUAL); }
|
||||
|
@ -1187,6 +1195,9 @@ pseudo_column(A) ::= WDURATION(B).
|
|||
pseudo_column(A) ::= IROWTS(B). { A = createRawExprNode(pCxt, &B, createFunctionNode(pCxt, &B, NULL)); }
|
||||
pseudo_column(A) ::= ISFILLED(B). { A = createRawExprNode(pCxt, &B, createFunctionNode(pCxt, &B, NULL)); }
|
||||
pseudo_column(A) ::= QTAGS(B). { A = createRawExprNode(pCxt, &B, createFunctionNode(pCxt, &B, NULL)); }
|
||||
pseudo_column(A) ::= FLOW(B). { A = createRawExprNode(pCxt, &B, createFunctionNode(pCxt, &B, NULL)); }
|
||||
pseudo_column(A) ::= FHIGH(B). { A = createRawExprNode(pCxt, &B, createFunctionNode(pCxt, &B, NULL)); }
|
||||
pseudo_column(A) ::= FROWTS(B). { A = createRawExprNode(pCxt, &B, createFunctionNode(pCxt, &B, NULL)); }
|
||||
|
||||
function_expression(A) ::= function_name(B) NK_LP expression_list(C) NK_RP(D). { A = createRawExprNodeExt(pCxt, &B, &D, createFunctionNode(pCxt, &B, C)); }
|
||||
function_expression(A) ::= star_func(B) NK_LP star_func_para_list(C) NK_RP(D). { A = createRawExprNodeExt(pCxt, &B, &D, createFunctionNode(pCxt, &B, C)); }
|
||||
|
@ -1505,6 +1516,10 @@ twindow_clause_opt(A) ::=
|
|||
COUNT_WINDOW NK_LP NK_INTEGER(B) NK_RP. { A = createCountWindowNode(pCxt, &B, &B); }
|
||||
twindow_clause_opt(A) ::=
|
||||
COUNT_WINDOW NK_LP NK_INTEGER(B) NK_COMMA NK_INTEGER(C) NK_RP. { A = createCountWindowNode(pCxt, &B, &C); }
|
||||
twindow_clause_opt(A) ::=
|
||||
ANOMALY_WINDOW NK_LP expr_or_subquery(B) NK_RP. { A = createAnomalyWindowNode(pCxt, releaseRawExprNode(pCxt, B), NULL); }
|
||||
twindow_clause_opt(A) ::=
|
||||
ANOMALY_WINDOW NK_LP expr_or_subquery(B) NK_COMMA NK_STRING(C) NK_RP. { A = createAnomalyWindowNode(pCxt, releaseRawExprNode(pCxt, B), &C); }
|
||||
|
||||
sliding_opt(A) ::= . { A = NULL; }
|
||||
sliding_opt(A) ::= SLIDING NK_LP interval_sliding_duration_literal(B) NK_RP. { A = releaseRawExprNode(pCxt, B); }
|
||||
|
|
|
@ -1367,6 +1367,25 @@ _err:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
SNode* createAnomalyWindowNode(SAstCreateContext* pCxt, SNode* pExpr, const SToken* pFuncOpt) {
|
||||
SAnomalyWindowNode* pAnomaly = NULL;
|
||||
CHECK_PARSER_STATUS(pCxt);
|
||||
pCxt->errCode = nodesMakeNode(QUERY_NODE_ANOMALY_WINDOW, (SNode**)&pAnomaly);
|
||||
CHECK_MAKE_NODE(pAnomaly);
|
||||
pAnomaly->pCol = createPrimaryKeyCol(pCxt, NULL);
|
||||
CHECK_MAKE_NODE(pAnomaly->pCol);
|
||||
pAnomaly->pExpr = pExpr;
|
||||
if (pFuncOpt == NULL) {
|
||||
tstrncpy(pAnomaly->anomalyOpt, "algo=iqr", TSDB_ANAL_ALGO_OPTION_LEN);
|
||||
} else {
|
||||
(void)trimString(pFuncOpt->z, pFuncOpt->n, pAnomaly->anomalyOpt, sizeof(pAnomaly->anomalyOpt));
|
||||
}
|
||||
return (SNode*)pAnomaly;
|
||||
_err:
|
||||
nodesDestroyNode((SNode*)pAnomaly);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SNode* createIntervalWindowNode(SAstCreateContext* pCxt, SNode* pInterval, SNode* pOffset, SNode* pSliding,
|
||||
SNode* pFill) {
|
||||
SIntervalWindowNode* interval = NULL;
|
||||
|
@ -2997,6 +3016,47 @@ _err:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
SNode* createCreateAnodeStmt(SAstCreateContext* pCxt, const SToken* pUrl) {
|
||||
CHECK_PARSER_STATUS(pCxt);
|
||||
SCreateAnodeStmt* pStmt = NULL;
|
||||
pCxt->errCode = nodesMakeNode(QUERY_NODE_CREATE_ANODE_STMT, (SNode**)&pStmt);
|
||||
CHECK_MAKE_NODE(pStmt);
|
||||
(void)trimString(pUrl->z, pUrl->n, pStmt->url, sizeof(pStmt->url));
|
||||
return (SNode*)pStmt;
|
||||
_err:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SNode* createDropAnodeStmt(SAstCreateContext* pCxt, const SToken* pAnode) {
|
||||
CHECK_PARSER_STATUS(pCxt);
|
||||
SUpdateAnodeStmt* pStmt = NULL;
|
||||
pCxt->errCode = nodesMakeNode(QUERY_NODE_DROP_ANODE_STMT, (SNode**)&pStmt);
|
||||
CHECK_MAKE_NODE(pStmt);
|
||||
if (NULL != pAnode) {
|
||||
pStmt->anodeId = taosStr2Int32(pAnode->z, NULL, 10);
|
||||
} else {
|
||||
pStmt->anodeId = -1;
|
||||
}
|
||||
return (SNode*)pStmt;
|
||||
_err:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SNode* createUpdateAnodeStmt(SAstCreateContext* pCxt, const SToken* pAnode, bool updateAll) {
|
||||
CHECK_PARSER_STATUS(pCxt);
|
||||
SUpdateAnodeStmt* pStmt = NULL;
|
||||
pCxt->errCode = nodesMakeNode(QUERY_NODE_UPDATE_ANODE_STMT, (SNode**)&pStmt);
|
||||
CHECK_MAKE_NODE(pStmt);
|
||||
if (NULL != pAnode) {
|
||||
pStmt->anodeId = taosStr2Int32(pAnode->z, NULL, 10);
|
||||
} else {
|
||||
pStmt->anodeId = -1;
|
||||
}
|
||||
return (SNode*)pStmt;
|
||||
_err:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SNode* createEncryptKeyStmt(SAstCreateContext* pCxt, const SToken* pValue) {
|
||||
SToken config;
|
||||
config.type = TK_NK_STRING;
|
||||
|
|
|
@ -555,6 +555,22 @@ static int32_t collectMetaKeyFromShowSnodes(SCollectMetaKeyCxt* pCxt, SShowStmt*
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t collectMetaKeyFromShowAnodes(SCollectMetaKeyCxt* pCxt, SShowStmt* pStmt) {
|
||||
if (pCxt->pParseCxt->enableSysInfo) {
|
||||
return reserveTableMetaInCache(pCxt->pParseCxt->acctId, TSDB_INFORMATION_SCHEMA_DB, TSDB_INS_TABLE_ANODES,
|
||||
pCxt->pMetaCache);
|
||||
}
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t collectMetaKeyFromShowAnodesFull(SCollectMetaKeyCxt* pCxt, SShowStmt* pStmt) {
|
||||
if (pCxt->pParseCxt->enableSysInfo) {
|
||||
return reserveTableMetaInCache(pCxt->pParseCxt->acctId, TSDB_INFORMATION_SCHEMA_DB, TSDB_INS_TABLE_ANODES_FULL,
|
||||
pCxt->pMetaCache);
|
||||
}
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t collectMetaKeyFromShowBnodes(SCollectMetaKeyCxt* pCxt, SShowStmt* pStmt) {
|
||||
if (pCxt->pParseCxt->enableSysInfo) {
|
||||
return reserveTableMetaInCache(pCxt->pParseCxt->acctId, TSDB_INFORMATION_SCHEMA_DB, TSDB_INS_TABLE_BNODES,
|
||||
|
@ -983,6 +999,10 @@ static int32_t collectMetaKeyFromQuery(SCollectMetaKeyCxt* pCxt, SNode* pStmt) {
|
|||
return collectMetaKeyFromShowQnodes(pCxt, (SShowStmt*)pStmt);
|
||||
case QUERY_NODE_SHOW_SNODES_STMT:
|
||||
return collectMetaKeyFromShowSnodes(pCxt, (SShowStmt*)pStmt);
|
||||
case QUERY_NODE_SHOW_ANODES_STMT:
|
||||
return collectMetaKeyFromShowAnodes(pCxt, (SShowStmt*)pStmt);
|
||||
case QUERY_NODE_SHOW_ANODES_FULL_STMT:
|
||||
return collectMetaKeyFromShowAnodesFull(pCxt, (SShowStmt*)pStmt);
|
||||
case QUERY_NODE_SHOW_BNODES_STMT:
|
||||
return collectMetaKeyFromShowBnodes(pCxt, (SShowStmt*)pStmt);
|
||||
case QUERY_NODE_SHOW_ARBGROUPS_STMT:
|
||||
|
|
|
@ -358,6 +358,8 @@ static int32_t authQuery(SAuthCxt* pCxt, SNode* pStmt) {
|
|||
case QUERY_NODE_SHOW_MNODES_STMT:
|
||||
case QUERY_NODE_SHOW_MODULES_STMT:
|
||||
case QUERY_NODE_SHOW_QNODES_STMT:
|
||||
case QUERY_NODE_SHOW_ANODES_STMT:
|
||||
case QUERY_NODE_SHOW_ANODES_FULL_STMT:
|
||||
case QUERY_NODE_SHOW_SNODES_STMT:
|
||||
case QUERY_NODE_SHOW_BNODES_STMT:
|
||||
case QUERY_NODE_SHOW_CLUSTER_STMT:
|
||||
|
|
|
@ -38,6 +38,9 @@ static SKeyword keywordTable[] = {
|
|||
{"ANALYZE", TK_ANALYZE},
|
||||
{"AND", TK_AND},
|
||||
{"ANTI", TK_ANTI},
|
||||
{"ANODE", TK_ANODE},
|
||||
{"ANODES", TK_ANODES},
|
||||
{"ANOMALY_WINDOW", TK_ANOMALY_WINDOW},
|
||||
// {"ANY", TK_ANY},
|
||||
{"APPS", TK_APPS},
|
||||
{"AS", TK_AS},
|
||||
|
@ -332,6 +335,9 @@ static SKeyword keywordTable[] = {
|
|||
{"_WDURATION", TK_WDURATION},
|
||||
{"_WEND", TK_WEND},
|
||||
{"_WSTART", TK_WSTART},
|
||||
{"_FLOW", TK_FLOW},
|
||||
{"_FHIGH", TK_FHIGH},
|
||||
{"_FROWTS", TK_FROWTS},
|
||||
{"ALIVE", TK_ALIVE},
|
||||
{"VARBINARY", TK_VARBINARY},
|
||||
{"S3_CHUNKSIZE", TK_S3_CHUNKSIZE},
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "parUtil.h"
|
||||
#include "scalar.h"
|
||||
#include "systable.h"
|
||||
#include "tanal.h"
|
||||
#include "tcol.h"
|
||||
#include "tglobal.h"
|
||||
#include "ttime.h"
|
||||
|
@ -348,6 +349,20 @@ static const SSysTableShowAdapter sysTableShowAdapter[] = {
|
|||
.numOfShowCols = 1,
|
||||
.pShowCols = {"*"}
|
||||
},
|
||||
{
|
||||
.showType = QUERY_NODE_SHOW_ANODES_STMT,
|
||||
.pDbName = TSDB_INFORMATION_SCHEMA_DB,
|
||||
.pTableName = TSDB_INS_TABLE_ANODES,
|
||||
.numOfShowCols = 1,
|
||||
.pShowCols = {"*"}
|
||||
},
|
||||
{
|
||||
.showType = QUERY_NODE_SHOW_ANODES_FULL_STMT,
|
||||
.pDbName = TSDB_INFORMATION_SCHEMA_DB,
|
||||
.pTableName = TSDB_INS_TABLE_ANODES_FULL,
|
||||
.numOfShowCols = 1,
|
||||
.pShowCols = {"*"}
|
||||
},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
|
@ -1035,6 +1050,14 @@ static bool isInterpPseudoColumnFunc(const SNode* pNode) {
|
|||
return (QUERY_NODE_FUNCTION == nodeType(pNode) && fmIsInterpPseudoColumnFunc(((SFunctionNode*)pNode)->funcId));
|
||||
}
|
||||
|
||||
static bool isForecastFunc(const SNode* pNode) {
|
||||
return (QUERY_NODE_FUNCTION == nodeType(pNode) && fmIsForecastFunc(((SFunctionNode*)pNode)->funcId));
|
||||
}
|
||||
|
||||
static bool isForecastPseudoColumnFunc(const SNode* pNode) {
|
||||
return (QUERY_NODE_FUNCTION == nodeType(pNode) && fmIsForecastPseudoColumnFunc(((SFunctionNode*)pNode)->funcId));
|
||||
}
|
||||
|
||||
#ifdef BUILD_NO_CALL
|
||||
static bool isTimelineFunc(const SNode* pNode) {
|
||||
return (QUERY_NODE_FUNCTION == nodeType(pNode) && fmIsTimelineFunc(((SFunctionNode*)pNode)->funcId));
|
||||
|
@ -1237,7 +1260,7 @@ bool isPrimaryKeyImpl(SNode* pExpr) {
|
|||
FUNCTION_TYPE_LAST_ROW == pFunc->funcType || FUNCTION_TYPE_TIMETRUNCATE == pFunc->funcType) {
|
||||
return isPrimaryKeyImpl(nodesListGetNode(pFunc->pParameterList, 0));
|
||||
} else if (FUNCTION_TYPE_WSTART == pFunc->funcType || FUNCTION_TYPE_WEND == pFunc->funcType ||
|
||||
FUNCTION_TYPE_IROWTS == pFunc->funcType) {
|
||||
FUNCTION_TYPE_IROWTS == pFunc->funcType || FUNCTION_TYPE_FORECAST_ROWTS == pFunc->funcType) {
|
||||
return true;
|
||||
}
|
||||
} else if (QUERY_NODE_OPERATOR == nodeType(pExpr)) {
|
||||
|
@ -2250,7 +2273,7 @@ static EDealRes translateOperator(STranslateContext* pCxt, SOperatorNode* pOp) {
|
|||
|
||||
static EDealRes haveVectorFunction(SNode* pNode, void* pContext) {
|
||||
if (isAggFunc(pNode) || isIndefiniteRowsFunc(pNode) || isWindowPseudoColumnFunc(pNode) ||
|
||||
isInterpPseudoColumnFunc(pNode)) {
|
||||
isInterpPseudoColumnFunc(pNode) || isForecastPseudoColumnFunc(pNode)) {
|
||||
*((bool*)pContext) = true;
|
||||
return DEAL_RES_END;
|
||||
}
|
||||
|
@ -2553,6 +2576,72 @@ static int32_t translateInterpPseudoColumnFunc(STranslateContext* pCxt, SNode**
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t translateForecastFunc(STranslateContext* pCxt, SFunctionNode* pFunc) {
|
||||
if (!fmIsForecastFunc(pFunc->funcId)) {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
if (!isSelectStmt(pCxt->pCurrStmt) || SQL_CLAUSE_SELECT != pCxt->currClause) {
|
||||
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_NOT_ALLOWED_FUNC);
|
||||
}
|
||||
SSelectStmt* pSelect = (SSelectStmt*)pCxt->pCurrStmt;
|
||||
SNode* pTable = pSelect->pFromTable;
|
||||
|
||||
if (pSelect->hasAggFuncs || pSelect->hasMultiRowsFunc || pSelect->hasIndefiniteRowsFunc) {
|
||||
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_NOT_ALLOWED_FUNC);
|
||||
}
|
||||
|
||||
if (pSelect->hasForecastFunc &&
|
||||
(FUNC_RETURN_ROWS_INDEFINITE == pSelect->returnRows || pSelect->returnRows != fmGetFuncReturnRows(pFunc))) {
|
||||
return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_NOT_ALLOWED_FUNC,
|
||||
"%s ignoring null value options cannot be used when applying to multiple columns",
|
||||
pFunc->functionName);
|
||||
}
|
||||
|
||||
if (NULL != pSelect->pWindow || NULL != pSelect->pGroupByList) {
|
||||
return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_NOT_ALLOWED_FUNC,
|
||||
"%s function is not supported in window query or group query", pFunc->functionName);
|
||||
}
|
||||
if (hasInvalidFuncNesting(pFunc->pParameterList)) {
|
||||
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_AGG_FUNC_NESTING);
|
||||
}
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t translateForecastPseudoColumnFunc(STranslateContext* pCxt, SNode** ppNode, bool* pRewriteToColumn) {
|
||||
SFunctionNode* pFunc = (SFunctionNode*)(*ppNode);
|
||||
if (!fmIsForecastPseudoColumnFunc(pFunc->funcId)) {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
if (!isSelectStmt(pCxt->pCurrStmt)) {
|
||||
return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_NOT_ALLOWED_FUNC,
|
||||
"%s must be used in select statements", pFunc->functionName);
|
||||
}
|
||||
if (pCxt->currClause == SQL_CLAUSE_WHERE) {
|
||||
return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_INTERP_CLAUSE,
|
||||
"%s is not allowed in where clause", pFunc->functionName);
|
||||
}
|
||||
|
||||
SSelectStmt* pSelect = (SSelectStmt*)pCxt->pCurrStmt;
|
||||
SNode* pNode = NULL;
|
||||
bool bFound = false;
|
||||
FOREACH(pNode, pSelect->pProjectionList) {
|
||||
if (nodeType(pNode) == QUERY_NODE_FUNCTION && strcasecmp(((SFunctionNode*)pNode)->functionName, "forecast") == 0) {
|
||||
bFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!bFound) {
|
||||
*pRewriteToColumn = true;
|
||||
int32_t code = replacePsedudoColumnFuncWithColumn(pCxt, ppNode);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
}
|
||||
(void)translateColumn(pCxt, (SColumnNode**)ppNode);
|
||||
return pCxt->errCode;
|
||||
}
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t translateTimelineFunc(STranslateContext* pCxt, SFunctionNode* pFunc) {
|
||||
if (!fmIsTimelineFunc(pFunc->funcId)) {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
|
@ -2738,7 +2827,9 @@ static void setFuncClassification(STranslateContext* pCxt, SFunctionNode* pFunc)
|
|||
pSelect->returnRows = fmGetFuncReturnRows(pFunc);
|
||||
} else if (fmIsInterpFunc(pFunc->funcId)) {
|
||||
pSelect->returnRows = fmGetFuncReturnRows(pFunc);
|
||||
}
|
||||
} else if (fmIsForecastFunc(pFunc->funcId)) {
|
||||
pSelect->returnRows = fmGetFuncReturnRows(pFunc);
|
||||
}
|
||||
if (fmIsProcessByRowFunc(pFunc->funcId)) {
|
||||
pSelect->lastProcessByRowFuncId = pFunc->funcId;
|
||||
}
|
||||
|
@ -2755,6 +2846,9 @@ static void setFuncClassification(STranslateContext* pCxt, SFunctionNode* pFunc)
|
|||
pSelect->hasInterpFunc = pSelect->hasInterpFunc ? true : (FUNCTION_TYPE_INTERP == pFunc->funcType);
|
||||
pSelect->hasInterpPseudoColFunc =
|
||||
pSelect->hasInterpPseudoColFunc ? true : fmIsInterpPseudoColumnFunc(pFunc->funcId);
|
||||
pSelect->hasForecastFunc = pSelect->hasForecastFunc ? true : (FUNCTION_TYPE_FORECAST == pFunc->funcType);
|
||||
pSelect->hasForecastPseudoColFunc =
|
||||
pSelect->hasForecastPseudoColFunc ? true : fmIsForecastPseudoColumnFunc(pFunc->funcId);
|
||||
pSelect->hasLastRowFunc = pSelect->hasLastRowFunc ? true : (FUNCTION_TYPE_LAST_ROW == pFunc->funcType);
|
||||
pSelect->hasLastFunc = pSelect->hasLastFunc ? true : (FUNCTION_TYPE_LAST == pFunc->funcType);
|
||||
pSelect->hasTimeLineFunc = pSelect->hasTimeLineFunc ? true : fmIsTimelineFunc(pFunc->funcId);
|
||||
|
@ -2946,6 +3040,9 @@ static int32_t translateScanPseudoColumnFunc(STranslateContext* pCxt, SNode** pp
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
if (0 == LIST_LENGTH(pFunc->pParameterList)) {
|
||||
if (pFunc->funcType == FUNCTION_TYPE_FORECAST_LOW || pFunc->funcType == FUNCTION_TYPE_FORECAST_HIGH) {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
if (!isSelectStmt(pCxt->pCurrStmt) || NULL == ((SSelectStmt*)pCxt->pCurrStmt)->pFromTable) {
|
||||
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_TBNAME);
|
||||
}
|
||||
|
@ -3016,6 +3113,16 @@ static int32_t translateNormalFunction(STranslateContext* pCxt, SNode** ppNode)
|
|||
return code;
|
||||
}
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = translateForecastFunc(pCxt, pFunc);
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
bool bRewriteToColumn = false;
|
||||
code = translateForecastPseudoColumnFunc(pCxt, ppNode, &bRewriteToColumn);
|
||||
if (bRewriteToColumn) {
|
||||
return code;
|
||||
}
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = translateTimelineFunc(pCxt, pFunc);
|
||||
}
|
||||
|
@ -3759,7 +3866,8 @@ static int32_t resetSelectFuncNumWithoutDup(SSelectStmt* pSelect) {
|
|||
|
||||
static int32_t checkAggColCoexist(STranslateContext* pCxt, SSelectStmt* pSelect) {
|
||||
if (NULL != pSelect->pGroupByList || NULL != pSelect->pWindow || isWindowJoinStmt(pSelect) ||
|
||||
(!pSelect->hasAggFuncs && !pSelect->hasIndefiniteRowsFunc && !pSelect->hasInterpFunc)) {
|
||||
(!pSelect->hasAggFuncs && !pSelect->hasIndefiniteRowsFunc && !pSelect->hasInterpFunc &&
|
||||
!pSelect->hasForecastFunc)) {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
if (!pSelect->onlyHasKeepOrderFunc) {
|
||||
|
@ -3782,7 +3890,7 @@ static int32_t checkAggColCoexist(STranslateContext* pCxt, SSelectStmt* pSelect)
|
|||
|
||||
static int32_t checkWinJoinAggColCoexist(STranslateContext* pCxt, SSelectStmt* pSelect) {
|
||||
if (!isWindowJoinStmt(pSelect) || (!pSelect->hasAggFuncs && !pSelect->hasIndefiniteRowsFunc &&
|
||||
!pSelect->hasInterpFunc)) {
|
||||
!pSelect->hasInterpFunc && !pSelect->hasForecastFunc)) {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
if (!pSelect->onlyHasKeepOrderFunc) {
|
||||
|
@ -5795,6 +5903,40 @@ static int32_t translateCountWindow(STranslateContext* pCxt, SSelectStmt* pSelec
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t checkAnomalyExpr(STranslateContext* pCxt, SNode* pNode) {
|
||||
int32_t type = ((SExprNode*)pNode)->resType.type;
|
||||
if (!IS_MATHABLE_TYPE(type)) {
|
||||
return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_ANOMALY_WIN_TYPE,
|
||||
"ANOMALY_WINDOW only support mathable column");
|
||||
}
|
||||
|
||||
if (QUERY_NODE_COLUMN == nodeType(pNode) && COLUMN_TYPE_TAG == ((SColumnNode*)pNode)->colType) {
|
||||
return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_ANOMALY_WIN_COL,
|
||||
"ANOMALY_WINDOW not support on tag column");
|
||||
}
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t translateAnomalyWindow(STranslateContext* pCxt, SSelectStmt* pSelect) {
|
||||
if (QUERY_NODE_TEMP_TABLE == nodeType(pSelect->pFromTable) &&
|
||||
!isGlobalTimeLineQuery(((STempTableNode*)pSelect->pFromTable)->pSubquery)) {
|
||||
return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_TIMELINE_QUERY,
|
||||
"ANOMALY_WINDOW requires valid time series input");
|
||||
}
|
||||
|
||||
SAnomalyWindowNode* pAnomaly = (SAnomalyWindowNode*)pSelect->pWindow;
|
||||
int32_t code = checkAnomalyExpr(pCxt, pAnomaly->pExpr);
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
if (!taosAnalGetOptStr(pAnomaly->anomalyOpt, "algo", NULL, 0) != 0) {
|
||||
return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_ANOMALY_WIN_OPT,
|
||||
"ANOMALY_WINDOW option should include algo field");
|
||||
}
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t translateSpecificWindow(STranslateContext* pCxt, SSelectStmt* pSelect) {
|
||||
switch (nodeType(pSelect->pWindow)) {
|
||||
case QUERY_NODE_STATE_WINDOW:
|
||||
|
@ -5807,6 +5949,8 @@ static int32_t translateSpecificWindow(STranslateContext* pCxt, SSelectStmt* pSe
|
|||
return translateEventWindow(pCxt, pSelect);
|
||||
case QUERY_NODE_COUNT_WINDOW:
|
||||
return translateCountWindow(pCxt, pSelect);
|
||||
case QUERY_NODE_ANOMALY_WINDOW:
|
||||
return translateAnomalyWindow(pCxt, pSelect);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -6043,6 +6187,26 @@ static int32_t translateInterp(STranslateContext* pCxt, SSelectStmt* pSelect) {
|
|||
return code;
|
||||
}
|
||||
|
||||
static int32_t translateForecast(STranslateContext* pCxt, SSelectStmt* pSelect) {
|
||||
if (!pSelect->hasForecastFunc) {
|
||||
if (pSelect->hasForecastPseudoColFunc) {
|
||||
return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_NOT_ALLOWED_FUNC,
|
||||
"Has Forecast pseudo column(s) but missing forcast function");
|
||||
}
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
if ((NULL != pSelect->pFromTable) && (QUERY_NODE_JOIN_TABLE == nodeType(pSelect->pFromTable))) {
|
||||
SJoinTableNode* pJoinTable = (SJoinTableNode*)pSelect->pFromTable;
|
||||
if (IS_WINDOW_JOIN(pJoinTable->subType)) {
|
||||
return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_FORECAST_CLAUSE,
|
||||
"Forecast not supported to be used in WINDOW join");
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t removeConstantValueFromList(SNodeList** pList) {
|
||||
SNode* pNode = NULL;
|
||||
WHERE_EACH(pNode, *pList) {
|
||||
|
@ -6884,6 +7048,9 @@ static int32_t translateSelectFrom(STranslateContext* pCxt, SSelectStmt* pSelect
|
|||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = translateInterp(pCxt, pSelect);
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = translateForecast(pCxt, pSelect);
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = appendTsForImplicitTsFunc(pCxt, pSelect);
|
||||
}
|
||||
|
@ -7895,6 +8062,19 @@ static int32_t fillCmdSql(STranslateContext* pCxt, int16_t msgType, void* pReq)
|
|||
break;
|
||||
}
|
||||
|
||||
case TDMT_MND_CREATE_ANODE: {
|
||||
FILL_CMD_SQL(sql, sqlLen, pCmdReq, SMCreateAnodeReq, pReq);
|
||||
break;
|
||||
}
|
||||
case TDMT_MND_DROP_ANODE: {
|
||||
FILL_CMD_SQL(sql, sqlLen, pCmdReq, SMDropAnodeReq, pReq);
|
||||
break;
|
||||
}
|
||||
case TDMT_MND_UPDATE_ANODE: {
|
||||
FILL_CMD_SQL(sql, sqlLen, pCmdReq, SMUpdateAnodeReq, pReq);
|
||||
break;
|
||||
}
|
||||
|
||||
case TDMT_MND_CREATE_MNODE: {
|
||||
FILL_CMD_SQL(sql, sqlLen, pCmdReq, SMCreateMnodeReq, pReq);
|
||||
break;
|
||||
|
@ -9398,6 +9578,43 @@ static int32_t translateDropUser(STranslateContext* pCxt, SDropUserStmt* pStmt)
|
|||
return code;
|
||||
}
|
||||
|
||||
static int32_t translateCreateAnode(STranslateContext* pCxt, SCreateAnodeStmt* pStmt) {
|
||||
SMCreateAnodeReq createReq = {0};
|
||||
createReq.urlLen = strlen(pStmt->url) + 1;
|
||||
if (createReq.urlLen > TSDB_ANAL_ANODE_URL_LEN) {
|
||||
return TSDB_CODE_MND_ANODE_TOO_LONG_URL;
|
||||
}
|
||||
|
||||
createReq.url = taosMemoryCalloc(createReq.urlLen, 1);
|
||||
if (createReq.url == NULL) {
|
||||
return TSDB_CODE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
tstrncpy(createReq.url, pStmt->url, createReq.urlLen);
|
||||
|
||||
int32_t code = buildCmdMsg(pCxt, TDMT_MND_CREATE_ANODE, (FSerializeFunc)tSerializeSMCreateAnodeReq, &createReq);
|
||||
tFreeSMCreateAnodeReq(&createReq);
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t translateDropAnode(STranslateContext* pCxt, SDropAnodeStmt* pStmt) {
|
||||
SMDropAnodeReq dropReq = {0};
|
||||
dropReq.anodeId = pStmt->anodeId;
|
||||
|
||||
int32_t code = buildCmdMsg(pCxt, TDMT_MND_DROP_ANODE, (FSerializeFunc)tSerializeSMDropAnodeReq, &dropReq);
|
||||
tFreeSMDropAnodeReq(&dropReq);
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t translateUpdateAnode(STranslateContext* pCxt, SUpdateAnodeStmt* pStmt) {
|
||||
SMUpdateAnodeReq updateReq = {0};
|
||||
updateReq.anodeId = pStmt->anodeId;
|
||||
|
||||
int32_t code = buildCmdMsg(pCxt, TDMT_MND_UPDATE_ANODE, (FSerializeFunc)tSerializeSMUpdateAnodeReq, &updateReq);
|
||||
tFreeSMUpdateAnodeReq(&updateReq);
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t translateCreateDnode(STranslateContext* pCxt, SCreateDnodeStmt* pStmt) {
|
||||
SCreateDnodeReq createReq = {0};
|
||||
strcpy(createReq.fqdn, pStmt->fqdn);
|
||||
|
@ -9820,7 +10037,7 @@ static int32_t translateDropComponentNode(STranslateContext* pCxt, SDropComponen
|
|||
}
|
||||
|
||||
static int32_t checkTopicQuery(STranslateContext* pCxt, SSelectStmt* pSelect) {
|
||||
if (pSelect->hasAggFuncs || pSelect->hasInterpFunc || pSelect->hasIndefiniteRowsFunc) {
|
||||
if (pSelect->hasAggFuncs || pSelect->hasForecastFunc || pSelect->hasInterpFunc || pSelect->hasIndefiniteRowsFunc) {
|
||||
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_TOPIC_QUERY);
|
||||
}
|
||||
return TSDB_CODE_SUCCESS;
|
||||
|
@ -10186,7 +10403,7 @@ static int32_t translateKillTransaction(STranslateContext* pCxt, SKillStmt* pStm
|
|||
|
||||
static bool crossTableWithoutAggOper(SSelectStmt* pSelect) {
|
||||
return NULL == pSelect->pWindow && !pSelect->hasAggFuncs && !pSelect->hasIndefiniteRowsFunc &&
|
||||
!pSelect->hasInterpFunc &&
|
||||
!pSelect->hasInterpFunc && !pSelect->hasForecastFunc &&
|
||||
TSDB_SUPER_TABLE == ((SRealTableNode*)pSelect->pFromTable)->pMeta->tableType &&
|
||||
!hasTbnameFunction(pSelect->pPartitionByList);
|
||||
}
|
||||
|
@ -12395,6 +12612,15 @@ static int32_t translateQuery(STranslateContext* pCxt, SNode* pNode) {
|
|||
case QUERY_NODE_ALTER_DNODE_STMT:
|
||||
code = translateAlterDnode(pCxt, (SAlterDnodeStmt*)pNode);
|
||||
break;
|
||||
case QUERY_NODE_CREATE_ANODE_STMT:
|
||||
code = translateCreateAnode(pCxt, (SCreateAnodeStmt*)pNode);
|
||||
break;
|
||||
case QUERY_NODE_DROP_ANODE_STMT:
|
||||
code = translateDropAnode(pCxt, (SDropAnodeStmt*)pNode);
|
||||
break;
|
||||
case QUERY_NODE_UPDATE_ANODE_STMT:
|
||||
code = translateUpdateAnode(pCxt, (SUpdateAnodeStmt*)pNode);
|
||||
break;
|
||||
case QUERY_NODE_CREATE_INDEX_STMT:
|
||||
code = translateCreateIndex(pCxt, (SCreateIndexStmt*)pNode);
|
||||
break;
|
||||
|
@ -15755,6 +15981,8 @@ static int32_t rewriteQuery(STranslateContext* pCxt, SQuery* pQuery) {
|
|||
case QUERY_NODE_SHOW_MNODES_STMT:
|
||||
case QUERY_NODE_SHOW_MODULES_STMT:
|
||||
case QUERY_NODE_SHOW_QNODES_STMT:
|
||||
case QUERY_NODE_SHOW_ANODES_STMT:
|
||||
case QUERY_NODE_SHOW_ANODES_FULL_STMT:
|
||||
case QUERY_NODE_SHOW_FUNCTIONS_STMT:
|
||||
case QUERY_NODE_SHOW_INDEXES_STMT:
|
||||
case QUERY_NODE_SHOW_STREAMS_STMT:
|
||||
|
|
|
@ -185,6 +185,8 @@ static char* getSyntaxErrFormat(int32_t errCode) {
|
|||
return "%s is not supported in system table query";
|
||||
case TSDB_CODE_PAR_INVALID_INTERP_CLAUSE:
|
||||
return "Invalid usage of RANGE clause, EVERY clause or FILL clause";
|
||||
case TSDB_CODE_PAR_INVALID_FORECAST_CLAUSE:
|
||||
return "Invalid usage of forecast clause";
|
||||
case TSDB_CODE_PAR_NO_VALID_FUNC_IN_WIN:
|
||||
return "No valid function in window query";
|
||||
case TSDB_CODE_PAR_INVALID_OPTR_USAGE:
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -973,6 +973,45 @@ static int32_t createInterpFuncLogicNode(SLogicPlanContext* pCxt, SSelectStmt* p
|
|||
return code;
|
||||
}
|
||||
|
||||
static bool isForecastFunc(int32_t funcId) {
|
||||
return fmIsForecastFunc(funcId) || fmIsForecastPseudoColumnFunc(funcId) || fmIsGroupKeyFunc(funcId) || fmisSelectGroupConstValueFunc(funcId);
|
||||
}
|
||||
|
||||
static int32_t createForecastFuncLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SLogicNode** pLogicNode) {
|
||||
if (!pSelect->hasForecastFunc) {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
SForecastFuncLogicNode* pForecastFunc = NULL;
|
||||
int32_t code = nodesMakeNode(QUERY_NODE_LOGIC_PLAN_FORECAST_FUNC, (SNode**)&pForecastFunc);
|
||||
if (NULL == pForecastFunc) {
|
||||
return code;
|
||||
}
|
||||
|
||||
pForecastFunc->node.groupAction = getGroupAction(pCxt, pSelect);
|
||||
pForecastFunc->node.requireDataOrder = getRequireDataOrder(true, pSelect);
|
||||
pForecastFunc->node.resultDataOrder = pForecastFunc->node.requireDataOrder;
|
||||
|
||||
// interp functions and _group_key functions
|
||||
code = nodesCollectFuncs(pSelect, SQL_CLAUSE_SELECT, NULL, isForecastFunc, &pForecastFunc->pFuncs);
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = rewriteExprsForSelect(pForecastFunc->pFuncs, pSelect, SQL_CLAUSE_SELECT, NULL);
|
||||
}
|
||||
|
||||
// set the output
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = createColumnByRewriteExprs(pForecastFunc->pFuncs, &pForecastFunc->node.pTargets);
|
||||
}
|
||||
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
*pLogicNode = (SLogicNode*)pForecastFunc;
|
||||
} else {
|
||||
nodesDestroyNode((SNode*)pForecastFunc);
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t createWindowLogicNodeFinalize(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SWindowLogicNode* pWindow,
|
||||
SLogicNode** pLogicNode) {
|
||||
if (pCxt->pPlanCxt->streamQuery) {
|
||||
|
@ -1174,6 +1213,48 @@ static int32_t createWindowLogicNodeByCount(SLogicPlanContext* pCxt, SCountWindo
|
|||
return createWindowLogicNodeFinalize(pCxt, pSelect, pWindow, pLogicNode);
|
||||
}
|
||||
|
||||
static int32_t createWindowLogicNodeByAnomaly(SLogicPlanContext* pCxt, SAnomalyWindowNode* pAnomaly,
|
||||
SSelectStmt* pSelect, SLogicNode** pLogicNode) {
|
||||
SWindowLogicNode* pWindow = NULL;
|
||||
int32_t code = nodesMakeNode(QUERY_NODE_LOGIC_PLAN_WINDOW, (SNode**)&pWindow);
|
||||
if (NULL == pWindow) {
|
||||
return code;
|
||||
}
|
||||
|
||||
pWindow->winType = WINDOW_TYPE_ANOMALY;
|
||||
pWindow->node.groupAction = getGroupAction(pCxt, pSelect);
|
||||
pWindow->node.requireDataOrder =
|
||||
pCxt->pPlanCxt->streamQuery ? DATA_ORDER_LEVEL_IN_BLOCK : getRequireDataOrder(true, pSelect);
|
||||
pWindow->node.resultDataOrder =
|
||||
pCxt->pPlanCxt->streamQuery ? DATA_ORDER_LEVEL_GLOBAL : pWindow->node.requireDataOrder;
|
||||
|
||||
pWindow->pAnomalyExpr = NULL;
|
||||
code = nodesCloneNode(pAnomaly->pExpr, &pWindow->pAnomalyExpr);
|
||||
if (TSDB_CODE_SUCCESS != code) {
|
||||
nodesDestroyNode((SNode*)pWindow);
|
||||
return code;
|
||||
}
|
||||
|
||||
tstrncpy(pWindow->anomalyOpt, pAnomaly->anomalyOpt, sizeof(pWindow->anomalyOpt));
|
||||
|
||||
pWindow->pTspk = NULL;
|
||||
code = nodesCloneNode(pAnomaly->pCol, &pWindow->pTspk);
|
||||
if (NULL == pWindow->pTspk) {
|
||||
nodesDestroyNode((SNode*)pWindow);
|
||||
return code;
|
||||
}
|
||||
|
||||
// rewrite the expression in subsequent clauses
|
||||
code = rewriteExprForSelect(pWindow->pAnomalyExpr, pSelect, SQL_CLAUSE_WINDOW);
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = createWindowLogicNodeFinalize(pCxt, pSelect, pWindow, pLogicNode);
|
||||
} else {
|
||||
nodesDestroyNode((SNode*)pWindow);
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t createWindowLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SLogicNode** pLogicNode) {
|
||||
if (NULL == pSelect->pWindow) {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
|
@ -1189,6 +1270,8 @@ static int32_t createWindowLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSele
|
|||
return createWindowLogicNodeByEvent(pCxt, (SEventWindowNode*)pSelect->pWindow, pSelect, pLogicNode);
|
||||
case QUERY_NODE_COUNT_WINDOW:
|
||||
return createWindowLogicNodeByCount(pCxt, (SCountWindowNode*)pSelect->pWindow, pSelect, pLogicNode);
|
||||
case QUERY_NODE_ANOMALY_WINDOW:
|
||||
return createWindowLogicNodeByAnomaly(pCxt, (SAnomalyWindowNode*)pSelect->pWindow, pSelect, pLogicNode);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -1600,6 +1683,9 @@ static int32_t createSelectFromLogicNode(SLogicPlanContext* pCxt, SSelectStmt* p
|
|||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = createSelectRootLogicNode(pCxt, pSelect, createInterpFuncLogicNode, &pRoot);
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = createSelectRootLogicNode(pCxt, pSelect, createForecastFuncLogicNode, &pRoot);
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = createSelectRootLogicNode(pCxt, pSelect, createDistinctLogicNode, &pRoot);
|
||||
}
|
||||
|
|
|
@ -2380,6 +2380,8 @@ static bool sortPriKeyOptHasUnsupportedPkFunc(SLogicNode* pLogicNode, EOrder sor
|
|||
case QUERY_NODE_LOGIC_PLAN_INTERP_FUNC:
|
||||
pFuncList = ((SInterpFuncLogicNode*)pLogicNode)->pFuncs;
|
||||
break;
|
||||
case QUERY_NODE_LOGIC_PLAN_FORECAST_FUNC:
|
||||
pFuncList = ((SForecastFuncLogicNode*)pLogicNode)->pFuncs;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -1990,6 +1990,50 @@ static int32_t createInterpFuncPhysiNode(SPhysiPlanContext* pCxt, SNodeList* pCh
|
|||
return code;
|
||||
}
|
||||
|
||||
static int32_t createForecastFuncPhysiNode(SPhysiPlanContext* pCxt, SNodeList* pChildren,
|
||||
SForecastFuncLogicNode* pFuncLogicNode, SPhysiNode** pPhyNode) {
|
||||
SForecastFuncPhysiNode* pForecastFunc =
|
||||
(SForecastFuncPhysiNode*)makePhysiNode(pCxt, (SLogicNode*)pFuncLogicNode, QUERY_NODE_PHYSICAL_PLAN_FORECAST_FUNC);
|
||||
if (NULL == pForecastFunc) {
|
||||
return terrno;
|
||||
}
|
||||
|
||||
SNodeList* pPrecalcExprs = NULL;
|
||||
SNodeList* pFuncs = NULL;
|
||||
int32_t code = rewritePrecalcExprs(pCxt, pFuncLogicNode->pFuncs, &pPrecalcExprs, &pFuncs);
|
||||
|
||||
SDataBlockDescNode* pChildTupe = (((SPhysiNode*)nodesListGetNode(pChildren, 0))->pOutputDataBlockDesc);
|
||||
// push down expression to pOutputDataBlockDesc of child node
|
||||
if (TSDB_CODE_SUCCESS == code && NULL != pPrecalcExprs) {
|
||||
code = setListSlotId(pCxt, pChildTupe->dataBlockId, -1, pPrecalcExprs, &pForecastFunc->pExprs);
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = pushdownDataBlockSlots(pCxt, pForecastFunc->pExprs, pChildTupe);
|
||||
}
|
||||
}
|
||||
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = setListSlotId(pCxt, pChildTupe->dataBlockId, -1, pFuncs, &pForecastFunc->pFuncs);
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = addDataBlockSlots(pCxt, pForecastFunc->pFuncs, pForecastFunc->node.pOutputDataBlockDesc);
|
||||
}
|
||||
}
|
||||
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = setConditionsSlotId(pCxt, (const SLogicNode*)pFuncLogicNode, (SPhysiNode*)pForecastFunc);
|
||||
}
|
||||
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
*pPhyNode = (SPhysiNode*)pForecastFunc;
|
||||
} else {
|
||||
nodesDestroyNode((SNode*)pForecastFunc);
|
||||
}
|
||||
|
||||
nodesDestroyList(pPrecalcExprs);
|
||||
nodesDestroyList(pFuncs);
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
static bool projectCanMergeDataBlock(SProjectLogicNode* pProject) {
|
||||
if (GROUP_ACTION_KEEP == pProject->node.groupAction) {
|
||||
return false;
|
||||
|
@ -2325,6 +2369,53 @@ static int32_t createCountWindowPhysiNode(SPhysiPlanContext* pCxt, SNodeList* pC
|
|||
return code;
|
||||
}
|
||||
|
||||
static int32_t createAnomalyWindowPhysiNode(SPhysiPlanContext* pCxt, SNodeList* pChildren,
|
||||
SWindowLogicNode* pWindowLogicNode, SPhysiNode** pPhyNode) {
|
||||
SAnomalyWindowPhysiNode* pAnomaly = (SAnomalyWindowPhysiNode*)makePhysiNode(
|
||||
pCxt, (SLogicNode*)pWindowLogicNode,
|
||||
(pCxt->pPlanCxt->streamQuery ? QUERY_NODE_PHYSICAL_PLAN_STREAM_ANOMALY : QUERY_NODE_PHYSICAL_PLAN_MERGE_ANOMALY));
|
||||
if (NULL == pAnomaly) {
|
||||
return terrno;
|
||||
}
|
||||
|
||||
SNodeList* pPrecalcExprs = NULL;
|
||||
SNode* pAnomalyKey = NULL;
|
||||
int32_t code = rewritePrecalcExpr(pCxt, pWindowLogicNode->pAnomalyExpr, &pPrecalcExprs, &pAnomalyKey);
|
||||
|
||||
SDataBlockDescNode* pChildTupe = (((SPhysiNode*)nodesListGetNode(pChildren, 0))->pOutputDataBlockDesc);
|
||||
// push down expression to pOutputDataBlockDesc of child node
|
||||
if (TSDB_CODE_SUCCESS == code && NULL != pPrecalcExprs) {
|
||||
code = setListSlotId(pCxt, pChildTupe->dataBlockId, -1, pPrecalcExprs, &pAnomaly->window.pExprs);
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = addDataBlockSlots(pCxt, pAnomaly->window.pExprs, pChildTupe);
|
||||
}
|
||||
}
|
||||
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = setNodeSlotId(pCxt, pChildTupe->dataBlockId, -1, pAnomalyKey, &pAnomaly->pAnomalyKey);
|
||||
// if (TSDB_CODE_SUCCESS == code) {
|
||||
// code = addDataBlockSlot(pCxt, &pAnomaly->pAnomalyKey, pAnomaly->window.node.pOutputDataBlockDesc);
|
||||
// }
|
||||
}
|
||||
|
||||
tstrncpy(pAnomaly->anomalyOpt, pWindowLogicNode->anomalyOpt, sizeof(pAnomaly->anomalyOpt));
|
||||
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = createWindowPhysiNodeFinalize(pCxt, pChildren, &pAnomaly->window, pWindowLogicNode);
|
||||
}
|
||||
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
*pPhyNode = (SPhysiNode*)pAnomaly;
|
||||
} else {
|
||||
nodesDestroyNode((SNode*)pAnomaly);
|
||||
}
|
||||
|
||||
nodesDestroyList(pPrecalcExprs);
|
||||
nodesDestroyNode(pAnomalyKey);
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t createWindowPhysiNode(SPhysiPlanContext* pCxt, SNodeList* pChildren, SWindowLogicNode* pWindowLogicNode,
|
||||
SPhysiNode** pPhyNode) {
|
||||
switch (pWindowLogicNode->winType) {
|
||||
|
@ -2338,6 +2429,8 @@ static int32_t createWindowPhysiNode(SPhysiPlanContext* pCxt, SNodeList* pChildr
|
|||
return createEventWindowPhysiNode(pCxt, pChildren, pWindowLogicNode, pPhyNode);
|
||||
case WINDOW_TYPE_COUNT:
|
||||
return createCountWindowPhysiNode(pCxt, pChildren, pWindowLogicNode, pPhyNode);
|
||||
case WINDOW_TYPE_ANOMALY:
|
||||
return createAnomalyWindowPhysiNode(pCxt, pChildren, pWindowLogicNode, pPhyNode);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -2652,6 +2745,8 @@ static int32_t doCreatePhysiNode(SPhysiPlanContext* pCxt, SLogicNode* pLogicNode
|
|||
return createIndefRowsFuncPhysiNode(pCxt, pChildren, (SIndefRowsFuncLogicNode*)pLogicNode, pPhyNode);
|
||||
case QUERY_NODE_LOGIC_PLAN_INTERP_FUNC:
|
||||
return createInterpFuncPhysiNode(pCxt, pChildren, (SInterpFuncLogicNode*)pLogicNode, pPhyNode);
|
||||
case QUERY_NODE_LOGIC_PLAN_FORECAST_FUNC:
|
||||
return createForecastFuncPhysiNode(pCxt, pChildren, (SForecastFuncLogicNode*)pLogicNode, pPhyNode);
|
||||
case QUERY_NODE_LOGIC_PLAN_MERGE:
|
||||
return createMergePhysiNode(pCxt, pChildren, (SMergeLogicNode*)pLogicNode, pPhyNode);
|
||||
case QUERY_NODE_LOGIC_PLAN_GROUP_CACHE:
|
||||
|
|
|
@ -939,6 +939,18 @@ static int32_t stbSplSplitCount(SSplitContext* pCxt, SStableSplitInfo* pInfo) {
|
|||
}
|
||||
}
|
||||
|
||||
static int32_t stbSplSplitAnomalyForStream(SSplitContext* pCxt, SStableSplitInfo* pInfo) {
|
||||
return TSDB_CODE_PLAN_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
static int32_t stbSplSplitAnomaly(SSplitContext* pCxt, SStableSplitInfo* pInfo) {
|
||||
if (pCxt->pPlanCxt->streamQuery) {
|
||||
return stbSplSplitAnomalyForStream(pCxt, pInfo);
|
||||
} else {
|
||||
return stbSplSplitSessionOrStateForBatch(pCxt, pInfo);
|
||||
}
|
||||
}
|
||||
|
||||
static int32_t stbSplSplitWindowForCrossTable(SSplitContext* pCxt, SStableSplitInfo* pInfo) {
|
||||
switch (((SWindowLogicNode*)pInfo->pSplitNode)->winType) {
|
||||
case WINDOW_TYPE_INTERVAL:
|
||||
|
@ -951,6 +963,8 @@ static int32_t stbSplSplitWindowForCrossTable(SSplitContext* pCxt, SStableSplitI
|
|||
return stbSplSplitEvent(pCxt, pInfo);
|
||||
case WINDOW_TYPE_COUNT:
|
||||
return stbSplSplitCount(pCxt, pInfo);
|
||||
case WINDOW_TYPE_ANOMALY:
|
||||
return stbSplSplitAnomaly(pCxt, pInfo);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -2000,7 +2014,8 @@ typedef struct SQnodeSplitInfo {
|
|||
static bool qndSplFindSplitNode(SSplitContext* pCxt, SLogicSubplan* pSubplan, SLogicNode* pNode,
|
||||
SQnodeSplitInfo* pInfo) {
|
||||
if (QUERY_NODE_LOGIC_PLAN_SCAN == nodeType(pNode) && NULL != pNode->pParent &&
|
||||
QUERY_NODE_LOGIC_PLAN_INTERP_FUNC != nodeType(pNode->pParent) && ((SScanLogicNode*)pNode)->scanSeq[0] <= 1 &&
|
||||
QUERY_NODE_LOGIC_PLAN_INTERP_FUNC != nodeType(pNode->pParent) &&
|
||||
QUERY_NODE_LOGIC_PLAN_FORECAST_FUNC != nodeType(pNode->pParent) && ((SScanLogicNode*)pNode)->scanSeq[0] <= 1 &&
|
||||
((SScanLogicNode*)pNode)->scanSeq[1] <= 1) {
|
||||
pInfo->pSplitNode = pNode;
|
||||
pInfo->pSubplan = pSubplan;
|
||||
|
|
|
@ -256,6 +256,15 @@ static int32_t adjustCountDataRequirement(SWindowLogicNode* pWindow, EDataOrderL
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t adjustAnomalyDataRequirement(SWindowLogicNode* pWindow, EDataOrderLevel requirement) {
|
||||
if (requirement <= pWindow->node.resultDataOrder) {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
pWindow->node.resultDataOrder = requirement;
|
||||
pWindow->node.requireDataOrder = requirement;
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t adjustWindowDataRequirement(SWindowLogicNode* pWindow, EDataOrderLevel requirement) {
|
||||
switch (pWindow->winType) {
|
||||
case WINDOW_TYPE_INTERVAL:
|
||||
|
@ -268,6 +277,8 @@ static int32_t adjustWindowDataRequirement(SWindowLogicNode* pWindow, EDataOrder
|
|||
return adjustEventDataRequirement(pWindow, requirement);
|
||||
case WINDOW_TYPE_COUNT:
|
||||
return adjustCountDataRequirement(pWindow, requirement);
|
||||
case WINDOW_TYPE_ANOMALY:
|
||||
return adjustAnomalyDataRequirement(pWindow, requirement);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -318,6 +329,15 @@ static int32_t adjustInterpDataRequirement(SInterpFuncLogicNode* pInterp, EDataO
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t adjustForecastDataRequirement(SForecastFuncLogicNode* pForecast, EDataOrderLevel requirement) {
|
||||
if (requirement <= pForecast->node.requireDataOrder) {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
pForecast->node.resultDataOrder = requirement;
|
||||
pForecast->node.requireDataOrder = requirement;
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t adjustLogicNodeDataRequirement(SLogicNode* pNode, EDataOrderLevel requirement) {
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
switch (nodeType(pNode)) {
|
||||
|
@ -355,6 +375,9 @@ int32_t adjustLogicNodeDataRequirement(SLogicNode* pNode, EDataOrderLevel requir
|
|||
case QUERY_NODE_LOGIC_PLAN_INTERP_FUNC:
|
||||
code = adjustInterpDataRequirement((SInterpFuncLogicNode*)pNode, requirement);
|
||||
break;
|
||||
case QUERY_NODE_LOGIC_PLAN_FORECAST_FUNC:
|
||||
code = adjustForecastDataRequirement((SForecastFuncLogicNode*)pNode, requirement);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -4080,6 +4080,10 @@ int32_t diffScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam
|
|||
return nonCalcScalarFunction(pInput, inputNum, pOutput);
|
||||
}
|
||||
|
||||
int32_t forecastScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
|
||||
return nonCalcScalarFunction(pInput, inputNum, pOutput);
|
||||
}
|
||||
|
||||
int32_t twaScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) {
|
||||
return avgScalarFunction(pInput, inputNum, pOutput);
|
||||
}
|
||||
|
|
|
@ -12,6 +12,10 @@ ELSE ()
|
|||
MESSAGE(STATUS "enable assert core")
|
||||
ENDIF (${ASSERT_NOT_CORE})
|
||||
|
||||
if(${BUILD_WITH_ANALYSIS})
|
||||
add_definitions(-DUSE_ANAL)
|
||||
endif()
|
||||
|
||||
target_include_directories(
|
||||
util
|
||||
PUBLIC "${TD_SOURCE_DIR}/include/util"
|
||||
|
|
|
@ -0,0 +1,752 @@
|
|||
/*
|
||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
||||
*
|
||||
* This program is free software: you can use, redistribute, and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3
|
||||
* or later ("AGPL"), as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#define _DEFAULT_SOURCE
|
||||
#include "tanal.h"
|
||||
#include "tmsg.h"
|
||||
#include "ttypes.h"
|
||||
#include "tutil.h"
|
||||
|
||||
#ifdef USE_ANAL
|
||||
#include <curl/curl.h>
|
||||
#define ANAL_ALGO_SPLIT ","
|
||||
|
||||
typedef struct {
|
||||
int64_t ver;
|
||||
SHashObj *hash; // algoname:algotype -> SAnalUrl
|
||||
TdThreadMutex lock;
|
||||
} SAlgoMgmt;
|
||||
|
||||
typedef struct {
|
||||
char *data;
|
||||
int64_t dataLen;
|
||||
} SCurlResp;
|
||||
|
||||
static SAlgoMgmt tsAlgos = {0};
|
||||
static int32_t taosAnalBufGetCont(SAnalBuf *pBuf, char **ppCont, int64_t *pContLen);
|
||||
|
||||
const char *taosAnalAlgoStr(EAnalAlgoType type) {
|
||||
switch (type) {
|
||||
case ANAL_ALGO_TYPE_ANOMALY_DETECT:
|
||||
return "anomaly-detection";
|
||||
case ANAL_ALGO_TYPE_FORECAST:
|
||||
return "forecast";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
const char *taosAnalAlgoUrlStr(EAnalAlgoType type) {
|
||||
switch (type) {
|
||||
case ANAL_ALGO_TYPE_ANOMALY_DETECT:
|
||||
return "anomaly-detect";
|
||||
case ANAL_ALGO_TYPE_FORECAST:
|
||||
return "forecast";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
EAnalAlgoType taosAnalAlgoInt(const char *name) {
|
||||
for (EAnalAlgoType i = 0; i < ANAL_ALGO_TYPE_END; ++i) {
|
||||
if (strcasecmp(name, taosAnalAlgoStr(i)) == 0) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return ANAL_ALGO_TYPE_END;
|
||||
}
|
||||
|
||||
int32_t taosAnalInit() {
|
||||
if (curl_global_init(CURL_GLOBAL_ALL) != 0) {
|
||||
uError("failed to init curl");
|
||||
return -1;
|
||||
}
|
||||
|
||||
tsAlgos.ver = 0;
|
||||
if (taosThreadMutexInit(&tsAlgos.lock, NULL) != 0) {
|
||||
uError("failed to init algo mutex");
|
||||
return -1;
|
||||
}
|
||||
|
||||
tsAlgos.hash = taosHashInit(64, MurmurHash3_32, true, HASH_ENTRY_LOCK);
|
||||
if (tsAlgos.hash == NULL) {
|
||||
uError("failed to init algo hash");
|
||||
return -1;
|
||||
}
|
||||
|
||||
uInfo("analysis env is initialized");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void taosAnalFreeHash(SHashObj *hash) {
|
||||
void *pIter = taosHashIterate(hash, NULL);
|
||||
while (pIter != NULL) {
|
||||
SAnalUrl *pUrl = (SAnalUrl *)pIter;
|
||||
taosMemoryFree(pUrl->url);
|
||||
pIter = taosHashIterate(hash, pIter);
|
||||
}
|
||||
taosHashCleanup(hash);
|
||||
}
|
||||
|
||||
void taosAnalCleanup() {
|
||||
curl_global_cleanup();
|
||||
if (taosThreadMutexDestroy(&tsAlgos.lock) != 0) {
|
||||
uError("failed to destroy anal lock");
|
||||
}
|
||||
taosAnalFreeHash(tsAlgos.hash);
|
||||
tsAlgos.hash = NULL;
|
||||
uInfo("analysis env is cleaned up");
|
||||
}
|
||||
|
||||
void taosAnalUpdate(int64_t newVer, SHashObj *pHash) {
|
||||
if (newVer > tsAlgos.ver) {
|
||||
if (taosThreadMutexLock(&tsAlgos.lock) == 0) {
|
||||
SHashObj *hash = tsAlgos.hash;
|
||||
tsAlgos.ver = newVer;
|
||||
tsAlgos.hash = pHash;
|
||||
if (taosThreadMutexUnlock(&tsAlgos.lock) != 0) {
|
||||
uError("failed to unlock hash")
|
||||
}
|
||||
taosAnalFreeHash(hash);
|
||||
}
|
||||
} else {
|
||||
taosAnalFreeHash(pHash);
|
||||
}
|
||||
}
|
||||
|
||||
bool taosAnalGetOptStr(const char *option, const char *optName, char *optValue, int32_t optMaxLen) {
|
||||
char buf[TSDB_ANAL_ALGO_OPTION_LEN] = {0};
|
||||
int32_t bufLen = tsnprintf(buf, sizeof(buf), "%s=", optName);
|
||||
|
||||
char *pos1 = strstr(option, buf);
|
||||
char *pos2 = strstr(option, ANAL_ALGO_SPLIT);
|
||||
if (pos1 != NULL) {
|
||||
if (optMaxLen > 0) {
|
||||
int32_t copyLen = optMaxLen;
|
||||
if (pos2 != NULL) {
|
||||
copyLen = (int32_t)(pos2 - pos1 - strlen(optName) + 1);
|
||||
copyLen = MIN(copyLen, optMaxLen);
|
||||
}
|
||||
tstrncpy(optValue, pos1 + bufLen, copyLen);
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool taosAnalGetOptInt(const char *option, const char *optName, int32_t *optValue) {
|
||||
char buf[TSDB_ANAL_ALGO_OPTION_LEN] = {0};
|
||||
int32_t bufLen = tsnprintf(buf, sizeof(buf), "%s=", optName);
|
||||
|
||||
char *pos1 = strstr(option, buf);
|
||||
char *pos2 = strstr(option, ANAL_ALGO_SPLIT);
|
||||
if (pos1 != NULL) {
|
||||
*optValue = taosStr2Int32(pos1 + bufLen + 1, NULL, 10);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t taosAnalGetAlgoUrl(const char *algoName, EAnalAlgoType type, char *url, int32_t urlLen) {
|
||||
int32_t code = 0;
|
||||
char name[TSDB_ANAL_ALGO_KEY_LEN] = {0};
|
||||
int32_t nameLen = 1 + tsnprintf(name, sizeof(name) - 1, "%d:%s", type, algoName);
|
||||
|
||||
if (taosThreadMutexLock(&tsAlgos.lock) == 0) {
|
||||
SAnalUrl *pUrl = taosHashAcquire(tsAlgos.hash, name, nameLen);
|
||||
if (pUrl != NULL) {
|
||||
tstrncpy(url, pUrl->url, urlLen);
|
||||
uDebug("algo:%s, type:%s, url:%s", algoName, taosAnalAlgoStr(type), url);
|
||||
} else {
|
||||
url[0] = 0;
|
||||
terrno = TSDB_CODE_ANAL_ALGO_NOT_FOUND;
|
||||
code = terrno;
|
||||
uError("algo:%s, type:%s, url not found", algoName, taosAnalAlgoStr(type));
|
||||
}
|
||||
if (taosThreadMutexUnlock(&tsAlgos.lock) != 0) {
|
||||
uError("failed to unlock hash");
|
||||
return TSDB_CODE_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
int64_t taosAnalGetVersion() { return tsAlgos.ver; }
|
||||
|
||||
static size_t taosCurlWriteData(char *pCont, size_t contLen, size_t nmemb, void *userdata) {
|
||||
SCurlResp *pRsp = userdata;
|
||||
if (contLen == 0 || nmemb == 0 || pCont == NULL) {
|
||||
pRsp->dataLen = 0;
|
||||
pRsp->data = NULL;
|
||||
uError("curl response is received, len:%" PRId64, pRsp->dataLen);
|
||||
return 0;
|
||||
}
|
||||
|
||||
pRsp->dataLen = (int64_t)contLen * (int64_t)nmemb;
|
||||
pRsp->data = taosMemoryMalloc(pRsp->dataLen + 1);
|
||||
|
||||
if (pRsp->data != NULL) {
|
||||
(void)memcpy(pRsp->data, pCont, pRsp->dataLen);
|
||||
pRsp->data[pRsp->dataLen] = 0;
|
||||
uDebug("curl response is received, len:%" PRId64 ", content:%s", pRsp->dataLen, pRsp->data);
|
||||
return pRsp->dataLen;
|
||||
} else {
|
||||
pRsp->dataLen = 0;
|
||||
uError("failed to malloc curl response");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int32_t taosCurlGetRequest(const char *url, SCurlResp *pRsp) {
|
||||
CURL *curl = NULL;
|
||||
CURLcode code = 0;
|
||||
|
||||
curl = curl_easy_init();
|
||||
if (curl == NULL) {
|
||||
uError("failed to create curl handle");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (curl_easy_setopt(curl, CURLOPT_URL, url) != 0) goto _OVER;
|
||||
if (curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, taosCurlWriteData) != 0) goto _OVER;
|
||||
if (curl_easy_setopt(curl, CURLOPT_WRITEDATA, pRsp) != 0) goto _OVER;
|
||||
if (curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, 100) != 0) goto _OVER;
|
||||
|
||||
uDebug("curl get request will sent, url:%s", url);
|
||||
code = curl_easy_perform(curl);
|
||||
if (code != CURLE_OK) {
|
||||
uError("failed to perform curl action, code:%d", code);
|
||||
}
|
||||
|
||||
_OVER:
|
||||
if (curl != NULL) curl_easy_cleanup(curl);
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t taosCurlPostRequest(const char *url, SCurlResp *pRsp, const char *buf, int32_t bufLen) {
|
||||
struct curl_slist *headers = NULL;
|
||||
CURL *curl = NULL;
|
||||
CURLcode code = 0;
|
||||
|
||||
curl = curl_easy_init();
|
||||
if (curl == NULL) {
|
||||
uError("failed to create curl handle");
|
||||
return -1;
|
||||
}
|
||||
|
||||
headers = curl_slist_append(headers, "Content-Type:application/json;charset=UTF-8");
|
||||
if (curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers) != 0) goto _OVER;
|
||||
if (curl_easy_setopt(curl, CURLOPT_URL, url) != 0) goto _OVER;
|
||||
if (curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, taosCurlWriteData) != 0) goto _OVER;
|
||||
if (curl_easy_setopt(curl, CURLOPT_WRITEDATA, pRsp) != 0) goto _OVER;
|
||||
if (curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, 60000) != 0) goto _OVER;
|
||||
if (curl_easy_setopt(curl, CURLOPT_POST, 1) != 0) goto _OVER;
|
||||
if (curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, bufLen) != 0) goto _OVER;
|
||||
if (curl_easy_setopt(curl, CURLOPT_POSTFIELDS, buf) != 0) goto _OVER;
|
||||
|
||||
uDebug("curl post request will sent, url:%s len:%d", url, bufLen);
|
||||
code = curl_easy_perform(curl);
|
||||
if (code != CURLE_OK) {
|
||||
uError("failed to perform curl action, code:%d", code);
|
||||
}
|
||||
|
||||
_OVER:
|
||||
if (curl != NULL) {
|
||||
curl_slist_free_all(headers);
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
SJson *taosAnalSendReqRetJson(const char *url, EAnalHttpType type, SAnalBuf *pBuf) {
|
||||
int32_t code = -1;
|
||||
char *pCont = NULL;
|
||||
int64_t contentLen;
|
||||
SJson *pJson = NULL;
|
||||
SCurlResp curlRsp = {0};
|
||||
|
||||
if (type == ANAL_HTTP_TYPE_GET) {
|
||||
if (taosCurlGetRequest(url, &curlRsp) != 0) {
|
||||
terrno = TSDB_CODE_ANAL_URL_CANT_ACCESS;
|
||||
goto _OVER;
|
||||
}
|
||||
} else {
|
||||
code = taosAnalBufGetCont(pBuf, &pCont, &contentLen);
|
||||
if (code != 0) {
|
||||
terrno = code;
|
||||
goto _OVER;
|
||||
}
|
||||
if (taosCurlPostRequest(url, &curlRsp, pCont, contentLen) != 0) {
|
||||
terrno = TSDB_CODE_ANAL_URL_CANT_ACCESS;
|
||||
goto _OVER;
|
||||
}
|
||||
}
|
||||
|
||||
if (curlRsp.data == NULL || curlRsp.dataLen == 0) {
|
||||
terrno = TSDB_CODE_ANAL_URL_RSP_IS_NULL;
|
||||
goto _OVER;
|
||||
}
|
||||
|
||||
pJson = tjsonParse(curlRsp.data);
|
||||
if (pJson == NULL) {
|
||||
terrno = TSDB_CODE_INVALID_JSON_FORMAT;
|
||||
goto _OVER;
|
||||
}
|
||||
|
||||
_OVER:
|
||||
if (curlRsp.data != NULL) taosMemoryFreeClear(curlRsp.data);
|
||||
if (pCont != NULL) taosMemoryFree(pCont);
|
||||
return pJson;
|
||||
}
|
||||
|
||||
static int32_t taosAnalJsonBufGetCont(const char *fileName, char **ppCont, int64_t *pContLen) {
|
||||
int32_t code = 0;
|
||||
int64_t contLen;
|
||||
char *pCont = NULL;
|
||||
TdFilePtr pFile = NULL;
|
||||
|
||||
pFile = taosOpenFile(fileName, TD_FILE_READ);
|
||||
if (pFile == NULL) {
|
||||
code = terrno;
|
||||
goto _OVER;
|
||||
}
|
||||
|
||||
code = taosFStatFile(pFile, &contLen, NULL);
|
||||
if (code != 0) goto _OVER;
|
||||
|
||||
pCont = taosMemoryMalloc(contLen + 1);
|
||||
if (pCont == NULL) {
|
||||
code = TSDB_CODE_OUT_OF_MEMORY;
|
||||
goto _OVER;
|
||||
}
|
||||
|
||||
if (taosReadFile(pFile, pCont, contLen) != contLen) {
|
||||
code = terrno;
|
||||
goto _OVER;
|
||||
}
|
||||
|
||||
pCont[contLen] = '\0';
|
||||
|
||||
_OVER:
|
||||
if (code == 0) {
|
||||
*ppCont = pCont;
|
||||
*pContLen = contLen;
|
||||
} else {
|
||||
if (pCont != NULL) taosMemoryFree(pCont);
|
||||
}
|
||||
if (pFile != NULL) taosCloseFile(&pFile);
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t taosAnalJsonBufWriteOptInt(SAnalBuf *pBuf, const char *optName, int64_t optVal) {
|
||||
char buf[64] = {0};
|
||||
int32_t bufLen = tsnprintf(buf, sizeof(buf), "\"%s\": %" PRId64 ",\n", optName, optVal);
|
||||
if (taosWriteFile(pBuf->filePtr, buf, bufLen) != bufLen) {
|
||||
return terrno;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t taosAnalJsonBufWriteOptStr(SAnalBuf *pBuf, const char *optName, const char *optVal) {
|
||||
char buf[128] = {0};
|
||||
int32_t bufLen = tsnprintf(buf, sizeof(buf), "\"%s\": \"%s\",\n", optName, optVal);
|
||||
if (taosWriteFile(pBuf->filePtr, buf, bufLen) != bufLen) {
|
||||
return terrno;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t taosAnalJsonBufWriteOptFloat(SAnalBuf *pBuf, const char *optName, float optVal) {
|
||||
char buf[128] = {0};
|
||||
int32_t bufLen = tsnprintf(buf, sizeof(buf), "\"%s\": %f,\n", optName, optVal);
|
||||
if (taosWriteFile(pBuf->filePtr, buf, bufLen) != bufLen) {
|
||||
return terrno;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t taosAnalJsonBufWriteStr(SAnalBuf *pBuf, const char *buf, int32_t bufLen) {
|
||||
if (bufLen <= 0) {
|
||||
bufLen = strlen(buf);
|
||||
}
|
||||
if (taosWriteFile(pBuf->filePtr, buf, bufLen) != bufLen) {
|
||||
return terrno;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t taosAnalJsonBufWriteStart(SAnalBuf *pBuf) { return taosAnalJsonBufWriteStr(pBuf, "{\n", 0); }
|
||||
|
||||
static int32_t tsosAnalJsonBufOpen(SAnalBuf *pBuf, int32_t numOfCols) {
|
||||
pBuf->filePtr = taosOpenFile(pBuf->fileName, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_TRUNC | TD_FILE_WRITE_THROUGH);
|
||||
if (pBuf->filePtr == NULL) {
|
||||
return terrno;
|
||||
}
|
||||
|
||||
pBuf->pCols = taosMemoryCalloc(numOfCols, sizeof(SAnalColBuf));
|
||||
if (pBuf->pCols == NULL) return TSDB_CODE_OUT_OF_MEMORY;
|
||||
pBuf->numOfCols = numOfCols;
|
||||
|
||||
if (pBuf->bufType == ANAL_BUF_TYPE_JSON) {
|
||||
return taosAnalJsonBufWriteStart(pBuf);
|
||||
}
|
||||
|
||||
for (int32_t i = 0; i < numOfCols; ++i) {
|
||||
SAnalColBuf *pCol = &pBuf->pCols[i];
|
||||
snprintf(pCol->fileName, sizeof(pCol->fileName), "%s-c%d", pBuf->fileName, i);
|
||||
pCol->filePtr =
|
||||
taosOpenFile(pCol->fileName, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_TRUNC | TD_FILE_WRITE_THROUGH);
|
||||
if (pCol->filePtr == NULL) {
|
||||
return terrno;
|
||||
}
|
||||
}
|
||||
|
||||
return taosAnalJsonBufWriteStart(pBuf);
|
||||
}
|
||||
|
||||
static int32_t taosAnalJsonBufWriteColMeta(SAnalBuf *pBuf, int32_t colIndex, int32_t colType, const char *colName) {
|
||||
char buf[128] = {0};
|
||||
bool first = (colIndex == 0);
|
||||
bool last = (colIndex == pBuf->numOfCols - 1);
|
||||
|
||||
if (first) {
|
||||
if (taosAnalJsonBufWriteStr(pBuf, "\"schema\": [\n", 0) != 0) {
|
||||
return terrno;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t bufLen = tsnprintf(buf, sizeof(buf), " [\"%s\", \"%s\", %d]%s\n", colName, tDataTypes[colType].name,
|
||||
tDataTypes[colType].bytes, last ? "" : ",");
|
||||
if (taosWriteFile(pBuf->filePtr, buf, bufLen) != bufLen) {
|
||||
return terrno;
|
||||
}
|
||||
|
||||
if (last) {
|
||||
if (taosAnalJsonBufWriteStr(pBuf, "],\n", 0) != 0) {
|
||||
return terrno;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t taosAnalJsonBufWriteDataBegin(SAnalBuf *pBuf) {
|
||||
return taosAnalJsonBufWriteStr(pBuf, "\"data\": [\n", 0);
|
||||
}
|
||||
|
||||
static int32_t taosAnalJsonBufWriteStrUseCol(SAnalBuf *pBuf, const char *buf, int32_t bufLen, int32_t colIndex) {
|
||||
if (bufLen <= 0) {
|
||||
bufLen = strlen(buf);
|
||||
}
|
||||
|
||||
if (pBuf->bufType == ANAL_BUF_TYPE_JSON) {
|
||||
if (taosWriteFile(pBuf->filePtr, buf, bufLen) != bufLen) {
|
||||
return terrno;
|
||||
}
|
||||
} else {
|
||||
if (taosWriteFile(pBuf->pCols[colIndex].filePtr, buf, bufLen) != bufLen) {
|
||||
return terrno;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t taosAnalJsonBufWriteColBegin(SAnalBuf *pBuf, int32_t colIndex) {
|
||||
return taosAnalJsonBufWriteStrUseCol(pBuf, "[\n", 0, colIndex);
|
||||
}
|
||||
|
||||
static int32_t taosAnalJsonBufWriteColEnd(SAnalBuf *pBuf, int32_t colIndex) {
|
||||
if (colIndex == pBuf->numOfCols - 1) {
|
||||
return taosAnalJsonBufWriteStrUseCol(pBuf, "\n]\n", 0, colIndex);
|
||||
|
||||
} else {
|
||||
return taosAnalJsonBufWriteStrUseCol(pBuf, "\n],\n", 0, colIndex);
|
||||
}
|
||||
}
|
||||
|
||||
static int32_t taosAnalJsonBufWriteColData(SAnalBuf *pBuf, int32_t colIndex, int32_t colType, void *colValue) {
|
||||
char buf[64];
|
||||
int32_t bufLen = 0;
|
||||
|
||||
if (pBuf->pCols[colIndex].numOfRows != 0) {
|
||||
buf[bufLen] = ',';
|
||||
buf[bufLen + 1] = '\n';
|
||||
buf[bufLen + 2] = 0;
|
||||
bufLen += 2;
|
||||
}
|
||||
|
||||
switch (colType) {
|
||||
case TSDB_DATA_TYPE_BOOL:
|
||||
bufLen += tsnprintf(buf + bufLen, sizeof(buf) - bufLen, "%d", (*((int8_t *)colValue) == 1) ? 1 : 0);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_TINYINT:
|
||||
bufLen += tsnprintf(buf + bufLen, sizeof(buf) - bufLen, "%d", *(int8_t *)colValue);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_UTINYINT:
|
||||
bufLen += tsnprintf(buf + bufLen, sizeof(buf) - bufLen, "%u", *(uint8_t *)colValue);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_SMALLINT:
|
||||
bufLen += tsnprintf(buf + bufLen, sizeof(buf) - bufLen, "%d", *(int16_t *)colValue);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_USMALLINT:
|
||||
bufLen += tsnprintf(buf + bufLen, sizeof(buf) - bufLen, "%u", *(uint16_t *)colValue);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_INT:
|
||||
bufLen += tsnprintf(buf + bufLen, sizeof(buf) - bufLen, "%d", *(int32_t *)colValue);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_UINT:
|
||||
bufLen += tsnprintf(buf + bufLen, sizeof(buf) - bufLen, "%u", *(uint32_t *)colValue);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_BIGINT:
|
||||
case TSDB_DATA_TYPE_TIMESTAMP:
|
||||
bufLen += tsnprintf(buf + bufLen, sizeof(buf) - bufLen, "%" PRId64 "", *(int64_t *)colValue);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_UBIGINT:
|
||||
bufLen += tsnprintf(buf + bufLen, sizeof(buf) - bufLen, "%" PRIu64 "", *(uint64_t *)colValue);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_FLOAT:
|
||||
bufLen += tsnprintf(buf + bufLen, sizeof(buf) - bufLen, "%f", GET_FLOAT_VAL(colValue));
|
||||
break;
|
||||
case TSDB_DATA_TYPE_DOUBLE:
|
||||
bufLen += tsnprintf(buf + bufLen, sizeof(buf) - bufLen, "%f", GET_DOUBLE_VAL(colValue));
|
||||
break;
|
||||
default:
|
||||
buf[bufLen] = '\0';
|
||||
}
|
||||
|
||||
pBuf->pCols[colIndex].numOfRows++;
|
||||
return taosAnalJsonBufWriteStrUseCol(pBuf, buf, bufLen, colIndex);
|
||||
}
|
||||
|
||||
static int32_t taosAnalJsonBufWriteDataEnd(SAnalBuf *pBuf) {
|
||||
int32_t code = 0;
|
||||
char *pCont = NULL;
|
||||
int64_t contLen = 0;
|
||||
|
||||
if (pBuf->bufType == ANAL_BUF_TYPE_JSON_COL) {
|
||||
for (int32_t i = 0; i < pBuf->numOfCols; ++i) {
|
||||
SAnalColBuf *pCol = &pBuf->pCols[i];
|
||||
|
||||
code = taosFsyncFile(pCol->filePtr);
|
||||
if (code != 0) return code;
|
||||
|
||||
code = taosCloseFile(&pCol->filePtr);
|
||||
if (code != 0) return code;
|
||||
|
||||
code = taosAnalJsonBufGetCont(pBuf->pCols[i].fileName, &pCont, &contLen);
|
||||
if (code != 0) return code;
|
||||
|
||||
code = taosAnalJsonBufWriteStr(pBuf, pCont, contLen);
|
||||
if (code != 0) return code;
|
||||
|
||||
taosMemoryFreeClear(pCont);
|
||||
contLen = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return taosAnalJsonBufWriteStr(pBuf, "],\n", 0);
|
||||
}
|
||||
|
||||
static int32_t taosAnalJsonBufWriteEnd(SAnalBuf *pBuf) {
|
||||
int32_t code = taosAnalJsonBufWriteOptInt(pBuf, "rows", pBuf->pCols[0].numOfRows);
|
||||
if (code != 0) return code;
|
||||
|
||||
return taosAnalJsonBufWriteStr(pBuf, "\"protocol\": 1.0\n}", 0);
|
||||
}
|
||||
|
||||
int32_t taosAnalJsonBufClose(SAnalBuf *pBuf) {
|
||||
int32_t code = taosAnalJsonBufWriteEnd(pBuf);
|
||||
if (code != 0) return code;
|
||||
|
||||
if (pBuf->filePtr != NULL) {
|
||||
code = taosFsyncFile(pBuf->filePtr);
|
||||
if (code != 0) return code;
|
||||
code = taosCloseFile(&pBuf->filePtr);
|
||||
if (code != 0) return code;
|
||||
}
|
||||
|
||||
if (pBuf->bufType == ANAL_BUF_TYPE_JSON_COL) {
|
||||
for (int32_t i = 0; i < pBuf->numOfCols; ++i) {
|
||||
SAnalColBuf *pCol = &pBuf->pCols[i];
|
||||
if (pCol->filePtr != NULL) {
|
||||
code = taosFsyncFile(pCol->filePtr);
|
||||
if (code != 0) return code;
|
||||
code = taosCloseFile(&pCol->filePtr);
|
||||
if (code != 0) return code;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void taosAnalBufDestroy(SAnalBuf *pBuf) {
|
||||
if (pBuf->fileName[0] != 0) {
|
||||
if (pBuf->filePtr != NULL) (void)taosCloseFile(&pBuf->filePtr);
|
||||
// taosRemoveFile(pBuf->fileName);
|
||||
pBuf->fileName[0] = 0;
|
||||
}
|
||||
|
||||
if (pBuf->bufType == ANAL_BUF_TYPE_JSON_COL) {
|
||||
for (int32_t i = 0; i < pBuf->numOfCols; ++i) {
|
||||
SAnalColBuf *pCol = &pBuf->pCols[i];
|
||||
if (pCol->fileName[0] != 0) {
|
||||
if (pCol->filePtr != NULL) (void)taosCloseFile(&pCol->filePtr);
|
||||
if (taosRemoveFile(pCol->fileName) != 0) {
|
||||
uError("failed to remove file %s", pCol->fileName);
|
||||
}
|
||||
pCol->fileName[0] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
taosMemoryFreeClear(pBuf->pCols);
|
||||
pBuf->numOfCols = 0;
|
||||
}
|
||||
|
||||
int32_t tsosAnalBufOpen(SAnalBuf *pBuf, int32_t numOfCols) {
|
||||
if (pBuf->bufType == ANAL_BUF_TYPE_JSON || pBuf->bufType == ANAL_BUF_TYPE_JSON_COL) {
|
||||
return tsosAnalJsonBufOpen(pBuf, numOfCols);
|
||||
} else {
|
||||
return TSDB_CODE_ANAL_BUF_INVALID_TYPE;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t taosAnalBufWriteOptStr(SAnalBuf *pBuf, const char *optName, const char *optVal) {
|
||||
if (pBuf->bufType == ANAL_BUF_TYPE_JSON || pBuf->bufType == ANAL_BUF_TYPE_JSON_COL) {
|
||||
return taosAnalJsonBufWriteOptStr(pBuf, optName, optVal);
|
||||
} else {
|
||||
return TSDB_CODE_ANAL_BUF_INVALID_TYPE;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t taosAnalBufWriteOptInt(SAnalBuf *pBuf, const char *optName, int64_t optVal) {
|
||||
if (pBuf->bufType == ANAL_BUF_TYPE_JSON || pBuf->bufType == ANAL_BUF_TYPE_JSON_COL) {
|
||||
return taosAnalJsonBufWriteOptInt(pBuf, optName, optVal);
|
||||
} else {
|
||||
return TSDB_CODE_ANAL_BUF_INVALID_TYPE;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t taosAnalBufWriteOptFloat(SAnalBuf *pBuf, const char *optName, float optVal) {
|
||||
if (pBuf->bufType == ANAL_BUF_TYPE_JSON || pBuf->bufType == ANAL_BUF_TYPE_JSON_COL) {
|
||||
return taosAnalJsonBufWriteOptFloat(pBuf, optName, optVal);
|
||||
} else {
|
||||
return TSDB_CODE_ANAL_BUF_INVALID_TYPE;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t taosAnalBufWriteColMeta(SAnalBuf *pBuf, int32_t colIndex, int32_t colType, const char *colName) {
|
||||
if (pBuf->bufType == ANAL_BUF_TYPE_JSON || pBuf->bufType == ANAL_BUF_TYPE_JSON_COL) {
|
||||
return taosAnalJsonBufWriteColMeta(pBuf, colIndex, colType, colName);
|
||||
} else {
|
||||
return TSDB_CODE_ANAL_BUF_INVALID_TYPE;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t taosAnalBufWriteDataBegin(SAnalBuf *pBuf) {
|
||||
if (pBuf->bufType == ANAL_BUF_TYPE_JSON || pBuf->bufType == ANAL_BUF_TYPE_JSON_COL) {
|
||||
return taosAnalJsonBufWriteDataBegin(pBuf);
|
||||
} else {
|
||||
return TSDB_CODE_ANAL_BUF_INVALID_TYPE;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t taosAnalBufWriteColBegin(SAnalBuf *pBuf, int32_t colIndex) {
|
||||
if (pBuf->bufType == ANAL_BUF_TYPE_JSON || pBuf->bufType == ANAL_BUF_TYPE_JSON_COL) {
|
||||
return taosAnalJsonBufWriteColBegin(pBuf, colIndex);
|
||||
} else {
|
||||
return TSDB_CODE_ANAL_BUF_INVALID_TYPE;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t taosAnalBufWriteColData(SAnalBuf *pBuf, int32_t colIndex, int32_t colType, void *colValue) {
|
||||
if (pBuf->bufType == ANAL_BUF_TYPE_JSON || pBuf->bufType == ANAL_BUF_TYPE_JSON_COL) {
|
||||
return taosAnalJsonBufWriteColData(pBuf, colIndex, colType, colValue);
|
||||
} else {
|
||||
return TSDB_CODE_ANAL_BUF_INVALID_TYPE;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t taosAnalBufWriteColEnd(SAnalBuf *pBuf, int32_t colIndex) {
|
||||
if (pBuf->bufType == ANAL_BUF_TYPE_JSON || pBuf->bufType == ANAL_BUF_TYPE_JSON_COL) {
|
||||
return taosAnalJsonBufWriteColEnd(pBuf, colIndex);
|
||||
} else {
|
||||
return TSDB_CODE_ANAL_BUF_INVALID_TYPE;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t taosAnalBufWriteDataEnd(SAnalBuf *pBuf) {
|
||||
if (pBuf->bufType == ANAL_BUF_TYPE_JSON || pBuf->bufType == ANAL_BUF_TYPE_JSON_COL) {
|
||||
return taosAnalJsonBufWriteDataEnd(pBuf);
|
||||
} else {
|
||||
return TSDB_CODE_ANAL_BUF_INVALID_TYPE;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t taosAnalBufClose(SAnalBuf *pBuf) {
|
||||
if (pBuf->bufType == ANAL_BUF_TYPE_JSON || pBuf->bufType == ANAL_BUF_TYPE_JSON_COL) {
|
||||
return taosAnalJsonBufClose(pBuf);
|
||||
} else {
|
||||
return TSDB_CODE_ANAL_BUF_INVALID_TYPE;
|
||||
}
|
||||
}
|
||||
|
||||
static int32_t taosAnalBufGetCont(SAnalBuf *pBuf, char **ppCont, int64_t *pContLen) {
|
||||
*ppCont = NULL;
|
||||
*pContLen = 0;
|
||||
|
||||
if (pBuf->bufType == ANAL_BUF_TYPE_JSON || pBuf->bufType == ANAL_BUF_TYPE_JSON_COL) {
|
||||
return taosAnalJsonBufGetCont(pBuf->fileName, ppCont, pContLen);
|
||||
} else {
|
||||
return TSDB_CODE_ANAL_BUF_INVALID_TYPE;
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int32_t taosAnalInit() { return 0; }
|
||||
void taosAnalCleanup() {}
|
||||
SJson *taosAnalSendReqRetJson(const char *url, EAnalHttpType type, SAnalBuf *pBuf) { return NULL; }
|
||||
|
||||
int32_t taosAnalGetAlgoUrl(const char *algoName, EAnalAlgoType type, char *url, int32_t urlLen) { return 0; }
|
||||
bool taosAnalGetOptStr(const char *option, const char *optName, char *optValue, int32_t optMaxLen) { return true; }
|
||||
bool taosAnalGetOptInt(const char *option, const char *optName, int32_t *optValue) { return true; }
|
||||
int64_t taosAnalGetVersion() { return 0; }
|
||||
void taosAnalUpdate(int64_t newVer, SHashObj *pHash) {}
|
||||
|
||||
int32_t tsosAnalBufOpen(SAnalBuf *pBuf, int32_t numOfCols) { return 0; }
|
||||
int32_t taosAnalBufWriteOptStr(SAnalBuf *pBuf, const char *optName, const char *optVal) { return 0; }
|
||||
int32_t taosAnalBufWriteOptInt(SAnalBuf *pBuf, const char *optName, int64_t optVal) { return 0; }
|
||||
int32_t taosAnalBufWriteOptFloat(SAnalBuf *pBuf, const char *optName, float optVal) { return 0; }
|
||||
int32_t taosAnalBufWriteColMeta(SAnalBuf *pBuf, int32_t colIndex, int32_t colType, const char *colName) { return 0; }
|
||||
int32_t taosAnalBufWriteDataBegin(SAnalBuf *pBuf) { return 0; }
|
||||
int32_t taosAnalBufWriteColBegin(SAnalBuf *pBuf, int32_t colIndex) { return 0; }
|
||||
int32_t taosAnalBufWriteColData(SAnalBuf *pBuf, int32_t colIndex, int32_t colType, void *colValue) { return 0; }
|
||||
int32_t taosAnalBufWriteColEnd(SAnalBuf *pBuf, int32_t colIndex) { return 0; }
|
||||
int32_t taosAnalBufWriteDataEnd(SAnalBuf *pBuf) { return 0; }
|
||||
int32_t taosAnalBufClose(SAnalBuf *pBuf) { return 0; }
|
||||
void taosAnalBufDestroy(SAnalBuf *pBuf) {}
|
||||
|
||||
const char *taosAnalAlgoStr(EAnalAlgoType algoType) { return 0; }
|
||||
EAnalAlgoType taosAnalAlgoInt(const char *algoName) { return 0; }
|
||||
const char *taosAnalAlgoUrlStr(EAnalAlgoType algoType) { return 0; }
|
||||
|
||||
#endif
|
|
@ -345,6 +345,22 @@ TAOS_DEFINE_ERROR(TSDB_CODE_MND_MULTI_REPLICA_SOURCE_DB, "Stream temporarily do
|
|||
TAOS_DEFINE_ERROR(TSDB_CODE_MND_TOO_MANY_STREAMS, "Too many streams")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_MND_INVALID_TARGET_TABLE, "Cannot write the same stable as other stream")
|
||||
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_MND_ANODE_ALREADY_EXIST, "Anode already exists")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_MND_ANODE_NOT_EXIST, "Anode not there")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_MND_ANODE_TOO_LONG_URL, "Anode too long url")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_MND_ANODE_INVALID_PROTOCOL, "Anode invalid protocol")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_MND_ANODE_INVALID_ALGO_TYPE, "Anode invalid algorithm type")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_MND_ANODE_INVALID_VERSION, "Anode invalid version")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_MND_ANODE_TOO_MANY_ALGO, "Anode too many algorithm")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_MND_ANODE_TOO_LONG_ALGO_NAME, "Anode too long algorithm name")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_MND_ANODE_TOO_MANY_ALGO_TYPE, "Anode too many algorithm type")
|
||||
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_ANAL_URL_RSP_IS_NULL, "Analysis url response is NULL")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_ANAL_URL_CANT_ACCESS, "Analysis url can't access")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_ANAL_ALGO_NOT_FOUND, "Analysis algorithm not found")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_ANAL_ALGO_NOT_LOAD, "Analysis algorithm not loaded")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_ANAL_BUF_INVALID_TYPE, "Analysis invalid buffer type")
|
||||
|
||||
// mnode-sma
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_MND_SMA_ALREADY_EXIST, "SMA already exists")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_MND_SMA_NOT_EXIST, "sma not exist")
|
||||
|
@ -709,6 +725,11 @@ TAOS_DEFINE_ERROR(TSDB_CODE_PAR_TBNAME_DUPLICATED, "Table name duplicat
|
|||
TAOS_DEFINE_ERROR(TSDB_CODE_PAR_TAG_NAME_DUPLICATED, "Tag name duplicated")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_PAR_NOT_ALLOWED_DIFFERENT_BY_ROW_FUNC, "Some functions cannot appear in the select list at the same time")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_PAR_REGULAR_EXPRESSION_ERROR, "Syntax error in regular expression")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_PAR_INVALID_ANOMALY_WIN_TYPE, "ANOMALY_WINDOW only support mathable column")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_PAR_INVALID_ANOMALY_WIN_COL, "ANOMALY_WINDOW not support on tag column")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_PAR_INVALID_ANOMALY_WIN_OPT, "ANOMALY_WINDOW option should include algo field")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_PAR_INVALID_FORECAST_CLAUSE, "Invalid forecast clause")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_PAR_REGULAR_EXPRESSION_ERROR, "Syntax error in regular expression")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_PAR_INTERNAL_ERROR, "Parser internal error")
|
||||
|
||||
//planner
|
||||
|
|
|
@ -194,6 +194,10 @@ int32_t tjsonGetObjectValueString(const SJson* pJson, char** pValueString) {
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
void tjsonGetObjectValueBigInt(const SJson* pJson, int64_t* pVal) { *pVal = (int64_t)((cJSON*)pJson)->valuedouble; }
|
||||
|
||||
void tjsonGetObjectValueDouble(const SJson* pJson, double* pVal) { *pVal = ((cJSON*)pJson)->valuedouble; }
|
||||
|
||||
int32_t tjsonGetStringValue(const SJson* pJson, const char* pName, char* pVal) {
|
||||
char* p = cJSON_GetStringValue(tjsonGetObjectItem((cJSON*)pJson, pName));
|
||||
if (NULL == p) {
|
||||
|
@ -203,6 +207,19 @@ int32_t tjsonGetStringValue(const SJson* pJson, const char* pName, char* pVal) {
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t tjsonGetStringValue2(const SJson* pJson, const char* pName, char* pVal, int32_t maxLen) {
|
||||
char* p = cJSON_GetStringValue(tjsonGetObjectItem((cJSON*)pJson, pName));
|
||||
if (NULL == p) {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
int32_t len = strlen(p);
|
||||
if (len >= maxLen - 1) {
|
||||
return TSDB_CODE_OUT_OF_MEMORY;
|
||||
}
|
||||
strcpy(pVal, p);
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t tjsonDupStringValue(const SJson* pJson, const char* pName, char** pVal) {
|
||||
char* p = cJSON_GetStringValue(tjsonGetObjectItem((cJSON*)pJson, pName));
|
||||
if (NULL == p) {
|
||||
|
|
|
@ -65,7 +65,7 @@ class TDTestCase:
|
|||
|
||||
tdSql.query('select count(*),db_name, stable_name from information_schema.ins_tables group by db_name, stable_name;')
|
||||
tdSql.checkRows(3)
|
||||
tdSql.checkData(0, 0, 32)
|
||||
tdSql.checkData(0, 0, 34)
|
||||
tdSql.checkData(0, 1, 'information_schema')
|
||||
tdSql.checkData(0, 2, None)
|
||||
tdSql.checkData(1, 0, 3)
|
||||
|
@ -77,7 +77,7 @@ class TDTestCase:
|
|||
|
||||
tdSql.query('select count(1) v,db_name, stable_name from information_schema.ins_tables group by db_name, stable_name order by v desc;')
|
||||
tdSql.checkRows(3)
|
||||
tdSql.checkData(0, 0, 32)
|
||||
tdSql.checkData(0, 0, 34)
|
||||
tdSql.checkData(0, 1, 'information_schema')
|
||||
tdSql.checkData(0, 2, None)
|
||||
tdSql.checkData(1, 0, 5)
|
||||
|
@ -93,7 +93,7 @@ class TDTestCase:
|
|||
tdSql.checkData(1, 1, 'performance_schema')
|
||||
tdSql.checkData(0, 0, 3)
|
||||
tdSql.checkData(0, 1, 'tbl_count')
|
||||
tdSql.checkData(2, 0, 32)
|
||||
tdSql.checkData(2, 0, 34)
|
||||
tdSql.checkData(2, 1, 'information_schema')
|
||||
|
||||
tdSql.query("select count(*) from information_schema.ins_tables where db_name='tbl_count'")
|
||||
|
@ -106,7 +106,7 @@ class TDTestCase:
|
|||
|
||||
tdSql.query('select count(*) from information_schema.ins_tables')
|
||||
tdSql.checkRows(1)
|
||||
tdSql.checkData(0, 0, 40)
|
||||
tdSql.checkData(0, 0, 42)
|
||||
|
||||
|
||||
tdSql.execute('create table stba (ts timestamp, c1 bool, c2 tinyint, c3 smallint, c4 int, c5 bigint, c6 float, c7 double, c8 binary(10), c9 nchar(10), c10 tinyint unsigned, c11 smallint unsigned, c12 int unsigned, c13 bigint unsigned) TAGS(t1 int, t2 binary(10), t3 double);')
|
||||
|
@ -189,7 +189,7 @@ class TDTestCase:
|
|||
tdSql.checkData(2, 0, 5)
|
||||
tdSql.checkData(2, 1, 'performance_schema')
|
||||
tdSql.checkData(2, 2, None)
|
||||
tdSql.checkData(3, 0, 32)
|
||||
tdSql.checkData(3, 0, 34)
|
||||
tdSql.checkData(3, 1, 'information_schema')
|
||||
tdSql.checkData(3, 2, None)
|
||||
|
||||
|
@ -204,7 +204,7 @@ class TDTestCase:
|
|||
tdSql.checkData(2, 0, 5)
|
||||
tdSql.checkData(2, 1, 'performance_schema')
|
||||
tdSql.checkData(2, 2, None)
|
||||
tdSql.checkData(3, 0, 32)
|
||||
tdSql.checkData(3, 0, 34)
|
||||
tdSql.checkData(3, 1, 'information_schema')
|
||||
tdSql.checkData(3, 2, None)
|
||||
|
||||
|
@ -215,7 +215,7 @@ class TDTestCase:
|
|||
tdSql.checkData(0, 1, 'tbl_count')
|
||||
tdSql.checkData(1, 0, 5)
|
||||
tdSql.checkData(1, 1, 'performance_schema')
|
||||
tdSql.checkData(2, 0, 32)
|
||||
tdSql.checkData(2, 0, 34)
|
||||
tdSql.checkData(2, 1, 'information_schema')
|
||||
|
||||
tdSql.query("select count(*) from information_schema.ins_tables where db_name='tbl_count'")
|
||||
|
@ -228,7 +228,7 @@ class TDTestCase:
|
|||
|
||||
tdSql.query('select count(*) from information_schema.ins_tables')
|
||||
tdSql.checkRows(1)
|
||||
tdSql.checkData(0, 0, 41)
|
||||
tdSql.checkData(0, 0, 43)
|
||||
|
||||
|
||||
tdSql.execute('drop database tbl_count')
|
||||
|
|
|
@ -58,7 +58,7 @@ endi
|
|||
|
||||
sql select tbname from information_schema.ins_tables;
|
||||
print $rows $data00
|
||||
if $rows != 41 then
|
||||
if $rows != 43 then
|
||||
return -1
|
||||
endi
|
||||
if $data00 != @ins_tables@ then
|
||||
|
|
|
@ -53,7 +53,7 @@ sql select stable_name,count(table_name) from information_schema.ins_tables grou
|
|||
if $rows != 3 then
|
||||
return -1
|
||||
endi
|
||||
if $data01 != 38 then
|
||||
if $data01 != 40 then
|
||||
return -1
|
||||
endi
|
||||
if $data11 != 10 then
|
||||
|
@ -72,7 +72,7 @@ endi
|
|||
if $data11 != 5 then
|
||||
return -1
|
||||
endi
|
||||
if $data21 != 32 then
|
||||
if $data21 != 34 then
|
||||
return -1
|
||||
endi
|
||||
if $data31 != 5 then
|
||||
|
@ -97,7 +97,7 @@ endi
|
|||
if $data42 != 3 then
|
||||
return -1
|
||||
endi
|
||||
if $data52 != 32 then
|
||||
if $data52 != 34 then
|
||||
return -1
|
||||
endi
|
||||
if $data62 != 5 then
|
||||
|
|
|
@ -61,7 +61,7 @@ class TDTestCase:
|
|||
self.ins_list = ['ins_dnodes','ins_mnodes','ins_qnodes','ins_snodes','ins_cluster','ins_databases','ins_functions',\
|
||||
'ins_indexes','ins_stables','ins_tables','ins_tags','ins_columns','ins_users','ins_grants','ins_vgroups','ins_configs','ins_dnode_variables',\
|
||||
'ins_topics','ins_subscriptions','ins_streams','ins_stream_tasks','ins_vnodes','ins_user_privileges','ins_views',
|
||||
'ins_compacts', 'ins_compact_details', 'ins_grants_full','ins_grants_logs', 'ins_machines', 'ins_arbgroups', 'ins_tsmas', "ins_encryptions"]
|
||||
'ins_compacts', 'ins_compact_details', 'ins_grants_full','ins_grants_logs', 'ins_machines', 'ins_arbgroups', 'ins_tsmas', "ins_encryptions", "ins_anodes", "ins_anodes_full"]
|
||||
self.perf_list = ['perf_connections','perf_queries','perf_consumers','perf_trans','perf_apps']
|
||||
def insert_data(self,column_dict,tbname,row_num):
|
||||
insert_sql = self.setsql.set_insertsql(column_dict,tbname,self.binary_str,self.nchar_str)
|
||||
|
@ -222,7 +222,7 @@ class TDTestCase:
|
|||
|
||||
tdSql.query("select * from information_schema.ins_columns where db_name ='information_schema'")
|
||||
tdLog.info(len(tdSql.queryResult))
|
||||
tdSql.checkEqual(True, len(tdSql.queryResult) in range(272, 273))
|
||||
tdSql.checkEqual(True, len(tdSql.queryResult) in range(280, 281))
|
||||
|
||||
tdSql.query("select * from information_schema.ins_columns where db_name ='performance_schema'")
|
||||
tdSql.checkEqual(56, len(tdSql.queryResult))
|
||||
|
|
Loading…
Reference in New Issue