mirror of
https://github.com/taosdata/TDengine
synced 2026-05-24 10:09:01 +00:00
* feat(xnode): support token auth when creating XNODE Closes [6725312703](https://project.feishu.cn/taosdata_td/feature/detail/6725312703) * chore: clean code & fix xnode transactions issues * chore: fix alter xnode job memory leak * fix: update workflow reference to use specific commit for new framework test --------- Co-authored-by: chenhaoran <haoran920c@163.com>
7921 lines
268 KiB
C
7921 lines
268 KiB
C
/*
|
|
* 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_ASTRA
|
|
#include <uv.h>
|
|
#endif
|
|
|
|
#include <regex.h>
|
|
#include <stddef.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#include "nodes.h"
|
|
#include "parAst.h"
|
|
#include "parUtil.h"
|
|
#include "tglobal.h"
|
|
#include "ttime.h"
|
|
#include "cmdnodes.h"
|
|
#include "osMemory.h"
|
|
#include "osString.h"
|
|
#include "parToken.h"
|
|
#include "tdef.h"
|
|
#include "tmsg.h"
|
|
#include "ttokendef.h"
|
|
|
|
#define CHECK_MAKE_NODE(p) \
|
|
do { \
|
|
if (NULL == (p)) { \
|
|
goto _err; \
|
|
} \
|
|
} while (0)
|
|
|
|
#define CHECK_OUT_OF_MEM(p) \
|
|
do { \
|
|
if (NULL == (p)) { \
|
|
pCxt->errCode = terrno; \
|
|
goto _err; \
|
|
} \
|
|
} while (0)
|
|
|
|
#define CHECK_PARSER_STATUS(pCxt) \
|
|
do { \
|
|
if (TSDB_CODE_SUCCESS != pCxt->errCode) { \
|
|
goto _err; \
|
|
} \
|
|
} while (0)
|
|
|
|
#define CHECK_NAME(p) \
|
|
do { \
|
|
if (!p) { \
|
|
goto _err; \
|
|
} \
|
|
} while (0)
|
|
|
|
#define COPY_STRING_FORM_ID_TOKEN(buf, pToken) strncpy(buf, (pToken)->z, TMIN((pToken)->n, sizeof(buf) - 1))
|
|
#define TRIM_STRING_FORM_ID_TOKEN(buf, pToken) \
|
|
do { \
|
|
if (pToken->z[0] == '`') { \
|
|
(void)trimString(pToken->z, pToken->n, buf, sizeof(buf) - 1); \
|
|
} else { \
|
|
COPY_STRING_FORM_ID_TOKEN(buf, pToken); \
|
|
} \
|
|
} while (0)
|
|
#define COPY_STRING_FORM_STR_TOKEN(buf, pToken) \
|
|
do { \
|
|
if ((pToken)->n > 2) { \
|
|
strncpy(buf, (pToken)->z + 1, TMIN((pToken)->n - 2, sizeof(buf) - 1)); \
|
|
} \
|
|
} while (0)
|
|
|
|
#define COPY_COW_STR_FROM_ID_TOKEN(cow, pToken) \
|
|
do { \
|
|
if (pToken->z[0] == '`') { \
|
|
(cow) = xCreateCowStr((pToken)->n - 2, (pToken)->z + 1, true); \
|
|
} else { \
|
|
(cow) = xCreateCowStr((pToken)->n, (pToken)->z, true); \
|
|
} \
|
|
} while (0)
|
|
#define COPY_COW_STR_FROM_STR_TOKEN(cow, pToken) \
|
|
do { \
|
|
if ((pToken)->n > 2) { \
|
|
(cow) = xCreateCowStr((pToken)->n - 2, (pToken)->z + 1, true); \
|
|
} \
|
|
} while (0)
|
|
SToken nil_token = {.type = TK_NK_NIL, .n = 0, .z = NULL};
|
|
|
|
void initAstCreateContext(SParseContext* pParseCxt, SAstCreateContext* pCxt) {
|
|
memset(pCxt, 0, sizeof(SAstCreateContext));
|
|
pCxt->pQueryCxt = pParseCxt;
|
|
pCxt->msgBuf.buf = pParseCxt->pMsg;
|
|
pCxt->msgBuf.len = pParseCxt->msgLen;
|
|
pCxt->notSupport = false;
|
|
pCxt->pRootNode = NULL;
|
|
pCxt->placeholderNo = 0;
|
|
pCxt->pPlaceholderValues = NULL;
|
|
pCxt->errCode = TSDB_CODE_SUCCESS;
|
|
}
|
|
|
|
static void trimEscape(SAstCreateContext* pCxt, SToken* pName, bool trimStar) {
|
|
// todo need to deal with `ioo``ii` -> ioo`ii: done
|
|
if (NULL != pName && pName->n > 1 && TS_ESCAPE_CHAR == pName->z[0]) {
|
|
if (!pCxt->pQueryCxt->hasDupQuoteChar) {
|
|
pName->z += 1;
|
|
pName->n -= 2;
|
|
// * is forbidden as an identifier name
|
|
if (pName->z[0] == '*' && trimStar && pName->n == 1) {
|
|
pName->z[0] = '\0';
|
|
pName->n = 0;
|
|
}
|
|
} else {
|
|
int32_t i = 1, j = 0;
|
|
for (; i < pName->n - 1; ++i) {
|
|
if ((pName->z[i] == TS_ESCAPE_CHAR) && (pName->z[i + 1] == TS_ESCAPE_CHAR)) {
|
|
pName->z[j++] = TS_ESCAPE_CHAR;
|
|
++i;
|
|
} else {
|
|
pName->z[j++] = pName->z[i];
|
|
}
|
|
}
|
|
pName->n = j;
|
|
}
|
|
}
|
|
}
|
|
|
|
static bool checkUserName(SAstCreateContext* pCxt, SToken* pUserName) {
|
|
if (NULL == pUserName) {
|
|
pCxt->errCode = TSDB_CODE_PAR_SYNTAX_ERROR;
|
|
} else {
|
|
if (pUserName->n >= TSDB_USER_LEN) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_NAME_OR_PASSWD_TOO_LONG);
|
|
}
|
|
}
|
|
if (TSDB_CODE_SUCCESS == pCxt->errCode) {
|
|
trimEscape(pCxt, pUserName, true);
|
|
}
|
|
return TSDB_CODE_SUCCESS == pCxt->errCode;
|
|
}
|
|
|
|
|
|
|
|
static bool isValidSimplePassword(const char* password) {
|
|
for (char c = *password; c != 0; c = *(++password)) {
|
|
if (c == ' ' || c == '\'' || c == '\"' || c == '`' || c == '\\') {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
static bool isValidPassword(SAstCreateContext* pCxt, const char* password, bool imported) {
|
|
if (imported) {
|
|
return strlen(password) == TSDB_PASSWORD_LEN;
|
|
}
|
|
|
|
if (tsEnableStrongPassword) {
|
|
return taosIsComplexString(password);
|
|
}
|
|
|
|
return isValidSimplePassword(password);
|
|
}
|
|
|
|
|
|
|
|
static int32_t parsePort(SAstCreateContext* pCxt, const char* p, int32_t* pPort) {
|
|
*pPort = taosStr2Int32(p, NULL, 10);
|
|
if (*pPort >= UINT16_MAX || *pPort <= 0) {
|
|
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_PORT);
|
|
}
|
|
return TSDB_CODE_SUCCESS;
|
|
}
|
|
|
|
static int32_t parseEndpoint(SAstCreateContext* pCxt, const SToken* pEp, char* pFqdn, int32_t* pPort) {
|
|
if (pEp->n >= (NULL == pPort ? (TSDB_FQDN_LEN + 1 + 5) : TSDB_FQDN_LEN)) { // format 'fqdn:port' or 'fqdn'
|
|
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_NAME_OR_PASSWD_TOO_LONG);
|
|
}
|
|
|
|
char ep[TSDB_FQDN_LEN + 1 + 5] = {0};
|
|
COPY_STRING_FORM_ID_TOKEN(ep, pEp);
|
|
(void)strdequote(ep);
|
|
(void)strtrim(ep);
|
|
if (NULL == pPort) {
|
|
tstrncpy(pFqdn, ep, TSDB_FQDN_LEN);
|
|
return TSDB_CODE_SUCCESS;
|
|
}
|
|
char* pColon = strrchr(ep, ':');
|
|
if (NULL == pColon) {
|
|
*pPort = tsServerPort;
|
|
tstrncpy(pFqdn, ep, TSDB_FQDN_LEN);
|
|
return TSDB_CODE_SUCCESS;
|
|
}
|
|
strncpy(pFqdn, ep, pColon - ep);
|
|
return parsePort(pCxt, pColon + 1, pPort);
|
|
}
|
|
|
|
static bool checkAndSplitEndpoint(SAstCreateContext* pCxt, const SToken* pEp, const SToken* pPortToken, char* pFqdn,
|
|
int32_t* pPort) {
|
|
if (NULL == pEp) {
|
|
pCxt->errCode = TSDB_CODE_PAR_SYNTAX_ERROR;
|
|
return false;
|
|
}
|
|
|
|
if (NULL != pPortToken) {
|
|
pCxt->errCode = parsePort(pCxt, pPortToken->z, pPort);
|
|
}
|
|
|
|
if (TSDB_CODE_SUCCESS == pCxt->errCode) {
|
|
pCxt->errCode = parseEndpoint(pCxt, pEp, pFqdn, (NULL != pPortToken ? NULL : pPort));
|
|
}
|
|
|
|
return TSDB_CODE_SUCCESS == pCxt->errCode;
|
|
}
|
|
|
|
static bool checkObjName(SAstCreateContext* pCxt, SToken* pObjName, bool need) {
|
|
if (NULL == pObjName || TK_NK_NIL == pObjName->type) {
|
|
if (need) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_IDENTIFIER_NAME);
|
|
}
|
|
} else {
|
|
trimEscape(pCxt, pObjName, true);
|
|
if (pObjName->n >= TSDB_OBJ_NAME_LEN || pObjName->n == 0) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_IDENTIFIER_NAME, pObjName->z);
|
|
}
|
|
}
|
|
return TSDB_CODE_SUCCESS == pCxt->errCode;
|
|
}
|
|
|
|
static bool checkDbName(SAstCreateContext* pCxt, SToken* pDbName, bool demandDb) {
|
|
if (NULL == pDbName) {
|
|
if (demandDb && NULL == pCxt->pQueryCxt->db) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_DB_NOT_SPECIFIED);
|
|
}
|
|
} else {
|
|
trimEscape(pCxt, pDbName, true);
|
|
if (pDbName->n >= TSDB_DB_NAME_LEN || (demandDb && (pDbName->n == 0))) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_IDENTIFIER_NAME, pDbName->z);
|
|
}
|
|
}
|
|
return TSDB_CODE_SUCCESS == pCxt->errCode;
|
|
}
|
|
|
|
static bool checkTableName(SAstCreateContext* pCxt, SToken* pTableName) {
|
|
trimEscape(pCxt, pTableName, true);
|
|
if (NULL != pTableName && pTableName->type != TK_NK_NIL &&
|
|
(pTableName->n >= TSDB_TABLE_NAME_LEN || pTableName->n == 0)) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_IDENTIFIER_NAME, pTableName->z);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool checkColumnName(SAstCreateContext* pCxt, SToken* pColumnName) {
|
|
trimEscape(pCxt, pColumnName, true);
|
|
if (NULL != pColumnName && pColumnName->type != TK_NK_NIL &&
|
|
(pColumnName->n >= TSDB_COL_NAME_LEN || pColumnName->n == 0)) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_IDENTIFIER_NAME, pColumnName->z);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool checkIndexName(SAstCreateContext* pCxt, SToken* pIndexName) {
|
|
trimEscape(pCxt, pIndexName, true);
|
|
if (NULL != pIndexName && (pIndexName->n >= TSDB_INDEX_NAME_LEN || pIndexName->n == 0)) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_IDENTIFIER_NAME, pIndexName->z);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool checkTopicName(SAstCreateContext* pCxt, SToken* pTopicName) {
|
|
trimEscape(pCxt, pTopicName, true);
|
|
if (pTopicName->n >= TSDB_TOPIC_NAME_LEN || pTopicName->n == 0) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_IDENTIFIER_NAME, pTopicName->z);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool checkCGroupName(SAstCreateContext* pCxt, SToken* pCGroup) {
|
|
trimEscape(pCxt, pCGroup, true);
|
|
if (pCGroup->n >= TSDB_CGROUP_LEN || pCGroup->n == 0) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_IDENTIFIER_NAME, pCGroup->z);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool checkViewName(SAstCreateContext* pCxt, SToken* pViewName) {
|
|
trimEscape(pCxt, pViewName, true);
|
|
if (pViewName->n >= TSDB_VIEW_NAME_LEN || pViewName->n == 0) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_IDENTIFIER_NAME, pViewName->z);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool checkStreamName(SAstCreateContext* pCxt, SToken* pStreamName) {
|
|
trimEscape(pCxt, pStreamName, true);
|
|
if (pStreamName->n >= TSDB_STREAM_NAME_LEN || pStreamName->n == 0) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_IDENTIFIER_NAME, pStreamName->z);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool checkComment(SAstCreateContext* pCxt, const SToken* pCommentToken, bool demand) {
|
|
if (NULL == pCommentToken) {
|
|
pCxt->errCode = demand ? TSDB_CODE_PAR_SYNTAX_ERROR : TSDB_CODE_SUCCESS;
|
|
} else if (pCommentToken->n >= (TSDB_TB_COMMENT_LEN + 2)) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_COMMENT_TOO_LONG);
|
|
}
|
|
return TSDB_CODE_SUCCESS == pCxt->errCode;
|
|
}
|
|
|
|
static bool checkRsmaName(SAstCreateContext* pCxt, SToken* pRsmaToken) {
|
|
trimEscape(pCxt, pRsmaToken, true);
|
|
if (NULL == pRsmaToken) {
|
|
pCxt->errCode = TSDB_CODE_PAR_SYNTAX_ERROR;
|
|
} else if (pRsmaToken->n >= TSDB_TABLE_NAME_LEN) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_TSMA_NAME_TOO_LONG);
|
|
} else if (pRsmaToken->n == 0) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_IDENTIFIER_NAME, pRsmaToken->z);
|
|
}
|
|
return pCxt->errCode == TSDB_CODE_SUCCESS;
|
|
}
|
|
|
|
static bool checkTsmaName(SAstCreateContext* pCxt, SToken* pTsmaToken) {
|
|
trimEscape(pCxt, pTsmaToken, true);
|
|
if (NULL == pTsmaToken) {
|
|
pCxt->errCode = TSDB_CODE_PAR_SYNTAX_ERROR;
|
|
} else if (pTsmaToken->n >= TSDB_TABLE_NAME_LEN - strlen(TSMA_RES_STB_POSTFIX)) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_TSMA_NAME_TOO_LONG);
|
|
} else if (pTsmaToken->n == 0) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_IDENTIFIER_NAME, pTsmaToken->z);
|
|
}
|
|
return pCxt->errCode == TSDB_CODE_SUCCESS;
|
|
}
|
|
|
|
static bool checkMountPath(SAstCreateContext* pCxt, SToken* pMountPath) {
|
|
trimEscape(pCxt, pMountPath, true);
|
|
if (pMountPath->n >= TSDB_MOUNT_PATH_LEN || pMountPath->n == 0) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_IDENTIFIER_NAME, pMountPath->z);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
SNode* createRawExprNode(SAstCreateContext* pCxt, const SToken* pToken, SNode* pNode) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SRawExprNode* target = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_RAW_EXPR, (SNode**)&target);
|
|
CHECK_MAKE_NODE(target);
|
|
target->p = pToken->z;
|
|
target->n = pToken->n;
|
|
target->pNode = pNode;
|
|
return (SNode*)target;
|
|
_err:
|
|
nodesDestroyNode(pNode);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createRawExprNodeExt(SAstCreateContext* pCxt, const SToken* pStart, const SToken* pEnd, SNode* pNode) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SRawExprNode* target = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_RAW_EXPR, (SNode**)&target);
|
|
CHECK_MAKE_NODE(target);
|
|
target->p = pStart->z;
|
|
target->n = (pEnd->z + pEnd->n) - pStart->z;
|
|
target->pNode = pNode;
|
|
return (SNode*)target;
|
|
_err:
|
|
nodesDestroyNode(pNode);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* setRawExprNodeIsPseudoColumn(SAstCreateContext* pCxt, SNode* pNode, bool isPseudoColumn) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
if (NULL == pNode || QUERY_NODE_RAW_EXPR != nodeType(pNode)) {
|
|
return pNode;
|
|
}
|
|
((SRawExprNode*)pNode)->isPseudoColumn = isPseudoColumn;
|
|
return pNode;
|
|
_err:
|
|
nodesDestroyNode(pNode);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* releaseRawExprNode(SAstCreateContext* pCxt, SNode* pNode) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SRawExprNode* pRawExpr = (SRawExprNode*)pNode;
|
|
SNode* pRealizedExpr = pRawExpr->pNode;
|
|
if (nodesIsExprNode(pRealizedExpr)) {
|
|
SExprNode* pExpr = (SExprNode*)pRealizedExpr;
|
|
if (QUERY_NODE_COLUMN == nodeType(pExpr)) {
|
|
tstrncpy(pExpr->aliasName, ((SColumnNode*)pExpr)->colName, TSDB_COL_NAME_LEN);
|
|
tstrncpy(pExpr->userAlias, ((SColumnNode*)pExpr)->colName, TSDB_COL_NAME_LEN);
|
|
} else if (pRawExpr->isPseudoColumn) {
|
|
// all pseudo column are translate to function with same name
|
|
tstrncpy(pExpr->aliasName, ((SFunctionNode*)pExpr)->functionName, TSDB_COL_NAME_LEN);
|
|
if (strcmp(((SFunctionNode*)pExpr)->functionName, "_placeholder_column") == 0) {
|
|
SValueNode* pColId = (SValueNode*)nodesListGetNode(((SFunctionNode*)pExpr)->pParameterList, 0);
|
|
snprintf(pExpr->userAlias, sizeof(pExpr->userAlias), "%%%%%s", pColId->literal);
|
|
} else if (strcmp(((SFunctionNode*)pExpr)->functionName, "_placeholder_tbname") == 0) {
|
|
tstrncpy(pExpr->userAlias, "%%tbname", TSDB_COL_NAME_LEN);
|
|
} else {
|
|
tstrncpy(pExpr->userAlias, ((SFunctionNode*)pExpr)->functionName, TSDB_COL_NAME_LEN);
|
|
}
|
|
} else {
|
|
int32_t len = TMIN(sizeof(pExpr->aliasName) - 1, pRawExpr->n);
|
|
|
|
// See TS-3398.
|
|
// Len of pRawExpr->p could be larger than len of aliasName[TSDB_COL_NAME_LEN].
|
|
// If aliasName is truncated, hash value of aliasName could be the same.
|
|
uint64_t hashVal = MurmurHash3_64(pRawExpr->p, pRawExpr->n);
|
|
snprintf(pExpr->aliasName, TSDB_COL_NAME_LEN, "%" PRIu64, hashVal);
|
|
strncpy(pExpr->userAlias, pRawExpr->p, len);
|
|
pExpr->userAlias[len] = 0;
|
|
}
|
|
}
|
|
pRawExpr->pNode = NULL;
|
|
nodesDestroyNode(pNode);
|
|
return pRealizedExpr;
|
|
_err:
|
|
nodesDestroyNode(pNode);
|
|
return NULL;
|
|
}
|
|
|
|
SToken getTokenFromRawExprNode(SAstCreateContext* pCxt, SNode* pNode) {
|
|
if (NULL == pNode || QUERY_NODE_RAW_EXPR != nodeType(pNode)) {
|
|
pCxt->errCode = TSDB_CODE_PAR_SYNTAX_ERROR;
|
|
return nil_token;
|
|
}
|
|
SRawExprNode* target = (SRawExprNode*)pNode;
|
|
SToken t = {.type = 0, .z = target->p, .n = target->n};
|
|
return t;
|
|
}
|
|
|
|
SNodeList* createColsFuncParamNodeList(SAstCreateContext* pCxt, SNode* pNode, SNodeList* pNodeList, SToken* pAlias) {
|
|
SRawExprNode* pRawExpr = (SRawExprNode*)pNode;
|
|
SNode* pFuncNode = pRawExpr->pNode;
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
if (NULL == pNode || QUERY_NODE_RAW_EXPR != nodeType(pNode)) {
|
|
pCxt->errCode = TSDB_CODE_PAR_SYNTAX_ERROR;
|
|
}
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
if (pFuncNode->type != QUERY_NODE_FUNCTION) {
|
|
pCxt->errCode = TSDB_CODE_PAR_SYNTAX_ERROR;
|
|
}
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SNodeList* list = NULL;
|
|
pCxt->errCode = nodesMakeList(&list);
|
|
CHECK_MAKE_NODE(list);
|
|
pCxt->errCode = nodesListAppend(list, pFuncNode);
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
pCxt->errCode = nodesListAppendList(list, pNodeList);
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
return list;
|
|
|
|
_err:
|
|
nodesDestroyNode(pFuncNode);
|
|
nodesDestroyList(pNodeList);
|
|
return NULL;
|
|
}
|
|
|
|
SNodeList* createNodeList(SAstCreateContext* pCxt, SNode* pNode) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SNodeList* list = NULL;
|
|
pCxt->errCode = nodesMakeList(&list);
|
|
CHECK_MAKE_NODE(list);
|
|
pCxt->errCode = nodesListAppend(list, pNode);
|
|
if (TSDB_CODE_SUCCESS != pCxt->errCode) {
|
|
nodesDestroyList(list);
|
|
return NULL;
|
|
}
|
|
return list;
|
|
_err:
|
|
nodesDestroyNode(pNode);
|
|
return NULL;
|
|
}
|
|
|
|
SNodeList* addNodeToList(SAstCreateContext* pCxt, SNodeList* pList, SNode* pNode) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
pCxt->errCode = nodesListAppend(pList, pNode);
|
|
return pList;
|
|
_err:
|
|
nodesDestroyNode(pNode);
|
|
nodesDestroyList(pList);
|
|
return NULL;
|
|
}
|
|
|
|
SPrivSetArgs privArgsAdd(SAstCreateContext* pCxt, SPrivSetArgs arg1, SPrivSetArgs arg2) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
if (arg1.nPrivArgs == 0 || arg2.nPrivArgs == 0) {
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR,
|
|
"Invalid privilege types: Unknown privilege type");
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
}
|
|
|
|
SPrivSetArgs merged = arg1;
|
|
merged.nPrivArgs += arg2.nPrivArgs;
|
|
if (merged.nPrivArgs > TSDB_PRIV_MAX_INPUT_ARGS) {
|
|
pCxt->errCode =
|
|
generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR,
|
|
"Invalid privilege types: exceed max privilege number:%d", TSDB_PRIV_MAX_INPUT_ARGS);
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
}
|
|
for (int32_t i = 0; i < PRIV_GROUP_CNT; ++i) {
|
|
if (arg2.privSet.set[i]) {
|
|
merged.privSet.set[i] |= arg2.privSet.set[i];
|
|
}
|
|
}
|
|
if (merged.selectCols) {
|
|
if (arg2.selectCols) {
|
|
pCxt->errCode = nodesListAppendList((SNodeList*)merged.selectCols, (SNodeList*)arg2.selectCols);
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
}
|
|
} else if (arg2.selectCols) {
|
|
merged.selectCols = arg2.selectCols;
|
|
}
|
|
if (LIST_LENGTH((SNodeList*)merged.selectCols) > TSDB_MAX_COLUMNS) {
|
|
pCxt->errCode =
|
|
generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR,
|
|
"Invalid privilege columns: SELECT exceed max columns number:%d", TSDB_MAX_COLUMNS);
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
}
|
|
if (merged.insertCols) {
|
|
if (arg2.insertCols) {
|
|
pCxt->errCode = nodesListAppendList((SNodeList*)merged.insertCols, (SNodeList*)arg2.insertCols);
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
}
|
|
} else if (arg2.insertCols) {
|
|
merged.insertCols = arg2.insertCols;
|
|
}
|
|
if (LIST_LENGTH((SNodeList*)merged.insertCols) > TSDB_MAX_COLUMNS) {
|
|
pCxt->errCode =
|
|
generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR,
|
|
"Invalid privilege columns: INSERT exceed max columns number:%d", TSDB_MAX_COLUMNS);
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
}
|
|
if (merged.updateCols) {
|
|
if (arg2.updateCols) {
|
|
pCxt->errCode = nodesListAppendList((SNodeList*)merged.updateCols, (SNodeList*)arg2.updateCols);
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
}
|
|
} else if (arg2.updateCols) {
|
|
merged.updateCols = arg2.updateCols;
|
|
}
|
|
if (LIST_LENGTH((SNodeList*)merged.updateCols) > TSDB_MAX_COLUMNS) {
|
|
pCxt->errCode =
|
|
generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR,
|
|
"Invalid privilege columns: UPDATE exceed max columns number:%d", TSDB_MAX_COLUMNS);
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
}
|
|
_err:
|
|
return merged;
|
|
}
|
|
|
|
SPrivSetArgs privArgsSetType(SAstCreateContext* pCxt, EPrivType type) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SPrivSetArgs args = {.nPrivArgs = 1};
|
|
privAddType(&args.privSet, type);
|
|
_err:
|
|
return args;
|
|
}
|
|
|
|
SPrivSetArgs privArgsSetCols(SAstCreateContext* pCxt, SNodeList* selectCols, SNodeList* insertCols,
|
|
SNodeList* updateCols) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SPrivSetArgs args = {.nPrivArgs = 1, .selectCols = selectCols, .insertCols = insertCols, .updateCols = updateCols};
|
|
_err:
|
|
return args;
|
|
}
|
|
|
|
/**
|
|
* @brief set privilege args from tokens as to decrease the definition of keywords
|
|
*
|
|
* @param pCxt
|
|
* @param type 0 alter, 1 read, 2 show, 3 set user
|
|
* @param t1
|
|
* @param t2
|
|
* @return SPrivSetArgs
|
|
*/
|
|
SPrivSetArgs privArgsSet(SAstCreateContext* pCxt, int32_t type, SToken* t1, SToken* t2) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SPrivSetArgs args = {0};
|
|
if (!t1) goto _err;
|
|
if (type == 0) { // alter
|
|
if (t1->n == 4) {
|
|
if (taosStrncasecmp(t1->z, TSDB_WORD_SELF, 4) == 0) {
|
|
if (t2 && t2->n == 4 && taosStrncasecmp(t2->z, TSDB_WORD_PASS, 4) == 0) {
|
|
return PRIV_SET_TYPE(PRIV_PASS_ALTER_SELF);
|
|
}
|
|
}
|
|
} else if (t1->n == 5) {
|
|
if (taosStrncasecmp(t1->z, TSDB_WORD_DEBUG, 5) == 0) {
|
|
if (t2 && t2->n == 8 && taosStrncasecmp(t2->z, TSDB_WORD_VARIABLE, 8) == 0) {
|
|
return PRIV_SET_TYPE(PRIV_VAR_DEBUG_ALTER);
|
|
}
|
|
} else if (taosStrncasecmp(t1->z, TSDB_WORD_AUDIT, 5) == 0) {
|
|
if (t2 && t2->n == 8 && taosStrncasecmp(t2->z, TSDB_WORD_VARIABLE, 8) == 0) {
|
|
return PRIV_SET_TYPE(PRIV_VAR_AUDIT_ALTER);
|
|
}
|
|
}
|
|
} else if (t1->n == 6) {
|
|
if (taosStrncasecmp(t1->z, TSDB_WORD_SYSTEM, 6) == 0) {
|
|
if (t2 && t2->n == 8 && taosStrncasecmp(t2->z, TSDB_WORD_VARIABLE, 8) == 0) {
|
|
return PRIV_SET_TYPE(PRIV_VAR_SYSTEM_ALTER);
|
|
}
|
|
}
|
|
} else if (t1->n == 8) {
|
|
if (taosStrncasecmp(t1->z, TSDB_WORD_SECURITY, 8) == 0) {
|
|
if (t2 && t2->n == 8 && taosStrncasecmp(t2->z, TSDB_WORD_VARIABLE, 8) == 0)
|
|
return PRIV_SET_TYPE(PRIV_VAR_SECURITY_ALTER);
|
|
}
|
|
}
|
|
} else if (type == 1) { // read
|
|
if (t1->n == 18) {
|
|
if (taosStrncasecmp(t1->z, TSDB_INFORMATION_SCHEMA_DB, 18) == 0) {
|
|
if (!t2) goto _err;
|
|
if (t2->n == 5) {
|
|
if (taosStrncasecmp(t2->z, TSDB_WORD_BASIC, 5) == 0) {
|
|
return PRIV_SET_TYPE(PRIV_INFO_SCHEMA_READ_BASIC);
|
|
} else if (taosStrncasecmp(t2->z, TSDB_WORD_AUDIT, 5) == 0) {
|
|
return PRIV_SET_TYPE(PRIV_INFO_SCHEMA_READ_AUDIT);
|
|
}
|
|
} else if ((t2->n == 8) && taosStrncasecmp(t2->z, TSDB_WORD_SECURITY, 8) == 0) {
|
|
return PRIV_SET_TYPE(PRIV_INFO_SCHEMA_READ_SEC);
|
|
} else if ((t2->n == 10) && taosStrncasecmp(t2->z, TSDB_WORD_PRIVILEGED, 10) == 0) {
|
|
return PRIV_SET_TYPE(PRIV_INFO_SCHEMA_READ_PRIVILEGED);
|
|
}
|
|
} else if (taosStrncasecmp(t1->z, TSDB_PERFORMANCE_SCHEMA_DB, 18) == 0) {
|
|
if (!t2) goto _err;
|
|
if (t2->n == 5) {
|
|
if (taosStrncasecmp(t2->z, TSDB_WORD_BASIC, 5) == 0) {
|
|
return PRIV_SET_TYPE(PRIV_PERF_SCHEMA_READ_BASIC);
|
|
}
|
|
} else if ((t2->n == 10) && taosStrncasecmp(t2->z, TSDB_WORD_PRIVILEGED, 10) == 0) {
|
|
return PRIV_SET_TYPE(PRIV_PERF_SCHEMA_READ_PRIVILEGED);
|
|
}
|
|
}
|
|
}
|
|
} else if (type == 2) { // show
|
|
if (t1->n == 5) {
|
|
if (taosStrncasecmp(t1->z, TSDB_WORD_DEBUG, 5) == 0) {
|
|
if (t2 && t2->n == 9 && taosStrncasecmp(t2->z, TSDB_WORD_VARIABLES, 9) == 0) {
|
|
return PRIV_SET_TYPE(PRIV_VAR_DEBUG_SHOW);
|
|
}
|
|
} else if (taosStrncasecmp(t1->z, TSDB_WORD_AUDIT, 5) == 0) {
|
|
if (t2 && t2->n == 9 && taosStrncasecmp(t2->z, TSDB_WORD_VARIABLES, 9) == 0) {
|
|
return PRIV_SET_TYPE(PRIV_VAR_AUDIT_SHOW);
|
|
}
|
|
}
|
|
} else if (t1->n == 6) {
|
|
if (taosStrncasecmp(t1->z, TSDB_WORD_SYSTEM, 6) == 0) {
|
|
if (t2 && t2->n == 9 && taosStrncasecmp(t2->z, TSDB_WORD_VARIABLES, 9) == 0) {
|
|
return PRIV_SET_TYPE(PRIV_VAR_SYSTEM_SHOW);
|
|
}
|
|
}
|
|
} else if (t1->n == 8) {
|
|
if (taosStrncasecmp(t1->z, TSDB_WORD_SECURITY, 8) == 0) {
|
|
if (t2 && t2->n == 9 && taosStrncasecmp(t2->z, TSDB_WORD_VARIABLES, 9) == 0)
|
|
return PRIV_SET_TYPE(PRIV_VAR_SECURITY_SHOW);
|
|
}
|
|
}
|
|
} else if (type == 3) { // set user
|
|
if (t1->n == 5) {
|
|
if (taosStrncasecmp(t1->z, TSDB_WORD_BASIC, 5) == 0) {
|
|
if (t2 && t2->n == 11 && taosStrncasecmp(t2->z, TSDB_WORD_INFORMATION, 11) == 0) {
|
|
return PRIV_SET_TYPE(PRIV_USER_SET_BASIC);
|
|
}
|
|
} else if (taosStrncasecmp(t1->z, TSDB_WORD_AUDIT, 5) == 0) {
|
|
if (t2 && t2->n == 11 && taosStrncasecmp(t2->z, TSDB_WORD_INFORMATION, 11) == 0) {
|
|
return PRIV_SET_TYPE(PRIV_USER_SET_AUDIT);
|
|
}
|
|
}
|
|
} else if ((t1->n == 8) && taosStrncasecmp(t1->z, TSDB_WORD_SECURITY, 8) == 0) {
|
|
if (t2 && t2->n == 11 && taosStrncasecmp(t2->z, TSDB_WORD_INFORMATION, 11) == 0) {
|
|
return PRIV_SET_TYPE(PRIV_USER_SET_SECURITY);
|
|
}
|
|
}
|
|
}
|
|
|
|
_err:
|
|
return args;
|
|
}
|
|
|
|
SNode* createColumnNode(SAstCreateContext* pCxt, SToken* pTableAlias, SToken* pColumnName) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
if (!checkTableName(pCxt, pTableAlias) || !checkColumnName(pCxt, pColumnName)) {
|
|
return NULL;
|
|
}
|
|
SColumnNode* col = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_COLUMN, (SNode**)&col);
|
|
CHECK_MAKE_NODE(col);
|
|
if (NULL != pTableAlias) {
|
|
COPY_STRING_FORM_ID_TOKEN(col->tableAlias, pTableAlias);
|
|
}
|
|
COPY_STRING_FORM_ID_TOKEN(col->colName, pColumnName);
|
|
return (SNode*)col;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
* @param type: 1 with mask; 0 without mask
|
|
*/
|
|
SNode* createColumnNodeExt(SAstCreateContext* pCxt, SToken* pTableAlias, SToken* pColumnName, int8_t type) {
|
|
SNode* result = createColumnNode(pCxt, pTableAlias, pColumnName);
|
|
if (result != NULL) {
|
|
if (type == 1) ((SColumnNode*)result)->hasMask = 1;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
SNode* createPlaceHolderColumnNode(SAstCreateContext* pCxt, SNode* pColId) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SFunctionNode* pFunc = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_FUNCTION, (SNode**)&pFunc);
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
tstrncpy(pFunc->functionName, "_placeholder_column", TSDB_FUNC_NAME_LEN);
|
|
((SValueNode*)pColId)->notReserved = true;
|
|
pCxt->errCode = nodesListMakeAppend(&pFunc->pParameterList, pColId);
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
pFunc->tz = pCxt->pQueryCxt->timezone;
|
|
pFunc->charsetCxt = pCxt->pQueryCxt->charsetCxt;
|
|
return (SNode*)pFunc;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
static void copyValueTrimEscape(char* buf, int32_t bufLen, const SToken* pToken, bool trim) {
|
|
int32_t len = TMIN(pToken->n, bufLen - 1);
|
|
if (trim && (pToken->z[0] == TS_ESCAPE_CHAR)) {
|
|
int32_t i = 1, j = 0;
|
|
for (; i < len - 1; ++i) {
|
|
buf[j++] = pToken->z[i];
|
|
if (pToken->z[i] == TS_ESCAPE_CHAR) {
|
|
if (pToken->z[i + 1] == TS_ESCAPE_CHAR) ++i;
|
|
}
|
|
}
|
|
buf[j] = 0;
|
|
} else {
|
|
tstrncpy(buf, pToken->z, len + 1);
|
|
}
|
|
}
|
|
|
|
SNode* createValueNode(SAstCreateContext* pCxt, int32_t dataType, const SToken* pLiteral) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SValueNode* val = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_VALUE, (SNode**)&val);
|
|
CHECK_MAKE_NODE(val);
|
|
if (!(val->literal = taosMemoryMalloc(pLiteral->n + 1))) {
|
|
pCxt->errCode = terrno;
|
|
nodesDestroyNode((SNode*)val);
|
|
return NULL;
|
|
}
|
|
copyValueTrimEscape(val->literal, pLiteral->n + 1, pLiteral,
|
|
pCxt->pQueryCxt->hasDupQuoteChar && (TK_NK_ID == pLiteral->type));
|
|
if (TK_NK_STRING == pLiteral->type) {
|
|
(void)trimString(pLiteral->z, pLiteral->n, val->literal, pLiteral->n);
|
|
}
|
|
val->node.resType.type = dataType;
|
|
val->node.resType.bytes = IS_VAR_DATA_TYPE(dataType) ? strlen(val->literal) : tDataTypes[dataType].bytes;
|
|
if (TSDB_DATA_TYPE_TIMESTAMP == dataType) {
|
|
val->node.resType.precision = TSDB_TIME_PRECISION_MILLI;
|
|
}
|
|
val->translate = false;
|
|
val->tz = pCxt->pQueryCxt->timezone;
|
|
val->charsetCxt = pCxt->pQueryCxt->charsetCxt;
|
|
return (SNode*)val;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createRawValueNode(SAstCreateContext* pCxt, int32_t dataType, const SToken* pLiteral, SNode* pNode) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SValueNode* val = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_VALUE, (SNode**)&val);
|
|
if (TSDB_CODE_SUCCESS != pCxt->errCode) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, pCxt->errCode, "");
|
|
goto _exit;
|
|
}
|
|
if (pLiteral) {
|
|
val->literal = taosStrndup(pLiteral->z, pLiteral->n);
|
|
if (!val->literal) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, terrno, "Out of memory");
|
|
goto _exit;
|
|
}
|
|
} else if (pNode) {
|
|
SRawExprNode* pRawExpr = (SRawExprNode*)pNode;
|
|
if (!nodesIsExprNode(pRawExpr->pNode)) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, pRawExpr->p);
|
|
goto _exit;
|
|
}
|
|
val->literal = taosStrndup(pRawExpr->p, pRawExpr->n);
|
|
if (!val->literal) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, terrno, "Out of memory");
|
|
goto _exit;
|
|
}
|
|
} else {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INTERNAL_ERROR, "Invalid parameters");
|
|
goto _exit;
|
|
}
|
|
if (!val->literal) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_OUT_OF_MEMORY, "Out of memory");
|
|
goto _exit;
|
|
}
|
|
|
|
val->node.resType.type = dataType;
|
|
val->node.resType.bytes = IS_VAR_DATA_TYPE(dataType) ? strlen(val->literal) : tDataTypes[dataType].bytes;
|
|
if (TSDB_DATA_TYPE_TIMESTAMP == dataType) {
|
|
val->node.resType.precision = TSDB_TIME_PRECISION_MILLI;
|
|
}
|
|
_exit:
|
|
nodesDestroyNode(pNode);
|
|
if (pCxt->errCode != 0) {
|
|
nodesDestroyNode((SNode*)val);
|
|
return NULL;
|
|
}
|
|
return (SNode*)val;
|
|
_err:
|
|
nodesDestroyNode(pNode);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createRawValueNodeExt(SAstCreateContext* pCxt, int32_t dataType, const SToken* pLiteral, SNode* pLeft,
|
|
SNode* pRight) {
|
|
SValueNode* val = NULL;
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_VALUE, (SNode**)&val);
|
|
if (TSDB_CODE_SUCCESS != pCxt->errCode) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, pCxt->errCode, "");
|
|
goto _exit;
|
|
}
|
|
if (pLiteral) {
|
|
if (!(val->literal = taosStrndup(pLiteral->z, pLiteral->n))) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, terrno, "Out of memory");
|
|
goto _exit;
|
|
}
|
|
} else {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INTERNAL_ERROR, "Invalid parameters");
|
|
goto _exit;
|
|
}
|
|
|
|
val->node.resType.type = dataType;
|
|
val->node.resType.bytes = IS_VAR_DATA_TYPE(dataType) ? strlen(val->literal) : tDataTypes[dataType].bytes;
|
|
if (TSDB_DATA_TYPE_TIMESTAMP == dataType) {
|
|
val->node.resType.precision = TSDB_TIME_PRECISION_MILLI;
|
|
}
|
|
_exit:
|
|
nodesDestroyNode(pLeft);
|
|
nodesDestroyNode(pRight);
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
return (SNode*)val;
|
|
_err:
|
|
nodesDestroyNode((SNode*)val);
|
|
nodesDestroyNode(pLeft);
|
|
nodesDestroyNode(pRight);
|
|
return NULL;
|
|
}
|
|
|
|
static bool hasHint(SNodeList* pHintList, EHintOption hint) {
|
|
if (!pHintList) return false;
|
|
SNode* pNode;
|
|
FOREACH(pNode, pHintList) {
|
|
SHintNode* pHint = (SHintNode*)pNode;
|
|
if (pHint->option == hint) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool addHintNodeToList(SAstCreateContext* pCxt, SNodeList** ppHintList, EHintOption opt, SToken* paramList,
|
|
int32_t paramNum) {
|
|
void* value = NULL;
|
|
switch (opt) {
|
|
case HINT_SKIP_TSMA:
|
|
case HINT_BATCH_SCAN:
|
|
case HINT_NO_BATCH_SCAN: {
|
|
if (paramNum > 0) {
|
|
return true;
|
|
}
|
|
break;
|
|
}
|
|
case HINT_SORT_FOR_GROUP:
|
|
if (paramNum > 0 || hasHint(*ppHintList, HINT_PARTITION_FIRST)) return true;
|
|
break;
|
|
case HINT_PARTITION_FIRST:
|
|
if (paramNum > 0 || hasHint(*ppHintList, HINT_SORT_FOR_GROUP)) return true;
|
|
break;
|
|
case HINT_PARA_TABLES_SORT:
|
|
if (paramNum > 0 || hasHint(*ppHintList, HINT_PARA_TABLES_SORT)) return true;
|
|
break;
|
|
case HINT_SMALLDATA_TS_SORT:
|
|
if (paramNum > 0 || hasHint(*ppHintList, HINT_SMALLDATA_TS_SORT)) return true;
|
|
break;
|
|
case HINT_HASH_JOIN:
|
|
if (paramNum > 0 || hasHint(*ppHintList, HINT_HASH_JOIN)) return true;
|
|
break;
|
|
case HINT_WIN_OPTIMIZE_BATCH:
|
|
if (paramNum > 0 || hasHint(*ppHintList, HINT_WIN_OPTIMIZE_BATCH)) return true;
|
|
break;
|
|
case HINT_WIN_OPTIMIZE_SINGLE:
|
|
if (paramNum > 0 || hasHint(*ppHintList, HINT_WIN_OPTIMIZE_SINGLE)) return true;
|
|
break;
|
|
default:
|
|
return true;
|
|
}
|
|
|
|
SHintNode* hint = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_HINT, (SNode**)&hint);
|
|
if (!hint) {
|
|
return true;
|
|
}
|
|
hint->option = opt;
|
|
hint->value = value;
|
|
|
|
if (NULL == *ppHintList) {
|
|
pCxt->errCode = nodesMakeList(ppHintList);
|
|
if (!*ppHintList) {
|
|
nodesDestroyNode((SNode*)hint);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
pCxt->errCode = nodesListStrictAppend(*ppHintList, (SNode*)hint);
|
|
if (pCxt->errCode) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
SNodeList* createHintNodeList(SAstCreateContext* pCxt, const SToken* pLiteral) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
if (NULL == pLiteral || pLiteral->n <= 5) {
|
|
return NULL;
|
|
}
|
|
SNodeList* pHintList = NULL;
|
|
char* hint = taosStrndup(pLiteral->z + 3, pLiteral->n - 5);
|
|
if (!hint) return NULL;
|
|
int32_t i = 0;
|
|
bool quit = false;
|
|
bool inParamList = false;
|
|
bool lastComma = false;
|
|
EHintOption opt = 0;
|
|
int32_t paramNum = 0;
|
|
SToken paramList[10];
|
|
while (!quit) {
|
|
SToken t0 = {0};
|
|
if (hint[i] == 0) {
|
|
break;
|
|
}
|
|
t0.n = tGetToken(&hint[i], &t0.type, NULL);
|
|
t0.z = hint + i;
|
|
i += t0.n;
|
|
|
|
switch (t0.type) {
|
|
case TK_BATCH_SCAN:
|
|
lastComma = false;
|
|
if (0 != opt || inParamList) {
|
|
quit = true;
|
|
break;
|
|
}
|
|
opt = HINT_BATCH_SCAN;
|
|
break;
|
|
case TK_NO_BATCH_SCAN:
|
|
lastComma = false;
|
|
if (0 != opt || inParamList) {
|
|
quit = true;
|
|
break;
|
|
}
|
|
opt = HINT_NO_BATCH_SCAN;
|
|
break;
|
|
case TK_SORT_FOR_GROUP:
|
|
lastComma = false;
|
|
if (0 != opt || inParamList) {
|
|
quit = true;
|
|
break;
|
|
}
|
|
opt = HINT_SORT_FOR_GROUP;
|
|
break;
|
|
case TK_PARTITION_FIRST:
|
|
lastComma = false;
|
|
if (0 != opt || inParamList) {
|
|
quit = true;
|
|
break;
|
|
}
|
|
opt = HINT_PARTITION_FIRST;
|
|
break;
|
|
case TK_PARA_TABLES_SORT:
|
|
lastComma = false;
|
|
if (0 != opt || inParamList) {
|
|
quit = true;
|
|
break;
|
|
}
|
|
opt = HINT_PARA_TABLES_SORT;
|
|
break;
|
|
case TK_SMALLDATA_TS_SORT:
|
|
lastComma = false;
|
|
if (0 != opt || inParamList) {
|
|
quit = true;
|
|
break;
|
|
}
|
|
opt = HINT_SMALLDATA_TS_SORT;
|
|
break;
|
|
case TK_HASH_JOIN:
|
|
lastComma = false;
|
|
if (0 != opt || inParamList) {
|
|
quit = true;
|
|
break;
|
|
}
|
|
opt = HINT_HASH_JOIN;
|
|
break;
|
|
case TK_SKIP_TSMA:
|
|
lastComma = false;
|
|
if (0 != opt || inParamList) {
|
|
quit = true;
|
|
break;
|
|
}
|
|
opt = HINT_SKIP_TSMA;
|
|
break;
|
|
case TK_WIN_OPTIMIZE_BATCH:
|
|
lastComma = false;
|
|
if (0 != opt || inParamList) {
|
|
quit = true;
|
|
break;
|
|
}
|
|
opt = HINT_WIN_OPTIMIZE_BATCH;
|
|
break;
|
|
case TK_WIN_OPTIMIZE_SINGLE:
|
|
lastComma = false;
|
|
if (0 != opt || inParamList) {
|
|
quit = true;
|
|
break;
|
|
}
|
|
opt = HINT_WIN_OPTIMIZE_SINGLE;
|
|
break;
|
|
case TK_NK_LP:
|
|
lastComma = false;
|
|
if (0 == opt || inParamList) {
|
|
quit = true;
|
|
}
|
|
inParamList = true;
|
|
break;
|
|
case TK_NK_RP:
|
|
lastComma = false;
|
|
if (0 == opt || !inParamList) {
|
|
quit = true;
|
|
} else {
|
|
quit = addHintNodeToList(pCxt, &pHintList, opt, paramList, paramNum);
|
|
inParamList = false;
|
|
paramNum = 0;
|
|
opt = 0;
|
|
}
|
|
break;
|
|
case TK_NK_ID:
|
|
lastComma = false;
|
|
if (0 == opt || !inParamList) {
|
|
quit = true;
|
|
} else {
|
|
paramList[paramNum++] = t0;
|
|
}
|
|
break;
|
|
case TK_NK_COMMA:
|
|
if (lastComma) {
|
|
quit = true;
|
|
}
|
|
lastComma = true;
|
|
break;
|
|
case TK_NK_SPACE:
|
|
break;
|
|
default:
|
|
lastComma = false;
|
|
quit = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
taosMemoryFree(hint);
|
|
return pHintList;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createIdentifierValueNode(SAstCreateContext* pCxt, SToken* pLiteral) {
|
|
trimEscape(pCxt, pLiteral, false);
|
|
return createValueNode(pCxt, TSDB_DATA_TYPE_BINARY, pLiteral);
|
|
}
|
|
|
|
SNode* createDurationValueNode(SAstCreateContext* pCxt, const SToken* pLiteral) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SValueNode* val = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_VALUE, (SNode**)&val);
|
|
CHECK_MAKE_NODE(val);
|
|
if (pLiteral->type == TK_NK_STRING) {
|
|
// like '100s' or "100d"
|
|
// check format: ^[0-9]+[smwbauhdny]$'
|
|
if (pLiteral->n < 4) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, pLiteral->z);
|
|
return NULL;
|
|
}
|
|
char unit = pLiteral->z[pLiteral->n - 2];
|
|
switch (unit) {
|
|
case 'a':
|
|
case 'b':
|
|
case 'd':
|
|
case 'h':
|
|
case 'm':
|
|
case 's':
|
|
case 'u':
|
|
case 'w':
|
|
case 'y':
|
|
case 'n':
|
|
break;
|
|
default:
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, pLiteral->z);
|
|
return NULL;
|
|
}
|
|
for (uint32_t i = 1; i < pLiteral->n - 2; ++i) {
|
|
if (!isdigit(pLiteral->z[i])) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, pLiteral->z);
|
|
return NULL;
|
|
}
|
|
}
|
|
val->literal = taosStrndup(pLiteral->z + 1, pLiteral->n - 2);
|
|
} else {
|
|
val->literal = taosStrndup(pLiteral->z, pLiteral->n);
|
|
}
|
|
if (!val->literal) {
|
|
nodesDestroyNode((SNode*)val);
|
|
pCxt->errCode = terrno;
|
|
return NULL;
|
|
}
|
|
val->flag |= VALUE_FLAG_IS_DURATION;
|
|
val->translate = false;
|
|
val->node.resType.type = TSDB_DATA_TYPE_BIGINT;
|
|
val->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_BIGINT].bytes;
|
|
val->node.resType.precision = TSDB_TIME_PRECISION_MILLI;
|
|
return (SNode*)val;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createTimeOffsetValueNode(SAstCreateContext* pCxt, const SToken* pLiteral) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SValueNode* val = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_VALUE, (SNode**)&val);
|
|
CHECK_MAKE_NODE(val);
|
|
if (pLiteral->type == TK_NK_STRING) {
|
|
// like '100s' or "100d"
|
|
// check format: ^[0-9]+[smwbauhdny]$'
|
|
if (pLiteral->n < 4) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, pLiteral->z);
|
|
return NULL;
|
|
}
|
|
char unit = pLiteral->z[pLiteral->n - 2];
|
|
switch (unit) {
|
|
case 'a':
|
|
case 'b':
|
|
case 'd':
|
|
case 'h':
|
|
case 'm':
|
|
case 's':
|
|
case 'u':
|
|
case 'w':
|
|
break;
|
|
default:
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, pLiteral->z);
|
|
return NULL;
|
|
}
|
|
for (uint32_t i = 1; i < pLiteral->n - 2; ++i) {
|
|
if (!isdigit(pLiteral->z[i])) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, pLiteral->z);
|
|
return NULL;
|
|
}
|
|
}
|
|
val->literal = taosStrndup(pLiteral->z + 1, pLiteral->n - 2);
|
|
} else {
|
|
val->literal = taosStrndup(pLiteral->z, pLiteral->n);
|
|
}
|
|
if (!val->literal) {
|
|
nodesDestroyNode((SNode*)val);
|
|
pCxt->errCode = terrno;
|
|
return NULL;
|
|
}
|
|
val->flag |= VALUE_FLAG_IS_TIME_OFFSET;
|
|
val->translate = false;
|
|
val->node.resType.type = TSDB_DATA_TYPE_BIGINT;
|
|
val->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_BIGINT].bytes;
|
|
val->node.resType.precision = TSDB_TIME_PRECISION_MILLI;
|
|
return (SNode*)val;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createDefaultDatabaseCondValue(SAstCreateContext* pCxt) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
if (NULL == pCxt->pQueryCxt->db) {
|
|
return NULL;
|
|
}
|
|
|
|
SValueNode* val = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_VALUE, (SNode**)&val);
|
|
CHECK_MAKE_NODE(val);
|
|
val->literal = taosStrdup(pCxt->pQueryCxt->db);
|
|
if (!val->literal) {
|
|
pCxt->errCode = TSDB_CODE_OUT_OF_MEMORY;
|
|
nodesDestroyNode((SNode*)val);
|
|
return NULL;
|
|
}
|
|
val->translate = false;
|
|
val->node.resType.type = TSDB_DATA_TYPE_BINARY;
|
|
val->node.resType.bytes = strlen(val->literal);
|
|
val->node.resType.precision = TSDB_TIME_PRECISION_MILLI;
|
|
return (SNode*)val;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createPlaceholderValueNode(SAstCreateContext* pCxt, const SToken* pLiteral) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
if (NULL == pCxt->pQueryCxt->pStmtCb) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, pLiteral->z);
|
|
return NULL;
|
|
}
|
|
SValueNode* val = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_VALUE, (SNode**)&val);
|
|
CHECK_MAKE_NODE(val);
|
|
val->literal = taosStrndup(pLiteral->z, pLiteral->n);
|
|
if (!val->literal) {
|
|
pCxt->errCode = terrno;
|
|
nodesDestroyNode((SNode*)val);
|
|
return NULL;
|
|
}
|
|
val->placeholderNo = ++pCxt->placeholderNo;
|
|
if (NULL == pCxt->pPlaceholderValues) {
|
|
pCxt->pPlaceholderValues = taosArrayInit(TARRAY_MIN_SIZE, POINTER_BYTES);
|
|
if (NULL == pCxt->pPlaceholderValues) {
|
|
nodesDestroyNode((SNode*)val);
|
|
return NULL;
|
|
}
|
|
}
|
|
if (NULL == taosArrayPush(pCxt->pPlaceholderValues, &val)) {
|
|
pCxt->errCode = TSDB_CODE_OUT_OF_MEMORY;
|
|
nodesDestroyNode((SNode*)val);
|
|
taosArrayDestroy(pCxt->pPlaceholderValues);
|
|
return NULL;
|
|
}
|
|
return (SNode*)val;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createDurationPlaceholderValueNode(SAstCreateContext* pCxt, const SToken* pLiteral) {
|
|
SNode* pNode = createPlaceholderValueNode(pCxt, pLiteral);
|
|
if (pNode != NULL) {
|
|
SValueNode* val = (SValueNode*)pNode;
|
|
val->flag |= VALUE_FLAG_IS_DURATION;
|
|
val->node.resType.type = TSDB_DATA_TYPE_BIGINT;
|
|
val->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_BIGINT].bytes;
|
|
val->node.resType.precision = TSDB_TIME_PRECISION_MILLI;
|
|
}
|
|
return pNode;
|
|
}
|
|
|
|
static int32_t addParamToLogicConditionNode(SLogicConditionNode* pCond, SNode* pParam) {
|
|
if (QUERY_NODE_LOGIC_CONDITION == nodeType(pParam) && pCond->condType == ((SLogicConditionNode*)pParam)->condType &&
|
|
((SLogicConditionNode*)pParam)->condType != LOGIC_COND_TYPE_NOT) {
|
|
int32_t code = nodesListAppendList(pCond->pParameterList, ((SLogicConditionNode*)pParam)->pParameterList);
|
|
((SLogicConditionNode*)pParam)->pParameterList = NULL;
|
|
nodesDestroyNode(pParam);
|
|
return code;
|
|
} else {
|
|
return nodesListAppend(pCond->pParameterList, pParam);
|
|
}
|
|
}
|
|
|
|
SNode* createLogicConditionNode(SAstCreateContext* pCxt, ELogicConditionType type, SNode* pParam1, SNode* pParam2) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SLogicConditionNode* cond = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_LOGIC_CONDITION, (SNode**)&cond);
|
|
CHECK_MAKE_NODE(cond);
|
|
cond->condType = type;
|
|
cond->pParameterList = NULL;
|
|
pCxt->errCode = nodesMakeList(&cond->pParameterList);
|
|
if (TSDB_CODE_SUCCESS == pCxt->errCode) {
|
|
pCxt->errCode = addParamToLogicConditionNode(cond, pParam1);
|
|
}
|
|
if (TSDB_CODE_SUCCESS == pCxt->errCode && NULL != pParam2) {
|
|
pCxt->errCode = addParamToLogicConditionNode(cond, pParam2);
|
|
}
|
|
if (TSDB_CODE_SUCCESS != pCxt->errCode) {
|
|
nodesDestroyNode((SNode*)cond);
|
|
return NULL;
|
|
}
|
|
return (SNode*)cond;
|
|
_err:
|
|
nodesDestroyNode(pParam1);
|
|
nodesDestroyNode(pParam2);
|
|
return NULL;
|
|
}
|
|
|
|
static uint8_t getMinusDataType(uint8_t orgType) {
|
|
switch (orgType) {
|
|
case TSDB_DATA_TYPE_UTINYINT:
|
|
case TSDB_DATA_TYPE_USMALLINT:
|
|
case TSDB_DATA_TYPE_UINT:
|
|
case TSDB_DATA_TYPE_UBIGINT:
|
|
return TSDB_DATA_TYPE_BIGINT;
|
|
default:
|
|
break;
|
|
}
|
|
return orgType;
|
|
}
|
|
|
|
SNode* createOperatorNode(SAstCreateContext* pCxt, EOperatorType type, SNode* pLeft, SNode* pRight) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
if (OP_TYPE_MINUS == type && QUERY_NODE_VALUE == nodeType(pLeft)) {
|
|
SValueNode* pVal = (SValueNode*)pLeft;
|
|
char* pNewLiteral = taosMemoryCalloc(1, strlen(pVal->literal) + 2);
|
|
if (!pNewLiteral) {
|
|
pCxt->errCode = terrno;
|
|
goto _err;
|
|
}
|
|
if ('+' == pVal->literal[0]) {
|
|
snprintf(pNewLiteral, strlen(pVal->literal) + 2, "-%s", pVal->literal + 1);
|
|
} else if ('-' == pVal->literal[0]) {
|
|
snprintf(pNewLiteral, strlen(pVal->literal) + 2, "%s", pVal->literal + 1);
|
|
} else {
|
|
snprintf(pNewLiteral, strlen(pVal->literal) + 2, "-%s", pVal->literal);
|
|
}
|
|
taosMemoryFree(pVal->literal);
|
|
pVal->literal = pNewLiteral;
|
|
pVal->node.resType.type = getMinusDataType(pVal->node.resType.type);
|
|
return pLeft;
|
|
}
|
|
if (pLeft && QUERY_NODE_VALUE == nodeType(pLeft)) {
|
|
SValueNode* pVal = (SValueNode*)pLeft;
|
|
pVal->tz = pCxt->pQueryCxt->timezone;
|
|
}
|
|
if (pRight && QUERY_NODE_VALUE == nodeType(pRight)) {
|
|
SValueNode* pVal = (SValueNode*)pRight;
|
|
pVal->tz = pCxt->pQueryCxt->timezone;
|
|
}
|
|
|
|
SOperatorNode* op = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_OPERATOR, (SNode**)&op);
|
|
CHECK_MAKE_NODE(op);
|
|
op->opType = type;
|
|
op->pLeft = pLeft;
|
|
op->pRight = pRight;
|
|
op->tz = pCxt->pQueryCxt->timezone;
|
|
op->charsetCxt = pCxt->pQueryCxt->charsetCxt;
|
|
return (SNode*)op;
|
|
_err:
|
|
nodesDestroyNode(pLeft);
|
|
nodesDestroyNode(pRight);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createBetweenAnd(SAstCreateContext* pCxt, SNode* pExpr, SNode* pLeft, SNode* pRight) {
|
|
SNode *pNew = NULL, *pGE = NULL, *pLE = NULL;
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
pCxt->errCode = nodesCloneNode(pExpr, &pNew);
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
pGE = createOperatorNode(pCxt, OP_TYPE_GREATER_EQUAL, pExpr, pLeft);
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
pLE = createOperatorNode(pCxt, OP_TYPE_LOWER_EQUAL, pNew, pRight);
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SNode* pRet = createLogicConditionNode(pCxt, LOGIC_COND_TYPE_AND, pGE, pLE);
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
return pRet;
|
|
_err:
|
|
nodesDestroyNode(pNew);
|
|
nodesDestroyNode(pGE);
|
|
nodesDestroyNode(pLE);
|
|
nodesDestroyNode(pExpr);
|
|
nodesDestroyNode(pLeft);
|
|
nodesDestroyNode(pRight);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createNotBetweenAnd(SAstCreateContext* pCxt, SNode* pExpr, SNode* pLeft, SNode* pRight) {
|
|
SNode *pNew = NULL, *pLT = NULL, *pGT = NULL;
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
pCxt->errCode = nodesCloneNode(pExpr, &pNew);
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
pLT = createOperatorNode(pCxt, OP_TYPE_LOWER_THAN, pExpr, pLeft);
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
pGT = createOperatorNode(pCxt, OP_TYPE_GREATER_THAN, pNew, pRight);
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SNode* pRet = createLogicConditionNode(pCxt, LOGIC_COND_TYPE_OR, pLT, pGT);
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
return pRet;
|
|
_err:
|
|
nodesDestroyNode(pNew);
|
|
nodesDestroyNode(pGT);
|
|
nodesDestroyNode(pLT);
|
|
nodesDestroyNode(pExpr);
|
|
nodesDestroyNode(pLeft);
|
|
nodesDestroyNode(pRight);
|
|
return NULL;
|
|
}
|
|
|
|
static SNode* createPrimaryKeyCol(SAstCreateContext* pCxt, const SToken* pFuncName) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SColumnNode* pCol = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_COLUMN, (SNode**)&pCol);
|
|
CHECK_MAKE_NODE(pCol);
|
|
pCol->colId = PRIMARYKEY_TIMESTAMP_COL_ID;
|
|
if (NULL == pFuncName) {
|
|
tstrncpy(pCol->colName, ROWTS_PSEUDO_COLUMN_NAME, TSDB_COL_NAME_LEN);
|
|
} else {
|
|
strncpy(pCol->colName, pFuncName->z, pFuncName->n);
|
|
}
|
|
pCol->isPrimTs = true;
|
|
return (SNode*)pCol;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createFunctionNode(SAstCreateContext* pCxt, const SToken* pFuncName, SNodeList* pParameterList) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
if (0 == strncasecmp("_rowts", pFuncName->z, pFuncName->n) || 0 == strncasecmp("_c0", pFuncName->z, pFuncName->n)) {
|
|
return createPrimaryKeyCol(pCxt, pFuncName);
|
|
}
|
|
SFunctionNode* func = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_FUNCTION, (SNode**)&func);
|
|
CHECK_MAKE_NODE(func);
|
|
COPY_STRING_FORM_ID_TOKEN(func->functionName, pFuncName);
|
|
func->pParameterList = pParameterList;
|
|
func->tz = pCxt->pQueryCxt->timezone;
|
|
func->charsetCxt = pCxt->pQueryCxt->charsetCxt;
|
|
return (SNode*)func;
|
|
_err:
|
|
nodesDestroyList(pParameterList);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createPHTbnameFunctionNode(SAstCreateContext* pCxt, const SToken* pFuncName, SNodeList* pParameterList) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SFunctionNode* func = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_FUNCTION, (SNode**)&func);
|
|
CHECK_MAKE_NODE(func);
|
|
tstrncpy(func->functionName, "_placeholder_tbname", TSDB_FUNC_NAME_LEN);
|
|
func->pParameterList = pParameterList;
|
|
func->tz = pCxt->pQueryCxt->timezone;
|
|
func->charsetCxt = pCxt->pQueryCxt->charsetCxt;
|
|
return (SNode*)func;
|
|
_err:
|
|
nodesDestroyList(pParameterList);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createCastFunctionNode(SAstCreateContext* pCxt, SNode* pExpr, SDataType dt) {
|
|
SFunctionNode* func = NULL;
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_FUNCTION, (SNode**)&func);
|
|
CHECK_MAKE_NODE(func);
|
|
tstrncpy(func->functionName, "cast", TSDB_FUNC_NAME_LEN);
|
|
func->node.resType = dt;
|
|
if (TSDB_DATA_TYPE_VARCHAR == dt.type || TSDB_DATA_TYPE_GEOMETRY == dt.type || TSDB_DATA_TYPE_VARBINARY == dt.type) {
|
|
func->node.resType.bytes = func->node.resType.bytes + VARSTR_HEADER_SIZE;
|
|
} else if (TSDB_DATA_TYPE_NCHAR == dt.type) {
|
|
func->node.resType.bytes = func->node.resType.bytes * TSDB_NCHAR_SIZE + VARSTR_HEADER_SIZE;
|
|
}
|
|
pCxt->errCode = nodesListMakeAppend(&func->pParameterList, pExpr);
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
func->tz = pCxt->pQueryCxt->timezone;
|
|
func->charsetCxt = pCxt->pQueryCxt->charsetCxt;
|
|
|
|
return (SNode*)func;
|
|
_err:
|
|
nodesDestroyNode((SNode*)func);
|
|
nodesDestroyNode(pExpr);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createPositionFunctionNode(SAstCreateContext* pCxt, SNode* pExpr, SNode* pExpr2) {
|
|
SFunctionNode* func = NULL;
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_FUNCTION, (SNode**)&func);
|
|
CHECK_MAKE_NODE(func);
|
|
tstrncpy(func->functionName, "position", TSDB_FUNC_NAME_LEN);
|
|
pCxt->errCode = nodesListMakeAppend(&func->pParameterList, pExpr);
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
pCxt->errCode = nodesListMakeAppend(&func->pParameterList, pExpr2);
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
return (SNode*)func;
|
|
_err:
|
|
nodesDestroyNode((SNode*)func);
|
|
nodesDestroyNode(pExpr);
|
|
nodesDestroyNode(pExpr2);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createTrimFunctionNode(SAstCreateContext* pCxt, SNode* pExpr, ETrimType type) {
|
|
SFunctionNode* func = NULL;
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_FUNCTION, (SNode**)&func);
|
|
CHECK_MAKE_NODE(func);
|
|
tstrncpy(func->functionName, "trim", TSDB_FUNC_NAME_LEN);
|
|
func->trimType = type;
|
|
pCxt->errCode = nodesListMakeAppend(&func->pParameterList, pExpr);
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
func->charsetCxt = pCxt->pQueryCxt->charsetCxt;
|
|
return (SNode*)func;
|
|
_err:
|
|
nodesDestroyNode((SNode*)func);
|
|
nodesDestroyNode(pExpr);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createTrimFunctionNodeExt(SAstCreateContext* pCxt, SNode* pExpr, SNode* pExpr2, ETrimType type) {
|
|
SFunctionNode* func = NULL;
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_FUNCTION, (SNode**)&func);
|
|
CHECK_MAKE_NODE(func);
|
|
tstrncpy(func->functionName, "trim", TSDB_FUNC_NAME_LEN);
|
|
func->trimType = type;
|
|
pCxt->errCode = nodesListMakeAppend(&func->pParameterList, pExpr);
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
pCxt->errCode = nodesListMakeAppend(&func->pParameterList, pExpr2);
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
func->charsetCxt = pCxt->pQueryCxt->charsetCxt;
|
|
return (SNode*)func;
|
|
_err:
|
|
nodesDestroyNode((SNode*)func);
|
|
nodesDestroyNode(pExpr);
|
|
nodesDestroyNode(pExpr2);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createSubstrFunctionNode(SAstCreateContext* pCxt, SNode* pExpr, SNode* pExpr2) {
|
|
SFunctionNode* func = NULL;
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_FUNCTION, (SNode**)&func);
|
|
CHECK_MAKE_NODE(func);
|
|
tstrncpy(func->functionName, "substr", TSDB_FUNC_NAME_LEN);
|
|
pCxt->errCode = nodesListMakeAppend(&func->pParameterList, pExpr);
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
pCxt->errCode = nodesListMakeAppend(&func->pParameterList, pExpr2);
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
return (SNode*)func;
|
|
_err:
|
|
nodesDestroyNode((SNode*)func);
|
|
nodesDestroyNode(pExpr);
|
|
nodesDestroyNode(pExpr2);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createSubstrFunctionNodeExt(SAstCreateContext* pCxt, SNode* pExpr, SNode* pExpr2, SNode* pExpr3) {
|
|
SFunctionNode* func = NULL;
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_FUNCTION, (SNode**)&func);
|
|
CHECK_MAKE_NODE(func);
|
|
tstrncpy(func->functionName, "substr", TSDB_FUNC_NAME_LEN);
|
|
pCxt->errCode = nodesListMakeAppend(&func->pParameterList, pExpr);
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
pCxt->errCode = nodesListMakeAppend(&func->pParameterList, pExpr2);
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
pCxt->errCode = nodesListMakeAppend(&func->pParameterList, pExpr3);
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
return (SNode*)func;
|
|
_err:
|
|
nodesDestroyNode((SNode*)func);
|
|
nodesDestroyNode(pExpr);
|
|
nodesDestroyNode(pExpr2);
|
|
nodesDestroyNode(pExpr3);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createNodeListNode(SAstCreateContext* pCxt, SNodeList* pList) {
|
|
SNodeListNode* list = NULL;
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_NODE_LIST, (SNode**)&list);
|
|
CHECK_MAKE_NODE(list);
|
|
list->pNodeList = pList;
|
|
return (SNode*)list;
|
|
_err:
|
|
nodesDestroyList(pList);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createNodeListNodeEx(SAstCreateContext* pCxt, SNode* p1, SNode* p2) {
|
|
SNodeListNode* list = NULL;
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_NODE_LIST, (SNode**)&list);
|
|
CHECK_MAKE_NODE(list);
|
|
pCxt->errCode = nodesListMakeStrictAppend(&list->pNodeList, p1);
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
pCxt->errCode = nodesListStrictAppend(list->pNodeList, p2);
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
return (SNode*)list;
|
|
_err:
|
|
nodesDestroyNode((SNode*)list);
|
|
nodesDestroyNode(p1);
|
|
nodesDestroyNode(p2);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createRealTableNode(SAstCreateContext* pCxt, SToken* pDbName, SToken* pTableName, SToken* pTableAlias) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
CHECK_NAME(checkDbName(pCxt, pDbName, true));
|
|
CHECK_NAME(checkTableName(pCxt, pTableName));
|
|
CHECK_NAME(checkTableName(pCxt, pTableAlias));
|
|
SRealTableNode* realTable = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_REAL_TABLE, (SNode**)&realTable);
|
|
CHECK_MAKE_NODE(realTable);
|
|
if (NULL != pDbName) {
|
|
COPY_STRING_FORM_ID_TOKEN(realTable->table.dbName, pDbName);
|
|
} else {
|
|
snprintf(realTable->table.dbName, sizeof(realTable->table.dbName), "%s", pCxt->pQueryCxt->db);
|
|
}
|
|
if (NULL != pTableAlias && TK_NK_NIL != pTableAlias->type) {
|
|
COPY_STRING_FORM_ID_TOKEN(realTable->table.tableAlias, pTableAlias);
|
|
} else {
|
|
COPY_STRING_FORM_ID_TOKEN(realTable->table.tableAlias, pTableName);
|
|
}
|
|
COPY_STRING_FORM_ID_TOKEN(realTable->table.tableName, pTableName);
|
|
return (SNode*)realTable;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createPlaceHolderTableNode(SAstCreateContext* pCxt, EStreamPlaceholder type, SToken* pTableAlias) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
|
|
SPlaceHolderTableNode* phTable = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_PLACE_HOLDER_TABLE, (SNode**)&phTable);
|
|
CHECK_MAKE_NODE(phTable);
|
|
|
|
if (NULL != pTableAlias && TK_NK_NIL != pTableAlias->type) {
|
|
COPY_STRING_FORM_ID_TOKEN(phTable->table.tableAlias, pTableAlias);
|
|
}
|
|
|
|
phTable->placeholderType = type;
|
|
return (SNode*)phTable;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createStreamNode(SAstCreateContext* pCxt, SToken* pDbName, SToken* pStreamName) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
CHECK_NAME(checkDbName(pCxt, pDbName, true));
|
|
CHECK_NAME(checkStreamName(pCxt, pStreamName));
|
|
SStreamNode* pStream = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_STREAM, (SNode**)&pStream);
|
|
CHECK_MAKE_NODE(pStream);
|
|
if (NULL != pDbName) {
|
|
COPY_STRING_FORM_ID_TOKEN(pStream->dbName, pDbName);
|
|
} else {
|
|
snprintf(pStream->dbName, sizeof(pStream->dbName), "%s", pCxt->pQueryCxt->db);
|
|
}
|
|
COPY_STRING_FORM_ID_TOKEN(pStream->streamName, pStreamName);
|
|
return (SNode*)pStream;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createRecalcRange(SAstCreateContext* pCxt, SNode* pStart, SNode* pEnd) {
|
|
SStreamCalcRangeNode* pRange = NULL;
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_STREAM_CALC_RANGE, (SNode**)&pRange);
|
|
CHECK_MAKE_NODE(pRange);
|
|
if (NULL == pStart && NULL == pEnd) {
|
|
pRange->calcAll = true;
|
|
} else {
|
|
pRange->calcAll = false;
|
|
pRange->pStart = pStart;
|
|
pRange->pEnd = pEnd;
|
|
}
|
|
|
|
return (SNode*)pRange;
|
|
_err:
|
|
nodesDestroyNode((SNode*)pRange);
|
|
nodesDestroyNode(pStart);
|
|
nodesDestroyNode(pEnd);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createTempTableNode(SAstCreateContext* pCxt, SNode* pSubquery, SToken* pTableAlias) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
if (!checkTableName(pCxt, pTableAlias)) {
|
|
return NULL;
|
|
}
|
|
STempTableNode* tempTable = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_TEMP_TABLE, (SNode**)&tempTable);
|
|
CHECK_MAKE_NODE(tempTable);
|
|
tempTable->pSubquery = pSubquery;
|
|
if (NULL != pTableAlias && TK_NK_NIL != pTableAlias->type) {
|
|
COPY_STRING_FORM_ID_TOKEN(tempTable->table.tableAlias, pTableAlias);
|
|
} else {
|
|
taosRandStr(tempTable->table.tableAlias, 32);
|
|
}
|
|
if (QUERY_NODE_SELECT_STMT == nodeType(pSubquery)) {
|
|
tstrncpy(((SSelectStmt*)pSubquery)->stmtName, tempTable->table.tableAlias, TSDB_TABLE_NAME_LEN);
|
|
((SSelectStmt*)pSubquery)->isSubquery = true;
|
|
} else if (QUERY_NODE_SET_OPERATOR == nodeType(pSubquery)) {
|
|
tstrncpy(((SSetOperator*)pSubquery)->stmtName, tempTable->table.tableAlias, TSDB_TABLE_NAME_LEN);
|
|
}
|
|
return (SNode*)tempTable;
|
|
_err:
|
|
nodesDestroyNode(pSubquery);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createJoinTableNode(SAstCreateContext* pCxt, EJoinType type, EJoinSubType stype, SNode* pLeft, SNode* pRight,
|
|
SNode* pJoinCond) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SJoinTableNode* joinTable = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_JOIN_TABLE, (SNode**)&joinTable);
|
|
CHECK_MAKE_NODE(joinTable);
|
|
joinTable->joinType = type;
|
|
joinTable->subType = stype;
|
|
joinTable->pLeft = pLeft;
|
|
joinTable->pRight = pRight;
|
|
joinTable->pOnCond = pJoinCond;
|
|
return (SNode*)joinTable;
|
|
_err:
|
|
nodesDestroyNode(pLeft);
|
|
nodesDestroyNode(pRight);
|
|
nodesDestroyNode(pJoinCond);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createViewNode(SAstCreateContext* pCxt, SToken* pDbName, SToken* pViewName) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
CHECK_NAME(checkDbName(pCxt, pDbName, true));
|
|
CHECK_NAME(checkViewName(pCxt, pViewName));
|
|
SViewNode* pView = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_VIEW, (SNode**)&pView);
|
|
CHECK_MAKE_NODE(pView);
|
|
if (NULL != pDbName) {
|
|
COPY_STRING_FORM_ID_TOKEN(pView->table.dbName, pDbName);
|
|
} else {
|
|
snprintf(pView->table.dbName, sizeof(pView->table.dbName), "%s", pCxt->pQueryCxt->db);
|
|
}
|
|
COPY_STRING_FORM_ID_TOKEN(pView->table.tableName, pViewName);
|
|
return (SNode*)pView;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createLimitNode(SAstCreateContext* pCxt, SNode* pLimit, SNode* pOffset) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SLimitNode* limitNode = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_LIMIT, (SNode**)&limitNode);
|
|
CHECK_MAKE_NODE(limitNode);
|
|
limitNode->limit = (SValueNode*)pLimit;
|
|
if (NULL != pOffset) {
|
|
limitNode->offset = (SValueNode*)pOffset;
|
|
}
|
|
return (SNode*)limitNode;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createOrderByExprNode(SAstCreateContext* pCxt, SNode* pExpr, EOrder order, ENullOrder nullOrder) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SOrderByExprNode* orderByExpr = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_ORDER_BY_EXPR, (SNode**)&orderByExpr);
|
|
CHECK_MAKE_NODE(orderByExpr);
|
|
orderByExpr->pExpr = pExpr;
|
|
orderByExpr->order = order;
|
|
if (NULL_ORDER_DEFAULT == nullOrder) {
|
|
nullOrder = (ORDER_ASC == order ? NULL_ORDER_FIRST : NULL_ORDER_LAST);
|
|
}
|
|
orderByExpr->nullOrder = nullOrder;
|
|
return (SNode*)orderByExpr;
|
|
_err:
|
|
nodesDestroyNode(pExpr);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createSessionWindowNode(SAstCreateContext* pCxt, SNode* pCol, SNode* pGap) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SSessionWindowNode* session = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_SESSION_WINDOW, (SNode**)&session);
|
|
CHECK_MAKE_NODE(session);
|
|
session->pCol = (SColumnNode*)pCol;
|
|
session->pGap = (SValueNode*)pGap;
|
|
return (SNode*)session;
|
|
_err:
|
|
nodesDestroyNode(pCol);
|
|
nodesDestroyNode(pGap);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createStateWindowNode(SAstCreateContext* pCxt, SNode* pExpr, SNodeList* pOptions, SNode* pTrueForLimit) {
|
|
SStateWindowNode* state = NULL;
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_STATE_WINDOW, (SNode**)&state);
|
|
CHECK_MAKE_NODE(state);
|
|
state->pCol = createPrimaryKeyCol(pCxt, NULL);
|
|
CHECK_MAKE_NODE(state->pCol);
|
|
state->pExpr = pExpr;
|
|
state->pTrueForLimit = pTrueForLimit;
|
|
if (pOptions != NULL) {
|
|
if (pOptions->length >= 1) {
|
|
pCxt->errCode = nodesCloneNode(nodesListGetNode(pOptions, 0), &state->pExtend);
|
|
CHECK_MAKE_NODE(state->pExtend);
|
|
}
|
|
if (pOptions->length == 2) {
|
|
pCxt->errCode = nodesCloneNode(nodesListGetNode(pOptions, 1), &state->pZeroth);
|
|
CHECK_MAKE_NODE(state->pZeroth);
|
|
}
|
|
nodesDestroyList(pOptions);
|
|
}
|
|
return (SNode*)state;
|
|
_err:
|
|
nodesDestroyNode((SNode*)state);
|
|
nodesDestroyNode(pExpr);
|
|
nodesDestroyNode(pTrueForLimit);
|
|
nodesDestroyList(pOptions);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createEventWindowNode(SAstCreateContext* pCxt, SNode* pStartCond, SNode* pEndCond, SNode* pTrueForLimit) {
|
|
SEventWindowNode* pEvent = NULL;
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_EVENT_WINDOW, (SNode**)&pEvent);
|
|
CHECK_MAKE_NODE(pEvent);
|
|
pEvent->pCol = createPrimaryKeyCol(pCxt, NULL);
|
|
CHECK_MAKE_NODE(pEvent->pCol);
|
|
pEvent->pStartCond = pStartCond;
|
|
pEvent->pEndCond = pEndCond;
|
|
pEvent->pTrueForLimit = pTrueForLimit;
|
|
return (SNode*)pEvent;
|
|
_err:
|
|
nodesDestroyNode((SNode*)pEvent);
|
|
nodesDestroyNode(pStartCond);
|
|
nodesDestroyNode(pEndCond);
|
|
nodesDestroyNode(pTrueForLimit);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createTrueForCountNode(SAstCreateContext* pCxt, const SToken* pCount) {
|
|
STrueForNode* pTrueFor = NULL;
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_TRUE_FOR, (SNode**)&pTrueFor);
|
|
CHECK_MAKE_NODE(pTrueFor);
|
|
pTrueFor->trueForType = TRUE_FOR_COUNT_ONLY;
|
|
pTrueFor->pDuration = NULL;
|
|
pTrueFor->count = taosStr2Int32(pCount->z, NULL, 10);
|
|
if (pTrueFor->count < 0) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_TRUE_FOR_COUNT);
|
|
goto _err;
|
|
}
|
|
return (SNode*)pTrueFor;
|
|
_err:
|
|
nodesDestroyNode((SNode*)pTrueFor);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createTrueForAndNode(SAstCreateContext* pCxt, SNode* pDuration, const SToken* pCount) {
|
|
STrueForNode* pTrueFor = NULL;
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_TRUE_FOR, (SNode**)&pTrueFor);
|
|
CHECK_MAKE_NODE(pTrueFor);
|
|
pTrueFor->trueForType = TRUE_FOR_AND;
|
|
pTrueFor->pDuration = pDuration;
|
|
pDuration = NULL;
|
|
pTrueFor->count = taosStr2Int32(pCount->z, NULL, 10);
|
|
return (SNode*)pTrueFor;
|
|
_err:
|
|
nodesDestroyNode((SNode*)pTrueFor);
|
|
nodesDestroyNode(pDuration);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createTrueForOrNode(SAstCreateContext* pCxt, SNode* pDuration, const SToken* pCount) {
|
|
STrueForNode* pTrueFor = NULL;
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_TRUE_FOR, (SNode**)&pTrueFor);
|
|
CHECK_MAKE_NODE(pTrueFor);
|
|
pTrueFor->trueForType = TRUE_FOR_OR;
|
|
pTrueFor->pDuration = pDuration;
|
|
pDuration = NULL;
|
|
pTrueFor->count = taosStr2Int32(pCount->z, NULL, 10);
|
|
return (SNode*)pTrueFor;
|
|
_err:
|
|
nodesDestroyNode((SNode*)pTrueFor);
|
|
nodesDestroyNode(pDuration);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createCountWindowNode(SAstCreateContext* pCxt, const SToken* pCountToken, const SToken* pSlidingToken,
|
|
SNodeList* pColList) {
|
|
SCountWindowNode* pCount = NULL;
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_COUNT_WINDOW, (SNode**)&pCount);
|
|
CHECK_MAKE_NODE(pCount);
|
|
pCount->pCol = createPrimaryKeyCol(pCxt, NULL);
|
|
CHECK_MAKE_NODE(pCount->pCol);
|
|
pCount->windowCount = taosStr2Int64(pCountToken->z, NULL, 10);
|
|
if (pSlidingToken == NULL) {
|
|
pCount->windowSliding = taosStr2Int64(pSlidingToken->z, NULL, 10);
|
|
} else {
|
|
pCount->windowSliding = taosStr2Int64(pCountToken->z, NULL, 10);
|
|
}
|
|
pCount->pColList = pColList;
|
|
return (SNode*)pCount;
|
|
_err:
|
|
nodesDestroyNode((SNode*)pCount);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createCountWindowNodeFromArgs(SAstCreateContext* pCxt, SNode* arg) {
|
|
SCountWindowArgs* args = (SCountWindowArgs*)arg;
|
|
SCountWindowNode* pCount = NULL;
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_COUNT_WINDOW, (SNode**)&pCount);
|
|
CHECK_MAKE_NODE(pCount);
|
|
pCount->pCol = createPrimaryKeyCol(pCxt, NULL);
|
|
CHECK_MAKE_NODE(pCount->pCol);
|
|
pCount->windowCount = args->count;
|
|
pCount->windowSliding = args->sliding;
|
|
pCount->pColList = args->pColList;
|
|
args->pColList = NULL;
|
|
nodesDestroyNode(arg);
|
|
return (SNode*)pCount;
|
|
_err:
|
|
nodesDestroyNode((SNode*)pCount);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createCountWindowArgs(SAstCreateContext* pCxt, const SToken* countToken, const SToken* slidingToken,
|
|
SNodeList* colList) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
|
|
SCountWindowArgs* args = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_COUNT_WINDOW_ARGS, (SNode**)&args);
|
|
CHECK_MAKE_NODE(args);
|
|
args->count = taosStr2Int64(countToken->z, NULL, 10);
|
|
if (slidingToken && slidingToken->type == TK_NK_INTEGER) {
|
|
args->sliding = taosStr2Int64(slidingToken->z, NULL, 10);
|
|
} else {
|
|
args->sliding = taosStr2Int64(countToken->z, NULL, 10);
|
|
}
|
|
args->pColList = colList;
|
|
return (SNode*)args;
|
|
_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_ANALYTIC_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* createIntervalWindowNodeExt(SAstCreateContext* pCxt, SNode* pInter, SNode* pSliding) {
|
|
SIntervalWindowNode* pInterval = NULL;
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
if (pInter) {
|
|
pInterval = (SIntervalWindowNode*)pInter;
|
|
} else {
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_INTERVAL_WINDOW, (SNode**)&pInterval);
|
|
CHECK_MAKE_NODE(pInterval);
|
|
}
|
|
pInterval->pCol = createPrimaryKeyCol(pCxt, NULL);
|
|
CHECK_MAKE_NODE(pInterval->pCol);
|
|
pInterval->pSliding = ((SSlidingWindowNode*)pSliding)->pSlidingVal;
|
|
pInterval->pSOffset = ((SSlidingWindowNode*)pSliding)->pOffset;
|
|
return (SNode*)pInterval;
|
|
_err:
|
|
nodesDestroyNode((SNode*)pInter);
|
|
nodesDestroyNode((SNode*)pInterval);
|
|
nodesDestroyNode((SNode*)pSliding);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createIntervalWindowNode(SAstCreateContext* pCxt, SNode* pInterval, SNode* pOffset, SNode* pSliding,
|
|
SNode* pFill) {
|
|
SIntervalWindowNode* interval = NULL;
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_INTERVAL_WINDOW, (SNode**)&interval);
|
|
CHECK_MAKE_NODE(interval);
|
|
interval->pCol = createPrimaryKeyCol(pCxt, NULL);
|
|
CHECK_MAKE_NODE(interval->pCol);
|
|
interval->pInterval = pInterval;
|
|
interval->pOffset = pOffset;
|
|
interval->pSliding = pSliding;
|
|
interval->pFill = pFill;
|
|
TAOS_SET_OBJ_ALIGNED(&interval->timeRange, TSWINDOW_INITIALIZER);
|
|
interval->timezone = pCxt->pQueryCxt->timezone;
|
|
return (SNode*)interval;
|
|
_err:
|
|
nodesDestroyNode((SNode*)interval);
|
|
nodesDestroyNode(pInterval);
|
|
nodesDestroyNode(pOffset);
|
|
nodesDestroyNode(pSliding);
|
|
nodesDestroyNode(pFill);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createPeriodWindowNode(SAstCreateContext* pCxt, SNode* pPeriodTime, SNode* pOffset) {
|
|
SPeriodWindowNode* pPeriod = NULL;
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_PERIOD_WINDOW, (SNode**)&pPeriod);
|
|
CHECK_MAKE_NODE(pPeriod);
|
|
pPeriod->pOffset = pOffset;
|
|
pPeriod->pPeroid = pPeriodTime;
|
|
return (SNode*)pPeriod;
|
|
_err:
|
|
nodesDestroyNode((SNode*)pOffset);
|
|
nodesDestroyNode((SNode*)pPeriodTime);
|
|
nodesDestroyNode((SNode*)pPeriod);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createWindowOffsetNode(SAstCreateContext* pCxt, SNode* pStartOffset, SNode* pEndOffset) {
|
|
SWindowOffsetNode* winOffset = NULL;
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_WINDOW_OFFSET, (SNode**)&winOffset);
|
|
CHECK_MAKE_NODE(winOffset);
|
|
winOffset->pStartOffset = pStartOffset;
|
|
winOffset->pEndOffset = pEndOffset;
|
|
return (SNode*)winOffset;
|
|
_err:
|
|
nodesDestroyNode((SNode*)winOffset);
|
|
nodesDestroyNode(pStartOffset);
|
|
nodesDestroyNode(pEndOffset);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createFillNode(SAstCreateContext* pCxt, EFillMode mode, SNode* pValues) {
|
|
SFillNode* fill = NULL;
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_FILL, (SNode**)&fill);
|
|
CHECK_MAKE_NODE(fill);
|
|
fill->mode = mode;
|
|
fill->pValues = pValues;
|
|
fill->pWStartTs = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_FUNCTION, (SNode**)&(fill->pWStartTs));
|
|
CHECK_MAKE_NODE(fill->pWStartTs);
|
|
tstrncpy(((SFunctionNode*)fill->pWStartTs)->functionName, "_wstart", TSDB_FUNC_NAME_LEN);
|
|
return (SNode*)fill;
|
|
_err:
|
|
nodesDestroyNode((SNode*)fill);
|
|
nodesDestroyNode(pValues);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createGroupingSetNode(SAstCreateContext* pCxt, SNode* pNode) {
|
|
SGroupingSetNode* groupingSet = NULL;
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_GROUPING_SET, (SNode**)&groupingSet);
|
|
CHECK_MAKE_NODE(groupingSet);
|
|
groupingSet->groupingSetType = GP_TYPE_NORMAL;
|
|
groupingSet->pParameterList = NULL;
|
|
pCxt->errCode = nodesListMakeAppend(&groupingSet->pParameterList, pNode);
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
return (SNode*)groupingSet;
|
|
_err:
|
|
nodesDestroyNode((SNode*)groupingSet);
|
|
nodesDestroyNode(pNode);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createInterpTimeRange(SAstCreateContext* pCxt, SNode* pStart, SNode* pEnd, SNode* pInterval) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
if (isSubQueryNode(pStart) || isSubQueryNode(pEnd) || isSubQueryNode(pInterval)) {
|
|
pCxt->errCode = TSDB_CODE_PAR_INVALID_SCALAR_SUBQ_USAGE;
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
}
|
|
|
|
if (NULL == pInterval) {
|
|
if (pEnd && nodeType(pEnd) == QUERY_NODE_VALUE && ((SValueNode*)pEnd)->flag & VALUE_FLAG_IS_DURATION) {
|
|
return createInterpTimeAround(pCxt, pStart, NULL, pEnd);
|
|
}
|
|
return createBetweenAnd(pCxt, createPrimaryKeyCol(pCxt, NULL), pStart, pEnd);
|
|
}
|
|
|
|
return createInterpTimeAround(pCxt, pStart, pEnd, pInterval);
|
|
|
|
_err:
|
|
|
|
nodesDestroyNode(pStart);
|
|
nodesDestroyNode(pEnd);
|
|
nodesDestroyNode(pInterval);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createInterpTimePoint(SAstCreateContext* pCxt, SNode* pPoint) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
if (isSubQueryNode(pPoint)) {
|
|
pCxt->errCode = TSDB_CODE_PAR_INVALID_SCALAR_SUBQ_USAGE;
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
}
|
|
|
|
return createOperatorNode(pCxt, OP_TYPE_EQUAL, createPrimaryKeyCol(pCxt, NULL), pPoint);
|
|
_err:
|
|
nodesDestroyNode(pPoint);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createInterpTimeAround(SAstCreateContext* pCxt, SNode* pStart, SNode* pEnd, SNode* pInterval) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SRangeAroundNode* pAround = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_RANGE_AROUND, (SNode**)&pAround);
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
if (NULL == pEnd) {
|
|
pAround->pRange = createInterpTimePoint(pCxt, pStart);
|
|
} else {
|
|
pAround->pRange = createBetweenAnd(pCxt, createPrimaryKeyCol(pCxt, NULL), pStart, pEnd);
|
|
}
|
|
pAround->pInterval = pInterval;
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
return (SNode*)pAround;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createWhenThenNode(SAstCreateContext* pCxt, SNode* pWhen, SNode* pThen) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SWhenThenNode* pWhenThen = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_WHEN_THEN, (SNode**)&pWhenThen);
|
|
CHECK_MAKE_NODE(pWhenThen);
|
|
pWhenThen->pWhen = pWhen;
|
|
pWhenThen->pThen = pThen;
|
|
return (SNode*)pWhenThen;
|
|
_err:
|
|
nodesDestroyNode(pWhen);
|
|
nodesDestroyNode(pThen);
|
|
return NULL;
|
|
}
|
|
|
|
static int32_t debugPrintNode(SNode* pNode) {
|
|
char* pStr = NULL;
|
|
int32_t code = nodesNodeToString(pNode, false, &pStr, NULL);
|
|
if (TSDB_CODE_SUCCESS == code) {
|
|
(void)printf("%s\n", pStr);
|
|
taosMemoryFree(pStr);
|
|
}
|
|
return code;
|
|
}
|
|
|
|
SNode* createCaseWhenNode(SAstCreateContext* pCxt, SNode* pCase, SNodeList* pWhenThenList, SNode* pElse) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SCaseWhenNode* pCaseWhen = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_CASE_WHEN, (SNode**)&pCaseWhen);
|
|
CHECK_MAKE_NODE(pCaseWhen);
|
|
pCaseWhen->pCase = pCase;
|
|
pCaseWhen->pWhenThenList = pWhenThenList;
|
|
pCaseWhen->pElse = pElse;
|
|
pCaseWhen->tz = pCxt->pQueryCxt->timezone;
|
|
pCaseWhen->charsetCxt = pCxt->pQueryCxt->charsetCxt;
|
|
// debugPrintNode((SNode*)pCaseWhen);
|
|
return (SNode*)pCaseWhen;
|
|
_err:
|
|
nodesDestroyNode(pCase);
|
|
nodesDestroyList(pWhenThenList);
|
|
nodesDestroyNode(pElse);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createNullIfNode(SAstCreateContext* pCxt, SNode* pExpr1, SNode* pExpr2) {
|
|
SNode * pCase = NULL, *pEqual = NULL, *pThen = NULL;
|
|
SNode * pWhenThenNode = NULL, *pElse = NULL;
|
|
SNodeList* pWhenThenList = NULL;
|
|
SNode* pCaseWhen = NULL;
|
|
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
pEqual = createOperatorNode(pCxt, OP_TYPE_EQUAL, pExpr1, pExpr2);
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SToken nullToken = {
|
|
.n = 4,
|
|
.type = TK_NULL,
|
|
.z = "null",
|
|
};
|
|
pThen = createValueNode(pCxt, TSDB_DATA_TYPE_NULL, &nullToken);
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
pWhenThenNode = createWhenThenNode(pCxt, pEqual, pThen);
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
pWhenThenList = createNodeList(pCxt, pWhenThenNode);
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
pCxt->errCode = nodesCloneNode(pExpr1, &pElse);
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
pCaseWhen = createCaseWhenNode(pCxt, pCase, pWhenThenList, pElse);
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
// debugPrintNode((SNode*)pCaseWhen);
|
|
return (SNode*)pCaseWhen;
|
|
_err:
|
|
nodesDestroyNode(pCase);
|
|
nodesDestroyNode(pEqual);
|
|
nodesDestroyNode(pThen);
|
|
nodesDestroyNode(pWhenThenNode);
|
|
nodesDestroyNode(pElse);
|
|
nodesDestroyList(pWhenThenList);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createIfNode(SAstCreateContext* pCxt, SNode* pExpr1, SNode* pExpr2, SNode* pExpr3) {
|
|
SNode* pCase = NULL;
|
|
SNode* pWhenThenNode = NULL;
|
|
SNodeList* pWhenThenList = NULL;
|
|
SNode* pCaseWhen = NULL;
|
|
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
pWhenThenNode = createWhenThenNode(pCxt, pExpr1, pExpr2);
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
pWhenThenList = createNodeList(pCxt, pWhenThenNode);
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
pCaseWhen = createCaseWhenNode(pCxt, pCase, pWhenThenList, pExpr3);
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
// debugPrintNode((SNode*)pCaseWhen);
|
|
return (SNode*)pCaseWhen;
|
|
_err:
|
|
nodesDestroyNode(pCase);
|
|
nodesDestroyNode(pWhenThenNode);
|
|
nodesDestroyList(pWhenThenList);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createNvlNode(SAstCreateContext* pCxt, SNode* pExpr1, SNode* pExpr2) {
|
|
SNode * pThen = NULL, *pEqual = NULL;
|
|
SNode* pWhenThenNode = NULL;
|
|
SNodeList* pWhenThenList = NULL;
|
|
SNode* pCaseWhen = NULL;
|
|
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
pEqual = createOperatorNode(pCxt, OP_TYPE_IS_NOT_NULL, pExpr1, NULL);
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
pCxt->errCode = nodesCloneNode(pExpr1, &pThen);
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
pWhenThenNode = createWhenThenNode(pCxt, pEqual, pThen);
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
pWhenThenList = createNodeList(pCxt, pWhenThenNode);
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
pCaseWhen = createCaseWhenNode(pCxt, NULL, pWhenThenList, pExpr2);
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
// debugPrintNode((SNode*)pCaseWhen);
|
|
return (SNode*)pCaseWhen;
|
|
_err:
|
|
nodesDestroyNode(pEqual);
|
|
nodesDestroyNode(pThen);
|
|
nodesDestroyNode(pWhenThenNode);
|
|
nodesDestroyList(pWhenThenList);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createNvl2Node(SAstCreateContext* pCxt, SNode* pExpr1, SNode* pExpr2, SNode* pExpr3) {
|
|
SNode * pEqual = NULL, *pWhenThenNode = NULL;
|
|
SNodeList* pWhenThenList = NULL;
|
|
SNode* pCaseWhen = NULL;
|
|
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
pEqual = createOperatorNode(pCxt, OP_TYPE_IS_NOT_NULL, pExpr1, NULL);
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
pWhenThenNode = createWhenThenNode(pCxt, pEqual, pExpr2);
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
pWhenThenList = createNodeList(pCxt, pWhenThenNode);
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
pCaseWhen = createCaseWhenNode(pCxt, NULL, pWhenThenList, pExpr3);
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
// debugPrintNode((SNode*)pCaseWhen);
|
|
return (SNode*)pCaseWhen;
|
|
_err:
|
|
nodesDestroyNode(pEqual);
|
|
nodesDestroyNode(pWhenThenNode);
|
|
nodesDestroyList(pWhenThenList);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createCoalesceNode(SAstCreateContext* pCxt, SNodeList* pParamList) {
|
|
int32_t sizeParam = LIST_LENGTH(pParamList);
|
|
SNode * pNotNullCond = NULL, *pWhenThenNode = NULL, *pExpr = NULL;
|
|
SNodeList* pWhenThenList = NULL;
|
|
SNode * pCaseWhen = NULL, *pThen = NULL;
|
|
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
|
|
for (int i = 0; i < sizeParam; ++i) {
|
|
pExpr = nodesListGetNode(pParamList, i);
|
|
|
|
pCxt->errCode = nodesCloneNode(pExpr, &pThen);
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
|
|
pNotNullCond = createOperatorNode(pCxt, OP_TYPE_IS_NOT_NULL, pExpr, NULL);
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
|
|
pWhenThenNode = createWhenThenNode(pCxt, pNotNullCond, pThen);
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
|
|
if (!pWhenThenList) {
|
|
pWhenThenList = createNodeList(pCxt, pWhenThenNode);
|
|
} else {
|
|
pCxt->errCode = nodesListAppend(pWhenThenList, pWhenThenNode);
|
|
}
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
}
|
|
|
|
pCaseWhen = createCaseWhenNode(pCxt, NULL, pWhenThenList, NULL);
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
// debugPrintNode((SNode*)pCaseWhen);
|
|
return (SNode*)pCaseWhen;
|
|
_err:
|
|
nodesDestroyNode(pExpr);
|
|
nodesDestroyNode(pNotNullCond);
|
|
nodesDestroyNode(pThen);
|
|
nodesDestroyNode(pWhenThenNode);
|
|
nodesDestroyList(pWhenThenList);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* setProjectionAlias(SAstCreateContext* pCxt, SNode* pNode, SToken* pAlias) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
trimEscape(pCxt, pAlias, false);
|
|
SExprNode* pExpr = (SExprNode*)pNode;
|
|
int32_t len = TMIN(sizeof(pExpr->aliasName) - 1, pAlias->n);
|
|
strncpy(pExpr->aliasName, pAlias->z, len);
|
|
pExpr->aliasName[len] = '\0';
|
|
strncpy(pExpr->userAlias, pAlias->z, len);
|
|
pExpr->userAlias[len] = '\0';
|
|
pExpr->asAlias = true;
|
|
return pNode;
|
|
_err:
|
|
nodesDestroyNode(pNode);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* addWhereClause(SAstCreateContext* pCxt, SNode* pStmt, SNode* pWhere) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
if (QUERY_NODE_SELECT_STMT == nodeType(pStmt)) {
|
|
((SSelectStmt*)pStmt)->pWhere = pWhere;
|
|
}
|
|
return pStmt;
|
|
_err:
|
|
nodesDestroyNode(pStmt);
|
|
nodesDestroyNode(pWhere);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* addPartitionByClause(SAstCreateContext* pCxt, SNode* pStmt, SNodeList* pPartitionByList) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
if (QUERY_NODE_SELECT_STMT == nodeType(pStmt)) {
|
|
((SSelectStmt*)pStmt)->pPartitionByList = pPartitionByList;
|
|
}
|
|
return pStmt;
|
|
_err:
|
|
nodesDestroyNode(pStmt);
|
|
nodesDestroyList(pPartitionByList);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* addWindowClauseClause(SAstCreateContext* pCxt, SNode* pStmt, SNode* pWindow) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
if (QUERY_NODE_SELECT_STMT == nodeType(pStmt)) {
|
|
((SSelectStmt*)pStmt)->pWindow = pWindow;
|
|
}
|
|
return pStmt;
|
|
_err:
|
|
nodesDestroyNode(pStmt);
|
|
nodesDestroyNode(pWindow);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* addGroupByClause(SAstCreateContext* pCxt, SNode* pStmt, SNodeList* pGroupByList) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
if (QUERY_NODE_SELECT_STMT == nodeType(pStmt)) {
|
|
((SSelectStmt*)pStmt)->pGroupByList = pGroupByList;
|
|
}
|
|
return pStmt;
|
|
_err:
|
|
nodesDestroyNode(pStmt);
|
|
nodesDestroyList(pGroupByList);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* addHavingClause(SAstCreateContext* pCxt, SNode* pStmt, SNode* pHaving) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
if (QUERY_NODE_SELECT_STMT == nodeType(pStmt)) {
|
|
((SSelectStmt*)pStmt)->pHaving = pHaving;
|
|
}
|
|
return pStmt;
|
|
_err:
|
|
nodesDestroyNode(pStmt);
|
|
nodesDestroyNode(pHaving);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* addOrderByClause(SAstCreateContext* pCxt, SNode* pStmt, SNodeList* pOrderByList) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
if (NULL == pOrderByList) {
|
|
return pStmt;
|
|
}
|
|
if (QUERY_NODE_SELECT_STMT == nodeType(pStmt)) {
|
|
((SSelectStmt*)pStmt)->pOrderByList = pOrderByList;
|
|
} else {
|
|
((SSetOperator*)pStmt)->pOrderByList = pOrderByList;
|
|
}
|
|
return pStmt;
|
|
_err:
|
|
nodesDestroyNode(pStmt);
|
|
nodesDestroyList(pOrderByList);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* addSlimitClause(SAstCreateContext* pCxt, SNode* pStmt, SNode* pSlimit) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
if (NULL == pSlimit) {
|
|
return pStmt;
|
|
}
|
|
if (QUERY_NODE_SELECT_STMT == nodeType(pStmt)) {
|
|
((SSelectStmt*)pStmt)->pSlimit = (SLimitNode*)pSlimit;
|
|
}
|
|
return pStmt;
|
|
_err:
|
|
nodesDestroyNode(pStmt);
|
|
nodesDestroyNode(pSlimit);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* addLimitClause(SAstCreateContext* pCxt, SNode* pStmt, SNode* pLimit) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
if (NULL == pLimit) {
|
|
return pStmt;
|
|
}
|
|
if (QUERY_NODE_SELECT_STMT == nodeType(pStmt)) {
|
|
((SSelectStmt*)pStmt)->pLimit = (SLimitNode*)pLimit;
|
|
} else {
|
|
((SSetOperator*)pStmt)->pLimit = pLimit;
|
|
}
|
|
return pStmt;
|
|
_err:
|
|
nodesDestroyNode(pStmt);
|
|
nodesDestroyNode(pLimit);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* addRangeClause(SAstCreateContext* pCxt, SNode* pStmt, SNode* pRange) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SSelectStmt* pSelect = (SSelectStmt*)pStmt;
|
|
if (QUERY_NODE_SELECT_STMT == nodeType(pStmt)) {
|
|
if (pRange && nodeType(pRange) == QUERY_NODE_RANGE_AROUND) {
|
|
pSelect->pRangeAround = pRange;
|
|
SRangeAroundNode* pAround = (SRangeAroundNode*)pRange;
|
|
TSWAP(pSelect->pRange, pAround->pRange);
|
|
} else {
|
|
pSelect->pRange = pRange;
|
|
}
|
|
}
|
|
return pStmt;
|
|
_err:
|
|
nodesDestroyNode(pStmt);
|
|
nodesDestroyNode(pRange);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* addEveryClause(SAstCreateContext* pCxt, SNode* pStmt, SNode* pEvery) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
if (QUERY_NODE_SELECT_STMT == nodeType(pStmt)) {
|
|
((SSelectStmt*)pStmt)->pEvery = pEvery;
|
|
}
|
|
return pStmt;
|
|
_err:
|
|
nodesDestroyNode(pStmt);
|
|
nodesDestroyNode(pEvery);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* addFillClause(SAstCreateContext* pCxt, SNode* pStmt, SNode* pFill) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
if (QUERY_NODE_SELECT_STMT == nodeType(pStmt) && NULL != pFill) {
|
|
SFillNode* pFillClause = (SFillNode*)pFill;
|
|
nodesDestroyNode(pFillClause->pWStartTs);
|
|
pFillClause->pWStartTs = createPrimaryKeyCol(pCxt, NULL);
|
|
CHECK_MAKE_NODE(pFillClause->pWStartTs);
|
|
((SSelectStmt*)pStmt)->pFill = (SNode*)pFillClause;
|
|
}
|
|
return pStmt;
|
|
_err:
|
|
nodesDestroyNode(pStmt);
|
|
nodesDestroyNode(pFill);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* addJLimitClause(SAstCreateContext* pCxt, SNode* pJoin, SNode* pJLimit) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
if (NULL == pJLimit) {
|
|
return pJoin;
|
|
}
|
|
SJoinTableNode* pJoinNode = (SJoinTableNode*)pJoin;
|
|
pJoinNode->pJLimit = pJLimit;
|
|
|
|
return pJoin;
|
|
_err:
|
|
nodesDestroyNode(pJoin);
|
|
nodesDestroyNode(pJLimit);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* addWindowOffsetClause(SAstCreateContext* pCxt, SNode* pJoin, SNode* pWinOffset) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
if (NULL == pWinOffset) {
|
|
return pJoin;
|
|
}
|
|
SJoinTableNode* pJoinNode = (SJoinTableNode*)pJoin;
|
|
pJoinNode->pWindowOffset = pWinOffset;
|
|
|
|
return pJoin;
|
|
_err:
|
|
nodesDestroyNode(pJoin);
|
|
nodesDestroyNode(pWinOffset);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createSelectStmt(SAstCreateContext* pCxt, bool isDistinct, SNodeList* pProjectionList, SNode* pTable,
|
|
SNodeList* pHint) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SNode* select = NULL;
|
|
pCxt->errCode = createSelectStmtImpl(isDistinct, pProjectionList, pTable, pHint, &select);
|
|
CHECK_MAKE_NODE(select);
|
|
return select;
|
|
_err:
|
|
nodesDestroyList(pProjectionList);
|
|
nodesDestroyNode(pTable);
|
|
nodesDestroyList(pHint);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* setSelectStmtTagMode(SAstCreateContext* pCxt, SNode* pStmt, bool bSelectTags) {
|
|
if (pStmt && QUERY_NODE_SELECT_STMT == nodeType(pStmt)) {
|
|
if (pCxt->pQueryCxt->biMode) {
|
|
((SSelectStmt*)pStmt)->tagScan = true;
|
|
} else {
|
|
((SSelectStmt*)pStmt)->tagScan = bSelectTags;
|
|
}
|
|
}
|
|
return pStmt;
|
|
}
|
|
|
|
static void setSubquery(SNode* pStmt) {
|
|
if (QUERY_NODE_SELECT_STMT == nodeType(pStmt)) {
|
|
((SSelectStmt*)pStmt)->isSubquery = true;
|
|
}
|
|
}
|
|
|
|
SNode* createSetOperator(SAstCreateContext* pCxt, ESetOperatorType type, SNode* pLeft, SNode* pRight) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SSetOperator* setOp = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_SET_OPERATOR, (SNode**)&setOp);
|
|
CHECK_MAKE_NODE(setOp);
|
|
setOp->opType = type;
|
|
setOp->pLeft = pLeft;
|
|
setSubquery(setOp->pLeft);
|
|
setOp->pRight = pRight;
|
|
setSubquery(setOp->pRight);
|
|
snprintf(setOp->stmtName, TSDB_TABLE_NAME_LEN, "%p", setOp);
|
|
return (SNode*)setOp;
|
|
_err:
|
|
nodesDestroyNode(pLeft);
|
|
nodesDestroyNode(pRight);
|
|
return NULL;
|
|
}
|
|
|
|
static void updateWalOptionsDefault(SDatabaseOptions* pOptions) {
|
|
if (!pOptions->walRetentionPeriodIsSet) {
|
|
pOptions->walRetentionPeriod =
|
|
pOptions->replica > 1 ? TSDB_REPS_DEF_DB_WAL_RET_PERIOD : TSDB_REP_DEF_DB_WAL_RET_PERIOD;
|
|
}
|
|
if (!pOptions->walRetentionSizeIsSet) {
|
|
pOptions->walRetentionSize = pOptions->replica > 1 ? TSDB_REPS_DEF_DB_WAL_RET_SIZE : TSDB_REP_DEF_DB_WAL_RET_SIZE;
|
|
}
|
|
if (!pOptions->walRollPeriodIsSet) {
|
|
pOptions->walRollPeriod =
|
|
pOptions->replica > 1 ? TSDB_REPS_DEF_DB_WAL_ROLL_PERIOD : TSDB_REP_DEF_DB_WAL_ROLL_PERIOD;
|
|
}
|
|
}
|
|
|
|
SNode* createDefaultDatabaseOptions(SAstCreateContext* pCxt) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SDatabaseOptions* pOptions = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_DATABASE_OPTIONS, (SNode**)&pOptions);
|
|
CHECK_MAKE_NODE(pOptions);
|
|
pOptions->buffer = TSDB_DEFAULT_BUFFER_PER_VNODE;
|
|
pOptions->cacheModel = TSDB_DEFAULT_CACHE_MODEL;
|
|
pOptions->cacheLastSize = TSDB_DEFAULT_CACHE_SIZE;
|
|
pOptions->compressionLevel = TSDB_DEFAULT_COMP_LEVEL;
|
|
pOptions->daysPerFile = TSDB_DEFAULT_DAYS_PER_FILE;
|
|
pOptions->fsyncPeriod = TSDB_DEFAULT_FSYNC_PERIOD;
|
|
pOptions->maxRowsPerBlock = TSDB_DEFAULT_MAXROWS_FBLOCK;
|
|
pOptions->minRowsPerBlock = TSDB_DEFAULT_MINROWS_FBLOCK;
|
|
pOptions->keep[0] = TSDB_DEFAULT_KEEP;
|
|
pOptions->keep[1] = TSDB_DEFAULT_KEEP;
|
|
pOptions->keep[2] = TSDB_DEFAULT_KEEP;
|
|
pOptions->pages = TSDB_DEFAULT_PAGES_PER_VNODE;
|
|
pOptions->pagesize = TSDB_DEFAULT_PAGESIZE_PER_VNODE;
|
|
pOptions->tsdbPageSize = TSDB_DEFAULT_TSDB_PAGESIZE;
|
|
pOptions->precision = TSDB_DEFAULT_PRECISION;
|
|
pOptions->replica = TSDB_DEFAULT_DB_REPLICA;
|
|
pOptions->strict = TSDB_DEFAULT_DB_STRICT;
|
|
pOptions->walLevel = TSDB_DEFAULT_WAL_LEVEL;
|
|
pOptions->numOfVgroups = TSDB_DEFAULT_VN_PER_DB;
|
|
pOptions->singleStable = TSDB_DEFAULT_DB_SINGLE_STABLE;
|
|
pOptions->schemaless = TSDB_DEFAULT_DB_SCHEMALESS;
|
|
updateWalOptionsDefault(pOptions);
|
|
pOptions->walSegmentSize = TSDB_DEFAULT_DB_WAL_SEGMENT_SIZE;
|
|
pOptions->sstTrigger = TSDB_DEFAULT_SST_TRIGGER;
|
|
pOptions->tablePrefix = TSDB_DEFAULT_HASH_PREFIX;
|
|
pOptions->tableSuffix = TSDB_DEFAULT_HASH_SUFFIX;
|
|
pOptions->ssChunkSize = TSDB_DEFAULT_SS_CHUNK_SIZE;
|
|
pOptions->ssKeepLocal = TSDB_DEFAULT_SS_KEEP_LOCAL;
|
|
pOptions->ssCompact = TSDB_DEFAULT_SS_COMPACT;
|
|
pOptions->withArbitrator = TSDB_DEFAULT_DB_WITH_ARBITRATOR;
|
|
pOptions->encryptAlgorithm = TSDB_DEFAULT_ENCRYPT_ALGO;
|
|
pOptions->dnodeListStr[0] = 0;
|
|
pOptions->compactInterval = TSDB_DEFAULT_COMPACT_INTERVAL;
|
|
pOptions->compactStartTime = TSDB_DEFAULT_COMPACT_START_TIME;
|
|
pOptions->compactEndTime = TSDB_DEFAULT_COMPACT_END_TIME;
|
|
pOptions->compactTimeOffset = TSDB_DEFAULT_COMPACT_TIME_OFFSET;
|
|
pOptions->encryptAlgorithmStr[0] = 0;
|
|
pOptions->isAudit = 0;
|
|
return (SNode*)pOptions;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createAlterDatabaseOptions(SAstCreateContext* pCxt) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SDatabaseOptions* pOptions = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_DATABASE_OPTIONS, (SNode**)&pOptions);
|
|
CHECK_MAKE_NODE(pOptions);
|
|
pOptions->buffer = -1;
|
|
pOptions->cacheModel = -1;
|
|
pOptions->cacheLastSize = -1;
|
|
pOptions->compressionLevel = -1;
|
|
pOptions->daysPerFile = -1;
|
|
pOptions->fsyncPeriod = -1;
|
|
pOptions->maxRowsPerBlock = -1;
|
|
pOptions->minRowsPerBlock = -1;
|
|
pOptions->keep[0] = -1;
|
|
pOptions->keep[1] = -1;
|
|
pOptions->keep[2] = -1;
|
|
pOptions->pages = -1;
|
|
pOptions->pagesize = -1;
|
|
pOptions->tsdbPageSize = -1;
|
|
pOptions->precision = -1;
|
|
pOptions->replica = -1;
|
|
pOptions->strict = -1;
|
|
pOptions->walLevel = -1;
|
|
pOptions->numOfVgroups = -1;
|
|
pOptions->singleStable = -1;
|
|
pOptions->schemaless = -1;
|
|
pOptions->walRetentionPeriod = -2; // -1 is a valid value
|
|
pOptions->walRetentionSize = -2; // -1 is a valid value
|
|
pOptions->walRollPeriod = -1;
|
|
pOptions->walSegmentSize = -1;
|
|
pOptions->sstTrigger = -1;
|
|
pOptions->tablePrefix = -1;
|
|
pOptions->tableSuffix = -1;
|
|
pOptions->ssChunkSize = -1;
|
|
pOptions->ssKeepLocal = -1;
|
|
pOptions->ssCompact = -1;
|
|
pOptions->withArbitrator = -1;
|
|
pOptions->encryptAlgorithm = TSDB_DEFAULT_ENCRYPT_ALGO;
|
|
pOptions->dnodeListStr[0] = 0;
|
|
pOptions->compactInterval = -1;
|
|
pOptions->compactStartTime = -1;
|
|
pOptions->compactEndTime = -1;
|
|
pOptions->compactTimeOffset = -1;
|
|
pOptions->encryptAlgorithmStr[0] = 0;
|
|
pOptions->isAudit = -1;
|
|
pOptions->allowDrop = -1;
|
|
return (SNode*)pOptions;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
static SNode* setDatabaseOptionImpl(SAstCreateContext* pCxt, SNode* pOptions, EDatabaseOptionType type, void* pVal,
|
|
bool alter) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SDatabaseOptions* pDbOptions = (SDatabaseOptions*)pOptions;
|
|
switch (type) {
|
|
case DB_OPTION_BUFFER:
|
|
pDbOptions->buffer = taosStr2Int32(((SToken*)pVal)->z, NULL, 10);
|
|
break;
|
|
case DB_OPTION_CACHEMODEL:
|
|
COPY_STRING_FORM_STR_TOKEN(pDbOptions->cacheModelStr, (SToken*)pVal);
|
|
break;
|
|
case DB_OPTION_CACHESIZE:
|
|
pDbOptions->cacheLastSize = taosStr2Int32(((SToken*)pVal)->z, NULL, 10);
|
|
break;
|
|
case DB_OPTION_COMP:
|
|
pDbOptions->compressionLevel = taosStr2Int8(((SToken*)pVal)->z, NULL, 10);
|
|
break;
|
|
case DB_OPTION_DAYS: {
|
|
SToken* pToken = pVal;
|
|
if (TK_NK_INTEGER == pToken->type) {
|
|
pDbOptions->daysPerFile = taosStr2Int32(pToken->z, NULL, 10) * 1440;
|
|
} else {
|
|
pDbOptions->pDaysPerFile = (SValueNode*)createDurationValueNode(pCxt, pToken);
|
|
}
|
|
break;
|
|
}
|
|
case DB_OPTION_FSYNC:
|
|
pDbOptions->fsyncPeriod = taosStr2Int32(((SToken*)pVal)->z, NULL, 10);
|
|
break;
|
|
case DB_OPTION_MAXROWS:
|
|
pDbOptions->maxRowsPerBlock = taosStr2Int32(((SToken*)pVal)->z, NULL, 10);
|
|
break;
|
|
case DB_OPTION_MINROWS:
|
|
pDbOptions->minRowsPerBlock = taosStr2Int32(((SToken*)pVal)->z, NULL, 10);
|
|
break;
|
|
case DB_OPTION_KEEP:
|
|
pDbOptions->pKeep = pVal;
|
|
break;
|
|
case DB_OPTION_PAGES:
|
|
pDbOptions->pages = taosStr2Int32(((SToken*)pVal)->z, NULL, 10);
|
|
break;
|
|
case DB_OPTION_PAGESIZE:
|
|
pDbOptions->pagesize = taosStr2Int32(((SToken*)pVal)->z, NULL, 10);
|
|
break;
|
|
case DB_OPTION_TSDB_PAGESIZE:
|
|
pDbOptions->tsdbPageSize = taosStr2Int32(((SToken*)pVal)->z, NULL, 10);
|
|
break;
|
|
case DB_OPTION_PRECISION:
|
|
COPY_STRING_FORM_STR_TOKEN(pDbOptions->precisionStr, (SToken*)pVal);
|
|
break;
|
|
case DB_OPTION_REPLICA:
|
|
pDbOptions->replica = taosStr2Int8(((SToken*)pVal)->z, NULL, 10);
|
|
pDbOptions->withArbitrator = (pDbOptions->replica == 2);
|
|
if (!alter) {
|
|
updateWalOptionsDefault(pDbOptions);
|
|
}
|
|
break;
|
|
case DB_OPTION_STRICT:
|
|
COPY_STRING_FORM_STR_TOKEN(pDbOptions->strictStr, (SToken*)pVal);
|
|
break;
|
|
case DB_OPTION_WAL:
|
|
pDbOptions->walLevel = taosStr2Int8(((SToken*)pVal)->z, NULL, 10);
|
|
break;
|
|
case DB_OPTION_VGROUPS:
|
|
pDbOptions->numOfVgroups = taosStr2Int32(((SToken*)pVal)->z, NULL, 10);
|
|
break;
|
|
case DB_OPTION_SINGLE_STABLE:
|
|
pDbOptions->singleStable = taosStr2Int8(((SToken*)pVal)->z, NULL, 10);
|
|
break;
|
|
case DB_OPTION_RETENTIONS:
|
|
pDbOptions->pRetentions = pVal;
|
|
break;
|
|
case DB_OPTION_WAL_RETENTION_PERIOD:
|
|
pDbOptions->walRetentionPeriod = taosStr2Int32(((SToken*)pVal)->z, NULL, 10);
|
|
pDbOptions->walRetentionPeriodIsSet = true;
|
|
break;
|
|
case DB_OPTION_WAL_RETENTION_SIZE:
|
|
pDbOptions->walRetentionSize = taosStr2Int32(((SToken*)pVal)->z, NULL, 10);
|
|
pDbOptions->walRetentionSizeIsSet = true;
|
|
break;
|
|
case DB_OPTION_WAL_ROLL_PERIOD:
|
|
pDbOptions->walRollPeriod = taosStr2Int32(((SToken*)pVal)->z, NULL, 10);
|
|
pDbOptions->walRollPeriodIsSet = true;
|
|
break;
|
|
case DB_OPTION_WAL_SEGMENT_SIZE:
|
|
pDbOptions->walSegmentSize = taosStr2Int32(((SToken*)pVal)->z, NULL, 10);
|
|
break;
|
|
case DB_OPTION_STT_TRIGGER:
|
|
pDbOptions->sstTrigger = taosStr2Int32(((SToken*)pVal)->z, NULL, 10);
|
|
break;
|
|
case DB_OPTION_TABLE_PREFIX: {
|
|
SValueNode* pNode = (SValueNode*)pVal;
|
|
if (TSDB_DATA_TYPE_BIGINT == pNode->node.resType.type || TSDB_DATA_TYPE_UBIGINT == pNode->node.resType.type) {
|
|
pDbOptions->tablePrefix = taosStr2Int32(pNode->literal, NULL, 10);
|
|
} else {
|
|
snprintf(pCxt->pQueryCxt->pMsg, pCxt->pQueryCxt->msgLen, "invalid table_prefix data type");
|
|
pCxt->errCode = TSDB_CODE_PAR_SYNTAX_ERROR;
|
|
}
|
|
nodesDestroyNode((SNode*)pNode);
|
|
break;
|
|
}
|
|
case DB_OPTION_TABLE_SUFFIX: {
|
|
SValueNode* pNode = (SValueNode*)pVal;
|
|
if (TSDB_DATA_TYPE_BIGINT == pNode->node.resType.type || TSDB_DATA_TYPE_UBIGINT == pNode->node.resType.type) {
|
|
pDbOptions->tableSuffix = taosStr2Int32(pNode->literal, NULL, 10);
|
|
} else {
|
|
snprintf(pCxt->pQueryCxt->pMsg, pCxt->pQueryCxt->msgLen, "invalid table_suffix data type");
|
|
pCxt->errCode = TSDB_CODE_PAR_SYNTAX_ERROR;
|
|
}
|
|
nodesDestroyNode((SNode*)pNode);
|
|
break;
|
|
}
|
|
case DB_OPTION_SS_CHUNKPAGES:
|
|
pDbOptions->ssChunkSize = taosStr2Int32(((SToken*)pVal)->z, NULL, 10);
|
|
break;
|
|
case DB_OPTION_SS_KEEPLOCAL: {
|
|
SToken* pToken = pVal;
|
|
if (TK_NK_INTEGER == pToken->type) {
|
|
pDbOptions->ssKeepLocal = taosStr2Int32(pToken->z, NULL, 10) * 1440;
|
|
} else {
|
|
pDbOptions->ssKeepLocalStr = (SValueNode*)createDurationValueNode(pCxt, pToken);
|
|
}
|
|
break;
|
|
}
|
|
case DB_OPTION_SS_COMPACT:
|
|
pDbOptions->ssCompact = taosStr2Int8(((SToken*)pVal)->z, NULL, 10);
|
|
break;
|
|
case DB_OPTION_KEEP_TIME_OFFSET:
|
|
if (TK_NK_INTEGER == ((SToken*)pVal)->type) {
|
|
pDbOptions->keepTimeOffset = taosStr2Int32(((SToken*)pVal)->z, NULL, 10);
|
|
} else {
|
|
pDbOptions->pKeepTimeOffsetNode = (SValueNode*)createDurationValueNode(pCxt, (SToken*)pVal);
|
|
}
|
|
break;
|
|
case DB_OPTION_ENCRYPT_ALGORITHM:
|
|
COPY_STRING_FORM_STR_TOKEN(pDbOptions->encryptAlgorithmStr, (SToken*)pVal);
|
|
if (strlen(pDbOptions->encryptAlgorithmStr) == 0) pDbOptions->encryptAlgorithm = -1;
|
|
break;
|
|
case DB_OPTION_DNODES:
|
|
if (((SToken*)pVal)->n >= TSDB_DNODE_LIST_LEN) {
|
|
snprintf(pCxt->pQueryCxt->pMsg, pCxt->pQueryCxt->msgLen, "the dnode list is too long (should less than %d)",
|
|
TSDB_DNODE_LIST_LEN);
|
|
pCxt->errCode = TSDB_CODE_PAR_SYNTAX_ERROR;
|
|
} else {
|
|
COPY_STRING_FORM_STR_TOKEN(pDbOptions->dnodeListStr, (SToken*)pVal);
|
|
}
|
|
break;
|
|
case DB_OPTION_COMPACT_INTERVAL:
|
|
if (TK_NK_INTEGER == ((SToken*)pVal)->type) {
|
|
pDbOptions->compactInterval = taosStr2Int32(((SToken*)pVal)->z, NULL, 10);
|
|
} else {
|
|
pDbOptions->pCompactIntervalNode = (SValueNode*)createDurationValueNode(pCxt, (SToken*)pVal);
|
|
}
|
|
break;
|
|
case DB_OPTION_COMPACT_TIME_RANGE:
|
|
pDbOptions->pCompactTimeRangeList = pVal;
|
|
break;
|
|
case DB_OPTION_COMPACT_TIME_OFFSET:
|
|
if (TK_NK_INTEGER == ((SToken*)pVal)->type) {
|
|
pDbOptions->compactTimeOffset = taosStr2Int32(((SToken*)pVal)->z, NULL, 10);
|
|
} else {
|
|
pDbOptions->pCompactTimeOffsetNode = (SValueNode*)createDurationValueNode(pCxt, (SToken*)pVal);
|
|
}
|
|
break;
|
|
case DB_OPTION_IS_AUDIT:
|
|
pDbOptions->isAudit = taosStr2Int8(((SToken*)pVal)->z, NULL, 10);
|
|
break;
|
|
case DB_OPTION_ALLOW_DROP:
|
|
pDbOptions->allowDrop = taosStr2Int8(((SToken*)pVal)->z, NULL, 10);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return pOptions;
|
|
_err:
|
|
nodesDestroyNode(pOptions);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* setDatabaseOption(SAstCreateContext* pCxt, SNode* pOptions, EDatabaseOptionType type, void* pVal) {
|
|
return setDatabaseOptionImpl(pCxt, pOptions, type, pVal, false);
|
|
}
|
|
|
|
SNode* setAlterDatabaseOption(SAstCreateContext* pCxt, SNode* pOptions, SAlterOption* pAlterOption) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
switch (pAlterOption->type) {
|
|
case DB_OPTION_KEEP:
|
|
case DB_OPTION_RETENTIONS:
|
|
case DB_OPTION_COMPACT_TIME_RANGE:
|
|
return setDatabaseOptionImpl(pCxt, pOptions, pAlterOption->type, pAlterOption->pList, true);
|
|
default:
|
|
break;
|
|
}
|
|
return setDatabaseOptionImpl(pCxt, pOptions, pAlterOption->type, &pAlterOption->val, true);
|
|
_err:
|
|
nodesDestroyNode(pOptions);
|
|
nodesDestroyList(pAlterOption->pList);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createCreateDatabaseStmt(SAstCreateContext* pCxt, bool ignoreExists, SToken* pDbName, SNode* pOptions) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
CHECK_NAME(checkDbName(pCxt, pDbName, false));
|
|
SCreateDatabaseStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_CREATE_DATABASE_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
COPY_STRING_FORM_ID_TOKEN(pStmt->dbName, pDbName);
|
|
pStmt->ignoreExists = ignoreExists;
|
|
pStmt->pOptions = (SDatabaseOptions*)pOptions;
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
nodesDestroyNode(pOptions);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createDropDatabaseStmt(SAstCreateContext* pCxt, bool ignoreNotExists, SToken* pDbName, bool force) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
CHECK_NAME(checkDbName(pCxt, pDbName, false));
|
|
SDropDatabaseStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_DROP_DATABASE_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
COPY_STRING_FORM_ID_TOKEN(pStmt->dbName, pDbName);
|
|
pStmt->ignoreNotExists = ignoreNotExists;
|
|
pStmt->force = force;
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createAlterDatabaseStmt(SAstCreateContext* pCxt, SToken* pDbName, SNode* pOptions) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
CHECK_NAME(checkDbName(pCxt, pDbName, false));
|
|
SAlterDatabaseStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_ALTER_DATABASE_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
COPY_STRING_FORM_ID_TOKEN(pStmt->dbName, pDbName);
|
|
pStmt->pOptions = (SDatabaseOptions*)pOptions;
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
nodesDestroyNode(pOptions);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createFlushDatabaseStmt(SAstCreateContext* pCxt, SToken* pDbName) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
CHECK_NAME(checkDbName(pCxt, pDbName, false));
|
|
SFlushDatabaseStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_FLUSH_DATABASE_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
COPY_STRING_FORM_ID_TOKEN(pStmt->dbName, pDbName);
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createTrimDatabaseStmt(SAstCreateContext* pCxt, SToken* pDbName, int32_t maxSpeed) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
CHECK_NAME(checkDbName(pCxt, pDbName, false));
|
|
STrimDatabaseStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_TRIM_DATABASE_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
COPY_STRING_FORM_ID_TOKEN(pStmt->dbName, pDbName);
|
|
pStmt->maxSpeed = maxSpeed;
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createTrimDbWalStmt(SAstCreateContext* pCxt, SToken* pDbName) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
CHECK_NAME(checkDbName(pCxt, pDbName, false));
|
|
STrimDbWalStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_TRIM_DATABASE_WAL_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
COPY_STRING_FORM_ID_TOKEN(pStmt->dbName, pDbName);
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createSsMigrateDatabaseStmt(SAstCreateContext* pCxt, SToken* pDbName) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
CHECK_NAME(checkDbName(pCxt, pDbName, false));
|
|
SSsMigrateDatabaseStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_SSMIGRATE_DATABASE_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
COPY_STRING_FORM_ID_TOKEN(pStmt->dbName, pDbName);
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createCompactStmt(SAstCreateContext* pCxt, SToken* pDbName, SNode* pStart, SNode* pEnd, bool metaOnly,
|
|
bool force) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
CHECK_NAME(checkDbName(pCxt, pDbName, false));
|
|
SCompactDatabaseStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_COMPACT_DATABASE_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
COPY_STRING_FORM_ID_TOKEN(pStmt->dbName, pDbName);
|
|
pStmt->pStart = pStart;
|
|
pStmt->pEnd = pEnd;
|
|
pStmt->metaOnly = metaOnly;
|
|
pStmt->force = force;
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
nodesDestroyNode(pStart);
|
|
nodesDestroyNode(pEnd);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createCreateMountStmt(SAstCreateContext* pCxt, bool ignoreExists, SToken* pMountName, SToken* pDnodeId,
|
|
SToken* pMountPath) {
|
|
#ifdef USE_MOUNT
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
CHECK_NAME(checkDbName(pCxt, pMountName, false));
|
|
CHECK_NAME(checkMountPath(pCxt, pMountPath));
|
|
SCreateMountStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_CREATE_MOUNT_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
COPY_STRING_FORM_ID_TOKEN(pStmt->mountName, pMountName);
|
|
COPY_STRING_FORM_STR_TOKEN(pStmt->mountPath, pMountPath);
|
|
pStmt->ignoreExists = ignoreExists;
|
|
if (TK_NK_INTEGER == pDnodeId->type) {
|
|
pStmt->dnodeId = taosStr2Int32(pDnodeId->z, NULL, 10);
|
|
} else {
|
|
goto _err;
|
|
}
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
nodesDestroyNode((SNode*)pStmt);
|
|
return NULL;
|
|
#else
|
|
pCxt->errCode = TSDB_CODE_OPS_NOT_SUPPORT;
|
|
return NULL;
|
|
#endif
|
|
}
|
|
|
|
SNode* createDropMountStmt(SAstCreateContext* pCxt, bool ignoreNotExists, SToken* pMountName) {
|
|
#ifdef USE_MOUNT
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
CHECK_NAME(checkDbName(pCxt, pMountName, false));
|
|
SDropMountStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_DROP_MOUNT_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
COPY_STRING_FORM_ID_TOKEN(pStmt->mountName, pMountName);
|
|
pStmt->ignoreNotExists = ignoreNotExists;
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
return NULL;
|
|
#else
|
|
pCxt->errCode = TSDB_CODE_OPS_NOT_SUPPORT;
|
|
return NULL;
|
|
#endif
|
|
}
|
|
|
|
SNode* createCompactVgroupsStmt(SAstCreateContext* pCxt, SNode* pDbName, SNodeList* vgidList, SNode* pStart,
|
|
SNode* pEnd, bool metaOnly, bool force) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
if (NULL == pDbName) {
|
|
snprintf(pCxt->pQueryCxt->pMsg, pCxt->pQueryCxt->msgLen, "database not specified");
|
|
pCxt->errCode = TSDB_CODE_PAR_DB_NOT_SPECIFIED;
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
}
|
|
SCompactVgroupsStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_COMPACT_VGROUPS_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
pStmt->pDbName = pDbName;
|
|
pStmt->vgidList = vgidList;
|
|
pStmt->pStart = pStart;
|
|
pStmt->pEnd = pEnd;
|
|
pStmt->metaOnly = metaOnly;
|
|
pStmt->force = force;
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
nodesDestroyNode(pDbName);
|
|
nodesDestroyList(vgidList);
|
|
nodesDestroyNode(pStart);
|
|
nodesDestroyNode(pEnd);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createDefaultTableOptions(SAstCreateContext* pCxt) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
STableOptions* pOptions = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_TABLE_OPTIONS, (SNode**)&pOptions);
|
|
CHECK_MAKE_NODE(pOptions);
|
|
pOptions->maxDelay1 = -1;
|
|
pOptions->maxDelay2 = -1;
|
|
pOptions->watermark1 = TSDB_DEFAULT_ROLLUP_WATERMARK;
|
|
pOptions->watermark2 = TSDB_DEFAULT_ROLLUP_WATERMARK;
|
|
pOptions->ttl = TSDB_DEFAULT_TABLE_TTL;
|
|
pOptions->keep = -1;
|
|
pOptions->virtualStb = false;
|
|
pOptions->commentNull = true; // mark null
|
|
return (SNode*)pOptions;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createAlterTableOptions(SAstCreateContext* pCxt) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
STableOptions* pOptions = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_TABLE_OPTIONS, (SNode**)&pOptions);
|
|
CHECK_MAKE_NODE(pOptions);
|
|
pOptions->ttl = -1;
|
|
pOptions->commentNull = true; // mark null
|
|
pOptions->keep = -1;
|
|
return (SNode*)pOptions;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* setTableOption(SAstCreateContext* pCxt, SNode* pOptions, ETableOptionType type, void* pVal) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
switch (type) {
|
|
case TABLE_OPTION_COMMENT:
|
|
if (checkComment(pCxt, (SToken*)pVal, true)) {
|
|
((STableOptions*)pOptions)->commentNull = false;
|
|
COPY_STRING_FORM_STR_TOKEN(((STableOptions*)pOptions)->comment, (SToken*)pVal);
|
|
}
|
|
break;
|
|
case TABLE_OPTION_MAXDELAY:
|
|
((STableOptions*)pOptions)->pMaxDelay = pVal;
|
|
break;
|
|
case TABLE_OPTION_WATERMARK:
|
|
((STableOptions*)pOptions)->pWatermark = pVal;
|
|
break;
|
|
case TABLE_OPTION_ROLLUP:
|
|
((STableOptions*)pOptions)->pRollupFuncs = pVal;
|
|
break;
|
|
case TABLE_OPTION_TTL: {
|
|
int64_t ttl = taosStr2Int64(((SToken*)pVal)->z, NULL, 10);
|
|
if (ttl > INT32_MAX) {
|
|
pCxt->errCode = TSDB_CODE_TSC_VALUE_OUT_OF_RANGE;
|
|
} else {
|
|
// ttl can not be smaller than 0, because there is a limitation in sql.y (TTL NK_INTEGER)
|
|
((STableOptions*)pOptions)->ttl = ttl;
|
|
}
|
|
break;
|
|
}
|
|
case TABLE_OPTION_SMA:
|
|
((STableOptions*)pOptions)->pSma = pVal;
|
|
break;
|
|
case TABLE_OPTION_DELETE_MARK:
|
|
((STableOptions*)pOptions)->pDeleteMark = pVal;
|
|
break;
|
|
case TABLE_OPTION_KEEP:
|
|
if (TK_NK_INTEGER == ((SToken*)pVal)->type) {
|
|
((STableOptions*)pOptions)->keep = taosStr2Int32(((SToken*)pVal)->z, NULL, 10) * 1440;
|
|
} else {
|
|
((STableOptions*)pOptions)->pKeepNode = (SValueNode*)createDurationValueNode(pCxt, (SToken*)pVal);
|
|
}
|
|
break;
|
|
case TABLE_OPTION_VIRTUAL: {
|
|
int64_t virtualStb = taosStr2Int64(((SToken*)pVal)->z, NULL, 10);
|
|
if (virtualStb != 0 && virtualStb != 1) {
|
|
pCxt->errCode = TSDB_CODE_TSC_VALUE_OUT_OF_RANGE;
|
|
} else {
|
|
((STableOptions*)pOptions)->virtualStb = virtualStb;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
return pOptions;
|
|
_err:
|
|
nodesDestroyNode(pOptions);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createDefaultColumnOptions(SAstCreateContext* pCxt) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SColumnOptions* pOptions = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_COLUMN_OPTIONS, (SNode**)&pOptions);
|
|
CHECK_MAKE_NODE(pOptions);
|
|
pOptions->commentNull = true;
|
|
pOptions->bPrimaryKey = false;
|
|
pOptions->hasRef = false;
|
|
return (SNode*)pOptions;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
EColumnOptionType getColumnOptionType(const char* optionType) {
|
|
if (0 == strcasecmp(optionType, "ENCODE")) {
|
|
return COLUMN_OPTION_ENCODE;
|
|
} else if (0 == strcasecmp(optionType, "COMPRESS")) {
|
|
return COLUMN_OPTION_COMPRESS;
|
|
} else if (0 == strcasecmp(optionType, "LEVEL")) {
|
|
return COLUMN_OPTION_LEVEL;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
SNode* setColumnReference(SAstCreateContext* pCxt, SNode* pOptions, SNode* pRef) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
|
|
((SColumnOptions*)pOptions)->hasRef = true;
|
|
tstrncpy(((SColumnOptions*)pOptions)->refDb, ((SColumnRefNode*)pRef)->refDbName, TSDB_DB_NAME_LEN);
|
|
tstrncpy(((SColumnOptions*)pOptions)->refTable, ((SColumnRefNode*)pRef)->refTableName, TSDB_TABLE_NAME_LEN);
|
|
tstrncpy(((SColumnOptions*)pOptions)->refColumn, ((SColumnRefNode*)pRef)->refColName, TSDB_COL_NAME_LEN);
|
|
return pOptions;
|
|
_err:
|
|
nodesDestroyNode(pOptions);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* setColumnOptionsPK(SAstCreateContext* pCxt, SNode* pOptions) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
((SColumnOptions*)pOptions)->bPrimaryKey = true;
|
|
return pOptions;
|
|
_err:
|
|
nodesDestroyNode(pOptions);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* setColumnOptions(SAstCreateContext* pCxt, SNode* pOptions, const SToken* pVal1, void* pVal2) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
char optionType[TSDB_CL_OPTION_LEN];
|
|
|
|
memset(optionType, 0, TSDB_CL_OPTION_LEN);
|
|
strncpy(optionType, pVal1->z, TMIN(pVal1->n, TSDB_CL_OPTION_LEN));
|
|
if (0 == strlen(optionType)) {
|
|
pCxt->errCode = TSDB_CODE_PAR_SYNTAX_ERROR;
|
|
return pOptions;
|
|
}
|
|
EColumnOptionType type = getColumnOptionType(optionType);
|
|
switch (type) {
|
|
case COLUMN_OPTION_ENCODE:
|
|
memset(((SColumnOptions*)pOptions)->encode, 0, TSDB_CL_COMPRESS_OPTION_LEN);
|
|
COPY_STRING_FORM_STR_TOKEN(((SColumnOptions*)pOptions)->encode, (SToken*)pVal2);
|
|
if (0 == strlen(((SColumnOptions*)pOptions)->encode)) {
|
|
pCxt->errCode = TSDB_CODE_TSC_ENCODE_PARAM_ERROR;
|
|
}
|
|
break;
|
|
case COLUMN_OPTION_COMPRESS:
|
|
memset(((SColumnOptions*)pOptions)->compress, 0, TSDB_CL_COMPRESS_OPTION_LEN);
|
|
COPY_STRING_FORM_STR_TOKEN(((SColumnOptions*)pOptions)->compress, (SToken*)pVal2);
|
|
if (0 == strlen(((SColumnOptions*)pOptions)->compress)) {
|
|
pCxt->errCode = TSDB_CODE_TSC_COMPRESS_PARAM_ERROR;
|
|
}
|
|
break;
|
|
case COLUMN_OPTION_LEVEL:
|
|
memset(((SColumnOptions*)pOptions)->compressLevel, 0, TSDB_CL_COMPRESS_OPTION_LEN);
|
|
COPY_STRING_FORM_STR_TOKEN(((SColumnOptions*)pOptions)->compressLevel, (SToken*)pVal2);
|
|
if (0 == strlen(((SColumnOptions*)pOptions)->compressLevel)) {
|
|
pCxt->errCode = TSDB_CODE_TSC_COMPRESS_LEVEL_ERROR;
|
|
}
|
|
break;
|
|
default:
|
|
pCxt->errCode = TSDB_CODE_PAR_SYNTAX_ERROR;
|
|
break;
|
|
}
|
|
return pOptions;
|
|
_err:
|
|
nodesDestroyNode(pOptions);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createColumnRefNodeByNode(SAstCreateContext* pCxt, SToken* pColName, SNode* pRef) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
CHECK_NAME(checkColumnName(pCxt, pColName));
|
|
|
|
SColumnRefNode* pCol = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_COLUMN_REF, (SNode**)&pCol);
|
|
CHECK_MAKE_NODE(pCol);
|
|
if (pColName) {
|
|
COPY_STRING_FORM_ID_TOKEN(pCol->colName, pColName);
|
|
}
|
|
tstrncpy(pCol->refDbName, ((SColumnRefNode*)pRef)->refDbName, TSDB_DB_NAME_LEN);
|
|
tstrncpy(pCol->refTableName, ((SColumnRefNode*)pRef)->refTableName, TSDB_TABLE_NAME_LEN);
|
|
tstrncpy(pCol->refColName, ((SColumnRefNode*)pRef)->refColName, TSDB_COL_NAME_LEN);
|
|
return (SNode*)pCol;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
STokenTriplet* createTokenTriplet(SAstCreateContext* pCxt, SToken pName) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
|
|
STokenTriplet* pTokenTri = taosMemoryMalloc(sizeof(STokenTriplet));
|
|
CHECK_OUT_OF_MEM(pTokenTri);
|
|
pTokenTri->name[0] = pName;
|
|
pTokenTri->numOfName = 1;
|
|
|
|
return pTokenTri;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
STokenTriplet* setColumnName(SAstCreateContext* pCxt, STokenTriplet* pTokenTri, SToken pName) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
|
|
if (pTokenTri->numOfName >= 3) {
|
|
pCxt->errCode = TSDB_CODE_PAR_SYNTAX_ERROR;
|
|
goto _err;
|
|
}
|
|
|
|
pTokenTri->name[pTokenTri->numOfName] = pName;
|
|
pTokenTri->numOfName++;
|
|
return pTokenTri;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createColumnRefNodeByName(SAstCreateContext* pCxt, STokenTriplet* pTokenTri) {
|
|
SColumnRefNode* pCol = NULL;
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_COLUMN_REF, (SNode**)&pCol);
|
|
CHECK_MAKE_NODE(pCol);
|
|
|
|
switch (pTokenTri->numOfName) {
|
|
case 2: {
|
|
CHECK_NAME(checkTableName(pCxt, &pTokenTri->name[0]));
|
|
CHECK_NAME(checkColumnName(pCxt, &pTokenTri->name[1]));
|
|
snprintf(pCol->refDbName, TSDB_DB_NAME_LEN, "%s", pCxt->pQueryCxt->db);
|
|
COPY_STRING_FORM_ID_TOKEN(pCol->refTableName, &pTokenTri->name[0]);
|
|
COPY_STRING_FORM_ID_TOKEN(pCol->refColName, &pTokenTri->name[1]);
|
|
break;
|
|
}
|
|
case 3: {
|
|
CHECK_NAME(checkDbName(pCxt, &pTokenTri->name[0], true));
|
|
CHECK_NAME(checkTableName(pCxt, &pTokenTri->name[1]));
|
|
CHECK_NAME(checkColumnName(pCxt, &pTokenTri->name[2]));
|
|
COPY_STRING_FORM_ID_TOKEN(pCol->refDbName, &pTokenTri->name[0]);
|
|
COPY_STRING_FORM_ID_TOKEN(pCol->refTableName, &pTokenTri->name[1]);
|
|
COPY_STRING_FORM_ID_TOKEN(pCol->refColName, &pTokenTri->name[2]);
|
|
break;
|
|
}
|
|
default: {
|
|
pCxt->errCode = TSDB_CODE_PAR_SYNTAX_ERROR;
|
|
goto _err;
|
|
}
|
|
}
|
|
|
|
taosMemFree(pTokenTri);
|
|
return (SNode*)pCol;
|
|
_err:
|
|
taosMemFree(pTokenTri);
|
|
nodesDestroyNode((SNode*)pCol);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createColumnDefNode(SAstCreateContext* pCxt, SToken* pColName, SDataType dataType, SNode* pNode) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
CHECK_NAME(checkColumnName(pCxt, pColName));
|
|
if (IS_VAR_DATA_TYPE(dataType.type) && dataType.bytes == 0) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_VAR_COLUMN_LEN);
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
}
|
|
SColumnDefNode* pCol = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_COLUMN_DEF, (SNode**)&pCol);
|
|
CHECK_MAKE_NODE(pCol);
|
|
COPY_STRING_FORM_ID_TOKEN(pCol->colName, pColName);
|
|
pCol->dataType = dataType;
|
|
pCol->pOptions = pNode;
|
|
pCol->sma = true;
|
|
return (SNode*)pCol;
|
|
_err:
|
|
nodesDestroyNode(pNode);
|
|
return NULL;
|
|
}
|
|
|
|
SDataType createDataType(uint8_t type) {
|
|
SDataType dt = {.type = type, .precision = 0, .scale = 0, .bytes = tDataTypes[type].bytes};
|
|
return dt;
|
|
}
|
|
|
|
SDataType createVarLenDataType(uint8_t type, const SToken* pLen) {
|
|
int32_t len = TSDB_MAX_BINARY_LEN - VARSTR_HEADER_SIZE;
|
|
if (type == TSDB_DATA_TYPE_NCHAR) len /= TSDB_NCHAR_SIZE;
|
|
if (pLen) len = taosStr2Int32(pLen->z, NULL, 10);
|
|
SDataType dt = {.type = type, .precision = 0, .scale = 0, .bytes = len};
|
|
return dt;
|
|
}
|
|
|
|
SDataType createDecimalDataType(uint8_t type, const SToken* pPrecisionToken, const SToken* pScaleToken) {
|
|
SDataType dt = {0};
|
|
dt.precision = taosStr2UInt8(pPrecisionToken->z, NULL, 10);
|
|
dt.scale = pScaleToken ? taosStr2Int32(pScaleToken->z, NULL, 10) : 0;
|
|
dt.type = decimalTypeFromPrecision(dt.precision);
|
|
dt.bytes = tDataTypes[dt.type].bytes;
|
|
return dt;
|
|
}
|
|
|
|
SNode* createCreateVTableStmt(SAstCreateContext* pCxt, bool ignoreExists, SNode* pRealTable, SNodeList* pCols) {
|
|
SCreateVTableStmt* pStmt = NULL;
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_CREATE_VIRTUAL_TABLE_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
strcpy(pStmt->dbName, ((SRealTableNode*)pRealTable)->table.dbName);
|
|
strcpy(pStmt->tableName, ((SRealTableNode*)pRealTable)->table.tableName);
|
|
pStmt->ignoreExists = ignoreExists;
|
|
pStmt->pCols = pCols;
|
|
nodesDestroyNode(pRealTable);
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
nodesDestroyNode(pRealTable);
|
|
nodesDestroyList(pCols);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createCreateVSubTableStmt(SAstCreateContext* pCxt, bool ignoreExists, SNode* pRealTable,
|
|
SNodeList* pSpecificColRefs, SNodeList* pColRefs, SNode* pUseRealTable,
|
|
SNodeList* pSpecificTags, SNodeList* pValsOfTags) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SCreateVSubTableStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_CREATE_VIRTUAL_SUBTABLE_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
strcpy(pStmt->dbName, ((SRealTableNode*)pRealTable)->table.dbName);
|
|
strcpy(pStmt->tableName, ((SRealTableNode*)pRealTable)->table.tableName);
|
|
strcpy(pStmt->useDbName, ((SRealTableNode*)pUseRealTable)->table.dbName);
|
|
strcpy(pStmt->useTableName, ((SRealTableNode*)pUseRealTable)->table.tableName);
|
|
pStmt->ignoreExists = ignoreExists;
|
|
pStmt->pSpecificTags = pSpecificTags;
|
|
pStmt->pValsOfTags = pValsOfTags;
|
|
pStmt->pSpecificColRefs = pSpecificColRefs;
|
|
pStmt->pColRefs = pColRefs;
|
|
nodesDestroyNode(pRealTable);
|
|
nodesDestroyNode(pUseRealTable);
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
nodesDestroyNode(pRealTable);
|
|
nodesDestroyNode(pUseRealTable);
|
|
nodesDestroyList(pSpecificTags);
|
|
nodesDestroyList(pValsOfTags);
|
|
nodesDestroyList(pSpecificColRefs);
|
|
nodesDestroyList(pColRefs);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createCreateTableStmt(SAstCreateContext* pCxt, bool ignoreExists, SNode* pRealTable, SNodeList* pCols,
|
|
SNodeList* pTags, SNode* pOptions) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SCreateTableStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_CREATE_TABLE_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
tstrncpy(pStmt->dbName, ((SRealTableNode*)pRealTable)->table.dbName, TSDB_DB_NAME_LEN);
|
|
tstrncpy(pStmt->tableName, ((SRealTableNode*)pRealTable)->table.tableName, TSDB_TABLE_NAME_LEN);
|
|
pStmt->ignoreExists = ignoreExists;
|
|
pStmt->pCols = pCols;
|
|
pStmt->pTags = pTags;
|
|
pStmt->pOptions = (STableOptions*)pOptions;
|
|
nodesDestroyNode(pRealTable);
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
nodesDestroyNode(pRealTable);
|
|
nodesDestroyList(pCols);
|
|
nodesDestroyList(pTags);
|
|
nodesDestroyNode(pOptions);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createCreateSubTableClause(SAstCreateContext* pCxt, bool ignoreExists, SNode* pRealTable, SNode* pUseRealTable,
|
|
SNodeList* pSpecificTags, SNodeList* pValsOfTags, SNode* pOptions) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SCreateSubTableClause* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_CREATE_SUBTABLE_CLAUSE, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
tstrncpy(pStmt->dbName, ((SRealTableNode*)pRealTable)->table.dbName, TSDB_DB_NAME_LEN);
|
|
tstrncpy(pStmt->tableName, ((SRealTableNode*)pRealTable)->table.tableName, TSDB_TABLE_NAME_LEN);
|
|
tstrncpy(pStmt->useDbName, ((SRealTableNode*)pUseRealTable)->table.dbName, TSDB_DB_NAME_LEN);
|
|
tstrncpy(pStmt->useTableName, ((SRealTableNode*)pUseRealTable)->table.tableName, TSDB_TABLE_NAME_LEN);
|
|
pStmt->ignoreExists = ignoreExists;
|
|
pStmt->pSpecificTags = pSpecificTags;
|
|
pStmt->pValsOfTags = pValsOfTags;
|
|
pStmt->pOptions = (STableOptions*)pOptions;
|
|
nodesDestroyNode(pRealTable);
|
|
nodesDestroyNode(pUseRealTable);
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
nodesDestroyNode(pRealTable);
|
|
nodesDestroyNode(pOptions);
|
|
nodesDestroyNode(pUseRealTable);
|
|
nodesDestroyList(pSpecificTags);
|
|
nodesDestroyList(pValsOfTags);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createCreateSubTableFromFileClause(SAstCreateContext* pCxt, bool ignoreExists, SNode* pUseRealTable,
|
|
SNodeList* pSpecificTags, const SToken* pFilePath) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SCreateSubTableFromFileClause* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_CREATE_SUBTABLE_FROM_FILE_CLAUSE, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
tstrncpy(pStmt->useDbName, ((SRealTableNode*)pUseRealTable)->table.dbName, TSDB_DB_NAME_LEN);
|
|
tstrncpy(pStmt->useTableName, ((SRealTableNode*)pUseRealTable)->table.tableName, TSDB_TABLE_NAME_LEN);
|
|
pStmt->ignoreExists = ignoreExists;
|
|
pStmt->pSpecificTags = pSpecificTags;
|
|
if (TK_NK_STRING == pFilePath->type) {
|
|
(void)trimString(pFilePath->z, pFilePath->n, pStmt->filePath, PATH_MAX);
|
|
} else {
|
|
strncpy(pStmt->filePath, pFilePath->z, pFilePath->n);
|
|
}
|
|
|
|
nodesDestroyNode(pUseRealTable);
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
nodesDestroyNode(pUseRealTable);
|
|
nodesDestroyList(pSpecificTags);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createCreateMultiTableStmt(SAstCreateContext* pCxt, SNodeList* pSubTables) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SCreateMultiTablesStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_CREATE_MULTI_TABLES_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
pStmt->pSubTables = pSubTables;
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
nodesDestroyList(pSubTables);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createDropTableClause(SAstCreateContext* pCxt, bool ignoreNotExists, SNode* pRealTable) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SDropTableClause* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_DROP_TABLE_CLAUSE, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
tstrncpy(pStmt->dbName, ((SRealTableNode*)pRealTable)->table.dbName, TSDB_DB_NAME_LEN);
|
|
tstrncpy(pStmt->tableName, ((SRealTableNode*)pRealTable)->table.tableName, TSDB_TABLE_NAME_LEN);
|
|
pStmt->ignoreNotExists = ignoreNotExists;
|
|
nodesDestroyNode(pRealTable);
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
nodesDestroyNode(pRealTable);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createDropTableStmt(SAstCreateContext* pCxt, bool withOpt, SNodeList* pTables) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SDropTableStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_DROP_TABLE_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
pStmt->pTables = pTables;
|
|
pStmt->withOpt = withOpt;
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
nodesDestroyList(pTables);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createDropSuperTableStmt(SAstCreateContext* pCxt, bool withOpt, bool ignoreNotExists, SNode* pRealTable) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SDropSuperTableStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_DROP_SUPER_TABLE_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
tstrncpy(pStmt->dbName, ((SRealTableNode*)pRealTable)->table.dbName, TSDB_DB_NAME_LEN);
|
|
tstrncpy(pStmt->tableName, ((SRealTableNode*)pRealTable)->table.tableName, TSDB_TABLE_NAME_LEN);
|
|
pStmt->ignoreNotExists = ignoreNotExists;
|
|
pStmt->withOpt = withOpt;
|
|
nodesDestroyNode(pRealTable);
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
nodesDestroyNode(pRealTable);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createDropVirtualTableStmt(SAstCreateContext* pCxt, bool withOpt, bool ignoreNotExists, SNode* pRealTable) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SDropVirtualTableStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_DROP_VIRTUAL_TABLE_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
tstrncpy(pStmt->dbName, ((SRealTableNode*)pRealTable)->table.dbName, TSDB_DB_NAME_LEN);
|
|
tstrncpy(pStmt->tableName, ((SRealTableNode*)pRealTable)->table.tableName, TSDB_TABLE_NAME_LEN);
|
|
pStmt->ignoreNotExists = ignoreNotExists;
|
|
pStmt->withOpt = withOpt;
|
|
nodesDestroyNode(pRealTable);
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
nodesDestroyNode(pRealTable);
|
|
return NULL;
|
|
}
|
|
|
|
static SNode* createAlterTableStmtFinalize(SNode* pRealTable, SAlterTableStmt* pStmt) {
|
|
tstrncpy(pStmt->dbName, ((SRealTableNode*)pRealTable)->table.dbName, TSDB_DB_NAME_LEN);
|
|
tstrncpy(pStmt->tableName, ((SRealTableNode*)pRealTable)->table.tableName, TSDB_TABLE_NAME_LEN);
|
|
nodesDestroyNode(pRealTable);
|
|
return (SNode*)pStmt;
|
|
}
|
|
|
|
SNode* createAlterTableModifyOptions(SAstCreateContext* pCxt, SNode* pRealTable, SNode* pOptions) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SAlterTableStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_ALTER_TABLE_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
pStmt->alterType = TSDB_ALTER_TABLE_UPDATE_OPTIONS;
|
|
pStmt->pOptions = (STableOptions*)pOptions;
|
|
return createAlterTableStmtFinalize(pRealTable, pStmt);
|
|
_err:
|
|
nodesDestroyNode(pRealTable);
|
|
nodesDestroyNode(pOptions);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createAlterTableAddModifyCol(SAstCreateContext* pCxt, SNode* pRealTable, int8_t alterType, SToken* pColName,
|
|
SDataType dataType) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
CHECK_NAME(checkColumnName(pCxt, pColName));
|
|
SAlterTableStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_ALTER_TABLE_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
pStmt->alterType = alterType;
|
|
COPY_STRING_FORM_ID_TOKEN(pStmt->colName, pColName);
|
|
pStmt->dataType = dataType;
|
|
return createAlterTableStmtFinalize(pRealTable, pStmt);
|
|
_err:
|
|
nodesDestroyNode(pRealTable);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createAlterTableAddModifyColOptions2(SAstCreateContext* pCxt, SNode* pRealTable, int8_t alterType,
|
|
SToken* pColName, SDataType dataType, SNode* pOptions) {
|
|
SAlterTableStmt* pStmt = NULL;
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
CHECK_NAME(checkColumnName(pCxt, pColName));
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_ALTER_TABLE_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
pStmt->alterType = alterType;
|
|
COPY_STRING_FORM_ID_TOKEN(pStmt->colName, pColName);
|
|
pStmt->dataType = dataType;
|
|
pStmt->pColOptions = (SColumnOptions*)pOptions;
|
|
|
|
if (pOptions != NULL) {
|
|
SColumnOptions* pOption = (SColumnOptions*)pOptions;
|
|
if (pOption->hasRef) {
|
|
if (!pOption->commentNull || pOption->bPrimaryKey || 0 != strcmp(pOption->compress, "") ||
|
|
0 != strcmp(pOption->encode, "") || 0 != strcmp(pOption->compressLevel, "")) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_ALTER_TABLE);
|
|
}
|
|
pStmt->alterType = TSDB_ALTER_TABLE_ADD_COLUMN_WITH_COLUMN_REF;
|
|
tstrncpy(pStmt->refDbName, pOption->refDb, TSDB_DB_NAME_LEN);
|
|
tstrncpy(pStmt->refTableName, pOption->refTable, TSDB_TABLE_NAME_LEN);
|
|
tstrncpy(pStmt->refColName, pOption->refColumn, TSDB_COL_NAME_LEN);
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
} else if (pOption->bPrimaryKey == false && pOption->commentNull == true) {
|
|
if (strlen(pOption->compress) != 0 || strlen(pOption->compressLevel) || strlen(pOption->encode) != 0) {
|
|
pStmt->alterType = TSDB_ALTER_TABLE_ADD_COLUMN_WITH_COMPRESS_OPTION;
|
|
} else {
|
|
// pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR,
|
|
// "not support alter column with option except compress");
|
|
// return NULL;
|
|
}
|
|
} else {
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR,
|
|
"not support alter column with option except compress");
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
}
|
|
}
|
|
return createAlterTableStmtFinalize(pRealTable, pStmt);
|
|
_err:
|
|
nodesDestroyNode(pOptions);
|
|
nodesDestroyNode((SNode*)pStmt);
|
|
nodesDestroyNode(pRealTable);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createAlterTableAddModifyColOptions(SAstCreateContext* pCxt, SNode* pRealTable, int8_t alterType,
|
|
SToken* pColName, SNode* pOptions) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
CHECK_NAME(checkColumnName(pCxt, pColName));
|
|
SAlterTableStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_ALTER_TABLE_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
pStmt->alterType = TSDB_ALTER_TABLE_UPDATE_COLUMN_COMPRESS;
|
|
COPY_STRING_FORM_ID_TOKEN(pStmt->colName, pColName);
|
|
pStmt->pColOptions = (SColumnOptions*)pOptions;
|
|
return createAlterTableStmtFinalize(pRealTable, pStmt);
|
|
_err:
|
|
nodesDestroyNode(pOptions);
|
|
nodesDestroyNode(pRealTable);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createAlterTableDropCol(SAstCreateContext* pCxt, SNode* pRealTable, int8_t alterType, SToken* pColName) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
CHECK_NAME(checkColumnName(pCxt, pColName));
|
|
SAlterTableStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_ALTER_TABLE_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
pStmt->alterType = alterType;
|
|
COPY_STRING_FORM_ID_TOKEN(pStmt->colName, pColName);
|
|
return createAlterTableStmtFinalize(pRealTable, pStmt);
|
|
_err:
|
|
nodesDestroyNode(pRealTable);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createAlterTableRenameCol(SAstCreateContext* pCxt, SNode* pRealTable, int8_t alterType, SToken* pOldColName,
|
|
SToken* pNewColName) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
CHECK_NAME(checkColumnName(pCxt, pOldColName));
|
|
CHECK_NAME(checkColumnName(pCxt, pNewColName));
|
|
SAlterTableStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_ALTER_TABLE_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
pStmt->alterType = alterType;
|
|
COPY_STRING_FORM_ID_TOKEN(pStmt->colName, pOldColName);
|
|
COPY_STRING_FORM_ID_TOKEN(pStmt->newColName, pNewColName);
|
|
return createAlterTableStmtFinalize(pRealTable, pStmt);
|
|
_err:
|
|
nodesDestroyNode(pRealTable);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createAlterTableAlterColRef(SAstCreateContext* pCxt, SNode* pRealTable, int8_t alterType, SToken* pColName,
|
|
SNode* pRef) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
CHECK_NAME(checkColumnName(pCxt, pColName));
|
|
SAlterTableStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_ALTER_TABLE_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
pStmt->alterType = alterType;
|
|
COPY_STRING_FORM_ID_TOKEN(pStmt->colName, pColName);
|
|
tstrncpy(pStmt->refDbName, ((SColumnRefNode*)pRef)->refDbName, TSDB_DB_NAME_LEN);
|
|
tstrncpy(pStmt->refTableName, ((SColumnRefNode*)pRef)->refTableName, TSDB_TABLE_NAME_LEN);
|
|
tstrncpy(pStmt->refColName, ((SColumnRefNode*)pRef)->refColName, TSDB_COL_NAME_LEN);
|
|
return createAlterTableStmtFinalize(pRealTable, pStmt);
|
|
_err:
|
|
nodesDestroyNode(pRealTable);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createAlterTableRemoveColRef(SAstCreateContext* pCxt, SNode* pRealTable, int8_t alterType, SToken* pColName,
|
|
const SToken* pLiteral) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
CHECK_NAME(checkColumnName(pCxt, pColName));
|
|
SAlterTableStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_ALTER_TABLE_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
pStmt->alterType = alterType;
|
|
COPY_STRING_FORM_ID_TOKEN(pStmt->colName, pColName);
|
|
return createAlterTableStmtFinalize(pRealTable, pStmt);
|
|
_err:
|
|
nodesDestroyNode(pRealTable);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createAlterSingleTagColumnNode(SAstCreateContext* pCtx, SToken* pTagName, SNode* pVal) {
|
|
CHECK_PARSER_STATUS(pCtx);
|
|
SAlterTableStmt* pStmt = NULL;
|
|
pCtx->errCode = nodesMakeNode(QUERY_NODE_ALTER_TABLE_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
pStmt->alterType = TSDB_ALTER_TABLE_UPDATE_TAG_VAL;
|
|
CHECK_NAME(checkColumnName(pCtx, pTagName));
|
|
COPY_STRING_FORM_ID_TOKEN(pStmt->colName, pTagName);
|
|
pStmt->pVal = (SValueNode*)pVal;
|
|
pStmt->pNodeListTagValue = NULL;
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createAlterTableSetTag(SAstCreateContext* pCxt, SNode* pRealTable, SToken* pTagName, SNode* pVal) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
CHECK_NAME(checkColumnName(pCxt, pTagName));
|
|
SAlterTableStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_ALTER_TABLE_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
pStmt->alterType = TSDB_ALTER_TABLE_UPDATE_TAG_VAL;
|
|
COPY_STRING_FORM_ID_TOKEN(pStmt->colName, pTagName);
|
|
pStmt->pVal = (SValueNode*)pVal;
|
|
return createAlterTableStmtFinalize(pRealTable, pStmt);
|
|
_err:
|
|
nodesDestroyNode(pVal);
|
|
nodesDestroyNode(pRealTable);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createAlterTableSetMultiTagValue(SAstCreateContext* pCxt, SNode* pRealTable, SNodeList* pList) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SAlterTableStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_ALTER_TABLE_STMT, (SNode**)&pStmt);
|
|
|
|
CHECK_MAKE_NODE(pStmt);
|
|
pStmt->alterType = TSDB_ALTER_TABLE_UPDATE_MULTI_TAG_VAL;
|
|
pStmt->pNodeListTagValue = pList;
|
|
return createAlterTableStmtFinalize(pRealTable, pStmt);
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* setAlterSuperTableType(SNode* pStmt) {
|
|
if (!pStmt) return NULL;
|
|
setNodeType(pStmt, QUERY_NODE_ALTER_SUPER_TABLE_STMT);
|
|
return pStmt;
|
|
}
|
|
|
|
SNode* setAlterVirtualTableType(SNode* pStmt) {
|
|
if (!pStmt) return NULL;
|
|
setNodeType(pStmt, QUERY_NODE_ALTER_VIRTUAL_TABLE_STMT);
|
|
return pStmt;
|
|
}
|
|
|
|
SNode* createUseDatabaseStmt(SAstCreateContext* pCxt, SToken* pDbName) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
CHECK_NAME(checkDbName(pCxt, pDbName, false));
|
|
SUseDatabaseStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_USE_DATABASE_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
COPY_STRING_FORM_ID_TOKEN(pStmt->dbName, pDbName);
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
static bool needDbShowStmt(ENodeType type) {
|
|
return QUERY_NODE_SHOW_TABLES_STMT == type || QUERY_NODE_SHOW_STABLES_STMT == type ||
|
|
QUERY_NODE_SHOW_VGROUPS_STMT == type || QUERY_NODE_SHOW_INDEXES_STMT == type ||
|
|
QUERY_NODE_SHOW_TAGS_STMT == type || QUERY_NODE_SHOW_TABLE_TAGS_STMT == type ||
|
|
QUERY_NODE_SHOW_VIEWS_STMT == type || QUERY_NODE_SHOW_TSMAS_STMT == type ||
|
|
QUERY_NODE_SHOW_USAGE_STMT == type || QUERY_NODE_SHOW_VTABLES_STMT == type ||
|
|
QUERY_NODE_SHOW_STREAMS_STMT == type;
|
|
}
|
|
|
|
SNode* createShowStmtWithLike(SAstCreateContext* pCxt, ENodeType type, SNode* pLikePattern) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SShowStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(type, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
pStmt->withFull = false;
|
|
pStmt->pTbName = pLikePattern;
|
|
if (pLikePattern) {
|
|
pStmt->tableCondType = OP_TYPE_LIKE;
|
|
}
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
nodesDestroyNode(pLikePattern);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createShowStmt(SAstCreateContext* pCxt, ENodeType type) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SShowStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(type, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
pStmt->withFull = false;
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createShowXnodeStmtWithCond(SAstCreateContext* pCxt, ENodeType type, SNode* pWhere) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SShowStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(type, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
pStmt->pWhere = pWhere;
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createShowXNodeResourcesWhereStmt(SAstCreateContext* pCxt, EXnodeResourceType resourceType, SNode* pWhere) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SShowStmt* pStmt = NULL;
|
|
ENodeType type;
|
|
switch (resourceType) {
|
|
case XNODE_TASK:
|
|
type = QUERY_NODE_SHOW_XNODE_TASKS_STMT;
|
|
break;
|
|
case XNODE_JOB:
|
|
type = QUERY_NODE_SHOW_XNODE_JOBS_STMT;
|
|
break;
|
|
case XNODE_AGENT:
|
|
type = QUERY_NODE_SHOW_XNODE_AGENTS_STMT;
|
|
break;
|
|
default:
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR,
|
|
"Xnode not support show xnode resource type");
|
|
goto _err;
|
|
}
|
|
|
|
pStmt = (SShowStmt*)createShowXnodeStmtWithCond(pCxt, type, pWhere);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createShowStmtWithFull(SAstCreateContext* pCxt, ENodeType type) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SShowStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(type, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
pStmt->withFull = true;
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createShowCompactsStmt(SAstCreateContext* pCxt, ENodeType type) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SShowCompactsStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(type, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createShowSsMigratesStmt(SAstCreateContext* pCxt, ENodeType type) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SShowSsMigratesStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(type, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createShowTokensStmt(SAstCreateContext* pCxt, ENodeType type) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SShowTokensStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(type, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* setShowKind(SAstCreateContext* pCxt, SNode* pStmt, EShowKind showKind) {
|
|
if (pStmt == NULL) {
|
|
return NULL;
|
|
}
|
|
SShowStmt* pShow = (SShowStmt*)pStmt;
|
|
pShow->showKind = showKind;
|
|
return pStmt;
|
|
}
|
|
|
|
SNode* createShowStmtWithCond(SAstCreateContext* pCxt, ENodeType type, SNode* pDbName, SNode* pTbName,
|
|
EOperatorType tableCondType) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
if (needDbShowStmt(type) && NULL == pDbName) {
|
|
snprintf(pCxt->pQueryCxt->pMsg, pCxt->pQueryCxt->msgLen, "database not specified");
|
|
pCxt->errCode = TSDB_CODE_PAR_SYNTAX_ERROR;
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
}
|
|
SShowStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(type, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
pStmt->pDbName = pDbName;
|
|
pStmt->pTbName = pTbName;
|
|
pStmt->tableCondType = tableCondType;
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
nodesDestroyNode(pDbName);
|
|
nodesDestroyNode(pTbName);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createShowTablesStmt(SAstCreateContext* pCxt, SShowTablesOption option, SNode* pTbName,
|
|
EOperatorType tableCondType) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SNode* pDbName = NULL;
|
|
if (option.dbName.type == TK_NK_NIL) {
|
|
pDbName = createDefaultDatabaseCondValue(pCxt);
|
|
} else {
|
|
pDbName = createIdentifierValueNode(pCxt, &option.dbName);
|
|
}
|
|
|
|
if (option.kind != SHOW_KIND_TABLES_NORMAL && option.kind != SHOW_KIND_TABLES_CHILD && option.kind != SHOW_KIND_ALL) {
|
|
pCxt->errCode = TSDB_CODE_PAR_SYNTAX_ERROR;
|
|
return NULL;
|
|
}
|
|
|
|
SNode* pStmt = createShowStmtWithCond(pCxt, QUERY_NODE_SHOW_TABLES_STMT, pDbName, pTbName, tableCondType);
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
(void)setShowKind(pCxt, pStmt, option.kind);
|
|
return pStmt;
|
|
_err:
|
|
nodesDestroyNode(pTbName);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createShowVTablesStmt(SAstCreateContext* pCxt, SShowTablesOption option, SNode* pTbName,
|
|
EOperatorType tableCondType) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SNode* pDbName = NULL;
|
|
if (option.dbName.type == TK_NK_NIL) {
|
|
pDbName = createDefaultDatabaseCondValue(pCxt);
|
|
} else {
|
|
pDbName = createIdentifierValueNode(pCxt, &option.dbName);
|
|
}
|
|
|
|
if (option.kind != SHOW_KIND_TABLES_NORMAL && option.kind != SHOW_KIND_TABLES_CHILD && option.kind != SHOW_KIND_ALL) {
|
|
pCxt->errCode = TSDB_CODE_PAR_SYNTAX_ERROR;
|
|
return NULL;
|
|
}
|
|
|
|
SNode* pStmt = createShowStmtWithCond(pCxt, QUERY_NODE_SHOW_VTABLES_STMT, pDbName, pTbName, tableCondType);
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
(void)setShowKind(pCxt, pStmt, option.kind);
|
|
return pStmt;
|
|
_err:
|
|
nodesDestroyNode(pTbName);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createShowSTablesStmt(SAstCreateContext* pCxt, SShowTablesOption option, SNode* pTbName,
|
|
EOperatorType tableCondType) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SNode* pDbName = NULL;
|
|
if (option.dbName.type == TK_NK_NIL) {
|
|
pDbName = createDefaultDatabaseCondValue(pCxt);
|
|
} else {
|
|
pDbName = createIdentifierValueNode(pCxt, &option.dbName);
|
|
}
|
|
|
|
if (option.kind != SHOW_KIND_TABLES_NORMAL && option.kind != SHOW_KIND_TABLES_VIRTUAL &&
|
|
option.kind != SHOW_KIND_ALL) {
|
|
pCxt->errCode = TSDB_CODE_PAR_SYNTAX_ERROR;
|
|
return NULL;
|
|
}
|
|
|
|
SNode* pStmt = createShowStmtWithCond(pCxt, QUERY_NODE_SHOW_STABLES_STMT, pDbName, pTbName, tableCondType);
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
(void)setShowKind(pCxt, pStmt, option.kind);
|
|
return pStmt;
|
|
_err:
|
|
nodesDestroyNode(pTbName);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createShowCreateDatabaseStmt(SAstCreateContext* pCxt, SToken* pDbName) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
CHECK_NAME(checkDbName(pCxt, pDbName, true));
|
|
SShowCreateDatabaseStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_SHOW_CREATE_DATABASE_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
COPY_STRING_FORM_ID_TOKEN(pStmt->dbName, pDbName);
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createShowAliveStmt(SAstCreateContext* pCxt, SNode* pNode, ENodeType type) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SToken dbToken = {0};
|
|
SToken* pDbToken = NULL;
|
|
|
|
if (pNode) {
|
|
SValueNode* pDbName = (SValueNode*)pNode;
|
|
if (pDbName->literal) {
|
|
dbToken.z = pDbName->literal;
|
|
dbToken.n = strlen(pDbName->literal);
|
|
pDbToken = &dbToken;
|
|
}
|
|
}
|
|
|
|
if (pDbToken) {
|
|
CHECK_NAME(checkDbName(pCxt, pDbToken, true));
|
|
}
|
|
|
|
SShowAliveStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(type, (SNode**)&pStmt);
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
|
|
if (pDbToken) {
|
|
COPY_STRING_FORM_ID_TOKEN(pStmt->dbName, pDbToken);
|
|
}
|
|
if (pNode) {
|
|
nodesDestroyNode(pNode);
|
|
}
|
|
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
nodesDestroyNode(pNode);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createShowCreateTableStmt(SAstCreateContext* pCxt, ENodeType type, SNode* pRealTable) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SShowCreateTableStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(type, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
tstrncpy(pStmt->dbName, ((SRealTableNode*)pRealTable)->table.dbName, TSDB_DB_NAME_LEN);
|
|
tstrncpy(pStmt->tableName, ((SRealTableNode*)pRealTable)->table.tableName, TSDB_TABLE_NAME_LEN);
|
|
nodesDestroyNode(pRealTable);
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
nodesDestroyNode(pRealTable);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createShowCreateVTableStmt(SAstCreateContext* pCxt, ENodeType type, SNode* pRealTable) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SShowCreateTableStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(type, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
tstrncpy(pStmt->dbName, ((SRealTableNode*)pRealTable)->table.dbName, TSDB_DB_NAME_LEN);
|
|
tstrncpy(pStmt->tableName, ((SRealTableNode*)pRealTable)->table.tableName, TSDB_TABLE_NAME_LEN);
|
|
nodesDestroyNode(pRealTable);
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
nodesDestroyNode(pRealTable);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createShowCreateViewStmt(SAstCreateContext* pCxt, ENodeType type, SNode* pRealTable) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SShowCreateViewStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(type, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
tstrncpy(pStmt->dbName, ((SRealTableNode*)pRealTable)->table.dbName, TSDB_DB_NAME_LEN);
|
|
tstrncpy(pStmt->viewName, ((SRealTableNode*)pRealTable)->table.tableName, TSDB_TABLE_NAME_LEN);
|
|
nodesDestroyNode(pRealTable);
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
nodesDestroyNode(pRealTable);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createShowTableDistributedStmt(SAstCreateContext* pCxt, SNode* pRealTable) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SShowTableDistributedStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_SHOW_TABLE_DISTRIBUTED_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
tstrncpy(pStmt->dbName, ((SRealTableNode*)pRealTable)->table.dbName, TSDB_DB_NAME_LEN);
|
|
tstrncpy(pStmt->tableName, ((SRealTableNode*)pRealTable)->table.tableName, TSDB_TABLE_NAME_LEN);
|
|
nodesDestroyNode(pRealTable);
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
nodesDestroyNode(pRealTable);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createShowDnodeVariablesStmt(SAstCreateContext* pCxt, SNode* pDnodeId, SNode* pLikePattern) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SShowDnodeVariablesStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_SHOW_DNODE_VARIABLES_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
pStmt->pDnodeId = pDnodeId;
|
|
pStmt->pLikePattern = pLikePattern;
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
nodesDestroyNode(pDnodeId);
|
|
nodesDestroyNode(pLikePattern);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createShowVnodesStmt(SAstCreateContext* pCxt, SNode* pDnodeId, SNode* pDnodeEndpoint) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SShowVnodesStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_SHOW_VNODES_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
pStmt->pDnodeId = pDnodeId;
|
|
pStmt->pDnodeEndpoint = pDnodeEndpoint;
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
nodesDestroyNode(pDnodeId);
|
|
nodesDestroyNode(pDnodeEndpoint);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createShowTableTagsStmt(SAstCreateContext* pCxt, SNode* pTbName, SNode* pDbName, SNodeList* pTags) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
if (NULL == pDbName) {
|
|
snprintf(pCxt->pQueryCxt->pMsg, pCxt->pQueryCxt->msgLen, "database not specified");
|
|
pCxt->errCode = TSDB_CODE_PAR_SYNTAX_ERROR;
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
}
|
|
SShowTableTagsStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_SHOW_TABLE_TAGS_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
pStmt->pDbName = pDbName;
|
|
pStmt->pTbName = pTbName;
|
|
pStmt->pTags = pTags;
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
nodesDestroyNode(pTbName);
|
|
nodesDestroyNode(pDbName);
|
|
nodesDestroyList(pTags);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createShowCompactDetailsStmt(SAstCreateContext* pCxt, SNode* pCompactId) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SShowCompactDetailsStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_SHOW_COMPACT_DETAILS_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
pStmt->pId = pCompactId;
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
nodesDestroyNode(pCompactId);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createShowRetentionDetailsStmt(SAstCreateContext* pCxt, SNode* pId) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SShowRetentionDetailsStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_SHOW_RETENTION_DETAILS_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
pStmt->pId = pId;
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
nodesDestroyNode(pId);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createShowTransactionDetailsStmt(SAstCreateContext* pCxt, SNode* pTransactionIdNode) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SShowTransactionDetailsStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_SHOW_TRANSACTION_DETAILS_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
pStmt->pTransactionId = pTransactionIdNode;
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
nodesDestroyNode(pTransactionIdNode);
|
|
return NULL;
|
|
}
|
|
|
|
|
|
|
|
static bool parseIp(const char* strIp, SIpRange* pIpRange) {
|
|
if (strchr(strIp, ':') == NULL) {
|
|
struct in_addr ip4;
|
|
if (inet_pton(AF_INET, strIp, &ip4) == 1) {
|
|
pIpRange->type = 0;
|
|
memcpy(&pIpRange->ipV4.ip, &ip4.s_addr, sizeof(ip4.s_addr));
|
|
return true;
|
|
}
|
|
} else {
|
|
struct in6_addr ip6;
|
|
if (inet_pton(AF_INET6, strIp, &ip6) == 1) {
|
|
pIpRange->type = 1;
|
|
memcpy(&pIpRange->ipV6.addr[0], ip6.s6_addr, 8);
|
|
memcpy(&pIpRange->ipV6.addr[1], ip6.s6_addr + 8, 8);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
|
|
SIpRangeNode* parseIpRange(SAstCreateContext* pCxt, const SToken* token) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
|
|
#ifdef TD_ASTRA
|
|
return NULL;
|
|
#else
|
|
|
|
SIpRangeNode* node = NULL;
|
|
int32_t code = nodesMakeNode(QUERY_NODE_IP_RANGE, (SNode**)&node);
|
|
if (node == NULL) {
|
|
goto _err;
|
|
}
|
|
|
|
char buf[64];
|
|
if (token->n >= sizeof(buf)) {
|
|
code = TSDB_CODE_PAR_INVALID_IP_RANGE;
|
|
goto _err;
|
|
}
|
|
memcpy(buf, token->z, token->n);
|
|
buf[token->n] = '\0';
|
|
(void)strdequote(buf);
|
|
|
|
char* slash = strchr(buf, '/');
|
|
if (slash) {
|
|
*slash = '\0';
|
|
}
|
|
|
|
if (!parseIp(buf, &node->range)) {
|
|
code = TSDB_CODE_PAR_INVALID_IP_RANGE;
|
|
goto _err;
|
|
}
|
|
|
|
int32_t mask = 0;
|
|
if (!slash) {
|
|
mask = node->range.type == 0 ? 32 : 128;
|
|
} else if (taosStr2int32(slash + 1, &mask) != TSDB_CODE_SUCCESS) {
|
|
code = TSDB_CODE_PAR_INVALID_IP_RANGE;
|
|
goto _err;
|
|
}
|
|
|
|
code = tIpRangeSetMask(&node->range, mask);
|
|
if (code != TSDB_CODE_SUCCESS) {
|
|
goto _err;
|
|
}
|
|
|
|
return node;
|
|
|
|
_err:
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, code);
|
|
nodesDestroyNode((SNode*)node);
|
|
return NULL;
|
|
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
SDateTimeRangeNode* parseDateTimeRange(SAstCreateContext* pCxt, const SToken* token) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
|
|
SDateTimeRangeNode* node = NULL;
|
|
int32_t code = nodesMakeNode(QUERY_NODE_DATE_TIME_RANGE, (SNode**)&node);
|
|
if (code != TSDB_CODE_SUCCESS) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, code);
|
|
goto _err;
|
|
}
|
|
|
|
char buf[128];
|
|
if (token->n >= sizeof(buf)) {
|
|
code = TSDB_CODE_PAR_OPTION_VALUE_TOO_LONG;
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, code, "Date time range string is too long");
|
|
goto _err;
|
|
}
|
|
memcpy(buf, token->z, token->n);
|
|
buf[token->n] = '\0';
|
|
(void)strdequote(buf);
|
|
|
|
code = TSDB_CODE_PAR_INVALID_OPTION_VALUE;
|
|
int32_t year = 0, month = 0, day = 0, hour = 0, minute = 0, duration = 0;
|
|
if (buf[0] >= '1' && buf[0] <= '9') {
|
|
// format: YYYY-MM-DD HH:MM duration
|
|
int ret = sscanf(buf, "%d-%d-%d %d:%d %d", &year, &month, &day, &hour, &minute, &duration);
|
|
if (ret != 6) {
|
|
goto _err;
|
|
}
|
|
if (month < 1 || month > 12) {
|
|
goto _err;
|
|
}
|
|
} else {
|
|
// format: WEEKDAY HH:MM duration
|
|
char weekday[4];
|
|
int ret = sscanf(buf, "%3s %d:%d %d", weekday, &hour, &minute, &duration);
|
|
if (ret != 4) {
|
|
goto _err;
|
|
}
|
|
day = taosParseShortWeekday(weekday);
|
|
if (day < 0 || day > 6) {
|
|
goto _err;
|
|
}
|
|
month = -1;
|
|
}
|
|
|
|
node->range.year = (int16_t)year;
|
|
node->range.month = (int8_t)month;
|
|
node->range.day = (int8_t)day;
|
|
node->range.hour = (int8_t)hour;
|
|
node->range.minute = (int8_t)minute;
|
|
node->range.duration = duration;
|
|
if (!isValidDateTimeRange(&node->range)) {
|
|
goto _err;
|
|
}
|
|
|
|
return node;
|
|
|
|
_err:
|
|
if (code == TSDB_CODE_PAR_INVALID_OPTION_VALUE) { // other error types have been set above
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, code, "Invalid date time range");
|
|
}
|
|
nodesDestroyNode((SNode*)node);
|
|
return NULL;
|
|
}
|
|
|
|
|
|
SUserOptions* createDefaultUserOptions(SAstCreateContext* pCxt) {
|
|
SUserOptions* pOptions = NULL;
|
|
int32_t code = nodesMakeNode(QUERY_NODE_USER_OPTIONS, (SNode**)&pOptions);
|
|
if (pOptions == NULL) {
|
|
pCxt->errCode = code;
|
|
return NULL;
|
|
}
|
|
|
|
pOptions->enable = 1;
|
|
pOptions->sysinfo = 1;
|
|
pOptions->createdb = 0;
|
|
pOptions->isImport = 0;
|
|
pOptions->changepass = 2;
|
|
pOptions->sessionPerUser = TSDB_USER_SESSION_PER_USER_DEFAULT;
|
|
pOptions->connectTime = TSDB_USER_CONNECT_TIME_DEFAULT;
|
|
pOptions->connectIdleTime = TSDB_USER_CONNECT_IDLE_TIME_DEFAULT;
|
|
pOptions->callPerSession = TSDB_USER_CALL_PER_SESSION_DEFAULT;
|
|
pOptions->vnodePerCall = TSDB_USER_VNODE_PER_CALL_DEFAULT;
|
|
pOptions->failedLoginAttempts = TSDB_USER_FAILED_LOGIN_ATTEMPTS_DEFAULT;
|
|
pOptions->passwordLifeTime = TSDB_USER_PASSWORD_LIFE_TIME_DEFAULT;
|
|
pOptions->passwordReuseTime = TSDB_USER_PASSWORD_REUSE_TIME_DEFAULT;
|
|
pOptions->passwordReuseMax = TSDB_USER_PASSWORD_REUSE_MAX_DEFAULT;
|
|
pOptions->passwordLockTime = TSDB_USER_PASSWORD_LOCK_TIME_DEFAULT;
|
|
pOptions->passwordGraceTime = TSDB_USER_PASSWORD_GRACE_TIME_DEFAULT;
|
|
pOptions->inactiveAccountTime = TSDB_USER_INACTIVE_ACCOUNT_TIME_DEFAULT;
|
|
pOptions->allowTokenNum = TSDB_USER_ALLOW_TOKEN_NUM_DEFAULT;
|
|
|
|
return pOptions;
|
|
}
|
|
|
|
|
|
|
|
SUserOptions* mergeUserOptions(SAstCreateContext* pCxt, SUserOptions* a, SUserOptions* b) {
|
|
if (a == NULL && b == NULL) {
|
|
return createDefaultUserOptions(pCxt);
|
|
}
|
|
if (b == NULL) {
|
|
return a;
|
|
}
|
|
if (a == NULL) {
|
|
return b;
|
|
}
|
|
|
|
if (b->hasPassword) {
|
|
if (a->hasPassword) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_OPTION_DUPLICATED, "PASS");
|
|
} else {
|
|
a->hasPassword = true;
|
|
tstrncpy(a->password, b->password, sizeof(a->password));
|
|
}
|
|
}
|
|
|
|
if (b->hasTotpseed) {
|
|
if (a->hasTotpseed) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_OPTION_DUPLICATED, "TOTPSEED");
|
|
} else {
|
|
a->hasTotpseed = true;
|
|
tstrncpy(a->totpseed, b->totpseed, sizeof(a->totpseed));
|
|
}
|
|
}
|
|
|
|
if (b->hasEnable) {
|
|
if (a->hasEnable) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_OPTION_DUPLICATED, "ENABLE/ACCOUNT LOCK/ACCOUNT UNLOCK");
|
|
} else {
|
|
a->hasEnable = true;
|
|
a->enable = b->enable;
|
|
}
|
|
}
|
|
|
|
if (b->hasSysinfo) {
|
|
if (a->hasSysinfo) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_OPTION_DUPLICATED, "SYSINFO");
|
|
} else {
|
|
a->hasSysinfo = true;
|
|
a->sysinfo = b->sysinfo;
|
|
}
|
|
}
|
|
|
|
if (b->hasCreatedb) {
|
|
if (a->hasCreatedb) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_OPTION_DUPLICATED, "CREATEDB");
|
|
} else {
|
|
a->hasCreatedb = true;
|
|
a->createdb = b->createdb;
|
|
}
|
|
}
|
|
|
|
if (b->hasChangepass) {
|
|
if (a->hasChangepass) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_OPTION_DUPLICATED, "CHANGEPASS");
|
|
} else {
|
|
a->hasChangepass = true;
|
|
a->changepass = b->changepass;
|
|
}
|
|
}
|
|
|
|
if (b->hasSessionPerUser) {
|
|
if (a->hasSessionPerUser) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_OPTION_DUPLICATED, "SESSION_PER_USER");
|
|
} else {
|
|
a->hasSessionPerUser = true;
|
|
a->sessionPerUser = b->sessionPerUser;
|
|
}
|
|
}
|
|
|
|
if (b->hasConnectTime) {
|
|
if (a->hasConnectTime) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_OPTION_DUPLICATED, "CONNECT_TIME");
|
|
} else {
|
|
a->hasConnectTime = true;
|
|
a->connectTime = b->connectTime;
|
|
}
|
|
}
|
|
|
|
if (b->hasConnectIdleTime) {
|
|
if (a->hasConnectIdleTime) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_OPTION_DUPLICATED, "CONNECT_IDLE_TIME");
|
|
} else {
|
|
a->hasConnectIdleTime = true;
|
|
a->connectIdleTime = b->connectIdleTime;
|
|
}
|
|
}
|
|
|
|
if (b->hasCallPerSession) {
|
|
if (a->hasCallPerSession) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_OPTION_DUPLICATED, "CALLS_PER_SESSION");
|
|
} else {
|
|
a->hasCallPerSession = true;
|
|
a->callPerSession = b->callPerSession;
|
|
}
|
|
}
|
|
|
|
if (b->hasVnodePerCall) {
|
|
if (a->hasVnodePerCall) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_OPTION_DUPLICATED, "VNODES_PER_CALL");
|
|
} else {
|
|
a->hasVnodePerCall = true;
|
|
a->vnodePerCall = b->vnodePerCall;
|
|
}
|
|
}
|
|
|
|
if (b->hasFailedLoginAttempts) {
|
|
if (a->hasFailedLoginAttempts) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_OPTION_DUPLICATED, "FAILED_LOGIN_ATTEMPTS");
|
|
} else {
|
|
a->hasFailedLoginAttempts = true;
|
|
a->failedLoginAttempts = b->failedLoginAttempts;
|
|
}
|
|
}
|
|
|
|
if (b->hasPasswordLifeTime) {
|
|
if (a->hasPasswordLifeTime) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_OPTION_DUPLICATED, "PASSWORD_LIFE_TIME");
|
|
} else {
|
|
a->hasPasswordLifeTime = true;
|
|
a->passwordLifeTime = b->passwordLifeTime;
|
|
}
|
|
}
|
|
|
|
if (b->hasPasswordReuseTime) {
|
|
if (a->hasPasswordReuseTime) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_OPTION_DUPLICATED, "PASSWORD_REUSE_TIME");
|
|
} else {
|
|
a->hasPasswordReuseTime = true;
|
|
a->passwordReuseTime = b->passwordReuseTime;
|
|
}
|
|
}
|
|
|
|
if (b->hasPasswordReuseMax) {
|
|
if (a->hasPasswordReuseMax) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_OPTION_DUPLICATED, "PASSWORD_REUSE_MAX");
|
|
} else {
|
|
a->hasPasswordReuseMax = true;
|
|
a->passwordReuseMax = b->passwordReuseMax;
|
|
}
|
|
}
|
|
|
|
if (b->hasPasswordLockTime) {
|
|
if (a->hasPasswordLockTime) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_OPTION_DUPLICATED, "PASSWORD_LOCK_TIME");
|
|
} else {
|
|
a->hasPasswordLockTime = true;
|
|
a->passwordLockTime = b->passwordLockTime;
|
|
}
|
|
}
|
|
|
|
if (b->hasPasswordGraceTime) {
|
|
if (a->hasPasswordGraceTime) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_OPTION_DUPLICATED, "PASSWORD_GRACE_TIME");
|
|
} else {
|
|
a->hasPasswordGraceTime = true;
|
|
a->passwordGraceTime = b->passwordGraceTime;
|
|
}
|
|
}
|
|
|
|
if (b->hasInactiveAccountTime) {
|
|
if (a->hasInactiveAccountTime) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_OPTION_DUPLICATED, "INACTIVE_ACCOUNT_TIME");
|
|
} else {
|
|
a->hasInactiveAccountTime = true;
|
|
a->inactiveAccountTime = b->inactiveAccountTime;
|
|
}
|
|
}
|
|
|
|
if (b->hasAllowTokenNum) {
|
|
if (a->hasAllowTokenNum) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_OPTION_DUPLICATED, "ALLOW_TOKEN_NUM");
|
|
} else {
|
|
a->hasAllowTokenNum = true;
|
|
a->allowTokenNum = b->allowTokenNum;
|
|
}
|
|
}
|
|
|
|
if (b->pIpRanges != NULL) {
|
|
if (a->pIpRanges == NULL) {
|
|
a->pIpRanges = b->pIpRanges;
|
|
} else {
|
|
int32_t code = nodesListAppendList(a->pIpRanges, b->pIpRanges);
|
|
if (code != TSDB_CODE_SUCCESS) {
|
|
pCxt->errCode = code;
|
|
}
|
|
}
|
|
b->pIpRanges = NULL;
|
|
}
|
|
|
|
if (b->pDropIpRanges != NULL) {
|
|
if (a->pDropIpRanges == NULL) {
|
|
a->pDropIpRanges = b->pDropIpRanges;
|
|
} else {
|
|
int32_t code = nodesListAppendList(a->pDropIpRanges, b->pDropIpRanges);
|
|
if (code != TSDB_CODE_SUCCESS) {
|
|
pCxt->errCode = code;
|
|
}
|
|
}
|
|
b->pDropIpRanges = NULL;
|
|
}
|
|
|
|
if (b->pTimeRanges != NULL) {
|
|
if (a->pTimeRanges == NULL) {
|
|
a->pTimeRanges = b->pTimeRanges;
|
|
} else {
|
|
int32_t code = nodesListAppendList(a->pTimeRanges, b->pTimeRanges);
|
|
if (code != TSDB_CODE_SUCCESS) {
|
|
pCxt->errCode = code;
|
|
}
|
|
}
|
|
b->pTimeRanges = NULL;
|
|
}
|
|
|
|
if (b->pDropTimeRanges != NULL) {
|
|
if (a->pDropTimeRanges == NULL) {
|
|
a->pDropTimeRanges = b->pDropTimeRanges;
|
|
} else {
|
|
int32_t code = nodesListAppendList(a->pDropTimeRanges, b->pDropTimeRanges);
|
|
if (code != TSDB_CODE_SUCCESS) {
|
|
pCxt->errCode = code;
|
|
}
|
|
}
|
|
b->pDropTimeRanges = NULL;
|
|
}
|
|
|
|
nodesDestroyNode((SNode*)b);
|
|
return a;
|
|
}
|
|
|
|
|
|
|
|
void setUserOptionsTotpseed(SAstCreateContext* pCxt, SUserOptions* pUserOptions, const SToken* pTotpseed) {
|
|
pUserOptions->hasTotpseed = true;
|
|
|
|
if (pTotpseed == NULL) { // clear TOTP secret
|
|
memset(pUserOptions->totpseed, 0, sizeof(pUserOptions->totpseed));
|
|
return;
|
|
}
|
|
|
|
if (pTotpseed->n >= sizeof(pUserOptions->totpseed) * 2) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_OPTION_VALUE_TOO_LONG, "TOTPSEED", sizeof(pUserOptions->totpseed));
|
|
return;
|
|
}
|
|
|
|
char buf[sizeof(pUserOptions->totpseed) * 2 + 1];
|
|
memcpy(buf, pTotpseed->z, pTotpseed->n);
|
|
buf[pTotpseed->n] = 0;
|
|
(void)strdequote(buf);
|
|
size_t len = strtrim(buf);
|
|
|
|
if (len >= sizeof(pUserOptions->totpseed)) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_OPTION_VALUE_TOO_LONG, "TOTPSEED", sizeof(pUserOptions->totpseed));
|
|
} else if (len < TSDB_USER_TOTPSEED_MIN_LEN) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_OPTION_VALUE_TOO_SHORT, "TOTPSEED", TSDB_USER_TOTPSEED_MIN_LEN);
|
|
} else {
|
|
tstrncpy(pUserOptions->totpseed, buf, sizeof(pUserOptions->totpseed));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void setUserOptionsPassword(SAstCreateContext* pCxt, SUserOptions* pUserOptions, const SToken* pPassword) {
|
|
pUserOptions->hasPassword = true;
|
|
|
|
if (pPassword->n >= sizeof(pUserOptions->password) * 2) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_NAME_OR_PASSWD_TOO_LONG);
|
|
return;
|
|
}
|
|
|
|
char buf[sizeof(pUserOptions->password) * 2 + 1];
|
|
memcpy(buf, pPassword->z, pPassword->n);
|
|
buf[pPassword->n] = 0;
|
|
(void)strdequote(buf);
|
|
size_t len = strtrim(buf);
|
|
|
|
if (len >= sizeof(pUserOptions->password)) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_NAME_OR_PASSWD_TOO_LONG);
|
|
} else if (len < TSDB_PASSWORD_MIN_LEN) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_PASSWD_TOO_SHORT_OR_EMPTY);
|
|
} else {
|
|
tstrncpy(pUserOptions->password, buf, sizeof(pUserOptions->password));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static bool isValidUserOptions(SAstCreateContext* pCxt, const SUserOptions* opts) {
|
|
if (opts->hasEnable && (opts->enable < 0 || opts->enable > 1)) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_OPTION_VALUE, "ENABLE");
|
|
return false;
|
|
}
|
|
|
|
if (opts->hasSysinfo && (opts->sysinfo < 0 || opts->sysinfo > 1)) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_OPTION_VALUE, "SYSINFO");
|
|
return false;
|
|
}
|
|
|
|
if (opts->hasIsImport && (opts->isImport < 0 || opts->isImport > 1)) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_OPTION_VALUE, "IS_IMPORT");
|
|
return false;
|
|
}
|
|
|
|
if (opts->hasCreatedb && (opts->createdb < 0 || opts->createdb > 1)) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_OPTION_VALUE, "CREATEDB");
|
|
return false;
|
|
}
|
|
|
|
if (opts->hasTotpseed && opts->totpseed[0] != 0 && !taosIsComplexString(opts->totpseed)) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_OPTION_VALUE, "TOTPSEED");
|
|
return false;
|
|
}
|
|
|
|
if (opts->hasPassword && !isValidPassword(pCxt, opts->password, opts->hasIsImport && opts->isImport)) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_PASSWD);
|
|
return false;
|
|
}
|
|
|
|
if (opts->hasChangepass && (opts->changepass < 0 || opts->changepass > 2)) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_OPTION_VALUE, "CHANGEPASS");
|
|
return false;
|
|
}
|
|
|
|
if (opts->hasSessionPerUser && (opts->sessionPerUser < -1 || opts->sessionPerUser == 0)) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_OPTION_VALUE, "SESSION_PER_USER");
|
|
return false;
|
|
}
|
|
|
|
if (opts->hasConnectTime && (opts->connectTime < -1 || opts->connectTime == 0)) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_OPTION_VALUE, "CONNECT_TIME");
|
|
return false;
|
|
}
|
|
|
|
if (opts->hasConnectIdleTime && (opts->connectIdleTime < -1 || opts->connectIdleTime == 0)) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_OPTION_VALUE, "CONNECT_IDLE_TIME");
|
|
return false;
|
|
}
|
|
|
|
if (opts->hasCallPerSession && (opts->callPerSession < -1 || opts->callPerSession == 0)) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_OPTION_VALUE, "CALLS_PER_SESSION");
|
|
return false;
|
|
}
|
|
|
|
if (opts->hasVnodePerCall && (opts->vnodePerCall < -1 || opts->vnodePerCall == 0)) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_OPTION_VALUE, "VNODES_PER_CALL");
|
|
return false;
|
|
}
|
|
|
|
if (opts->hasFailedLoginAttempts && (opts->failedLoginAttempts < -1 || opts->failedLoginAttempts == 0)) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_OPTION_VALUE, "FAILED_LOGIN_ATTEMPTS");
|
|
return false;
|
|
}
|
|
|
|
if (opts->hasPasswordLockTime && (opts->passwordLockTime < -1 || opts->passwordLockTime == 0)) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_OPTION_VALUE, "PASSWORD_LOCK_TIME");
|
|
return false;
|
|
}
|
|
|
|
if (opts->hasPasswordLifeTime && (opts->passwordLifeTime < -1 || opts->passwordLifeTime == 0)) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_OPTION_VALUE, "PASSWORD_LIFE_TIME");
|
|
return false;
|
|
}
|
|
|
|
if (opts->hasPasswordGraceTime && (opts->passwordGraceTime < -1)) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_OPTION_VALUE, "PASSWORD_GRACE_TIME");
|
|
return false;
|
|
}
|
|
|
|
if (opts->hasPasswordReuseTime && (opts->passwordReuseTime < 0 || opts->passwordReuseTime > TSDB_USER_PASSWORD_REUSE_TIME_MAX)) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_OPTION_VALUE, "PASSWORD_REUSE_TIME");
|
|
return false;
|
|
}
|
|
|
|
if (opts->hasPasswordReuseMax && (opts->passwordReuseMax < 0 || opts->passwordReuseMax > TSDB_USER_PASSWORD_REUSE_MAX_MAX)) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_OPTION_VALUE, "PASSWORD_REUSE_MAX");
|
|
return false;
|
|
}
|
|
|
|
if (opts->hasInactiveAccountTime && (opts->inactiveAccountTime < -1 || opts->inactiveAccountTime == 0)) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_OPTION_VALUE, "INACTIVE_ACCOUNT_TIME");
|
|
return false;
|
|
}
|
|
|
|
if (opts->hasAllowTokenNum && opts->allowTokenNum < -1) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_OPTION_VALUE, "ALLOW_TOKEN_NUM");
|
|
return false;
|
|
}
|
|
|
|
// ip ranges and date time ranges has been validated during parsing
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
SNode* createCreateUserStmt(SAstCreateContext* pCxt, SToken* pUserName, SUserOptions* opts, bool ignoreExists) {
|
|
SCreateUserStmt* pStmt = NULL;
|
|
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
CHECK_NAME(checkUserName(pCxt, pUserName));
|
|
|
|
if (!isValidUserOptions(pCxt, opts)) {
|
|
goto _err;
|
|
}
|
|
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_CREATE_USER_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
COPY_STRING_FORM_ID_TOKEN(pStmt->userName, pUserName);
|
|
tstrncpy(pStmt->password, opts->password, sizeof(pStmt->password));
|
|
tstrncpy(pStmt->totpseed, opts->totpseed, sizeof(pStmt->totpseed));
|
|
|
|
pStmt->ignoreExists = ignoreExists;
|
|
pStmt->sysinfo = opts->sysinfo;
|
|
pStmt->createDb = opts->createdb;
|
|
pStmt->isImport = opts->isImport;
|
|
pStmt->changepass = opts->changepass;
|
|
pStmt->enable = opts->enable;
|
|
|
|
pStmt->sessionPerUser = opts->sessionPerUser;
|
|
pStmt->connectTime = opts->connectTime;
|
|
pStmt->connectIdleTime = opts->connectIdleTime;
|
|
pStmt->callPerSession = opts->callPerSession;
|
|
pStmt->vnodePerCall = opts->vnodePerCall;
|
|
pStmt->failedLoginAttempts = opts->failedLoginAttempts;
|
|
pStmt->passwordLifeTime = opts->passwordLifeTime;
|
|
pStmt->passwordReuseTime = opts->passwordReuseTime;
|
|
pStmt->passwordReuseMax = opts->passwordReuseMax;
|
|
pStmt->passwordLockTime = opts->passwordLockTime;
|
|
pStmt->passwordGraceTime = opts->passwordGraceTime;
|
|
pStmt->inactiveAccountTime = opts->inactiveAccountTime;
|
|
pStmt->allowTokenNum = opts->allowTokenNum;
|
|
|
|
pStmt->numIpRanges = LIST_LENGTH(opts->pIpRanges);
|
|
pStmt->pIpRanges = taosMemoryMalloc(pStmt->numIpRanges * sizeof(SIpRange));
|
|
CHECK_OUT_OF_MEM(pStmt->pIpRanges);
|
|
int i = 0;
|
|
SNode* pNode = NULL;
|
|
FOREACH(pNode, opts->pIpRanges) {
|
|
SIpRangeNode* node = (SIpRangeNode*)(pNode);
|
|
pStmt->pIpRanges[i++] = node->range;
|
|
}
|
|
|
|
pStmt->numTimeRanges = LIST_LENGTH(opts->pTimeRanges);
|
|
pStmt->pTimeRanges = taosMemoryMalloc(pStmt->numTimeRanges * sizeof(SDateTimeRange));
|
|
CHECK_OUT_OF_MEM(pStmt->pTimeRanges);
|
|
i = 0;
|
|
pNode = NULL;
|
|
FOREACH(pNode, opts->pTimeRanges) {
|
|
SDateTimeRangeNode* node = (SDateTimeRangeNode*)(pNode);
|
|
pStmt->pTimeRanges[i++] = node->range;
|
|
}
|
|
|
|
nodesDestroyNode((SNode*)opts);
|
|
return (SNode*)pStmt;
|
|
|
|
_err:
|
|
nodesDestroyNode((SNode*)pStmt);
|
|
nodesDestroyNode((SNode*)opts);
|
|
return NULL;
|
|
}
|
|
|
|
|
|
|
|
SNode* createAlterUserStmt(SAstCreateContext* pCxt, SToken* pUserName, SUserOptions* pUserOptions) {
|
|
SAlterUserStmt* pStmt = NULL;
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
CHECK_NAME(checkUserName(pCxt, pUserName));
|
|
if (!isValidUserOptions(pCxt, pUserOptions)) {
|
|
goto _err;
|
|
}
|
|
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_ALTER_USER_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
COPY_STRING_FORM_ID_TOKEN(pStmt->userName, pUserName);
|
|
pStmt->pUserOptions = pUserOptions;
|
|
return (SNode*)pStmt;
|
|
|
|
_err:
|
|
nodesDestroyNode((SNode*)pStmt);
|
|
nodesDestroyNode((SNode*)pUserOptions);
|
|
return NULL;
|
|
}
|
|
|
|
|
|
|
|
SNode* createDropUserStmt(SAstCreateContext* pCxt, SToken* pUserName, bool ignoreNotExists) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
CHECK_NAME(checkUserName(pCxt, pUserName));
|
|
SDropUserStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_DROP_USER_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
COPY_STRING_FORM_ID_TOKEN(pStmt->userName, pUserName);
|
|
pStmt->ignoreNotExists = ignoreNotExists;
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
static bool checkRoleName(SAstCreateContext* pCxt, SToken* pName, bool checkSysName) {
|
|
if (NULL == pName) {
|
|
pCxt->errCode = TSDB_CODE_PAR_SYNTAX_ERROR;
|
|
} else {
|
|
if (pName->n >= TSDB_ROLE_LEN) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_NAME_OR_PASSWD_TOO_LONG);
|
|
}
|
|
}
|
|
if (TSDB_CODE_SUCCESS == pCxt->errCode) {
|
|
trimEscape(pCxt, pName, true);
|
|
}
|
|
if (TSDB_CODE_SUCCESS == pCxt->errCode) {
|
|
if (checkSysName && taosStrncasecmp(pName->z, "sys", 3) == 0) { // system reserved role name prefix
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR,
|
|
"Cannot create/drop/alter roles with reserved prefix 'sys'");
|
|
}
|
|
}
|
|
return TSDB_CODE_SUCCESS == pCxt->errCode;
|
|
}
|
|
|
|
|
|
STokenOptions* createDefaultTokenOptions(SAstCreateContext* pCxt) {
|
|
STokenOptions* pOptions = NULL;
|
|
int32_t code = nodesMakeNode(QUERY_NODE_TOKEN_OPTIONS, (SNode**)&pOptions);
|
|
if (pOptions == NULL) {
|
|
pCxt->errCode = code;
|
|
return NULL;
|
|
}
|
|
|
|
pOptions->enable = 1;
|
|
pOptions->ttl = 0;
|
|
return pOptions;
|
|
}
|
|
|
|
|
|
|
|
STokenOptions* mergeTokenOptions(SAstCreateContext* pCxt, STokenOptions* a, STokenOptions* b) {
|
|
if (a == NULL && b == NULL) {
|
|
return createDefaultTokenOptions(pCxt);
|
|
}
|
|
if (b == NULL) {
|
|
return a;
|
|
}
|
|
if (a == NULL) {
|
|
return b;
|
|
}
|
|
|
|
if (b->hasEnable) {
|
|
if (a->hasEnable) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_OPTION_DUPLICATED, "ENABLE");
|
|
} else {
|
|
a->hasEnable = true;
|
|
a->enable = b->enable;
|
|
}
|
|
}
|
|
|
|
if (b->hasTtl) {
|
|
if (a->hasTtl) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_OPTION_DUPLICATED, "TTL");
|
|
} else {
|
|
a->hasTtl = true;
|
|
a->ttl = b->ttl;
|
|
}
|
|
}
|
|
|
|
if (b->hasProvider) {
|
|
if (a->hasProvider) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_OPTION_DUPLICATED, "PROVIDER");
|
|
} else {
|
|
a->hasProvider = true;
|
|
tstrncpy(a->provider, b->provider, sizeof(a->provider));
|
|
}
|
|
}
|
|
|
|
if (b->hasExtraInfo) {
|
|
if (a->hasExtraInfo) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_OPTION_DUPLICATED, "EXTRA_INFO");
|
|
} else {
|
|
a->hasExtraInfo = true;
|
|
tstrncpy(a->extraInfo, b->extraInfo, sizeof(a->extraInfo));
|
|
}
|
|
}
|
|
nodesDestroyNode((SNode*)b);
|
|
return a;
|
|
}
|
|
|
|
|
|
|
|
void setTokenOptionsProvider(SAstCreateContext* pCxt, STokenOptions* pTokenOptions, const SToken* pProvider) {
|
|
pTokenOptions->hasProvider = true;
|
|
|
|
if (pProvider->n >= sizeof(pTokenOptions->provider) * 2) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_OPTION_VALUE_TOO_LONG, "PROVIDER", sizeof(pTokenOptions->provider));
|
|
return;
|
|
}
|
|
|
|
char buf[sizeof(pTokenOptions->provider) * 2 + 1];
|
|
memcpy(buf, pProvider->z, pProvider->n);
|
|
buf[pProvider->n] = 0;
|
|
(void)strdequote(buf);
|
|
size_t len = strtrim(buf);
|
|
|
|
if (len >= sizeof(pTokenOptions->provider)) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_OPTION_VALUE_TOO_LONG, "PROVIDER", sizeof(pTokenOptions->provider));
|
|
} else {
|
|
tstrncpy(pTokenOptions->provider, buf, sizeof(pTokenOptions->provider));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void setTokenOptionsExtraInfo(SAstCreateContext* pCxt, STokenOptions* pTokenOptions, const SToken* pExtraInfo) {
|
|
pTokenOptions->hasExtraInfo = true;
|
|
|
|
if (pExtraInfo->n >= sizeof(pTokenOptions->extraInfo) * 2) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_OPTION_VALUE_TOO_LONG, "EXTRA_INFO", sizeof(pTokenOptions->extraInfo));
|
|
return;
|
|
}
|
|
|
|
char buf[sizeof(pTokenOptions->extraInfo) * 2 + 1];
|
|
memcpy(buf, pExtraInfo->z, pExtraInfo->n);
|
|
buf[pExtraInfo->n] = 0;
|
|
(void)strdequote(buf);
|
|
size_t len = strtrim(buf);
|
|
|
|
if (len >= sizeof(pTokenOptions->extraInfo)) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_OPTION_VALUE_TOO_LONG, "EXTRA_INFO", sizeof(pTokenOptions->extraInfo));
|
|
} else {
|
|
tstrncpy(pTokenOptions->extraInfo, buf, sizeof(pTokenOptions->extraInfo));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static bool isValidTokenOptions(SAstCreateContext* pCxt, const STokenOptions* opts) {
|
|
if (opts->hasEnable && (opts->enable < 0 || opts->enable > 1)) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_OPTION_VALUE, "ENABLE");
|
|
return false;
|
|
}
|
|
|
|
if (opts->hasTtl && (opts->ttl < 0)) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_OPTION_VALUE, "TTL");
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
static bool checkTokenName(SAstCreateContext* pCxt, SToken* pTokenName) {
|
|
if (NULL == pTokenName) {
|
|
pCxt->errCode = TSDB_CODE_PAR_SYNTAX_ERROR;
|
|
} else {
|
|
if (pTokenName->n >= TSDB_TOKEN_NAME_LEN) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_OPTION_VALUE_TOO_LONG, "TOKEN_NAME", TSDB_TOKEN_NAME_LEN);
|
|
}
|
|
}
|
|
if (TSDB_CODE_SUCCESS == pCxt->errCode) {
|
|
trimEscape(pCxt, pTokenName, true);
|
|
}
|
|
return TSDB_CODE_SUCCESS == pCxt->errCode;
|
|
}
|
|
|
|
SNode* createCreateRoleStmt(SAstCreateContext* pCxt, bool ignoreExists, SToken* pName) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
CHECK_NAME(checkRoleName(pCxt, pName, true));
|
|
SCreateRoleStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_CREATE_ROLE_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
COPY_STRING_FORM_ID_TOKEN(pStmt->name, pName);
|
|
pStmt->ignoreExists = ignoreExists;
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createDropRoleStmt(SAstCreateContext* pCxt, bool ignoreNotExists, SToken* pName) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
CHECK_NAME(checkRoleName(pCxt, pName, true));
|
|
SDropRoleStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_DROP_ROLE_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
COPY_STRING_FORM_ID_TOKEN(pStmt->name, pName);
|
|
pStmt->ignoreNotExists = ignoreNotExists;
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
* used by user and role
|
|
*/
|
|
SNode* createAlterRoleStmt(SAstCreateContext* pCxt, SToken* pName, int8_t alterType, void* pAlterInfo) {
|
|
SAlterRoleStmt* pStmt = NULL;
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
CHECK_NAME(checkUserName(pCxt, pName));
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_ALTER_ROLE_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
COPY_STRING_FORM_ID_TOKEN(pStmt->name, pName);
|
|
pStmt->alterType = alterType;
|
|
switch (alterType) {
|
|
case TSDB_ALTER_ROLE_LOCK: {
|
|
SToken* pVal = pAlterInfo;
|
|
pStmt->lock = taosStr2Int8(pVal->z, NULL, 10);
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
nodesDestroyNode((SNode*)pStmt);
|
|
return NULL;
|
|
}
|
|
|
|
|
|
SNode* createCreateTokenStmt(SAstCreateContext* pCxt, SToken* pTokenName, SToken* pUserName, STokenOptions* opts, bool ignoreExists) {
|
|
SCreateTokenStmt* pStmt = NULL;
|
|
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
CHECK_NAME(checkTokenName(pCxt, pTokenName));
|
|
CHECK_NAME(checkUserName(pCxt, pUserName));
|
|
|
|
if (opts == NULL) {
|
|
opts = createDefaultTokenOptions(pCxt);
|
|
} else if (!isValidTokenOptions(pCxt, opts)) {
|
|
goto _err;
|
|
}
|
|
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_CREATE_TOKEN_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
|
|
COPY_STRING_FORM_ID_TOKEN(pStmt->name, pTokenName);
|
|
COPY_STRING_FORM_ID_TOKEN(pStmt->user, pUserName);
|
|
pStmt->enable = opts->enable;
|
|
pStmt->ignoreExists = ignoreExists;
|
|
pStmt->ttl = opts->ttl;
|
|
tstrncpy(pStmt->provider, opts->provider, sizeof(pStmt->provider));
|
|
tstrncpy(pStmt->extraInfo, opts->extraInfo, sizeof(pStmt->extraInfo));
|
|
nodesDestroyNode((SNode*)opts);
|
|
return (SNode*)pStmt;
|
|
|
|
_err:
|
|
nodesDestroyNode((SNode*)pStmt);
|
|
nodesDestroyNode((SNode*)opts);
|
|
return NULL;
|
|
}
|
|
|
|
|
|
|
|
SNode* createAlterTokenStmt(SAstCreateContext* pCxt, SToken* pTokenName, STokenOptions* opts) {
|
|
SAlterTokenStmt* pStmt = NULL;
|
|
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
CHECK_NAME(checkTokenName(pCxt, pTokenName));
|
|
if (!isValidTokenOptions(pCxt, opts)) {
|
|
goto _err;
|
|
}
|
|
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_ALTER_TOKEN_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
|
|
COPY_STRING_FORM_ID_TOKEN(pStmt->name, pTokenName);
|
|
pStmt->pTokenOptions = opts;
|
|
return (SNode*)pStmt;
|
|
|
|
_err:
|
|
nodesDestroyNode((SNode*)pStmt);
|
|
nodesDestroyNode((SNode*)opts);
|
|
return NULL;
|
|
}
|
|
|
|
|
|
|
|
SNode* createDropTokenStmt(SAstCreateContext* pCxt, SToken* pTokenName, bool ignoreNotExists) {
|
|
SDropTokenStmt* pStmt = NULL;
|
|
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
CHECK_NAME(checkTokenName(pCxt, pTokenName));
|
|
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_DROP_TOKEN_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
|
|
COPY_STRING_FORM_ID_TOKEN(pStmt->name, pTokenName);
|
|
pStmt->ignoreNotExists = ignoreNotExists;
|
|
return (SNode*)pStmt;
|
|
|
|
_err:
|
|
nodesDestroyNode((SNode*)pStmt);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createCreateTotpSecretStmt(SAstCreateContext* pCxt, SToken* pUserName) {
|
|
SCreateTotpSecretStmt* pStmt = NULL;
|
|
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
CHECK_NAME(checkUserName(pCxt, pUserName));
|
|
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_CREATE_TOTP_SECRET_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
|
|
COPY_STRING_FORM_ID_TOKEN(pStmt->user, pUserName);
|
|
return (SNode*)pStmt;
|
|
|
|
_err:
|
|
nodesDestroyNode((SNode*)pStmt);
|
|
return NULL;
|
|
}
|
|
|
|
|
|
SNode* createDropTotpSecretStmt(SAstCreateContext* pCxt, SToken* pUserName) {
|
|
SDropTotpSecretStmt* pStmt = NULL;
|
|
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
CHECK_NAME(checkUserName(pCxt, pUserName));
|
|
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_DROP_TOTP_SECRET_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
|
|
COPY_STRING_FORM_ID_TOKEN(pStmt->user, pUserName);
|
|
return (SNode*)pStmt;
|
|
|
|
_err:
|
|
nodesDestroyNode((SNode*)pStmt);
|
|
return NULL;
|
|
}
|
|
|
|
|
|
SNode* createDropEncryptAlgrStmt(SAstCreateContext* pCxt, SToken* algorithmId) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
if (algorithmId->n >= TSDB_ENCRYPT_ALGR_NAME_LEN) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_ALGR_ID_TOO_LONG);
|
|
goto _err;
|
|
}
|
|
SDropEncryptAlgrStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_DROP_ENCRYPT_ALGR_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
(void)trimString(algorithmId->z, algorithmId->n, pStmt->algorithmId, sizeof(pStmt->algorithmId));
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createCreateDnodeStmt(SAstCreateContext* pCxt, const SToken* pFqdn, const SToken* pPort) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SCreateDnodeStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_CREATE_DNODE_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
if (!checkAndSplitEndpoint(pCxt, pFqdn, pPort, pStmt->fqdn, &pStmt->port)) {
|
|
nodesDestroyNode((SNode*)pStmt);
|
|
return NULL;
|
|
}
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createDropDnodeStmt(SAstCreateContext* pCxt, const SToken* pDnode, bool force, bool unsafe) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SDropDnodeStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_DROP_DNODE_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
if (TK_NK_INTEGER == pDnode->type) {
|
|
pStmt->dnodeId = taosStr2Int32(pDnode->z, NULL, 10);
|
|
} else {
|
|
if (!checkAndSplitEndpoint(pCxt, pDnode, NULL, pStmt->fqdn, &pStmt->port)) {
|
|
nodesDestroyNode((SNode*)pStmt);
|
|
return NULL;
|
|
}
|
|
}
|
|
pStmt->force = force;
|
|
pStmt->unsafe = unsafe;
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createAlterDnodeStmt(SAstCreateContext* pCxt, const SToken* pDnode, const SToken* pConfig,
|
|
const SToken* pValue) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SAlterDnodeStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_ALTER_DNODE_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
if (NULL != pDnode) {
|
|
pStmt->dnodeId = taosStr2Int32(pDnode->z, NULL, 10);
|
|
} else {
|
|
pStmt->dnodeId = -1;
|
|
}
|
|
(void)trimString(pConfig->z, pConfig->n, pStmt->config, sizeof(pStmt->config));
|
|
if (NULL != pValue) {
|
|
(void)trimString(pValue->z, pValue->n, pStmt->value, sizeof(pStmt->value));
|
|
}
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createCreateAlgrStmt(SAstCreateContext* pCxt, SToken* algorithmId, const SToken* name, const SToken* desc,
|
|
const SToken* type, const SToken* osslAlgrName) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SCreateEncryptAlgrStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_CREATE_ENCRYPT_ALGORITHMS_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
if (algorithmId->n >= TSDB_ENCRYPT_ALGR_NAME_LEN) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_ALGR_ID_TOO_LONG);
|
|
goto _err;
|
|
}
|
|
if (name->n >= TSDB_ENCRYPT_ALGR_NAME_LEN) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_ALGR_NAME_TOO_LONG);
|
|
goto _err;
|
|
}
|
|
if (desc->n >= TSDB_ENCRYPT_ALGR_DESC_LEN) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_ALGR_DESC_TOO_LONG);
|
|
goto _err;
|
|
}
|
|
if (type->n >= TSDB_ENCRYPT_ALGR_TYPE_LEN) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_ALGR_TYPE_TOO_LONG);
|
|
goto _err;
|
|
}
|
|
if (osslAlgrName->n >= TSDB_ENCRYPT_ALGR_NAME_LEN) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_ALGR_OSSL_NAME_TOO_LONG);
|
|
goto _err;
|
|
}
|
|
(void)trimString(algorithmId->z, algorithmId->n, pStmt->algorithmId, sizeof(pStmt->algorithmId));
|
|
(void)trimString(name->z, name->n, pStmt->name, sizeof(pStmt->name));
|
|
(void)trimString(desc->z, desc->n, pStmt->desc, sizeof(pStmt->desc));
|
|
(void)trimString(type->z, type->n, pStmt->algrType, sizeof(pStmt->algrType));
|
|
(void)trimString(osslAlgrName->z, osslAlgrName->n, pStmt->osslAlgrName, sizeof(pStmt->osslAlgrName));
|
|
return (SNode*)pStmt;
|
|
_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* createCreateBnodeStmt(SAstCreateContext* pCxt, const SToken* pDnodeId, SNode* pOptions) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SCreateBnodeStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_CREATE_BNODE_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
pStmt->dnodeId = taosStr2Int32(pDnodeId->z, NULL, 10);
|
|
|
|
pStmt->pOptions = (SBnodeOptions*)pOptions;
|
|
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createDropBnodeStmt(SAstCreateContext* pCxt, const SToken* pDnodeId) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SUpdateBnodeStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_DROP_BNODE_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
pStmt->dnodeId = taosStr2Int32(pDnodeId->z, NULL, 10);
|
|
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createDefaultBnodeOptions(SAstCreateContext* pCxt) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SBnodeOptions* pOptions = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_BNODE_OPTIONS, (SNode**)&pOptions);
|
|
CHECK_MAKE_NODE(pOptions);
|
|
|
|
tstrncpy(pOptions->protoStr, TSDB_BNODE_OPT_PROTO_DFT_STR, TSDB_BNODE_OPT_PROTO_STR_LEN);
|
|
pOptions->proto = TSDB_BNODE_OPT_PROTO_DEFAULT;
|
|
|
|
return (SNode*)pOptions;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
static SNode* setBnodeOptionImpl(SAstCreateContext* pCxt, SNode* pBodeOptions, EBnodeOptionType type, void* pVal,
|
|
bool alter) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SBnodeOptions* pOptions = (SBnodeOptions*)pBodeOptions;
|
|
switch (type) {
|
|
case BNODE_OPTION_PROTOCOL:
|
|
COPY_STRING_FORM_STR_TOKEN(pOptions->protoStr, (SToken*)pVal);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return pBodeOptions;
|
|
_err:
|
|
nodesDestroyNode(pBodeOptions);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* setBnodeOption(SAstCreateContext* pCxt, SNode* pOptions, const SToken* pOption, void* pVal) {
|
|
if (0 == strncasecmp(pOption->z, "protocol", 8)) {
|
|
return setBnodeOptionImpl(pCxt, pOptions, BNODE_OPTION_PROTOCOL, pVal, false);
|
|
} else {
|
|
pCxt->errCode = TSDB_CODE_PAR_SYNTAX_ERROR;
|
|
return pOptions;
|
|
}
|
|
}
|
|
|
|
SNode* createCreateXnodeWithTokenStmt(SAstCreateContext* pCxt, const SToken* pUrl, SToken* pToken) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SCreateXnodeStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_CREATE_XNODE_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
|
|
(void)trimString(pUrl->z, pUrl->n, pStmt->url, sizeof(pStmt->url));
|
|
|
|
if (pToken != NULL) {
|
|
if (pToken->n <= 2) {
|
|
pCxt->errCode =
|
|
generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, "Xnode token should not be empty");
|
|
goto _err;
|
|
}
|
|
if (pToken->n > TSDB_TOKEN_LEN + 2) {
|
|
pCxt->errCode =
|
|
generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, "Xnode token length is illegal");
|
|
goto _err;
|
|
}
|
|
strncpy(pStmt->token, pToken->z + 1, pToken->n - 2);
|
|
pStmt->token[sizeof(pStmt->token) - 1] = '\0';
|
|
}
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createCreateXnodeWithUserPassStmt(SAstCreateContext* pCxt, const SToken* pUrl, SToken* pUser,
|
|
const SToken* pPass) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SCreateXnodeStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_CREATE_XNODE_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
|
|
(void)trimString(pUrl->z, pUrl->n, pStmt->url, sizeof(pStmt->url));
|
|
|
|
if (pUser != NULL) {
|
|
CHECK_NAME(checkUserName(pCxt, pUser));
|
|
COPY_STRING_FORM_ID_TOKEN(pStmt->user, pUser);
|
|
}
|
|
if (pPass != NULL) {
|
|
if (pPass->n <= 2) {
|
|
pCxt->errCode =
|
|
generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, "Xnode password should not be empty");
|
|
goto _err;
|
|
}
|
|
strncpy(pStmt->pass, pPass->z + 1, pPass->n - 2);
|
|
pStmt->pass[sizeof(pStmt->pass) - 1] = '\0';
|
|
}
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
SNode* createCreateXnodeStmt(SAstCreateContext* pCxt, const SToken* pUrl) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SCreateXnodeStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_CREATE_XNODE_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* createDropXnodeStmt(SAstCreateContext* pCxt, const SToken* pXnode, bool force) {
|
|
if (NULL == pXnode) {
|
|
pCxt->errCode =
|
|
generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, "xnode id should not be NULL or empty");
|
|
goto _err;
|
|
}
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SDropXnodeStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_DROP_XNODE_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
|
|
pStmt->force = force;
|
|
if (pXnode->type == TK_NK_STRING) {
|
|
if (pXnode->n <= 2) {
|
|
pCxt->errCode =
|
|
generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, "xnode url should not be all be NULL");
|
|
goto _err;
|
|
}
|
|
COPY_STRING_FORM_STR_TOKEN(pStmt->url, pXnode);
|
|
} else if(pXnode->type == TK_NK_INTEGER) {
|
|
pStmt->xnodeId = taosStr2Int32(pXnode->z, NULL, 10);
|
|
} else {
|
|
pCxt->errCode =
|
|
generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, "xnode id or url should not be all be NULL");
|
|
}
|
|
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createDrainXnodeStmt(SAstCreateContext* pCxt, const SToken* pXnode) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
if (NULL == pXnode) {
|
|
pCxt->errCode =
|
|
generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, "xnode id should not be NULL or empty");
|
|
goto _err;
|
|
}
|
|
if (pXnode->type != TK_NK_INTEGER) {
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, "xnode id should be an integer");
|
|
goto _err;
|
|
}
|
|
|
|
SDrainXnodeStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_DRAIN_XNODE_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
pStmt->xnodeId = taosStr2Int32(pXnode->z, NULL, 10);
|
|
if (pStmt->xnodeId <= 0) {
|
|
pCxt->errCode =
|
|
generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, "xnode id should be greater than 0");
|
|
goto _err;
|
|
}
|
|
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createAlterXnodeStmt(SAstCreateContext* pCxt, const SToken* pToken, const SToken* pUser, const SToken* pPass) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SAlterXnodeStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_ALTER_XNODE_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
if (pToken != NULL) {
|
|
pStmt->token = xCreateCowStr(pToken->n - 2, pToken->z + 1, true);
|
|
}
|
|
if (pUser != NULL && pPass != NULL) {
|
|
if (pUser->n <= 2) {
|
|
pCxt->errCode =
|
|
generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, "xnode user should not be NULL or empty");
|
|
goto _err;
|
|
}
|
|
if (pPass->n <= 2) {
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR,
|
|
"xnode password should not be NULL or empty");
|
|
goto _err;
|
|
}
|
|
char buf[TSDB_XNODE_RESOURCE_NAME_LEN + 1] = {0};
|
|
COPY_COW_STR_FROM_ID_TOKEN(pStmt->user, pUser);
|
|
pStmt->pass = xCreateCowStr(pPass->n - 2, pPass->z + 1, true);
|
|
}
|
|
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
nodesDestroyNode((SNode*)pStmt);
|
|
return NULL;
|
|
}
|
|
|
|
EXnodeResourceType setXnodeResourceType(SAstCreateContext* pCxt, const SToken* pResourceId) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
const size_t TASK_LEN = 4;
|
|
const size_t TASKS_LEN = 5;
|
|
const size_t AGENT_LEN = 5;
|
|
const size_t AGENTS_LEN = 6;
|
|
const size_t JOB_LEN = 3;
|
|
const size_t JOBS_LEN = 4;
|
|
|
|
if (pResourceId->z[0] == '`') {
|
|
if (strncmp(pResourceId->z + 1, "task", TASK_LEN) == 0 || strncmp(pResourceId->z + 1, "tasks", TASKS_LEN) == 0) {
|
|
return XNODE_TASK;
|
|
}
|
|
if (strncmp(pResourceId->z + 1, "agent", AGENT_LEN) == 0 ||
|
|
strncmp(pResourceId->z + 1, "agents", AGENTS_LEN) == 0) {
|
|
return XNODE_AGENT;
|
|
}
|
|
if (strncmp(pResourceId->z + 1, "job", JOB_LEN) == 0 || strncmp(pResourceId->z + 1, "jobs", JOBS_LEN) == 0) {
|
|
return XNODE_JOB;
|
|
}
|
|
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR,
|
|
"Invalid xnode resource type (task/agent) at: %s", pResourceId->z);
|
|
goto _err;
|
|
}
|
|
if (strncmp(pResourceId->z, "task", TASK_LEN) == 0 || strncmp(pResourceId->z, "tasks", TASKS_LEN) == 0) {
|
|
return XNODE_TASK;
|
|
}
|
|
if (strncmp(pResourceId->z, "agent", AGENT_LEN) == 0 || strncmp(pResourceId->z, "agents", AGENTS_LEN) == 0) {
|
|
return XNODE_AGENT;
|
|
}
|
|
if (strncmp(pResourceId->z, "job", JOB_LEN) == 0 || strncmp(pResourceId->z, "jobs", JOBS_LEN) == 0) {
|
|
return XNODE_JOB;
|
|
}
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR,
|
|
"Invalid xnode resource type (task/agent/job) at: %s", pResourceId->z);
|
|
goto _err;
|
|
|
|
_err:
|
|
return XNODE_UNKNOWN;
|
|
}
|
|
SNode* createXnodeSourceAsDsn(SAstCreateContext* pCxt, const SToken* pToken) {
|
|
SXTaskSource* pSource = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_XNODE_TASK_SOURCE_OPT, (SNode**)&pSource);
|
|
CHECK_MAKE_NODE(pSource);
|
|
if (pToken == NULL || pToken->n <= 0) {
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR,
|
|
"xnode source dsn should not be NULL or empty");
|
|
goto _err;
|
|
}
|
|
if (pToken->n > TSDB_XNODE_TASK_SOURCE_LEN) {
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR,
|
|
"Invalid xnode source dsn length: %d, max length: %d", pToken->n,
|
|
TSDB_XNODE_TASK_SOURCE_LEN);
|
|
goto _err;
|
|
}
|
|
pSource->source.type = XNODE_TASK_SOURCE_DSN;
|
|
COPY_COW_STR_FROM_STR_TOKEN(pSource->source.cstr, pToken);
|
|
return (SNode*)pSource;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
SNode* createXnodeSourceAsDatabase(SAstCreateContext* pCxt, const SToken* pToken) {
|
|
SXTaskSource* pSource = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_XNODE_TASK_SOURCE_OPT, (SNode**)&pSource);
|
|
CHECK_MAKE_NODE(pSource);
|
|
if (pToken == NULL || pToken->n <= 0) {
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR,
|
|
"xnode source database should not be NULL or empty");
|
|
goto _err;
|
|
}
|
|
if (pToken->n > TSDB_XNODE_TASK_SOURCE_LEN) {
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR,
|
|
"Invalid xnode source database length: %d, max length: %d", pToken->n,
|
|
TSDB_XNODE_TASK_SOURCE_LEN);
|
|
goto _err;
|
|
}
|
|
pSource->source.type = XNODE_TASK_SOURCE_DATABASE;
|
|
COPY_COW_STR_FROM_ID_TOKEN(pSource->source.cstr, pToken);
|
|
return (SNode*)pSource;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
SNode* createXnodeSourceAsTopic(SAstCreateContext* pCxt, const SToken* pToken) {
|
|
SXTaskSource* pSource = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_XNODE_TASK_SOURCE_OPT, (SNode**)&pSource);
|
|
CHECK_MAKE_NODE(pSource);
|
|
if (pToken == NULL || pToken->n <= 0) {
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR,
|
|
"xnode source dsn should not be NULL or empty");
|
|
goto _err;
|
|
}
|
|
if (pToken->n > TSDB_TOPIC_NAME_LEN) {
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR,
|
|
"Invalid xnode source topic length: %d, max length: %d", pToken->n,
|
|
TSDB_TOPIC_NAME_LEN);
|
|
goto _err;
|
|
}
|
|
pSource->source.type = XNODE_TASK_SOURCE_TOPIC;
|
|
COPY_COW_STR_FROM_STR_TOKEN(pSource->source.cstr, pToken);
|
|
return (SNode*)pSource;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
SNode* createXnodeSinkAsDsn(SAstCreateContext* pCxt, const SToken* pToken) {
|
|
SXTaskSink* pSink = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_XNODE_TASK_SINK_OPT, (SNode**)&pSink);
|
|
CHECK_MAKE_NODE(pSink);
|
|
if (pToken == NULL || pToken->n <= 0) {
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR,
|
|
"xnode sink dsn should not be NULL or empty");
|
|
goto _err;
|
|
}
|
|
if (pToken->n > TSDB_XNODE_TASK_SINK_LEN) {
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR,
|
|
"Invalid xnode sink dsn length: %d, max length: %d", pToken->n,
|
|
TSDB_XNODE_TASK_SINK_LEN);
|
|
goto _err;
|
|
}
|
|
pSink->sink.type = XNODE_TASK_SINK_DSN;
|
|
COPY_COW_STR_FROM_STR_TOKEN(pSink->sink.cstr, pToken);
|
|
return (SNode*)pSink;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
SNode* createXnodeSinkAsDatabase(SAstCreateContext* pCxt, const SToken* pToken) {
|
|
SXTaskSink* pSink = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_XNODE_TASK_SINK_OPT, (SNode**)&pSink);
|
|
CHECK_MAKE_NODE(pSink);
|
|
if (pToken == NULL || pToken->n <= 0) {
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR,
|
|
"Xnode sink database should not be NULL or empty");
|
|
goto _err;
|
|
}
|
|
if (pToken->n > TSDB_XNODE_TASK_SINK_LEN) {
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR,
|
|
"Invalid xnode sink database length: %d, max length: %d", pToken->n,
|
|
TSDB_XNODE_TASK_SINK_LEN);
|
|
goto _err;
|
|
}
|
|
pSink->sink.type = XNODE_TASK_SINK_DATABASE;
|
|
if (pToken->type == TK_NK_STRING) {
|
|
COPY_COW_STR_FROM_STR_TOKEN(pSink->sink.cstr, pToken);
|
|
} else if (pToken->type == TK_NK_ID) {
|
|
COPY_COW_STR_FROM_ID_TOKEN(pSink->sink.cstr, pToken);
|
|
} else {
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR,
|
|
"Invalid xnode sink database type: %d", pToken->type);
|
|
goto _err;
|
|
}
|
|
|
|
return (SNode*)pSink;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createXnodeTaskWithOptionsDirectly(SAstCreateContext* pCxt, const SToken* pResourceName, SNode* pSource,
|
|
SNode* pSink, SNode* pNode) {
|
|
SNode* pStmt = NULL;
|
|
if (pResourceName == NULL) {
|
|
pCxt->errCode =
|
|
generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, "Xnode task name should not be NULL");
|
|
goto _err;
|
|
}
|
|
if (pSource == NULL || pSink == NULL) {
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR,
|
|
"Xnode task source and sink should not be NULL");
|
|
goto _err;
|
|
}
|
|
if (nodeType(pSource) != QUERY_NODE_XNODE_TASK_SOURCE_OPT || nodeType(pSink) != QUERY_NODE_XNODE_TASK_SINK_OPT) {
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR,
|
|
"Xnode task source and sink should be valid nodes");
|
|
goto _err;
|
|
}
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_CREATE_XNODE_TASK_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
SCreateXnodeTaskStmt* pTaskStmt = (SCreateXnodeTaskStmt*)pStmt;
|
|
if (pResourceName->type == TK_NK_STRING) {
|
|
COPY_STRING_FORM_STR_TOKEN(pTaskStmt->name, pResourceName);
|
|
} else if (pResourceName->type == TK_NK_ID) {
|
|
COPY_STRING_FORM_STR_TOKEN(pTaskStmt->name, pResourceName);
|
|
} else {
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, "Invalid xnode name type: %d",
|
|
pResourceName->type);
|
|
goto _err;
|
|
}
|
|
|
|
if (pSource != NULL) {
|
|
SXTaskSource* source = (SXTaskSource*)(pSource);
|
|
pTaskStmt->source = source;
|
|
}
|
|
if (pSink != NULL) {
|
|
SXTaskSink* sink = (SXTaskSink*)(pSink);
|
|
pTaskStmt->sink = sink;
|
|
}
|
|
if (pNode != NULL) {
|
|
if (nodeType(pNode) == QUERY_NODE_XNODE_TASK_OPTIONS) {
|
|
SXnodeTaskOptions* options = (SXnodeTaskOptions*)(pNode);
|
|
pTaskStmt->options = options;
|
|
}
|
|
}
|
|
return (SNode*)pTaskStmt;
|
|
_err:
|
|
if (pStmt != NULL) {
|
|
nodesDestroyNode(pStmt);
|
|
}
|
|
if (pNode != NULL) {
|
|
nodesDestroyNode(pNode);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createXnodeAgentWithOptionsDirectly(SAstCreateContext* pCxt, const SToken* pResourceName, SNode* pOptions) {
|
|
SNode* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_CREATE_XNODE_AGENT_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
SCreateXnodeAgentStmt* pAgentStmt = (SCreateXnodeAgentStmt*)pStmt;
|
|
|
|
if (pOptions != NULL) {
|
|
if (nodeType(pOptions) == QUERY_NODE_XNODE_TASK_OPTIONS) {
|
|
SXnodeTaskOptions* options = (SXnodeTaskOptions*)(pOptions);
|
|
pAgentStmt->options = options;
|
|
}
|
|
}
|
|
|
|
if (pResourceName->type == TK_NK_STRING && pResourceName->n > 2) {
|
|
COPY_STRING_FORM_STR_TOKEN(pAgentStmt->name, pResourceName);
|
|
} else {
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR,
|
|
"Invalid xnode agent name type: %d", pResourceName->type);
|
|
goto _err;
|
|
}
|
|
|
|
return (SNode*)pAgentStmt;
|
|
_err:
|
|
if (pStmt != NULL) {
|
|
nodesDestroyNode(pStmt);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createXnodeTaskWithOptions(SAstCreateContext* pCxt, EXnodeResourceType resourceType, const SToken* pResourceName,
|
|
SNode* pSource, SNode* pSink, SNode* pOptions) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
|
|
switch (resourceType) {
|
|
case XNODE_TASK: {
|
|
return createXnodeTaskWithOptionsDirectly(pCxt, pResourceName, pSource, pSink, pOptions);
|
|
}
|
|
case XNODE_AGENT: {
|
|
return createXnodeAgentWithOptionsDirectly(pCxt, pResourceName, pOptions);
|
|
break;
|
|
}
|
|
default:
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR,
|
|
"Invalid xnode resource type: %d", resourceType);
|
|
goto _err;
|
|
}
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createStartXnodeTaskStmt(SAstCreateContext* pCxt, const EXnodeResourceType resourceType, SToken* pIdOrName) {
|
|
SNode* pStmt = NULL;
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
if (resourceType != XNODE_TASK) {
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR,
|
|
"Invalid xnode resource type: %d", resourceType);
|
|
goto _err;
|
|
}
|
|
if (pIdOrName == NULL || (pIdOrName != NULL && pIdOrName->type != TK_NK_INTEGER && pIdOrName->type != TK_NK_STRING)) {
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR,
|
|
"Xnode task id or name should be an integer or string");
|
|
goto _err;
|
|
}
|
|
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_START_XNODE_TASK_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
SStartXnodeTaskStmt* pTaskStmt = (SStartXnodeTaskStmt*)pStmt;
|
|
if (pIdOrName->type == TK_NK_INTEGER) {
|
|
pTaskStmt->tid = taosStr2Int32(pIdOrName->z, NULL, 10);
|
|
if (pTaskStmt->tid <= 0) {
|
|
pCxt->errCode =
|
|
generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, "Task id should be greater than 0");
|
|
goto _err;
|
|
}
|
|
} else {
|
|
if (pIdOrName->n > TSDB_XNODE_RESOURCE_NAME_LEN + 2) {
|
|
pCxt->errCode =
|
|
generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR,
|
|
"Xnode task name should be less than %d characters", TSDB_XNODE_RESOURCE_NAME_LEN);
|
|
goto _err;
|
|
}
|
|
char buf[TSDB_XNODE_RESOURCE_NAME_LEN + 1] = {0};
|
|
COPY_STRING_FORM_STR_TOKEN(buf, pIdOrName);
|
|
pTaskStmt->name = xCreateCowStr(strlen(buf), buf, true);
|
|
}
|
|
|
|
return (SNode*)pTaskStmt;
|
|
_err:
|
|
if (pStmt != NULL) {
|
|
nodesDestroyNode(pStmt);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createStopXnodeTaskStmt(SAstCreateContext* pCxt, const EXnodeResourceType resourceType, SToken* pIdOrName) {
|
|
SNode* pStmt = NULL;
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
if (resourceType != XNODE_TASK) {
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR,
|
|
"Only support stop task, invalid resource type: %d", resourceType);
|
|
goto _err;
|
|
}
|
|
if (pIdOrName != NULL && pIdOrName->type != TK_NK_INTEGER && pIdOrName->type != TK_NK_STRING) {
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR,
|
|
"Xnode task id or name should be an integer or string");
|
|
goto _err;
|
|
}
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_STOP_XNODE_TASK_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
SStopXnodeTaskStmt* pTaskStmt = (SStopXnodeTaskStmt*)pStmt;
|
|
if (pIdOrName->type == TK_NK_INTEGER) {
|
|
pTaskStmt->tid = taosStr2Int32(pIdOrName->z, NULL, 10);
|
|
if (pTaskStmt->tid <= 0) {
|
|
pCxt->errCode =
|
|
generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, "Task id should be greater than 0");
|
|
goto _err;
|
|
}
|
|
} else {
|
|
if (pIdOrName->n > TSDB_XNODE_RESOURCE_NAME_LEN + 2) {
|
|
pCxt->errCode =
|
|
generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR,
|
|
"Xnode task name should be less than %d characters", TSDB_XNODE_RESOURCE_NAME_LEN);
|
|
goto _err;
|
|
}
|
|
char buf[TSDB_XNODE_RESOURCE_NAME_LEN + 1] = {0};
|
|
COPY_STRING_FORM_STR_TOKEN(buf, pIdOrName);
|
|
pTaskStmt->name = xCreateCowStr(strlen(buf), buf, true);
|
|
}
|
|
|
|
return (SNode*)pTaskStmt;
|
|
_err:
|
|
if (pStmt != NULL) {
|
|
nodesDestroyNode(pStmt);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
SNode* rebalanceXnodeJobWithOptionsDirectly(SAstCreateContext* pCxt, const SToken* pResourceId, SNode* pNode) {
|
|
SNode* pStmt = NULL;
|
|
if (pResourceId == NULL) {
|
|
pCxt->errCode =
|
|
generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, "Xnode job id should not be NULL");
|
|
goto _err;
|
|
}
|
|
if (pNode == NULL) {
|
|
pCxt->errCode =
|
|
generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, "Xnode job options should not be NULL");
|
|
goto _err;
|
|
}
|
|
if (pResourceId->type != TK_NK_INTEGER) {
|
|
pCxt->errCode =
|
|
generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, "Xnode job id should be an integer");
|
|
goto _err;
|
|
}
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_REBALANCE_XNODE_JOB_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
|
|
SRebalanceXnodeJobStmt* pJobStmt = (SRebalanceXnodeJobStmt*)pStmt;
|
|
char buf[TSDB_XNODE_RESOURCE_ID_LEN] = {0};
|
|
COPY_STRING_FORM_ID_TOKEN(buf, pResourceId);
|
|
pJobStmt->jid = atoi(buf);
|
|
|
|
if (nodeType(pNode) == QUERY_NODE_XNODE_TASK_OPTIONS) {
|
|
SXnodeTaskOptions* options = (SXnodeTaskOptions*)(pNode);
|
|
// printXnodeTaskOptions(&options->opts);
|
|
pJobStmt->options = options;
|
|
}
|
|
return (SNode*)pJobStmt;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createRebalanceXnodeJobStmt(SAstCreateContext* pCxt, EXnodeResourceType resourceType, const SToken* resourceId,
|
|
SNode* pNodeOptions) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
|
|
switch (resourceType) {
|
|
case XNODE_JOB: {
|
|
return rebalanceXnodeJobWithOptionsDirectly(pCxt, resourceId, pNodeOptions);
|
|
}
|
|
default:
|
|
pCxt->errCode =
|
|
generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR,
|
|
"Invalid xnode resource type: %d, rebalance only support job", resourceType);
|
|
goto _err;
|
|
}
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* rebalanceXnodeJobWhereDirectly(SAstCreateContext* pCxt, SNode* pWhere) {
|
|
int32_t code = 0;
|
|
SNode* pStmt = NULL;
|
|
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_REBALANCE_XNODE_JOB_WHERE_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
|
|
SRebalanceXnodeJobWhereStmt* pJobStmt = (SRebalanceXnodeJobWhereStmt*)pStmt;
|
|
pJobStmt->pWhere = pWhere;
|
|
|
|
return (SNode*)pJobStmt;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createRebalanceXnodeJobWhereStmt(SAstCreateContext* pCxt, EXnodeResourceType resourceType, SNode* pWhere) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
|
|
switch (resourceType) {
|
|
case XNODE_JOB: {
|
|
return rebalanceXnodeJobWhereDirectly(pCxt, pWhere);
|
|
}
|
|
default:
|
|
pCxt->errCode =
|
|
generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR,
|
|
"Invalid xnode resource type: %d, rebalance only support job", resourceType);
|
|
goto _err;
|
|
}
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* updateXnodeTaskWithOptionsDirectly(SAstCreateContext* pCxt, const SToken* pResIdOrName, SNode* pSource,
|
|
SNode* pSink, SNode* pNode) {
|
|
SNode* pStmt = NULL;
|
|
|
|
if ((pSource != NULL && nodeType(pSource) != QUERY_NODE_XNODE_TASK_SOURCE_OPT) ||
|
|
(pSink != NULL && nodeType(pSink) != QUERY_NODE_XNODE_TASK_SINK_OPT)) {
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR,
|
|
"Xnode task source and sink should be valid nodes");
|
|
goto _err;
|
|
}
|
|
if (pSource == NULL && pSink == NULL && pNode == NULL) {
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR,
|
|
"Xnode task source, sink, and with options can't all be NULL");
|
|
goto _err;
|
|
}
|
|
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_UPDATE_XNODE_TASK_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
SUpdateXnodeTaskStmt* pTaskStmt = (SUpdateXnodeTaskStmt*)pStmt;
|
|
if (pResIdOrName->type == TK_NK_INTEGER) {
|
|
pTaskStmt->tid = taosStr2Int32(pResIdOrName->z, NULL, 10);
|
|
} else {
|
|
if (pResIdOrName->n <= 2) {
|
|
pCxt->errCode =
|
|
generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, "Xnode task name can't be empty string");
|
|
goto _err;
|
|
}
|
|
char buf[TSDB_XNODE_TASK_NAME_LEN] = {0};
|
|
COPY_STRING_FORM_STR_TOKEN(buf, pResIdOrName);
|
|
pTaskStmt->name = xCreateCowStr(strlen(buf), buf, true);
|
|
}
|
|
|
|
if (pSource != NULL) {
|
|
SXTaskSource* source = (SXTaskSource*)(pSource);
|
|
pTaskStmt->source = source;
|
|
}
|
|
if (pSink != NULL) {
|
|
SXTaskSink* sink = (SXTaskSink*)(pSink);
|
|
pTaskStmt->sink = sink;
|
|
}
|
|
if (pNode != NULL) {
|
|
if (nodeType(pNode) == QUERY_NODE_XNODE_TASK_OPTIONS) {
|
|
SXnodeTaskOptions* options = (SXnodeTaskOptions*)(pNode);
|
|
pTaskStmt->options = options;
|
|
}
|
|
}
|
|
return (SNode*)pTaskStmt;
|
|
_err:
|
|
if (pStmt != NULL) {
|
|
nodesDestroyNode(pStmt);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
SNode* alterXnodeJobWithOptionsDirectly(SAstCreateContext* pCxt, const SToken* pResourceName, SNode* pNode) {
|
|
SNode* pStmt = NULL;
|
|
if (pResourceName == NULL) {
|
|
pCxt->errCode =
|
|
generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, "Xnode job id should not be NULL");
|
|
goto _err;
|
|
}
|
|
if (pNode == NULL) {
|
|
pCxt->errCode =
|
|
generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, "Xnode job options should not be NULL");
|
|
goto _err;
|
|
}
|
|
if (pResourceName->type != TK_NK_INTEGER) {
|
|
pCxt->errCode =
|
|
generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, "Xnode job id should be integer");
|
|
goto _err;
|
|
}
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_ALTER_XNODE_JOB_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
|
|
SAlterXnodeJobStmt* pJobStmt = (SAlterXnodeJobStmt*)pStmt;
|
|
char buf[TSDB_XNODE_RESOURCE_ID_LEN] = {0};
|
|
COPY_STRING_FORM_ID_TOKEN(buf, pResourceName);
|
|
pJobStmt->jid = atoi(buf);
|
|
|
|
if (nodeType(pNode) == QUERY_NODE_XNODE_TASK_OPTIONS) {
|
|
SXnodeTaskOptions* options = (SXnodeTaskOptions*)(pNode);
|
|
pJobStmt->options = options;
|
|
}
|
|
return (SNode*)pJobStmt;
|
|
_err:
|
|
if (pStmt != NULL) {
|
|
nodesDestroyNode(pStmt);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
SNode* alterXnodeAgentWithOptionsDirectly(SAstCreateContext* pCxt, const SToken* pResIdOrName, SNode* pNode) {
|
|
SNode* pStmt = NULL;
|
|
if (NULL == pNode) {
|
|
pCxt->errCode =
|
|
generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, "Xnode alter agent options can't be null");
|
|
goto _err;
|
|
}
|
|
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_ALTER_XNODE_AGENT_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
SAlterXnodeAgentStmt* pAgentStmt = (SAlterXnodeAgentStmt*)pStmt;
|
|
if (pResIdOrName->type == TK_NK_INTEGER) {
|
|
pAgentStmt->id = taosStr2Int32(pResIdOrName->z, NULL, 10);
|
|
} else {
|
|
if (pResIdOrName->n <= 2) {
|
|
pCxt->errCode =
|
|
generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, "Xnode alter agent name can't be empty string");
|
|
goto _err;
|
|
}
|
|
char buf[TSDB_XNODE_AGENT_NAME_LEN] = {0};
|
|
COPY_STRING_FORM_STR_TOKEN(buf, pResIdOrName);
|
|
pAgentStmt->name = xCreateCowStr(strlen(buf), buf, true);
|
|
}
|
|
|
|
if (nodeType(pNode) == QUERY_NODE_XNODE_TASK_OPTIONS) {
|
|
SXnodeTaskOptions* options = (SXnodeTaskOptions*)(pNode);
|
|
pAgentStmt->options = options;
|
|
}
|
|
|
|
return (SNode*)pAgentStmt;
|
|
_err:
|
|
if (pStmt != NULL) {
|
|
nodesDestroyNode(pStmt);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
SNode* alterXnodeTaskWithOptions(SAstCreateContext* pCxt, EXnodeResourceType resourceType, const SToken* pResIdOrName,
|
|
SNode* pSource, SNode* pSink, SNode* pNode) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
|
|
switch (resourceType) {
|
|
case XNODE_TASK: {
|
|
return updateXnodeTaskWithOptionsDirectly(pCxt, pResIdOrName, pSource, pSink, pNode);
|
|
}
|
|
case XNODE_AGENT: {
|
|
return alterXnodeAgentWithOptionsDirectly(pCxt, pResIdOrName, pNode);
|
|
}
|
|
case XNODE_JOB: {
|
|
return alterXnodeJobWithOptionsDirectly(pCxt, pResIdOrName, pNode);
|
|
}
|
|
default:
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR,
|
|
"Invalid xnode resource type: %d", resourceType);
|
|
goto _err;
|
|
}
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* dropXnodeResource(SAstCreateContext* pCxt, EXnodeResourceType resourceType, SToken* pResourceName) {
|
|
SNode* pStmt = NULL;
|
|
char buf[TSDB_XNODE_TASK_NAME_LEN + 1] = {0};
|
|
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
if (pResourceName == NULL || pResourceName->n <= 0) {
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR,
|
|
"Xnode resource name should not be NULL or empty");
|
|
goto _err;
|
|
}
|
|
if (pResourceName->n > TSDB_XNODE_RESOURCE_NAME_LEN) {
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR,
|
|
"Invalid xnode resource name length: %d, max length: %d", pResourceName->n,
|
|
TSDB_XNODE_RESOURCE_NAME_LEN);
|
|
goto _err;
|
|
}
|
|
switch (resourceType) {
|
|
case XNODE_TASK:
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_DROP_XNODE_TASK_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
SDropXnodeTaskStmt* pTaskStmt = (SDropXnodeTaskStmt*)pStmt;
|
|
|
|
if (pResourceName->type == TK_NK_STRING) {
|
|
if (pResourceName->n > TSDB_XNODE_TASK_NAME_LEN + 2) {
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR,
|
|
"Invalid xnode task name length: %d, max length: %d",
|
|
pResourceName->n, TSDB_XNODE_TASK_NAME_LEN);
|
|
goto _err;
|
|
}
|
|
COPY_STRING_FORM_STR_TOKEN(buf, pResourceName);
|
|
pTaskStmt->name = taosStrndupi(buf, sizeof(buf));
|
|
} else if (pResourceName->type == TK_NK_ID) {
|
|
COPY_STRING_FORM_ID_TOKEN(buf, pResourceName);
|
|
pTaskStmt->name = taosStrndupi(buf, sizeof(buf));
|
|
} else if (pResourceName->type == TK_NK_INTEGER) {
|
|
pTaskStmt->id = taosStr2Int32(pResourceName->z, NULL, 10);
|
|
} else {
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR,
|
|
"Invalid xnode job id type: %d", pResourceName->type);
|
|
goto _err;
|
|
}
|
|
break;
|
|
case XNODE_AGENT:
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_DROP_XNODE_AGENT_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
SDropXnodeAgentStmt* pDropAgent = (SDropXnodeAgentStmt*)pStmt;
|
|
|
|
if (pResourceName->type == TK_NK_STRING) {
|
|
if (pResourceName->n > TSDB_XNODE_TASK_NAME_LEN + 2) {
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR,
|
|
"Invalid xnode task name length: %d, max length: %d",
|
|
pResourceName->n, TSDB_XNODE_TASK_NAME_LEN);
|
|
goto _err;
|
|
}
|
|
COPY_STRING_FORM_STR_TOKEN(buf, pResourceName);
|
|
pDropAgent->name = taosStrndupi(buf, sizeof(buf));
|
|
} else if (pResourceName->type == TK_NK_ID) {
|
|
COPY_STRING_FORM_ID_TOKEN(buf, pResourceName);
|
|
pDropAgent->name = taosStrndupi(buf, sizeof(buf));
|
|
} else if (pResourceName->type == TK_NK_INTEGER) {
|
|
pDropAgent->id = taosStr2Int32(pResourceName->z, NULL, 10);
|
|
} else {
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR,
|
|
"Invalid xnode agent id type: %d", pResourceName->type);
|
|
goto _err;
|
|
}
|
|
break;
|
|
case XNODE_JOB:
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_DROP_XNODE_JOB_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
SDropXnodeJobStmt* pJobStmt = (SDropXnodeJobStmt*)pStmt;
|
|
|
|
if (pResourceName->type == TK_NK_STRING) {
|
|
pJobStmt->jid = taosStr2Int32(pResourceName->z, NULL, 10);
|
|
} else if (pResourceName->type == TK_NK_INTEGER) {
|
|
pJobStmt->jid = taosStr2Int32(pResourceName->z, NULL, 10);
|
|
} else {
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR,
|
|
"Invalid xnode job id type: %d", pResourceName->type);
|
|
goto _err;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
if (pStmt != NULL) {
|
|
nodesDestroyNode(pStmt);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
SNode* dropXnodeResourceWhere(SAstCreateContext* pCxt, EXnodeResourceType resourceType, SNode* pWhere) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SDropXnodeJobStmt* pStmt = NULL;
|
|
switch (resourceType) {
|
|
case XNODE_TASK:
|
|
case XNODE_AGENT:
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR,
|
|
"Xnode only drop xnode job where ... support");
|
|
break;
|
|
case XNODE_JOB:
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_DROP_XNODE_JOB_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
pStmt->pWhere = pWhere;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createDefaultXnodeTaskOptions(SAstCreateContext* pCxt) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SXnodeTaskOptions* pOptions = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_XNODE_TASK_OPTIONS, (SNode**)&pOptions);
|
|
CHECK_MAKE_NODE(pOptions);
|
|
return (SNode*)pOptions;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
static char TRIGGER[8] = "trigger";
|
|
static SToken TRIGGER_TOKEN = {
|
|
.n = 7,
|
|
.type = TK_NK_ID,
|
|
.z = TRIGGER,
|
|
};
|
|
SToken* createTriggerToken() { return &TRIGGER_TOKEN; }
|
|
|
|
SNode* setXnodeTaskOption(SAstCreateContext* pCxt, SNode* pTaskOptions, SToken* pKey, SToken* pVal) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
if (pTaskOptions == NULL) {
|
|
pTaskOptions = createDefaultXnodeTaskOptions(pCxt);
|
|
if (pTaskOptions == NULL) {
|
|
pCxt->errCode =
|
|
generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, "Xnode task options should not be NULL");
|
|
goto _err;
|
|
}
|
|
}
|
|
SXnodeTaskOptions* pOptions = (SXnodeTaskOptions*)pTaskOptions;
|
|
char key[TSDB_COL_NAME_LEN] = {0};
|
|
if (pKey == NULL) {
|
|
pCxt->errCode =
|
|
generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, "Option name for xnode should not be empty");
|
|
goto _err;
|
|
}
|
|
TRIM_STRING_FORM_ID_TOKEN(key, pKey);
|
|
|
|
if (strlen(key) == 0) {
|
|
pCxt->errCode =
|
|
generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, "Option name for xnode should not be empty");
|
|
goto _err;
|
|
}
|
|
char via[TSDB_COL_NAME_LEN] = {0};
|
|
char buf[TSDB_XNODE_TASK_OPTIONS_MAX_NUM] = {0};
|
|
if (strcmp(key, "trigger") == 0) {
|
|
if (pVal->type == TK_NK_STRING) {
|
|
(void)trimString(pVal->z, pVal->n, pOptions->trigger, sizeof(pOptions->trigger));
|
|
pOptions->triggerLen = pVal->n == 2 ? 1 : pVal->n - 2;
|
|
} else {
|
|
pCxt->errCode =
|
|
generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, "Option trigger must be string");
|
|
goto _err;
|
|
}
|
|
} else if (strcmp(key, "parser") == 0 || strcmp(key, "transform") == 0) {
|
|
if (pVal->type == TK_NK_STRING) {
|
|
(void)trimString(pVal->z, pVal->n, pOptions->parser, sizeof(pOptions->parser));
|
|
pOptions->parserLen = pVal->n == 2 ? 1 : pVal->n - 2;
|
|
} else {
|
|
pCxt->errCode =
|
|
generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, "Option parser must be string");
|
|
goto _err;
|
|
}
|
|
} else if (strcmp(key, "health") == 0) {
|
|
if (pVal->type == TK_NK_STRING) {
|
|
(void)trimString(pVal->z, pVal->n, pOptions->health, sizeof(pOptions->health));
|
|
pOptions->healthLen = pVal->n == 2 ? 1 : pVal->n - 2;
|
|
} else {
|
|
pCxt->errCode =
|
|
generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, "Option health must be string");
|
|
goto _err;
|
|
}
|
|
} else if (strcmp(key, "via") == 0) {
|
|
switch (pVal->type) {
|
|
case TK_NK_STRING:
|
|
(void)trimString(pVal->z, pVal->n, via, sizeof(via));
|
|
pOptions->via = taosStr2Int32(via, NULL, 10);
|
|
if (pOptions->via <= 0) {
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR,
|
|
"Invalid xnode task option via: %s", pVal->z);
|
|
goto _err;
|
|
}
|
|
break;
|
|
case TK_NK_INTEGER:
|
|
pOptions->via = taosStr2Int32(pVal->z, NULL, 10);
|
|
break;
|
|
default:
|
|
pCxt->errCode =
|
|
generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, "Invalid xnode task option: %s", key);
|
|
}
|
|
} else {
|
|
if (pOptions->optionsNum < TSDB_XNODE_TASK_OPTIONS_MAX_NUM) {
|
|
char* pKeyVal = NULL;
|
|
if (pVal != NULL) {
|
|
parserDebug("key value length expected: %d, actual: %d\n", pKey->n + pVal->n + 2, pKey->n + pVal->n);
|
|
pKeyVal = taosMemoryMalloc(pKey->n + pVal->n + 2);
|
|
memset(pKeyVal, 0, pKey->n + pVal->n + 2);
|
|
|
|
CHECK_OUT_OF_MEM(pKeyVal);
|
|
size_t pos = strlen(key);
|
|
memcpy(pKeyVal, key, pos);
|
|
pKeyVal[pos] = '='; // Add '=' after the key
|
|
pos++;
|
|
|
|
if (pVal->type == TK_NK_STRING) {
|
|
(void)trimString(pVal->z, pVal->n, pKeyVal + pos, pVal->n + 1);
|
|
} else {
|
|
strncpy(pKeyVal + pos, pVal->z, TMIN(pVal->n, pKey->n + pVal->n + 2 - pos - 1));
|
|
pKeyVal[pos + pVal->n] = '\0';
|
|
}
|
|
} else {
|
|
size_t keyLen = strlen(key);
|
|
pKeyVal = taosMemoryMalloc(keyLen + 1);
|
|
memset(pKeyVal, 0, keyLen + 1);
|
|
CHECK_OUT_OF_MEM(pKeyVal);
|
|
memcpy(pKeyVal, key, keyLen);
|
|
}
|
|
pOptions->options[pOptions->optionsNum] = pKeyVal;
|
|
pOptions->optionsNum++;
|
|
} else {
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR,
|
|
"reaches max options number(%d) %s", pOptions->optionsNum, key);
|
|
goto _err;
|
|
}
|
|
}
|
|
_err:
|
|
return pTaskOptions;
|
|
}
|
|
|
|
SNode* createXnodeTaskJobWithOptions(SAstCreateContext* pCxt, EXnodeResourceType resourceType, const SToken* pTidToken,
|
|
SNode* pNodeOptions) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SNode* pStmt = NULL;
|
|
|
|
switch (resourceType) {
|
|
case XNODE_JOB: {
|
|
if (pTidToken == NULL || pTidToken->n <= 0) {
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR,
|
|
"Xnode job task id should not be NULL or empty");
|
|
goto _err;
|
|
}
|
|
if (pNodeOptions == NULL || nodeType(pNodeOptions) != QUERY_NODE_XNODE_TASK_OPTIONS) {
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR,
|
|
"Xnode job options should not be NULL or empty");
|
|
goto _err;
|
|
}
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_CREATE_XNODE_JOB_STMT, &pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
SCreateXnodeJobStmt* pJobStmt = (SCreateXnodeJobStmt*)pStmt;
|
|
pJobStmt->options = (SXnodeTaskOptions*)pNodeOptions;
|
|
pJobStmt->tid = pTidToken->type == TK_NK_STRING ? atoi(pTidToken->z) : taosStr2Int32(pTidToken->z, NULL, 10);
|
|
break;
|
|
}
|
|
default:
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR,
|
|
"Invalid xnode resource type: %d with ON clause", resourceType);
|
|
goto _err;
|
|
}
|
|
return pStmt;
|
|
_err:
|
|
if (pStmt != NULL) {
|
|
nodesDestroyNode(pStmt);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createEncryptKeyStmt(SAstCreateContext* pCxt, const SToken* pValue) {
|
|
SToken config;
|
|
config.type = TK_NK_STRING;
|
|
config.z = "\"encrypt_key\"";
|
|
config.n = strlen(config.z);
|
|
return createAlterDnodeStmt(pCxt, NULL, &config, pValue);
|
|
}
|
|
|
|
SNode* createAlterEncryptKeyStmt(SAstCreateContext* pCxt, int8_t keyType, const SToken* pValue) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SAlterEncryptKeyStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_ALTER_ENCRYPT_KEY_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
|
|
pStmt->keyType = keyType;
|
|
if (NULL != pValue) {
|
|
(void)trimString(pValue->z, pValue->n, pStmt->newKey, sizeof(pStmt->newKey));
|
|
}
|
|
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createAlterKeyExpirationStmt(SAstCreateContext* pCxt, const SToken* pDays, const SToken* pStrategy) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SAlterKeyExpirationStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_ALTER_KEY_EXPIRATION_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
|
|
if (NULL != pDays) {
|
|
pStmt->days = taosStr2Int32(pDays->z, NULL, 10);
|
|
}
|
|
if (NULL != pStrategy) {
|
|
(void)trimString(pStrategy->z, pStrategy->n, pStmt->strategy, sizeof(pStmt->strategy));
|
|
}
|
|
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createRealTableNodeForIndexName(SAstCreateContext* pCxt, SToken* pDbName, SToken* pIndexName) {
|
|
if (!checkIndexName(pCxt, pIndexName)) {
|
|
return NULL;
|
|
}
|
|
return createRealTableNode(pCxt, pDbName, pIndexName, NULL);
|
|
}
|
|
|
|
SNode* createCreateIndexStmt(SAstCreateContext* pCxt, EIndexType type, bool ignoreExists, SNode* pIndexName,
|
|
SNode* pRealTable, SNodeList* pCols, SNode* pOptions) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SCreateIndexStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_CREATE_INDEX_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
pStmt->indexType = type;
|
|
pStmt->ignoreExists = ignoreExists;
|
|
|
|
SRealTableNode* pFullTable = (SRealTableNode*)pRealTable;
|
|
if (strlen(pFullTable->table.dbName) == 0) {
|
|
// no db specified,
|
|
if (pCxt->pQueryCxt->db == NULL) {
|
|
pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_DB_NOT_SPECIFIED);
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
} else {
|
|
snprintf(pStmt->indexDbName, sizeof(pStmt->indexDbName), "%s", pCxt->pQueryCxt->db);
|
|
}
|
|
} else {
|
|
snprintf(pStmt->indexDbName, sizeof(pStmt->indexDbName), "%s", pFullTable->table.dbName);
|
|
}
|
|
snprintf(pStmt->indexName, sizeof(pStmt->indexName), "%s", ((SColumnNode*)pIndexName)->colName);
|
|
snprintf(pStmt->dbName, sizeof(pStmt->dbName), "%s", ((SRealTableNode*)pRealTable)->table.dbName);
|
|
snprintf(pStmt->tableName, sizeof(pStmt->tableName), "%s", ((SRealTableNode*)pRealTable)->table.tableName);
|
|
nodesDestroyNode(pIndexName);
|
|
nodesDestroyNode(pRealTable);
|
|
pStmt->pCols = pCols;
|
|
pStmt->pOptions = (SIndexOptions*)pOptions;
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
nodesDestroyNode(pIndexName);
|
|
nodesDestroyNode(pRealTable);
|
|
nodesDestroyNode(pOptions);
|
|
nodesDestroyList(pCols);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createIndexOption(SAstCreateContext* pCxt, SNodeList* pFuncs, SNode* pInterval, SNode* pOffset, SNode* pSliding,
|
|
SNode* pStreamOptions) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SIndexOptions* pOptions = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_INDEX_OPTIONS, (SNode**)&pOptions);
|
|
CHECK_MAKE_NODE(pOptions);
|
|
pOptions->pFuncs = pFuncs;
|
|
pOptions->pInterval = pInterval;
|
|
pOptions->pOffset = pOffset;
|
|
pOptions->pSliding = pSliding;
|
|
pOptions->pStreamOptions = pStreamOptions;
|
|
return (SNode*)pOptions;
|
|
_err:
|
|
nodesDestroyNode(pInterval);
|
|
nodesDestroyNode(pOffset);
|
|
nodesDestroyNode(pSliding);
|
|
nodesDestroyNode(pStreamOptions);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createDropIndexStmt(SAstCreateContext* pCxt, bool ignoreNotExists, SNode* pIndexName) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SDropIndexStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_DROP_INDEX_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
pStmt->ignoreNotExists = ignoreNotExists;
|
|
snprintf(pStmt->indexDbName, sizeof(pStmt->indexDbName), "%s", ((SRealTableNode*)pIndexName)->table.dbName);
|
|
snprintf(pStmt->indexName, sizeof(pStmt->indexName), "%s", ((SRealTableNode*)pIndexName)->table.tableName);
|
|
nodesDestroyNode(pIndexName);
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
nodesDestroyNode(pIndexName);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createCreateComponentNodeStmt(SAstCreateContext* pCxt, ENodeType type, const SToken* pDnodeId) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SCreateComponentNodeStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(type, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
pStmt->dnodeId = taosStr2Int32(pDnodeId->z, NULL, 10);
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createDropComponentNodeStmt(SAstCreateContext* pCxt, ENodeType type, const SToken* pDnodeId) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SDropComponentNodeStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(type, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
pStmt->dnodeId = taosStr2Int32(pDnodeId->z, NULL, 10);
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createRestoreComponentNodeStmt(SAstCreateContext* pCxt, ENodeType type, const SToken* pDnodeId) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SRestoreComponentNodeStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(type, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
pStmt->dnodeId = taosStr2Int32(pDnodeId->z, NULL, 10);
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createCreateTopicStmtUseQuery(SAstCreateContext* pCxt, bool ignoreExists, SToken* pTopicName, SNode* pQuery, bool reload) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
CHECK_NAME(checkTopicName(pCxt, pTopicName));
|
|
SCreateTopicStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_CREATE_TOPIC_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
COPY_STRING_FORM_ID_TOKEN(pStmt->topicName, pTopicName);
|
|
pStmt->ignoreExists = ignoreExists;
|
|
pStmt->pQuery = pQuery;
|
|
pStmt->reload = reload;
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
nodesDestroyNode(pQuery);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createCreateTopicStmtUseDb(SAstCreateContext* pCxt, bool ignoreExists, SToken* pTopicName, SToken* pSubDbName,
|
|
int8_t withMeta) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
CHECK_NAME(checkTopicName(pCxt, pTopicName));
|
|
CHECK_NAME(checkDbName(pCxt, pSubDbName, true));
|
|
SCreateTopicStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_CREATE_TOPIC_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
COPY_STRING_FORM_ID_TOKEN(pStmt->topicName, pTopicName);
|
|
pStmt->ignoreExists = ignoreExists;
|
|
COPY_STRING_FORM_ID_TOKEN(pStmt->subDbName, pSubDbName);
|
|
pStmt->withMeta = withMeta;
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createCreateTopicStmtUseTable(SAstCreateContext* pCxt, bool ignoreExists, SToken* pTopicName, SNode* pRealTable,
|
|
int8_t withMeta, SNode* pWhere) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
CHECK_NAME(checkTopicName(pCxt, pTopicName));
|
|
SCreateTopicStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_CREATE_TOPIC_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
COPY_STRING_FORM_ID_TOKEN(pStmt->topicName, pTopicName);
|
|
pStmt->ignoreExists = ignoreExists;
|
|
pStmt->withMeta = withMeta;
|
|
pStmt->pWhere = pWhere;
|
|
|
|
tstrncpy(pStmt->subDbName, ((SRealTableNode*)pRealTable)->table.dbName, TSDB_DB_NAME_LEN);
|
|
tstrncpy(pStmt->subSTbName, ((SRealTableNode*)pRealTable)->table.tableName, TSDB_TABLE_NAME_LEN);
|
|
nodesDestroyNode(pRealTable);
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
nodesDestroyNode(pRealTable);
|
|
nodesDestroyNode(pWhere);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createDropTopicStmt(SAstCreateContext* pCxt, bool ignoreNotExists, SToken* pTopicName, bool force) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
CHECK_NAME(checkTopicName(pCxt, pTopicName));
|
|
SDropTopicStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_DROP_TOPIC_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
COPY_STRING_FORM_ID_TOKEN(pStmt->topicName, pTopicName);
|
|
pStmt->ignoreNotExists = ignoreNotExists;
|
|
pStmt->force = force;
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createDropCGroupStmt(SAstCreateContext* pCxt, bool ignoreNotExists, SToken* pCGroupId, SToken* pTopicName,
|
|
bool force) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
CHECK_NAME(checkTopicName(pCxt, pTopicName));
|
|
CHECK_NAME(checkCGroupName(pCxt, pCGroupId));
|
|
SDropCGroupStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_DROP_CGROUP_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
pStmt->ignoreNotExists = ignoreNotExists;
|
|
pStmt->force = force;
|
|
COPY_STRING_FORM_ID_TOKEN(pStmt->topicName, pTopicName);
|
|
COPY_STRING_FORM_ID_TOKEN(pStmt->cgroup, pCGroupId);
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createAlterClusterStmt(SAstCreateContext* pCxt, const SToken* pConfig, const SToken* pValue) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SAlterClusterStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_ALTER_CLUSTER_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
(void)trimString(pConfig->z, pConfig->n, pStmt->config, sizeof(pStmt->config));
|
|
if (NULL != pValue) {
|
|
(void)trimString(pValue->z, pValue->n, pStmt->value, sizeof(pStmt->value));
|
|
}
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createAlterLocalStmt(SAstCreateContext* pCxt, const SToken* pConfig, const SToken* pValue) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SAlterLocalStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_ALTER_LOCAL_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
(void)trimString(pConfig->z, pConfig->n, pStmt->config, sizeof(pStmt->config));
|
|
if (NULL != pValue) {
|
|
(void)trimString(pValue->z, pValue->n, pStmt->value, sizeof(pStmt->value));
|
|
}
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createDefaultExplainOptions(SAstCreateContext* pCxt) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SExplainOptions* pOptions = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_EXPLAIN_OPTIONS, (SNode**)&pOptions);
|
|
CHECK_MAKE_NODE(pOptions);
|
|
pOptions->verbose = TSDB_DEFAULT_EXPLAIN_VERBOSE;
|
|
pOptions->ratio = TSDB_DEFAULT_EXPLAIN_RATIO;
|
|
return (SNode*)pOptions;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* setExplainVerbose(SAstCreateContext* pCxt, SNode* pOptions, const SToken* pVal) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
((SExplainOptions*)pOptions)->verbose = (0 == strncasecmp(pVal->z, "true", pVal->n));
|
|
return pOptions;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* setExplainRatio(SAstCreateContext* pCxt, SNode* pOptions, const SToken* pVal) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
((SExplainOptions*)pOptions)->ratio = taosStr2Double(pVal->z, NULL);
|
|
return pOptions;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createExplainStmt(SAstCreateContext* pCxt, bool analyze, SNode* pOptions, SNode* pQuery) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SExplainStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_EXPLAIN_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
pStmt->analyze = analyze;
|
|
pStmt->pOptions = (SExplainOptions*)pOptions;
|
|
pStmt->pQuery = pQuery;
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
nodesDestroyNode(pOptions);
|
|
nodesDestroyNode(pQuery);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createDescribeStmt(SAstCreateContext* pCxt, SNode* pRealTable) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SDescribeStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_DESCRIBE_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
tstrncpy(pStmt->dbName, ((SRealTableNode*)pRealTable)->table.dbName, TSDB_DB_NAME_LEN);
|
|
tstrncpy(pStmt->tableName, ((SRealTableNode*)pRealTable)->table.tableName, TSDB_TABLE_NAME_LEN);
|
|
nodesDestroyNode(pRealTable);
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
nodesDestroyNode(pRealTable);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createResetQueryCacheStmt(SAstCreateContext* pCxt) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SNode* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_RESET_QUERY_CACHE_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
return pStmt;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
static int32_t convertUdfLanguageType(SAstCreateContext* pCxt, const SToken* pLanguageToken, int8_t* pLanguage) {
|
|
if (TK_NK_NIL == pLanguageToken->type || 0 == strncasecmp(pLanguageToken->z + 1, "c", pLanguageToken->n - 2)) {
|
|
*pLanguage = TSDB_FUNC_SCRIPT_BIN_LIB;
|
|
} else if (0 == strncasecmp(pLanguageToken->z + 1, "python", pLanguageToken->n - 2)) {
|
|
*pLanguage = TSDB_FUNC_SCRIPT_PYTHON;
|
|
} else {
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR,
|
|
"udf programming language supports c and python");
|
|
}
|
|
return pCxt->errCode;
|
|
}
|
|
|
|
SNode* createCreateFunctionStmt(SAstCreateContext* pCxt, bool ignoreExists, bool aggFunc, const SToken* pFuncName,
|
|
const SToken* pLibPath, SDataType dataType, int32_t bufSize, const SToken* pLanguage,
|
|
bool orReplace) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
if (pLibPath->n <= 2) {
|
|
pCxt->errCode = TSDB_CODE_PAR_SYNTAX_ERROR;
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
}
|
|
int8_t language = 0;
|
|
pCxt->errCode = convertUdfLanguageType(pCxt, pLanguage, &language);
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SCreateFunctionStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_CREATE_FUNCTION_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
pStmt->orReplace = orReplace;
|
|
pStmt->ignoreExists = ignoreExists;
|
|
COPY_STRING_FORM_ID_TOKEN(pStmt->funcName, pFuncName);
|
|
pStmt->isAgg = aggFunc;
|
|
COPY_STRING_FORM_STR_TOKEN(pStmt->libraryPath, pLibPath);
|
|
pStmt->outputDt = dataType;
|
|
pStmt->bufSize = bufSize;
|
|
pStmt->language = language;
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createDropFunctionStmt(SAstCreateContext* pCxt, bool ignoreNotExists, const SToken* pFuncName) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SDropFunctionStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_DROP_FUNCTION_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
pStmt->ignoreNotExists = ignoreNotExists;
|
|
COPY_STRING_FORM_ID_TOKEN(pStmt->funcName, pFuncName);
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createCreateViewStmt(SAstCreateContext* pCxt, bool orReplace, SNode* pView, const SToken* pAs, SNode* pQuery) {
|
|
SCreateViewStmt* pStmt = NULL;
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_CREATE_VIEW_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
int32_t i = pAs->n;
|
|
while (isspace(*(pAs->z + i))) {
|
|
++i;
|
|
}
|
|
pStmt->pQuerySql = tstrdup(pAs->z + i);
|
|
CHECK_OUT_OF_MEM(pStmt->pQuerySql);
|
|
tstrncpy(pStmt->dbName, ((SViewNode*)pView)->table.dbName, TSDB_DB_NAME_LEN);
|
|
tstrncpy(pStmt->viewName, ((SViewNode*)pView)->table.tableName, TSDB_VIEW_NAME_LEN);
|
|
nodesDestroyNode(pView);
|
|
pStmt->orReplace = orReplace;
|
|
pStmt->pQuery = pQuery;
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
nodesDestroyNode(pView);
|
|
nodesDestroyNode(pQuery);
|
|
nodesDestroyNode((SNode*)pStmt);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createDropViewStmt(SAstCreateContext* pCxt, bool ignoreNotExists, SNode* pView) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SDropViewStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_DROP_VIEW_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
pStmt->ignoreNotExists = ignoreNotExists;
|
|
tstrncpy(pStmt->dbName, ((SViewNode*)pView)->table.dbName, TSDB_DB_NAME_LEN);
|
|
tstrncpy(pStmt->viewName, ((SViewNode*)pView)->table.tableName, TSDB_VIEW_NAME_LEN);
|
|
nodesDestroyNode(pView);
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
nodesDestroyNode(pView);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createStreamOutTableNode(SAstCreateContext* pCxt, SNode* pIntoTable, SNode* pOutputSubTable, SNodeList* pColList,
|
|
SNodeList* pTagList) {
|
|
SStreamOutTableNode* pOutTable = NULL;
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_STREAM_OUT_TABLE, (SNode**)&pOutTable);
|
|
CHECK_MAKE_NODE(pOutTable);
|
|
pOutTable->pOutTable = pIntoTable;
|
|
pOutTable->pSubtable = pOutputSubTable;
|
|
pOutTable->pCols = pColList;
|
|
pOutTable->pTags = pTagList;
|
|
return (SNode*)pOutTable;
|
|
|
|
_err:
|
|
nodesDestroyNode((SNode*)pOutTable);
|
|
nodesDestroyNode(pIntoTable);
|
|
nodesDestroyNode(pOutputSubTable);
|
|
nodesDestroyList(pColList);
|
|
nodesDestroyList(pTagList);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createStreamTriggerNode(SAstCreateContext* pCxt, SNode* pTriggerWindow, SNode* pTriggerTable,
|
|
SNodeList* pPartitionList, SNode* pOptions, SNode* pNotification) {
|
|
SStreamTriggerNode* pTrigger = NULL;
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_STREAM_TRIGGER, (SNode**)&pTrigger);
|
|
CHECK_MAKE_NODE(pTrigger);
|
|
|
|
pTrigger->pOptions = pOptions;
|
|
pTrigger->pNotify = pNotification;
|
|
pTrigger->pTrigerTable = pTriggerTable;
|
|
pTrigger->pPartitionList = pPartitionList;
|
|
pTrigger->pTriggerWindow = pTriggerWindow;
|
|
return (SNode*)pTrigger;
|
|
|
|
_err:
|
|
nodesDestroyNode((SNode*)pTrigger);
|
|
nodesDestroyNode(pTriggerWindow);
|
|
nodesDestroyNode(pTriggerTable);
|
|
nodesDestroyNode(pOptions);
|
|
nodesDestroyNode(pNotification);
|
|
nodesDestroyList(pPartitionList);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createSlidingWindowNode(SAstCreateContext* pCxt, SNode* pSlidingVal, SNode* pOffset) {
|
|
SSlidingWindowNode* pSliding = NULL;
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_SLIDING_WINDOW, (SNode**)&pSliding);
|
|
CHECK_MAKE_NODE(pSliding);
|
|
pSliding->pSlidingVal = pSlidingVal;
|
|
pSliding->pOffset = pOffset;
|
|
return (SNode*)pSliding;
|
|
_err:
|
|
nodesDestroyNode(pSlidingVal);
|
|
nodesDestroyNode(pOffset);
|
|
nodesDestroyNode((SNode*)pSliding);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createStreamTriggerOptions(SAstCreateContext* pCxt) {
|
|
SStreamTriggerOptions* pOptions = NULL;
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_STREAM_TRIGGER_OPTIONS, (SNode**)&pOptions);
|
|
CHECK_MAKE_NODE(pOptions);
|
|
pOptions->pPreFilter = NULL;
|
|
pOptions->pWaterMark = NULL;
|
|
pOptions->pMaxDelay = NULL;
|
|
pOptions->pExpiredTime = NULL;
|
|
pOptions->pFillHisStartTime = NULL;
|
|
pOptions->pEventType = EVENT_NONE;
|
|
pOptions->calcNotifyOnly = false;
|
|
pOptions->deleteOutputTable = false;
|
|
pOptions->deleteRecalc = false;
|
|
pOptions->fillHistory = false;
|
|
pOptions->fillHistoryFirst = false;
|
|
pOptions->lowLatencyCalc = false;
|
|
pOptions->forceOutput = false;
|
|
pOptions->ignoreDisorder = false;
|
|
pOptions->ignoreNoDataTrigger = false;
|
|
return (SNode*)pOptions;
|
|
_err:
|
|
nodesDestroyNode((SNode*)pOptions);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createStreamTagDefNode(SAstCreateContext* pCxt, SToken* pTagName, SDataType dataType, SNode* tagExpression) {
|
|
SStreamTagDefNode* pTagDef = NULL;
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_STREAM_TAG_DEF, (SNode**)&pTagDef);
|
|
CHECK_MAKE_NODE(pTagDef);
|
|
COPY_STRING_FORM_ID_TOKEN(pTagDef->tagName, pTagName);
|
|
int32_t nameLen = strdequote(pTagDef->tagName);
|
|
pTagDef->tagName[nameLen] = '\0';
|
|
pTagDef->dataType = dataType;
|
|
pTagDef->pTagExpr = tagExpression;
|
|
return (SNode*)pTagDef;
|
|
_err:
|
|
nodesDestroyNode(tagExpression);
|
|
nodesDestroyNode((SNode*)pTagDef);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* setStreamTriggerOptions(SAstCreateContext* pCxt, SNode* pOptions, SStreamTriggerOption* pOptionUnit) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SStreamTriggerOptions* pStreamOptions = (SStreamTriggerOptions*)pOptions;
|
|
switch (pOptionUnit->type) {
|
|
case STREAM_TRIGGER_OPTION_CALC_NOTIFY_ONLY:
|
|
if (pStreamOptions->calcNotifyOnly) {
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR,
|
|
"CALC_NOTIFY_ONLY specified multiple times");
|
|
goto _err;
|
|
}
|
|
pStreamOptions->calcNotifyOnly = true;
|
|
break;
|
|
case STREAM_TRIGGER_OPTION_DELETE_OUTPUT_TABLE:
|
|
if (pStreamOptions->deleteOutputTable) {
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR,
|
|
"DELETE_OUTPUT_TABLE specified multiple times");
|
|
goto _err;
|
|
}
|
|
pStreamOptions->deleteOutputTable = true;
|
|
break;
|
|
case STREAM_TRIGGER_OPTION_DELETE_RECALC:
|
|
if (pStreamOptions->deleteRecalc) {
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR,
|
|
"DELETE_RECALC specified multiple times");
|
|
goto _err;
|
|
}
|
|
pStreamOptions->deleteRecalc = true;
|
|
break;
|
|
case STREAM_TRIGGER_OPTION_EXPIRED_TIME:
|
|
if (pStreamOptions->pExpiredTime != NULL) {
|
|
pCxt->errCode =
|
|
generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, "EXPIRED_TIME specified multiple times");
|
|
goto _err;
|
|
}
|
|
pStreamOptions->pExpiredTime = pOptionUnit->pNode;
|
|
break;
|
|
case STREAM_TRIGGER_OPTION_FORCE_OUTPUT:
|
|
if (pStreamOptions->forceOutput) {
|
|
pCxt->errCode =
|
|
generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, "FORCE_OUTPUT specified multiple times");
|
|
goto _err;
|
|
}
|
|
pStreamOptions->forceOutput = true;
|
|
break;
|
|
case STREAM_TRIGGER_OPTION_FILL_HISTORY:
|
|
if (pStreamOptions->fillHistoryFirst) {
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR,
|
|
"FILL_HISTORY_FIRST and FILL_HISTORY cannot be used at the same time");
|
|
goto _err;
|
|
}
|
|
if (pStreamOptions->pFillHisStartTime != NULL) {
|
|
pCxt->errCode =
|
|
generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, "FILL_HISTORY specified multiple times");
|
|
goto _err;
|
|
}
|
|
pStreamOptions->fillHistory = true;
|
|
if (pOptionUnit->pNode == NULL) {
|
|
pCxt->errCode = nodesMakeValueNodeFromInt64(INT64_MIN, &pStreamOptions->pFillHisStartTime);
|
|
CHECK_MAKE_NODE(pStreamOptions->pFillHisStartTime);
|
|
} else {
|
|
pStreamOptions->pFillHisStartTime = pOptionUnit->pNode;
|
|
}
|
|
break;
|
|
case STREAM_TRIGGER_OPTION_FILL_HISTORY_FIRST:
|
|
if (pStreamOptions->fillHistory) {
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR,
|
|
"FILL_HISTORY_FIRST and FILL_HISTORY cannot be used at the same time");
|
|
goto _err;
|
|
}
|
|
if (pStreamOptions->pFillHisStartTime != NULL) {
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR,
|
|
"FILL_HISTORY_FIRST specified multiple times");
|
|
goto _err;
|
|
}
|
|
pStreamOptions->fillHistoryFirst = true;
|
|
if (pOptionUnit->pNode == NULL) {
|
|
pCxt->errCode = nodesMakeValueNodeFromInt64(INT64_MIN, &pStreamOptions->pFillHisStartTime);
|
|
CHECK_MAKE_NODE(pStreamOptions->pFillHisStartTime);
|
|
} else {
|
|
pStreamOptions->pFillHisStartTime = pOptionUnit->pNode;
|
|
}
|
|
break;
|
|
case STREAM_TRIGGER_OPTION_IGNORE_DISORDER:
|
|
if (pStreamOptions->ignoreDisorder) {
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR,
|
|
"IGNORE_DISORDER specified multiple times");
|
|
goto _err;
|
|
}
|
|
pStreamOptions->ignoreDisorder = true;
|
|
break;
|
|
case STREAM_TRIGGER_OPTION_LOW_LATENCY_CALC:
|
|
if (pStreamOptions->lowLatencyCalc) {
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR,
|
|
"LOW_LATENCY_CALC specified multiple times");
|
|
goto _err;
|
|
}
|
|
pStreamOptions->lowLatencyCalc = true;
|
|
break;
|
|
case STREAM_TRIGGER_OPTION_MAX_DELAY:
|
|
if (pStreamOptions->pMaxDelay != NULL) {
|
|
pCxt->errCode =
|
|
generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, "MAX_DELAY specified multiple times");
|
|
goto _err;
|
|
}
|
|
pStreamOptions->pMaxDelay = pOptionUnit->pNode;
|
|
break;
|
|
case STREAM_TRIGGER_OPTION_WATERMARK:
|
|
if (pStreamOptions->pWaterMark != NULL) {
|
|
pCxt->errCode =
|
|
generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, "WATERMARK specified multiple times");
|
|
goto _err;
|
|
}
|
|
pStreamOptions->pWaterMark = pOptionUnit->pNode;
|
|
break;
|
|
case STREAM_TRIGGER_OPTION_PRE_FILTER:
|
|
if (pStreamOptions->pPreFilter != NULL) {
|
|
pCxt->errCode =
|
|
generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, "PRE_FILTER specified multiple times");
|
|
goto _err;
|
|
}
|
|
pStreamOptions->pPreFilter = pOptionUnit->pNode;
|
|
break;
|
|
case STREAM_TRIGGER_OPTION_EVENT_TYPE:
|
|
if (pStreamOptions->pEventType != EVENT_NONE) {
|
|
pCxt->errCode =
|
|
generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, "EVENT_TYPE specified multiple times");
|
|
goto _err;
|
|
}
|
|
pStreamOptions->pEventType = pOptionUnit->flag;
|
|
break;
|
|
case STREAM_TRIGGER_OPTION_IGNORE_NODATA_TRIGGER:
|
|
if (pStreamOptions->ignoreNoDataTrigger) {
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR,
|
|
"IGNORE_NODATA_TRIGGER specified multiple times");
|
|
goto _err;
|
|
}
|
|
pStreamOptions->ignoreNoDataTrigger = true;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return pOptions;
|
|
_err:
|
|
nodesDestroyNode(pOptionUnit->pNode);
|
|
nodesDestroyNode(pOptions);
|
|
return NULL;
|
|
}
|
|
|
|
static bool validateNotifyUrl(const char* url) {
|
|
const char* prefix[] = {"ws://", "wss://"};
|
|
const char* host = NULL;
|
|
|
|
if (!url || *url == '\0') return false;
|
|
|
|
for (int32_t i = 0; i < ARRAY_SIZE(prefix); ++i) {
|
|
if (taosStrncasecmp(url, prefix[i], strlen(prefix[i])) == 0) {
|
|
host = url + strlen(prefix[i]);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return (host != NULL) && (*host != '\0') && (*host != '/');
|
|
}
|
|
|
|
SNode* createStreamNotifyOptions(SAstCreateContext* pCxt, SNodeList* pAddrUrls, int64_t eventType, SNode* pWhere,
|
|
int64_t notifyType) {
|
|
SNode* pNode = NULL;
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
|
|
if (LIST_LENGTH(pAddrUrls) == 0) {
|
|
pCxt->errCode =
|
|
generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, "notification address cannot be empty");
|
|
goto _err;
|
|
}
|
|
|
|
FOREACH(pNode, pAddrUrls) {
|
|
char* url = ((SValueNode*)pNode)->literal;
|
|
if (strlen(url) >= TSDB_STREAM_NOTIFY_URL_LEN) {
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR,
|
|
"notification address \"%s\" exceed maximum length %d", url,
|
|
TSDB_STREAM_NOTIFY_URL_LEN);
|
|
goto _err;
|
|
}
|
|
if (!validateNotifyUrl(url)) {
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR,
|
|
"invalid notification address \"%s\"", url);
|
|
goto _err;
|
|
}
|
|
}
|
|
|
|
SStreamNotifyOptions* pNotifyOptions = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_STREAM_NOTIFY_OPTIONS, (SNode**)&pNotifyOptions);
|
|
CHECK_MAKE_NODE(pNotifyOptions);
|
|
pNotifyOptions->pAddrUrls = pAddrUrls;
|
|
pNotifyOptions->pWhere = pWhere;
|
|
pNotifyOptions->eventType = eventType;
|
|
pNotifyOptions->notifyType = notifyType;
|
|
return (SNode*)pNotifyOptions;
|
|
_err:
|
|
nodesDestroyList(pAddrUrls);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createCreateStreamStmt(SAstCreateContext* pCxt, bool ignoreExists, SNode* pStream, SNode* pTrigger,
|
|
SNode* pOutTable, SNode* pQuery) {
|
|
SCreateStreamStmt* pStmt = NULL;
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_CREATE_STREAM_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
|
|
if (pOutTable && ((SStreamOutTableNode*)pOutTable)->pOutTable) {
|
|
tstrncpy(pStmt->targetDbName, ((SRealTableNode*)((SStreamOutTableNode*)pOutTable)->pOutTable)->table.dbName,
|
|
TSDB_DB_NAME_LEN);
|
|
tstrncpy(pStmt->targetTabName, ((SRealTableNode*)((SStreamOutTableNode*)pOutTable)->pOutTable)->table.tableName,
|
|
TSDB_TABLE_NAME_LEN);
|
|
}
|
|
|
|
if (pStream) {
|
|
tstrncpy(pStmt->streamDbName, ((SStreamNode*)pStream)->dbName, TSDB_DB_NAME_LEN);
|
|
tstrncpy(pStmt->streamName, ((SStreamNode*)pStream)->streamName, TSDB_STREAM_NAME_LEN);
|
|
} else {
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, "stream name cannot be empty");
|
|
goto _err;
|
|
}
|
|
nodesDestroyNode(pStream);
|
|
|
|
pStmt->ignoreExists = ignoreExists;
|
|
pStmt->pTrigger = pTrigger;
|
|
pStmt->pQuery = pQuery;
|
|
pStmt->pTags = pOutTable ? ((SStreamOutTableNode*)pOutTable)->pTags : NULL;
|
|
pStmt->pSubtable = pOutTable ? ((SStreamOutTableNode*)pOutTable)->pSubtable : NULL;
|
|
pStmt->pCols = pOutTable ? ((SStreamOutTableNode*)pOutTable)->pCols : NULL;
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
nodesDestroyNode(pOutTable);
|
|
nodesDestroyNode(pQuery);
|
|
nodesDestroyNode(pTrigger);
|
|
nodesDestroyNode(pQuery);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createDropStreamStmt(SAstCreateContext* pCxt, bool ignoreNotExists, SNodeList* pStreamList) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SDropStreamStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_DROP_STREAM_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
|
|
if (pStreamList) {
|
|
pStmt->pStreamList = pStreamList;
|
|
} else {
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, "stream name cannot be empty");
|
|
goto _err;
|
|
}
|
|
|
|
pStmt->ignoreNotExists = ignoreNotExists;
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
nodesDestroyList(pStreamList);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createPauseStreamStmt(SAstCreateContext* pCxt, bool ignoreNotExists, SNode* pStream) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SPauseStreamStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_PAUSE_STREAM_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
if (pStream) {
|
|
tstrncpy(pStmt->streamDbName, ((SStreamNode*)pStream)->dbName, TSDB_DB_NAME_LEN);
|
|
tstrncpy(pStmt->streamName, ((SStreamNode*)pStream)->streamName, TSDB_STREAM_NAME_LEN);
|
|
} else {
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, "stream name cannot be empty");
|
|
goto _err;
|
|
}
|
|
nodesDestroyNode(pStream);
|
|
pStmt->ignoreNotExists = ignoreNotExists;
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createResumeStreamStmt(SAstCreateContext* pCxt, bool ignoreNotExists, bool ignoreUntreated, SNode* pStream) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SResumeStreamStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_RESUME_STREAM_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
if (pStream) {
|
|
tstrncpy(pStmt->streamDbName, ((SStreamNode*)pStream)->dbName, TSDB_DB_NAME_LEN);
|
|
tstrncpy(pStmt->streamName, ((SStreamNode*)pStream)->streamName, TSDB_STREAM_NAME_LEN);
|
|
} else {
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, "stream name cannot be empty");
|
|
goto _err;
|
|
}
|
|
nodesDestroyNode(pStream);
|
|
pStmt->ignoreNotExists = ignoreNotExists;
|
|
pStmt->ignoreUntreated = ignoreUntreated;
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createRecalcStreamStmt(SAstCreateContext* pCxt, SNode* pStream, SNode* pRange) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SRecalcStreamStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_RECALCULATE_STREAM_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
if (pStream) {
|
|
tstrncpy(pStmt->streamDbName, ((SStreamNode*)pStream)->dbName, TSDB_DB_NAME_LEN);
|
|
tstrncpy(pStmt->streamName, ((SStreamNode*)pStream)->streamName, TSDB_STREAM_NAME_LEN);
|
|
} else {
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, "stream name cannot be empty");
|
|
goto _err;
|
|
}
|
|
pStmt->pRange = pRange;
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createKillStmt(SAstCreateContext* pCxt, ENodeType type, const SToken* pId) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SKillStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(type, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
pStmt->targetId = taosStr2Int32(pId->z, NULL, 10);
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createKillQueryStmt(SAstCreateContext* pCxt, const SToken* pQueryId) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SKillQueryStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_KILL_QUERY_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
(void)trimString(pQueryId->z, pQueryId->n, pStmt->queryId, sizeof(pStmt->queryId) - 1);
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createBalanceVgroupStmt(SAstCreateContext* pCxt) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SBalanceVgroupStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_BALANCE_VGROUP_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createAssignLeaderStmt(SAstCreateContext* pCxt) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SAssignLeaderStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_ASSIGN_LEADER_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createBalanceVgroupLeaderStmt(SAstCreateContext* pCxt, const SToken* pVgId) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SBalanceVgroupLeaderStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_BALANCE_VGROUP_LEADER_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
if (NULL != pVgId && NULL != pVgId->z) {
|
|
pStmt->vgId = taosStr2Int32(pVgId->z, NULL, 10);
|
|
}
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createBalanceVgroupLeaderDBNameStmt(SAstCreateContext* pCxt, const SToken* pDbName) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SBalanceVgroupLeaderStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_BALANCE_VGROUP_LEADER_DATABASE_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
if (NULL != pDbName) {
|
|
COPY_STRING_FORM_ID_TOKEN(pStmt->dbName, pDbName);
|
|
}
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createSetVgroupKeepVersionStmt(SAstCreateContext* pCxt, const SToken* pVgId, const SToken* pKeepVersion) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SSetVgroupKeepVersionStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_SET_VGROUP_KEEP_VERSION_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
if (NULL != pVgId && NULL != pVgId->z) {
|
|
pStmt->vgId = taosStr2Int32(pVgId->z, NULL, 10);
|
|
}
|
|
if (NULL != pKeepVersion && NULL != pKeepVersion->z) {
|
|
pStmt->keepVersion = taosStr2Int64(pKeepVersion->z, NULL, 10);
|
|
}
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createMergeVgroupStmt(SAstCreateContext* pCxt, const SToken* pVgId1, const SToken* pVgId2) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SMergeVgroupStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_MERGE_VGROUP_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
pStmt->vgId1 = taosStr2Int32(pVgId1->z, NULL, 10);
|
|
pStmt->vgId2 = taosStr2Int32(pVgId2->z, NULL, 10);
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createRedistributeVgroupStmt(SAstCreateContext* pCxt, const SToken* pVgId, SNodeList* pDnodes) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SRedistributeVgroupStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_REDISTRIBUTE_VGROUP_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
pStmt->vgId = taosStr2Int32(pVgId->z, NULL, 10);
|
|
pStmt->pDnodes = pDnodes;
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
nodesDestroyList(pDnodes);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createSplitVgroupStmt(SAstCreateContext* pCxt, const SToken* pVgId, bool force) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SSplitVgroupStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_SPLIT_VGROUP_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
pStmt->vgId = taosStr2Int32(pVgId->z, NULL, 10);
|
|
pStmt->force = force;
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createSyncdbStmt(SAstCreateContext* pCxt, const SToken* pDbName) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SNode* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_SYNCDB_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
return pStmt;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createGrantStmt(SAstCreateContext* pCxt, void* resouces, SPrivLevelArgs* pPrivLevel, SToken* pPrincipal,
|
|
SNode* pCond, int8_t optrType) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
CHECK_NAME(checkRoleName(pCxt, pPrincipal, false));
|
|
SGrantStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_GRANT_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
pStmt->optrType = optrType;
|
|
COPY_STRING_FORM_ID_TOKEN(pStmt->principal, pPrincipal);
|
|
switch (optrType) {
|
|
case TSDB_ALTER_ROLE_LOCK:
|
|
break;
|
|
case TSDB_ALTER_ROLE_PRIVILEGES: {
|
|
CHECK_NAME(checkObjName(pCxt, &pPrivLevel->first, false));
|
|
CHECK_NAME(checkTableName(pCxt, &pPrivLevel->second));
|
|
pStmt->privileges = *(SPrivSetArgs*)resouces;
|
|
if(pStmt->privileges.nPrivArgs <= 0) {
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, "Unknown privilege type");
|
|
goto _err;
|
|
}
|
|
if (TK_NK_NIL != pPrivLevel->first.type) {
|
|
COPY_STRING_FORM_ID_TOKEN(pStmt->objName, &pPrivLevel->first);
|
|
}
|
|
if (TK_NK_NIL != pPrivLevel->second.type) {
|
|
COPY_STRING_FORM_ID_TOKEN(pStmt->tabName, &pPrivLevel->second);
|
|
}
|
|
pStmt->privileges.objType = pPrivLevel->objType;
|
|
pStmt->pCond = pCond;
|
|
break;
|
|
}
|
|
case TSDB_ALTER_ROLE_ROLE: {
|
|
SToken* pRole = (SToken*)resouces;
|
|
CHECK_NAME(checkRoleName(pCxt, pRole, false));
|
|
COPY_STRING_FORM_ID_TOKEN(pStmt->roleName, pRole);
|
|
break;
|
|
}
|
|
default:
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, "unsupported grant type");
|
|
goto _err;
|
|
}
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
nodesDestroyNode(pCond);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createRevokeStmt(SAstCreateContext* pCxt, void* resouces, SPrivLevelArgs* pPrivLevel, SToken* pPrincipal,
|
|
SNode* pCond, int8_t optrType) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
CHECK_NAME(checkUserName(pCxt, pPrincipal));
|
|
SRevokeStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_REVOKE_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
pStmt->optrType = optrType;
|
|
COPY_STRING_FORM_ID_TOKEN(pStmt->principal, pPrincipal);
|
|
if (optrType == TSDB_ALTER_ROLE_PRIVILEGES) {
|
|
CHECK_NAME(checkDbName(pCxt, &pPrivLevel->first, false));
|
|
CHECK_NAME(checkTableName(pCxt, &pPrivLevel->second));
|
|
pStmt->privileges = *(SPrivSetArgs*)resouces;
|
|
if (TK_NK_NIL != pPrivLevel->first.type) {
|
|
COPY_STRING_FORM_ID_TOKEN(pStmt->objName, &pPrivLevel->first);
|
|
}
|
|
if (TK_NK_NIL != pPrivLevel->second.type) {
|
|
COPY_STRING_FORM_ID_TOKEN(pStmt->tabName, &pPrivLevel->second);
|
|
}
|
|
pStmt->privileges.objType = pPrivLevel->objType;
|
|
pStmt->pCond = pCond;
|
|
} else if (optrType == TSDB_ALTER_ROLE_ROLE) {
|
|
SToken* pRole = (SToken*)resouces;
|
|
CHECK_NAME(checkRoleName(pCxt, pRole, false));
|
|
COPY_STRING_FORM_ID_TOKEN(pStmt->roleName, pRole);
|
|
} else {
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, "unsupported revoke type");
|
|
goto _err;
|
|
}
|
|
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
nodesDestroyNode(pCond);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createFuncForDelete(SAstCreateContext* pCxt, const char* pFuncName) {
|
|
SFunctionNode* pFunc = NULL;
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_FUNCTION, (SNode**)&pFunc);
|
|
CHECK_MAKE_NODE(pFunc);
|
|
snprintf(pFunc->functionName, sizeof(pFunc->functionName), "%s", pFuncName);
|
|
SNode* pCol = createPrimaryKeyCol(pCxt, NULL);
|
|
CHECK_MAKE_NODE(pCol);
|
|
pCxt->errCode = nodesListMakeStrictAppend(&pFunc->pParameterList, pCol);
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
return (SNode*)pFunc;
|
|
_err:
|
|
nodesDestroyNode((SNode*)pFunc);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createDeleteStmt(SAstCreateContext* pCxt, SNode* pTable, SNode* pWhere) {
|
|
SDeleteStmt* pStmt = NULL;
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_DELETE_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
pStmt->pFromTable = pTable;
|
|
pStmt->pWhere = pWhere;
|
|
pStmt->pCountFunc = createFuncForDelete(pCxt, "count");
|
|
pStmt->pFirstFunc = createFuncForDelete(pCxt, "first");
|
|
pStmt->pLastFunc = createFuncForDelete(pCxt, "last");
|
|
CHECK_MAKE_NODE(pStmt->pCountFunc);
|
|
CHECK_MAKE_NODE(pStmt->pFirstFunc);
|
|
CHECK_MAKE_NODE(pStmt->pLastFunc);
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
nodesDestroyNode((SNode*)pStmt);
|
|
nodesDestroyNode(pTable);
|
|
nodesDestroyNode(pWhere);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createInsertStmt(SAstCreateContext* pCxt, SNode* pTable, SNodeList* pCols, SNode* pQuery) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SInsertStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_INSERT_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
pStmt->pTable = pTable;
|
|
pStmt->pCols = pCols;
|
|
pStmt->pQuery = pQuery;
|
|
if (QUERY_NODE_SELECT_STMT == nodeType(pQuery)) {
|
|
tstrncpy(((SSelectStmt*)pQuery)->stmtName, ((STableNode*)pTable)->tableAlias, TSDB_TABLE_NAME_LEN);
|
|
} else if (QUERY_NODE_SET_OPERATOR == nodeType(pQuery)) {
|
|
tstrncpy(((SSetOperator*)pQuery)->stmtName, ((STableNode*)pTable)->tableAlias, TSDB_TABLE_NAME_LEN);
|
|
}
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
nodesDestroyNode(pTable);
|
|
nodesDestroyNode(pQuery);
|
|
nodesDestroyList(pCols);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createCreateRsmaStmt(SAstCreateContext* pCxt, bool ignoreExists, SToken* rsmaName, SNode* pRealTable,
|
|
SNodeList* pFuncs, SNodeList* pIntervals) {
|
|
SCreateRsmaStmt* pStmt = NULL;
|
|
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
CHECK_NAME(checkRsmaName(pCxt, rsmaName));
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_CREATE_RSMA_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
|
|
pStmt->ignoreExists = ignoreExists;
|
|
pStmt->pFuncs = pFuncs;
|
|
pStmt->pIntervals = pIntervals;
|
|
COPY_STRING_FORM_ID_TOKEN(pStmt->rsmaName, rsmaName);
|
|
|
|
SRealTableNode* pTable = (SRealTableNode*)pRealTable;
|
|
memcpy(pStmt->dbName, pTable->table.dbName, TSDB_DB_NAME_LEN);
|
|
memcpy(pStmt->tableName, pTable->table.tableName, TSDB_TABLE_NAME_LEN);
|
|
nodesDestroyNode(pRealTable);
|
|
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
nodesDestroyNode((SNode*)pStmt);
|
|
nodesDestroyList(pFuncs);
|
|
nodesDestroyNode(pRealTable);
|
|
nodesDestroyList(pIntervals);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createDropRsmaStmt(SAstCreateContext* pCxt, bool ignoreNotExists, SNode* pRealTable) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SDropRsmaStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_DROP_RSMA_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
|
|
pStmt->ignoreNotExists = ignoreNotExists;
|
|
SRealTableNode* pTableNode = (SRealTableNode*)pRealTable;
|
|
|
|
memcpy(pStmt->rsmaName, pTableNode->table.tableName, TSDB_TABLE_NAME_LEN);
|
|
memcpy(pStmt->dbName, pTableNode->table.dbName, TSDB_DB_NAME_LEN);
|
|
|
|
nodesDestroyNode(pRealTable);
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
nodesDestroyNode(pRealTable);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createAlterRsmaStmt(SAstCreateContext* pCxt, bool ignoreNotExists, SNode* pRsma, int8_t alterType,
|
|
void* alterInfo) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SAlterRsmaStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_ALTER_RSMA_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
pStmt->ignoreNotExists = ignoreNotExists;
|
|
SRealTableNode* pTableNode = (SRealTableNode*)pRsma;
|
|
|
|
memcpy(pStmt->rsmaName, pTableNode->table.tableName, TSDB_TABLE_NAME_LEN);
|
|
memcpy(pStmt->dbName, pTableNode->table.dbName, TSDB_DB_NAME_LEN);
|
|
nodesDestroyNode(pRsma);
|
|
|
|
pStmt->alterType = alterType;
|
|
switch (alterType) {
|
|
case TSDB_ALTER_RSMA_FUNCTION: {
|
|
pStmt->pFuncs = (SNodeList*)alterInfo;
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createShowCreateRsmaStmt(SAstCreateContext* pCxt, ENodeType type, SNode* pRealTable) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SShowCreateRsmaStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(type, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
tstrncpy(pStmt->dbName, ((SRealTableNode*)pRealTable)->table.dbName, sizeof(pStmt->dbName));
|
|
tstrncpy(pStmt->rsmaName, ((SRealTableNode*)pRealTable)->table.tableName, sizeof(pStmt->rsmaName));
|
|
nodesDestroyNode(pRealTable);
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
nodesDestroyNode(pRealTable);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createRollupStmt(SAstCreateContext* pCxt, SToken* pDbName, SNode* pStart, SNode* pEnd) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
CHECK_NAME(checkDbName(pCxt, pDbName, false));
|
|
SRollupDatabaseStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_ROLLUP_DATABASE_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
COPY_STRING_FORM_ID_TOKEN(pStmt->dbName, pDbName);
|
|
pStmt->pStart = pStart;
|
|
pStmt->pEnd = pEnd;
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
nodesDestroyNode(pStart);
|
|
nodesDestroyNode(pEnd);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createRollupVgroupsStmt(SAstCreateContext* pCxt, SNode* pDbName, SNodeList* vgidList, SNode* pStart,
|
|
SNode* pEnd) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
if (NULL == pDbName) {
|
|
snprintf(pCxt->pQueryCxt->pMsg, pCxt->pQueryCxt->msgLen, "database not specified");
|
|
pCxt->errCode = TSDB_CODE_PAR_DB_NOT_SPECIFIED;
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
}
|
|
SRollupVgroupsStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_ROLLUP_VGROUPS_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
pStmt->pDbName = pDbName;
|
|
pStmt->vgidList = vgidList;
|
|
pStmt->pStart = pStart;
|
|
pStmt->pEnd = pEnd;
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
nodesDestroyNode(pDbName);
|
|
nodesDestroyList(vgidList);
|
|
nodesDestroyNode(pStart);
|
|
nodesDestroyNode(pEnd);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createCreateTSMAStmt(SAstCreateContext* pCxt, bool ignoreExists, SToken* tsmaName, SNode* pOptions,
|
|
SNode* pRealTable, SNode* pInterval) {
|
|
SCreateTSMAStmt* pStmt = NULL;
|
|
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
CHECK_NAME(checkTsmaName(pCxt, tsmaName));
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_CREATE_TSMA_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
|
|
pStmt->ignoreExists = ignoreExists;
|
|
if (!pOptions) {
|
|
// recursive tsma
|
|
pStmt->pOptions = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_TSMA_OPTIONS, (SNode**)&pStmt->pOptions);
|
|
CHECK_MAKE_NODE(pStmt->pOptions);
|
|
pStmt->pOptions->recursiveTsma = true;
|
|
} else {
|
|
pStmt->pOptions = (STSMAOptions*)pOptions;
|
|
}
|
|
pStmt->pOptions->pInterval = pInterval;
|
|
COPY_STRING_FORM_ID_TOKEN(pStmt->tsmaName, tsmaName);
|
|
|
|
SRealTableNode* pTable = (SRealTableNode*)pRealTable;
|
|
memcpy(pStmt->dbName, pTable->table.dbName, TSDB_DB_NAME_LEN);
|
|
memcpy(pStmt->tableName, pTable->table.tableName, TSDB_TABLE_NAME_LEN);
|
|
memcpy(pStmt->originalTbName, pTable->table.tableName, TSDB_TABLE_NAME_LEN);
|
|
nodesDestroyNode(pRealTable);
|
|
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
nodesDestroyNode((SNode*)pStmt);
|
|
nodesDestroyNode(pOptions);
|
|
nodesDestroyNode(pRealTable);
|
|
nodesDestroyNode(pInterval);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createTSMAOptions(SAstCreateContext* pCxt, SNodeList* pFuncs) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
STSMAOptions* pOptions = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_TSMA_OPTIONS, (SNode**)&pOptions);
|
|
CHECK_MAKE_NODE(pOptions);
|
|
pOptions->pFuncs = pFuncs;
|
|
return (SNode*)pOptions;
|
|
_err:
|
|
nodesDestroyList(pFuncs);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createDefaultTSMAOptions(SAstCreateContext* pCxt) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
STSMAOptions* pOptions = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_TSMA_OPTIONS, (SNode**)&pOptions);
|
|
CHECK_MAKE_NODE(pOptions);
|
|
return (SNode*)pOptions;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createDropTSMAStmt(SAstCreateContext* pCxt, bool ignoreNotExists, SNode* pRealTable) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SDropTSMAStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_DROP_TSMA_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
|
|
pStmt->ignoreNotExists = ignoreNotExists;
|
|
SRealTableNode* pTableNode = (SRealTableNode*)pRealTable;
|
|
|
|
memcpy(pStmt->tsmaName, pTableNode->table.tableName, TSDB_TABLE_NAME_LEN);
|
|
memcpy(pStmt->dbName, pTableNode->table.dbName, TSDB_DB_NAME_LEN);
|
|
|
|
nodesDestroyNode(pRealTable);
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
nodesDestroyNode(pRealTable);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createShowTSMASStmt(SAstCreateContext* pCxt, SNode* dbName) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
|
|
SShowStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_SHOW_TSMAS_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
|
|
pStmt->pDbName = dbName;
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
nodesDestroyNode(dbName);
|
|
return NULL;
|
|
}
|
|
SNode* createShowDiskUsageStmt(SAstCreateContext* pCxt, SNode* dbName, ENodeType type) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
if (NULL == dbName) {
|
|
snprintf(pCxt->pQueryCxt->pMsg, pCxt->pQueryCxt->msgLen, "database not specified");
|
|
pCxt->errCode = TSDB_CODE_PAR_SYNTAX_ERROR;
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
}
|
|
|
|
SShowStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(type, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
|
|
pStmt->pDbName = dbName;
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
nodesDestroyNode(dbName);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createShowStreamsStmt(SAstCreateContext* pCxt, SNode* pDbName, ENodeType type) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
|
|
if (needDbShowStmt(type) && NULL == pDbName) {
|
|
snprintf(pCxt->pQueryCxt->pMsg, pCxt->pQueryCxt->msgLen, "database not specified");
|
|
pCxt->errCode = TSDB_CODE_PAR_SYNTAX_ERROR;
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
}
|
|
|
|
SShowStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(type, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
pStmt->withFull = false;
|
|
pStmt->pDbName = pDbName;
|
|
|
|
return (SNode*)pStmt;
|
|
|
|
_err:
|
|
nodesDestroyNode(pDbName);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createScanStmt(SAstCreateContext* pCxt, SToken* pDbName, SNode* pStart, SNode* pEnd) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
CHECK_NAME(checkDbName(pCxt, pDbName, false));
|
|
SScanDatabaseStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_SCAN_DATABASE_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
COPY_STRING_FORM_ID_TOKEN(pStmt->dbName, pDbName);
|
|
pStmt->pStart = pStart;
|
|
pStmt->pEnd = pEnd;
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
nodesDestroyNode(pStart);
|
|
nodesDestroyNode(pEnd);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createScanVgroupsStmt(SAstCreateContext* pCxt, SNode* pDbName, SNodeList* vgidList, SNode* pStart, SNode* pEnd) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
if (NULL == pDbName) {
|
|
snprintf(pCxt->pQueryCxt->pMsg, pCxt->pQueryCxt->msgLen, "database not specified");
|
|
pCxt->errCode = TSDB_CODE_PAR_DB_NOT_SPECIFIED;
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
}
|
|
SScanVgroupsStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_SCAN_VGROUPS_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
pStmt->pDbName = pDbName;
|
|
pStmt->vgidList = vgidList;
|
|
pStmt->pStart = pStart;
|
|
pStmt->pEnd = pEnd;
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
nodesDestroyNode(pDbName);
|
|
nodesDestroyList(vgidList);
|
|
nodesDestroyNode(pStart);
|
|
nodesDestroyNode(pEnd);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createShowScansStmt(SAstCreateContext* pCxt, ENodeType type) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SShowScansStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(type, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createShowScanDetailsStmt(SAstCreateContext* pCxt, SNode* pScanIdNode) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SShowScanDetailsStmt* pStmt = NULL;
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_SHOW_SCAN_DETAILS_STMT, (SNode**)&pStmt);
|
|
CHECK_MAKE_NODE(pStmt);
|
|
pStmt->pScanId = pScanIdNode;
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
nodesDestroyNode(pScanIdNode);
|
|
return NULL;
|
|
}
|
|
|
|
SNode* createAlterAllDnodeTLSStmt(SAstCreateContext* pCxt, SToken* alterName) {
|
|
CHECK_PARSER_STATUS(pCxt);
|
|
SAlterDnodeStmt* pStmt = NULL;
|
|
static char* tls = "TLS";
|
|
if (NULL == alterName || alterName->n <= 0) {
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, "alter name is empty");
|
|
goto _err;
|
|
}
|
|
|
|
if (alterName->n == strlen(tls) && taosStrncasecmp(alterName->z, tls, alterName->n) == 0) {
|
|
pCxt->errCode = nodesMakeNode(QUERY_NODE_ALTER_DNODES_RELOAD_TLS_STMT, (SNode**)&pStmt);
|
|
|
|
memcpy(pStmt->config, "reload", strlen("reload"));
|
|
memcpy(pStmt->value, "tls", strlen("tls"));
|
|
pStmt->dnodeId = -1;
|
|
} else {
|
|
pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, "alter is not supported");
|
|
goto _err;
|
|
}
|
|
|
|
CHECK_MAKE_NODE(pStmt);
|
|
|
|
return (SNode*)pStmt;
|
|
_err:
|
|
return NULL;
|
|
}
|