diff --git a/include/common/tmsg.h b/include/common/tmsg.h index 1e3deed987..102ee7973a 100644 --- a/include/common/tmsg.h +++ b/include/common/tmsg.h @@ -247,6 +247,7 @@ typedef enum ENodeType { QUERY_NODE_VIEW, QUERY_NODE_WINDOW_OFFSET, QUERY_NODE_COUNT_WINDOW, + QUERY_NODE_TSMA_OPTIONS, // Statement nodes are used in parser and planner module. QUERY_NODE_SET_OPERATOR = 100, @@ -368,6 +369,10 @@ typedef enum ENodeType { QUERY_NODE_SHOW_GRANTS_FULL_STMT, QUERY_NODE_SHOW_GRANTS_LOGS_STMT, QUERY_NODE_SHOW_CLUSTER_MACHINES_STMT, + QUERY_NODE_CREATE_TSMA_STMT, + QUERY_NODE_SHOW_CREATE_TSMA_STMT, + QUERY_NODE_SHOW_TSMAS_STMT, + QUERY_NODE_DROP_TSMA_STMT, // logic plan node QUERY_NODE_LOGIC_PLAN_SCAN = 1000, diff --git a/include/libs/nodes/cmdnodes.h b/include/libs/nodes/cmdnodes.h index d0a4608cb6..1d94936873 100644 --- a/include/libs/nodes/cmdnodes.h +++ b/include/libs/nodes/cmdnodes.h @@ -590,6 +590,37 @@ typedef struct SSplitVgroupStmt { int32_t vgId; } SSplitVgroupStmt; +typedef struct STSMAOptions { + ENodeType type; + SNodeList* pFuncs; + SNodeList* pCols; + SNode* pInterval; + uint8_t tsPrecision; +} STSMAOptions; + +typedef struct SCreateTSMAStmt { + ENodeType type; + bool ignoreExists; + char tsmaName[TSDB_INDEX_NAME_LEN]; + char dbName[TSDB_DB_NAME_LEN]; + char tableName[TSDB_TABLE_NAME_LEN]; + STSMAOptions* pOptions; + SMCreateSmaReq* pReq; +} SCreateTSMAStmt; + +typedef struct SShowCreateTSMAStmt { + ENodeType type; + char dbName[TSDB_DB_NAME_LEN]; + char tsmaName[TSDB_INDEX_NAME_LEN]; +}SShowCreateTSMAStmt; + +typedef struct SDropTSMAStmt { + ENodeType type; + bool ignoreNotExists; + char dbName[TSDB_DB_NAME_LEN]; + char tsmaName[TSDB_INDEX_NAME_LEN]; +} SDropTSMAStmt; + #ifdef __cplusplus } #endif diff --git a/source/libs/nodes/src/nodesCodeFuncs.c b/source/libs/nodes/src/nodesCodeFuncs.c index ad01ab47dd..39d6b061b3 100644 --- a/source/libs/nodes/src/nodesCodeFuncs.c +++ b/source/libs/nodes/src/nodesCodeFuncs.c @@ -7311,6 +7311,131 @@ static int32_t jsonToInsertStmt(const SJson* pJson, void* pObj) { return code; } +static const char* jkTSMAOptionFuncs = "Funcs"; +static const char* jkTSMAOptionCols = "Cols"; +static const char* jkTSMAOptionInterval = "Interval"; +static const char* jkTSMAOptionTsPrecision = "Precision"; + +static int32_t tsmaOptionToJson(const void* pObj, SJson* pJson) { + const STSMAOptions* pNode = (const STSMAOptions*)pObj; + int32_t code = nodeListToJson(pJson, jkTSMAOptionFuncs, pNode->pFuncs); + if (TSDB_CODE_SUCCESS == code) { + code = nodeListToJson(pJson, jkTSMAOptionCols, pNode->pCols); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddObject(pJson, jkTSMAOptionInterval, nodeToJson, pNode->pInterval); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddIntegerToObject(pJson, jkTSMAOptionTsPrecision, pNode->tsPrecision); + } + return code; +} + +static int32_t jsonToTSMAOption(const SJson* pJson, void* pObj) { + STSMAOptions* pNode = (STSMAOptions*)pObj; + int32_t code = jsonToNodeList(pJson, jkTSMAOptionFuncs, &pNode->pFuncs); + if (TSDB_CODE_SUCCESS == code) { + code = jsonToNodeList(pJson, jkTSMAOptionCols, &pNode->pCols); + } + if (TSDB_CODE_SUCCESS == code) { + code = jsonToNodeObject(pJson, jkTSMAOptionInterval, &pNode->pInterval); + } + if (TSDB_CODE_SUCCESS == code) { + tjsonGetUTinyIntValue(pJson, jkTSMAOptionTsPrecision, &pNode->tsPrecision); + } + return code; +} + +static const char* jkCreateTSMAStmtIgnoreExists = "IgnoreExists"; +static const char* jkCreateTSMAStmtTsmaName = "TSMAName"; +static const char* jkCreateTSMAStmtDbName = "DbName"; +static const char* jkCreateTSMAStmtTableName = "TableName"; +static const char* jkCreateTSMAStmtpOptions = "Options"; + +static int32_t createTSMAStmtToJson(const void* pObj, SJson* pJson) { + const SCreateTSMAStmt* pNode = (const SCreateTSMAStmt*)pObj; + int32_t code = tjsonAddBoolToObject(pJson, jkCreateTSMAStmtIgnoreExists, pNode->ignoreExists); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddStringToObject(pJson, jkCreateTSMAStmtTsmaName, pNode->tsmaName); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddStringToObject(pJson, jkCreateTSMAStmtDbName, pNode->dbName); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddStringToObject(pJson, jkCreateTSMAStmtTableName, pNode->tableName); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddObject(pJson, jkCreateTSMAStmtpOptions, nodeToJson, pNode->pOptions); + } +} + +static int32_t jsonToCreateTSMAStmt(const SJson* pJson, void* pObj) { + SCreateTSMAStmt* pNode = (SCreateTSMAStmt*)pObj; + int32_t code = tjsonGetBoolValue(pJson, jkCreateTSMAStmtIgnoreExists, &pNode->ignoreExists); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetStringValue(pJson, jkCreateTSMAStmtTsmaName, pNode->tsmaName); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetStringValue(pJson, jkCreateTSMAStmtDbName, pNode->dbName); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetStringValue(pJson, jkCreateTSMAStmtTableName, pNode->tableName); + } + if (TSDB_CODE_SUCCESS == code) { + code = jsonToNodeObject(pJson, jkCreateTSMAStmtpOptions, &pNode->pOptions); + } + return code; +} + +static const char* jkDropTSMAStmtIgnoreNotExists = "IgnoreNotExists"; +static const char* jkDropTSMAStmtDbName = "DbName"; +static const char* jkDropTSMAStmtTsmaName = "TSMAName"; + +static int32_t dropTSMAStmtToJson(const void* pObj, SJson* pJson) { + const SDropTSMAStmt* pNode = (const SDropTSMAStmt*)pObj; + int32_t code = tjsonAddBoolToObject(pJson, jkDropTSMAStmtIgnoreNotExists, pNode->ignoreNotExists); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddStringToObject(pJson, jkDropTSMAStmtDbName, pNode->dbName); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddStringToObject(pJson, jkDropTSMAStmtTsmaName, pNode->tsmaName); + } + return code; +} + +static int32_t jsonToDropTSMAStmt(const SJson* pJson, void* pObj) { + SDropTSMAStmt* pNode = (SDropTSMAStmt*)pObj; + int32_t code = tjsonGetBoolValue(pJson, jkDropTSMAStmtIgnoreNotExists, &pNode->ignoreNotExists); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetStringValue(pJson, jkDropTSMAStmtDbName, pNode->dbName); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetStringValue(pJson, jkDropTSMAStmtTsmaName, pNode->tsmaName); + } + return code; +} + +static const char* jkShowCreateTSMAStmtDbName = "DbName"; +static const char* jkShowCreateTSMAStmtTsmaName = "TSMAName"; + +static int32_t showCreateTSMAStmtToJson(const void* pObj, SJson* pJson) { + const SShowCreateTSMAStmt* pNode = (const SShowCreateTSMAStmt*)pObj; + int32_t code = tjsonAddStringToObject(pJson, jkShowCreateTSMAStmtDbName, pNode->dbName); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddStringToObject(pJson, jkShowCreateTSMAStmtTsmaName, pNode->tsmaName); + } + return code; +} + +static int32_t jsonToShowCreateTSMAStmt(const SJson* pJson, void* pObj) { + SShowCreateTSMAStmt* pNode = (SShowCreateTSMAStmt*)pObj; + int32_t code = tjsonGetStringValue(pJson, jkShowCreateTSMAStmtDbName, pNode->dbName); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetStringValue(pJson, jkShowCreateTSMAStmtTsmaName, pNode->tsmaName); + } + return code; +} + static int32_t specificNodeToJson(const void* pObj, SJson* pJson) { switch (nodeType(pObj)) { case QUERY_NODE_COLUMN: diff --git a/source/libs/parser/inc/parAst.h b/source/libs/parser/inc/parAst.h index b9df1b147c..702c1836de 100644 --- a/source/libs/parser/inc/parAst.h +++ b/source/libs/parser/inc/parAst.h @@ -274,6 +274,15 @@ SNode* createCreateViewStmt(SAstCreateContext* pCxt, bool orReplace, SNode* pVie SNode* createDropViewStmt(SAstCreateContext* pCxt, bool ignoreNotExists, SNode* pView); SNode* createShowCompactDetailsStmt(SAstCreateContext* pCxt, SNode* pCompactIdNode); SNode* createShowCompactsStmt(SAstCreateContext* pCxt, ENodeType type); + +SNode* createCreateTSMAStmt(SAstCreateContext* pCxt, bool ignoreExists, SToken* tsmaName, SNode* pOptions, + SNode* pRealTable, SNode* pInterval); +SNode* createTSMAOptions(SAstCreateContext* pCxt, SNodeList* pFuncs, SNodeList* pCols); +SNode* createDefaultTSMAOptions(SAstCreateContext* pCxt); +SNode* createDropTSMAStmt(SAstCreateContext* pCxt, bool ignoreNotExists, SNode* pRealTable); +SNode* createShowCreateTSMAStmt(SAstCreateContext* pCxt, SNode* pRealTable); +SNode* createShowTSMASStmt(SAstCreateContext* pCxt, SNode* dbName); + #ifdef __cplusplus } #endif diff --git a/source/libs/parser/inc/sql.y b/source/libs/parser/inc/sql.y index e036985823..1e24efd3a0 100755 --- a/source/libs/parser/inc/sql.y +++ b/source/libs/parser/inc/sql.y @@ -579,6 +579,32 @@ db_kind_opt(A) ::= . db_kind_opt(A) ::= USER. { A = SHOW_KIND_DATABASES_USER; } db_kind_opt(A) ::= SYSTEM. { A = SHOW_KIND_DATABASES_SYSTEM; } + +/************************************************ tsma ********************************************************/ +cmd ::= CREATE TSMA not_exists_opt(B) tsma_name(C) + ON full_table_name(E) tsma_opt(D) INTERVAL NK_LP duration_literal(F) NK_RP. { pCxt->pRootNode = createCreateTSMAStmt(pCxt, B, &C, D, E, releaseRawExprNode(pCxt, F)); } +cmd ::= DROP TSMA exists_opt(B) full_tsma_name(C). { pCxt->pRootNode = createDropTSMAStmt(pCxt, B, C); } +cmd ::= SHOW CREATE TSMA full_tsma_name(B). { pCxt->pRootNode = createShowCreateTSMAStmt(pCxt, B); } +cmd ::= SHOW db_name_cond_opt(B) TSMAS. { pCxt->pRootNode = createShowTSMASStmt(pCxt, B); } + +full_tsma_name(A) ::= tsma_name(B). { A = createRealTableNodeForIndexName(pCxt, NULL, &B); } +full_tsma_name(A) ::= db_name(B) NK_DOT tsma_name(C). { A = createRealTableNodeForIndexName(pCxt, &B, &C); } + +%type tsma_opt { SNode* } +%destructor tsma_opt { nodesDestroyNode($$); } +tsma_opt(A) ::= . { A = createDefaultTSMAOptions(pCxt); } +tsma_opt(A) ::= FUNCTION NK_LP tsma_func_list(B) NK_RP + COLUMN NK_LP col_name_list(C) NK_RP. { A = createTSMAOptions(pCxt, B, C); } + +%type tsma_func_list { SNodeList* } +%destructor tsma_func_list { nodesDestroyList($$); } +tsma_func_list(A) ::= tsma_func_name(B). { A = createNodeList(pCxt, B); } +tsma_func_list(A) ::= tsma_func_list(B) NK_COMMA tsma_func_name(C). { A = addNodeToList(pCxt, B, C); } + +%type tsma_func_name { SNode* } +%destructor tsma_func_name { nodesDestroyNode($$); } +tsma_func_name(A) ::= sma_func_name(B). { A = createFunctionNode(pCxt, &B, NULL); } + /************************************************ create index ********************************************************/ cmd ::= CREATE SMA INDEX not_exists_opt(D) col_name(A) ON full_table_name(B) index_options(C). { pCxt->pRootNode = createCreateIndexStmt(pCxt, INDEX_TYPE_SMA, D, A, B, NULL, C); } @@ -1052,6 +1078,10 @@ cgroup_name(A) ::= NK_ID(B). %destructor index_name { } index_name(A) ::= NK_ID(B). { A = B; } +%type tsma_name { SToken } +%destructor tsma_name { } +tsma_name(A) ::= NK_ID(B). { A = B; } + /************************************************ expression **********************************************************/ expr_or_subquery(A) ::= expression(B). { A = B; } //expr_or_subquery(A) ::= subquery(B). { A = createTempTableNode(pCxt, releaseRawExprNode(pCxt, B), NULL); } diff --git a/source/libs/parser/src/parAstCreater.c b/source/libs/parser/src/parAstCreater.c index 85eef1ad5a..b7d18c9eb6 100644 --- a/source/libs/parser/src/parAstCreater.c +++ b/source/libs/parser/src/parAstCreater.c @@ -2836,3 +2836,109 @@ SNode* createInsertStmt(SAstCreateContext* pCxt, SNode* pTable, SNodeList* pCols } return (SNode*)pStmt; } + +SNode* createCreateTSMAStmt(SAstCreateContext* pCxt, bool ignoreExists, SToken* tsmaName, SNode* pOptions, + SNode* pRealTable, SNode* pInterval) { + CHECK_PARSER_STATUS(pCxt); + if (!checkIndexName(pCxt, tsmaName)) return NULL; + + SCreateTSMAStmt* pStmt = (SCreateTSMAStmt*)nodesMakeNode(QUERY_NODE_CREATE_TSMA_STMT); + CHECK_OUT_OF_MEM(pStmt); + + pStmt->ignoreExists = ignoreExists; + pStmt->pOptions = (STSMAOptions*)pOptions; + pStmt->pOptions->pInterval = pInterval; + COPY_STRING_FORM_STR_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); + nodesDestroyNode(pRealTable); + + return (SNode*)pStmt; +} + +SNode* createTSMAOptions(SAstCreateContext* pCxt, SNodeList* pFuncs, SNodeList* pCols) { + CHECK_PARSER_STATUS(pCxt); + /* + SNode *pNode1, *pNode2; + SNodeList* pTSMAFuncs = nodesMakeList(); + CHECK_OUT_OF_MEM(pTSMAFuncs); + FOREACH(pNode1, pFuncs) { + FOREACH(pNode2, pCols) { + SFunctionNode* pFunc = (SFunctionNode*)nodesCloneNode(pNode1); + SColumnNode* pCol = (SColumnNode*)nodesCloneNode(pNode2); + if (!pFunc || !pCol || + (TSDB_CODE_SUCCESS != nodesListMakeAppend(&pFunc->pParameterList, (SNode*)pCol) || (pCol = NULL)) || + TSDB_CODE_SUCCESS != nodesListAppend(pTSMAFuncs, (SNode*)pFunc)) { + nodesDestroyNode((SNode*)pFunc); + nodesDestroyNode((SNode*)pCol); + nodesDestroyList(pTSMAFuncs); + pCxt->errCode = TSDB_CODE_OUT_OF_MEMORY; + snprintf(pCxt->pQueryCxt->pMsg, pCxt->pQueryCxt->msgLen, "Out of memory"); + return NULL; + } + } + } + */ + STSMAOptions* pOptions = (STSMAOptions*)nodesMakeNode(QUERY_NODE_TSMA_OPTIONS); + if (!pOptions) { + //nodesDestroyList(pTSMAFuncs); + pCxt->errCode = TSDB_CODE_OUT_OF_MEMORY; + snprintf(pCxt->pQueryCxt->pMsg, pCxt->pQueryCxt->msgLen, "Out of memory"); + return NULL; + } + pOptions->pFuncs = pFuncs; + pOptions->pCols = pCols; + + //nodesDestroyList(pFuncs); + //nodesDestroyList(pCols); + + return (SNode*)pOptions; +} + +SNode* createDefaultTSMAOptions(SAstCreateContext* pCxt) { + CHECK_PARSER_STATUS(pCxt); + STSMAOptions* pOptions = (STSMAOptions*)nodesMakeNode(QUERY_NODE_TSMA_OPTIONS); + CHECK_OUT_OF_MEM(pOptions); + return (SNode*)pOptions; +} + +SNode* createDropTSMAStmt(SAstCreateContext* pCxt, bool ignoreNotExists, SNode* pRealTable) { + CHECK_PARSER_STATUS(pCxt); + SDropTSMAStmt* pStmt = (SDropTSMAStmt*)nodesMakeNode(QUERY_NODE_DROP_TSMA_STMT); + CHECK_OUT_OF_MEM(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; +} + +SNode* createShowCreateTSMAStmt(SAstCreateContext* pCxt, SNode* pRealTable) { + CHECK_PARSER_STATUS(pCxt); + SShowCreateTSMAStmt* pStmt = (SShowCreateTSMAStmt*)nodesMakeNode(QUERY_NODE_SHOW_CREATE_TSMA_STMT); + CHECK_OUT_OF_MEM(pStmt); + + 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; +} + +SNode* createShowTSMASStmt(SAstCreateContext* pCxt, SNode* dbName) { + CHECK_PARSER_STATUS(pCxt); + + SShowStmt* pStmt = (SShowStmt*)nodesMakeNode(QUERY_NODE_SHOW_TSMAS_STMT); + CHECK_OUT_OF_MEM(pStmt); + + pStmt->pDbName = dbName; + return (SNode*)pStmt; +} diff --git a/source/libs/parser/src/parAstParser.c b/source/libs/parser/src/parAstParser.c index f746304730..b032c15e09 100644 --- a/source/libs/parser/src/parAstParser.c +++ b/source/libs/parser/src/parAstParser.c @@ -760,6 +760,20 @@ static int32_t collectMetaKeyFromDropViewStmt(SCollectMetaKeyCxt* pCxt, SDropVie return code; } +static int32_t collectMetaKeyFromCreateTSMAStmt(SCollectMetaKeyCxt* pCxt, SCreateTSMAStmt* pStmt) { + int32_t code; + code = reserveTableMetaInCache(pCxt->pParseCxt->acctId, pStmt->dbName, pStmt->tableName, pCxt->pMetaCache); + if (TSDB_CODE_SUCCESS == code) { + code = reserveTableVgroupInCache(pCxt->pParseCxt->acctId, pStmt->dbName, pStmt->tableName, pCxt->pMetaCache); + } + if (TSDB_CODE_SUCCESS == code) { + code = reserveDbVgInfoInCache(pCxt->pParseCxt->acctId, pStmt->dbName, pCxt->pMetaCache); + } + if (TSDB_CODE_SUCCESS == code) { + code = reserveDbCfgInCache(pCxt->pParseCxt->acctId, pStmt->dbName, pCxt->pMetaCache); + } + return code; +} static int32_t collectMetaKeyFromQuery(SCollectMetaKeyCxt* pCxt, SNode* pStmt) { pCxt->pStmt = pStmt; @@ -891,6 +905,10 @@ static int32_t collectMetaKeyFromQuery(SCollectMetaKeyCxt* pCxt, SNode* pStmt) { return collectMetaKeyFromCreateViewStmt(pCxt, (SCreateViewStmt*)pStmt); case QUERY_NODE_DROP_VIEW_STMT: return collectMetaKeyFromDropViewStmt(pCxt, (SDropViewStmt*)pStmt); + case QUERY_NODE_CREATE_TSMA_STMT: + return collectMetaKeyFromCreateTSMAStmt(pCxt, (SCreateTSMAStmt*)pStmt); + case QUERY_NODE_DROP_TSMA_STMT: + break; default: break; } diff --git a/source/libs/parser/src/parTokenizer.c b/source/libs/parser/src/parTokenizer.c index 3432a1c140..09696d057b 100644 --- a/source/libs/parser/src/parTokenizer.c +++ b/source/libs/parser/src/parTokenizer.c @@ -268,6 +268,8 @@ static SKeyword keywordTable[] = { {"TRIM", TK_TRIM}, {"TSDB_PAGESIZE", TK_TSDB_PAGESIZE}, {"TSERIES", TK_TSERIES}, + {"TSMA", TK_TSMA}, + {"TSMAS", TK_TSMAS}, {"TTL", TK_TTL}, {"UNION", TK_UNION}, {"UNSAFE", TK_UNSAFE}, diff --git a/source/libs/parser/src/parTranslater.c b/source/libs/parser/src/parTranslater.c index a078f8e2da..1e3596af63 100644 --- a/source/libs/parser/src/parTranslater.c +++ b/source/libs/parser/src/parTranslater.c @@ -10353,6 +10353,141 @@ static int32_t translateShowCreateView(STranslateContext* pCxt, SShowCreateViewS #endif } +static int32_t buildTSMAAst(STranslateContext* pCxt, SCreateTSMAStmt* pStmt, char** pAst, int32_t* pLen, char** pExpr, + int32_t* pExprLen) { + int32_t code = TSDB_CODE_SUCCESS; + SSampleAstInfo info = {0}; + info.createSmaIndex = true; + info.pDbName = pStmt->dbName; + info.pTableName = pStmt->tableName; + info.pFuncs = nodesCloneList(pStmt->pOptions->pFuncs); + info.pInterval = nodesCloneNode(pStmt->pOptions->pInterval); + if (!info.pFuncs || !info.pInterval) code = TSDB_CODE_OUT_OF_MEMORY; + if (code == TSDB_CODE_SUCCESS) { + code = buildSampleAst(pCxt, &info, pAst, pLen, pExpr, pExprLen); + } + clearSampleAstInfo(&info); + return code; +} + +static char* defaultTSMAFuncs[4] = {"MAX", "MIN", "SUM", "COUNT"}; + +static int32_t +translateTSMAFuncs(STranslateContext * pCxt, SCreateTSMAStmt* pStmt, STableMeta* pTableMeta) { + int32_t code = TSDB_CODE_SUCCESS; + if (!pStmt->pOptions->pFuncs) { + // add default funcs for TSMA + for (int32_t i = 0; i < sizeof(defaultTSMAFuncs) / sizeof(char*); ++i) { + SFunctionNode* pFunc = (SFunctionNode*)nodesMakeNode(QUERY_NODE_FUNCTION); + if (!pFunc || TSDB_CODE_SUCCESS != nodesListMakeAppend(&pStmt->pOptions->pFuncs, (SNode*)pFunc)) { + nodesDestroyNode((SNode*)pFunc); + code = TSDB_CODE_OUT_OF_MEMORY; + break; + } + strcpy(pFunc->functionName, defaultTSMAFuncs[i]); + } + // add all numeric cols + if (TSDB_CODE_SUCCESS == code) { + for (int32_t i = 0; i < pTableMeta->tableInfo.numOfColumns; ++i) { + const SSchema* schema = &pTableMeta->schema[i]; + if (!IS_NUMERIC_TYPE(schema->type)) continue; + SColumnNode* pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN); + if (!pCol || TSDB_CODE_SUCCESS != nodesListMakeAppend(&pStmt->pOptions->pCols, (SNode*)pCol)) { + nodesDestroyNode((SNode*)pCol); + code = TSDB_CODE_OUT_OF_MEMORY; + break; + } + strcpy(pCol->colName, schema->name); + } + } + } + if (TSDB_CODE_SUCCESS == code) { + // assemble funcs with columns + SNode *pNode1, *pNode2; + SNodeList* pTSMAFuncs = nodesMakeList(); + if (!pTSMAFuncs) { + code = TSDB_CODE_OUT_OF_MEMORY; + return code; + } + FOREACH(pNode1, pStmt->pOptions->pFuncs) { + FOREACH(pNode2, pStmt->pOptions->pCols) { + SFunctionNode* pFunc = (SFunctionNode*)nodesCloneNode(pNode1); + SColumnNode* pCol = (SColumnNode*)nodesCloneNode(pNode2); + if (!pFunc || !pCol || + (TSDB_CODE_SUCCESS != nodesListMakeAppend(&pFunc->pParameterList, (SNode*)pCol) || (pCol = NULL)) || + TSDB_CODE_SUCCESS != nodesListAppend(pTSMAFuncs, (SNode*)pFunc)) { + nodesDestroyNode((SNode*)pFunc); + nodesDestroyNode((SNode*)pCol); + nodesDestroyList(pTSMAFuncs); + return TSDB_CODE_OUT_OF_MEMORY; + } + } + } + nodesDestroyList(pStmt->pOptions->pFuncs); + pStmt->pOptions->pFuncs = pTSMAFuncs; + } + return code; +} + +static int32_t buildCreateTSMAReq(STranslateContext* pCxt, SCreateTSMAStmt* pStmt, SMCreateSmaReq* pReq) { + SName name; + tNameExtractFullName(toName(pCxt->pParseCxt->acctId, pStmt->dbName, pStmt->tsmaName, &name), pReq->name); + memset(&name, 0, sizeof(SName)); + tNameExtractFullName(toName(pCxt->pParseCxt->acctId, pStmt->dbName, pStmt->tableName, &name), pReq->stb); + pReq->igExists = pStmt->ignoreExists; + pReq->interval = ((SValueNode*)pStmt->pOptions->pInterval)->datum.i; + pReq->intervalUnit = ((SValueNode*)pStmt->pOptions->pInterval)->unit; + + int32_t code = TSDB_CODE_SUCCESS; + + STableMeta* pTableMeta = NULL; + code = getTableMeta(pCxt, pStmt->dbName, pStmt->tableName, &pTableMeta); + + if (TSDB_CODE_SUCCESS == code) { + code = getSmaIndexDstVgId(pCxt, pStmt->dbName, pStmt->tableName, &pReq->dstVgId); + } + if (TSDB_CODE_SUCCESS == code) { + code = getSmaIndexSql(pCxt, &pReq->sql, &pReq->sqlLen); + } + + if (TSDB_CODE_SUCCESS == code) { + code = translateTSMAFuncs(pCxt, pStmt, pTableMeta); + } + if (TSDB_CODE_SUCCESS == code) { + code = buildTSMAAst(pCxt, pStmt, &pReq->ast, &pReq->astLen, &pReq->expr, &pReq->exprLen); + } + /* + if (TSDB_CODE_SUCCESS == code) { + STableMeta* pMetaCache = NULL; + code = getTableMeta(pCxt, pStmt->dbName, pStmt->tableName, &pMetaCache); + if (TSDB_CODE_SUCCESS == code) { + pStmt->pOptions->tsPrecision = pMetaCache->tableInfo.precision; + code = createLastTsSelectStmt(pStmt->dbName, pStmt->tableName, pMetaCache, &pStmt->pPrevQuery); + } + taosMemoryFreeClear(pMetaCache); + } + */ + + taosMemoryFreeClear(pTableMeta); + + return code; +} + +static int32_t translateCreateTSMA(STranslateContext* pCxt, SCreateTSMAStmt* pStmt) { + int32_t code = doTranslateValue(pCxt, (SValueNode*)pStmt->pOptions->pInterval); + + pStmt->pReq = taosMemoryCalloc(1, sizeof(SMCreateSmaReq)); + if (pStmt->pReq == NULL) code = TSDB_CODE_OUT_OF_MEMORY; + if (code == TSDB_CODE_SUCCESS) { + code = buildCreateTSMAReq(pCxt, pStmt, pStmt->pReq); + } + if (TSDB_CODE_SUCCESS == code) { + code = buildCmdMsg(pCxt, TDMT_MND_CREATE_SMA, (FSerializeFunc)tSerializeSMCreateSmaReq, pStmt->pReq); + } + tFreeSMCreateSmaReq(pStmt->pReq); + return code; +} + static int32_t translateQuery(STranslateContext* pCxt, SNode* pNode) { int32_t code = TSDB_CODE_SUCCESS; switch (nodeType(pNode)) { @@ -10535,6 +10670,12 @@ static int32_t translateQuery(STranslateContext* pCxt, SNode* pNode) { case QUERY_NODE_DROP_VIEW_STMT: code = translateDropView(pCxt, (SDropViewStmt*)pNode); break; + case QUERY_NODE_CREATE_TSMA_STMT: + code = translateCreateTSMA(pCxt, (SCreateTSMAStmt*)pNode); + break; + case QUERY_NODE_SHOW_CREATE_TSMA_STMT: + case QUERY_NODE_DROP_TSMA_STMT: + break; default: break; diff --git a/source/libs/parser/src/sql.c b/source/libs/parser/src/sql.c index 431070b0bb..5384846133 100644 --- a/source/libs/parser/src/sql.c +++ b/source/libs/parser/src/sql.c @@ -1340,9 +1340,11 @@ static const YYCODETYPE yyFallback[] = { 0, /* QTAGS => nothing */ 0, /* AS => nothing */ 0, /* SYSTEM => nothing */ - 0, /* INDEX => nothing */ - 0, /* FUNCTION => nothing */ + 0, /* TSMA => nothing */ 0, /* INTERVAL => nothing */ + 0, /* TSMAS => nothing */ + 0, /* FUNCTION => nothing */ + 0, /* INDEX => nothing */ 0, /* COUNT => nothing */ 0, /* LAST_ROW => nothing */ 0, /* META => nothing */