diff --git a/cmake/taosadapter_CMakeLists.txt.in b/cmake/taosadapter_CMakeLists.txt.in index a47b3b0febcbe968273ffae4cc428abdb6347a1a..31ca6b30fa1ccc5058276ace1429354d26fb3941 100644 --- a/cmake/taosadapter_CMakeLists.txt.in +++ b/cmake/taosadapter_CMakeLists.txt.in @@ -2,7 +2,7 @@ # taosadapter ExternalProject_Add(taosadapter GIT_REPOSITORY https://github.com/taosdata/taosadapter.git - GIT_TAG f0c1753 + GIT_TAG 5662a6d SOURCE_DIR "${TD_SOURCE_DIR}/tools/taosadapter" BINARY_DIR "" #BUILD_IN_SOURCE TRUE diff --git a/docs/en/12-taos-sql/02-database.md b/docs/en/12-taos-sql/02-database.md index 0aec22fbc072409916cfa7a7a8ff0d1702fb226b..c3c7e5928bb6705939dfae7d4e0096b202025520 100644 --- a/docs/en/12-taos-sql/02-database.md +++ b/docs/en/12-taos-sql/02-database.md @@ -30,6 +30,8 @@ database_option: { | WAL_LEVEL {1 | 2} | VGROUPS value | SINGLE_STABLE {0 | 1} + | TABLE_PREFIX value + | TABLE_SUFFIX value | WAL_RETENTION_PERIOD value | WAL_ROLL_PERIOD value | WAL_RETENTION_SIZE value @@ -67,6 +69,8 @@ database_option: { - SINGLE_STABLE: specifies whether the database can contain more than one supertable. - 0: The database can contain multiple supertables. - 1: The database can contain only one supertable. +- TABLE_PREFIX:The prefix length in the table name that is ignored when distributing table to vnode based on table name. +- TABLE_SUFFIX:The suffix length in the table name that is ignored when distributing table to vnode based on table name. - WAL_RETENTION_PERIOD: specifies the time after which WAL files are deleted. This parameter is used for data subscription. Enter a time in seconds. The default value of single copy is 0. A value of 0 indicates that each WAL file is deleted immediately after its contents are written to disk. -1: WAL files are never deleted. The default value of multiple copy is 4 days. - WAL_RETENTION_SIZE: specifies the size at which WAL files are deleted. This parameter is used for data subscription. Enter a size in KB. The default value of single copy is 0. A value of 0 indicates that each WAL file is deleted immediately after its contents are written to disk. -1: WAL files are never deleted. The default value of multiple copy is -1. - WAL_ROLL_PERIOD: specifies the time after which WAL files are rotated. After this period elapses, a new WAL file is created. The default value of single copy is 0. A value of 0 indicates that a new WAL file is created only after the previous WAL file was written to disk. The default values of multiple copy is 1 day. diff --git a/docs/zh/12-taos-sql/02-database.md b/docs/zh/12-taos-sql/02-database.md index 232a6c7326ba10740f9e8606254ae97591dc9084..df52a0890b6ff091b8d5cfb051618c88e8195cf0 100644 --- a/docs/zh/12-taos-sql/02-database.md +++ b/docs/zh/12-taos-sql/02-database.md @@ -30,6 +30,8 @@ database_option: { | WAL_LEVEL {1 | 2} | VGROUPS value | SINGLE_STABLE {0 | 1} + | TABLE_PREFIX value + | TABLE_SUFFIX value | WAL_RETENTION_PERIOD value | WAL_ROLL_PERIOD value | WAL_RETENTION_SIZE value @@ -67,6 +69,8 @@ database_option: { - SINGLE_STABLE:表示此数据库中是否只可以创建一个超级表,用于超级表列非常多的情况。 - 0:表示可以创建多张超级表。 - 1:表示只可以创建一张超级表。 +- TABLE_PREFIX:内部存储引擎根据表名分配存储该表数据的 VNODE 时要忽略的前缀的长度。 +- TABLE_SUFFIX:内部存储引擎根据表名分配存储该表数据的 VNODE 时要忽略的后缀的长度。 - WAL_RETENTION_PERIOD:wal 文件的额外保留策略,用于数据订阅。wal 的保存时长,单位为 s。单副本默认为 0,即落盘后立即删除。-1 表示不删除。多副本默认为 4 天。 - WAL_RETENTION_SIZE:wal 文件的额外保留策略,用于数据订阅。wal 的保存的最大上限,单位为 KB。单副本默认为 0,即落盘后立即删除。多副本默认为-1,表示不删除。 - WAL_ROLL_PERIOD:wal 文件切换时长,单位为 s。当 wal 文件创建并写入后,经过该时间,会自动创建一个新的 wal 文件。单副本默认为 0,即仅在落盘时创建新文件。多副本默认为 1 天。 diff --git a/include/libs/executor/executor.h b/include/libs/executor/executor.h index 412b4b4cf6c950113a2f7e6d319692695cde0c07..cfd5bd1ed77bc1a0c4f158f00cb8c2462ac70443 100644 --- a/include/libs/executor/executor.h +++ b/include/libs/executor/executor.h @@ -213,6 +213,7 @@ int32_t qStreamSourceRecoverStep1(qTaskInfo_t tinfo, int64_t ver); int32_t qStreamSourceRecoverStep2(qTaskInfo_t tinfo, int64_t ver); int32_t qStreamRecoverFinish(qTaskInfo_t tinfo); int32_t qStreamRestoreParam(qTaskInfo_t tinfo); +bool qStreamRecoverScanFinished(qTaskInfo_t tinfo); #ifdef __cplusplus } diff --git a/source/dnode/vnode/src/meta/metaQuery.c b/source/dnode/vnode/src/meta/metaQuery.c index cfdb4ab8d1d18aee42ef0528d64d72581c25630d..6c468b89f66e438d2f923a034f18f1f02282d349 100644 --- a/source/dnode/vnode/src/meta/metaQuery.c +++ b/source/dnode/vnode/src/meta/metaQuery.c @@ -19,7 +19,7 @@ void metaReaderInit(SMetaReader *pReader, SMeta *pMeta, int32_t flags) { memset(pReader, 0, sizeof(*pReader)); pReader->flags = flags; pReader->pMeta = pMeta; - if (!(flags & META_READER_NOLOCK)) { + if (pReader->pMeta && !(flags & META_READER_NOLOCK)) { metaRLock(pMeta); } } @@ -152,7 +152,7 @@ bool metaIsTableExist(SMeta *pMeta, tb_uid_t uid) { } int metaGetTableEntryByUid(SMetaReader *pReader, tb_uid_t uid) { - SMeta *pMeta = pReader->pMeta; + SMeta *pMeta = pReader->pMeta; int64_t version1; // query uid.idx @@ -239,7 +239,6 @@ int metaGetTableSzNameByUid(void *meta, uint64_t uid, char *tbName) { return 0; } - int metaGetTableUidByName(void *meta, char *tbName, uint64_t *uid) { int code = 0; SMetaReader mr = {0}; @@ -756,9 +755,7 @@ int64_t metaGetTimeSeriesNum(SMeta *pMeta) { return pMeta->pVnode->config.vndStats.numOfTimeSeries + pMeta->pVnode->config.vndStats.numOfNTimeSeries; } -int64_t metaGetNtbNum(SMeta *pMeta) { - return pMeta->pVnode->config.vndStats.numOfNTables; -} +int64_t metaGetNtbNum(SMeta *pMeta) { return pMeta->pVnode->config.vndStats.numOfNTables; } typedef struct { SMeta *pMeta; diff --git a/source/libs/executor/inc/executorimpl.h b/source/libs/executor/inc/executorimpl.h index 647da78a78895c21e6dd10da278d95b92bf85051..60efefb1e4505106c267b63291927d1c4736e430 100644 --- a/source/libs/executor/inc/executorimpl.h +++ b/source/libs/executor/inc/executorimpl.h @@ -136,6 +136,7 @@ typedef struct { SSchemaWrapper* schema; char tbName[TSDB_TABLE_NAME_LEN]; int8_t recoverStep; + int8_t recoverScanFinished; SQueryTableDataCond tableCond; int64_t fillHistoryVer1; int64_t fillHistoryVer2; @@ -182,7 +183,7 @@ struct SExecTaskInfo { SSubplan* pSubplan; struct SOperatorInfo* pRoot; SLocalFetch localFetch; - SArray* pResultBlockList;// result block list + SArray* pResultBlockList; // result block list STaskStopInfo stopInfo; }; @@ -199,7 +200,7 @@ typedef struct SOperatorFpSet { __optr_fn_t getNextFn; __optr_fn_t cleanupFn; // call this function to release the allocated resources ASAP __optr_close_fn_t closeFn; - __optr_reqBuf_fn_t reqBufFn; // total used buffer for blocking operator + __optr_reqBuf_fn_t reqBufFn; // total used buffer for blocking operator __optr_encode_fn_t encodeResultRow; __optr_decode_fn_t decodeResultRow; __optr_explain_fn_t getExplainFn; @@ -255,22 +256,22 @@ typedef struct SLimitInfo { } SLimitInfo; typedef struct SExchangeInfo { - SArray* pSources; - SArray* pSourceDataInfo; - tsem_t ready; - void* pTransporter; + SArray* pSources; + SArray* pSourceDataInfo; + tsem_t ready; + void* pTransporter; // SArray, result block list, used to keep the multi-block that // passed by downstream operator - SArray* pResultBlockList; - SArray* pRecycledBlocks;// build a pool for small data block to avoid to repeatly create and then destroy. - SSDataBlock* pDummyBlock; // dummy block, not keep data - bool seqLoadData; // sequential load data or not, false by default - int32_t current; + SArray* pResultBlockList; + SArray* pRecycledBlocks; // build a pool for small data block to avoid to repeatly create and then destroy. + SSDataBlock* pDummyBlock; // dummy block, not keep data + bool seqLoadData; // sequential load data or not, false by default + int32_t current; SLoadRemoteDataInfo loadInfo; uint64_t self; SLimitInfo limitInfo; - int64_t openedTs; // start exec time stamp, todo: move to SLoadRemoteDataInfo + int64_t openedTs; // start exec time stamp, todo: move to SLoadRemoteDataInfo } SExchangeInfo; typedef struct SScanInfo { @@ -305,9 +306,9 @@ typedef struct { } SAggOptrPushDownInfo; typedef struct STableMetaCacheInfo { - SLRUCache* pTableMetaEntryCache; // 100 by default - uint64_t metaFetch; - uint64_t cacheHit; + SLRUCache* pTableMetaEntryCache; // 100 by default + uint64_t metaFetch; + uint64_t cacheHit; } STableMetaCacheInfo; typedef struct STableScanBase { @@ -325,16 +326,16 @@ typedef struct STableScanBase { } STableScanBase; typedef struct STableScanInfo { - STableScanBase base; - SScanInfo scanInfo; - int32_t scanTimes; - SSDataBlock* pResBlock; - SSampleExecInfo sample; // sample execution info - int32_t currentGroupId; - int32_t currentTable; - int8_t scanMode; - int8_t assignBlockUid; - bool hasGroupByTag; + STableScanBase base; + SScanInfo scanInfo; + int32_t scanTimes; + SSDataBlock* pResBlock; + SSampleExecInfo sample; // sample execution info + int32_t currentGroupId; + int32_t currentTable; + int8_t scanMode; + int8_t assignBlockUid; + bool hasGroupByTag; } STableScanInfo; typedef struct STableMergeScanInfo { @@ -360,11 +361,11 @@ typedef struct STableMergeScanInfo { } STableMergeScanInfo; typedef struct STagScanInfo { - SColumnInfo* pCols; - SSDataBlock* pRes; - SColMatchInfo matchInfo; - int32_t curPos; - SReadHandle readHandle; + SColumnInfo* pCols; + SSDataBlock* pRes; + SColMatchInfo matchInfo; + int32_t curPos; + SReadHandle readHandle; } STagScanInfo; typedef enum EStreamScanMode { @@ -468,6 +469,11 @@ typedef struct SStreamScanInfo { SNodeList* pGroupTags; SNode* pTagCond; SNode* pTagIndexCond; + + // recover + int32_t blockRecoverContiCnt; + int32_t blockRecoverTotCnt; + } SStreamScanInfo; typedef struct { @@ -499,8 +505,8 @@ typedef struct STableCountScanOperatorInfo { STableCountScanSupp supp; - int32_t currGrpIdx; - SArray* stbUidList; // when group by db_name and/or stable_name + int32_t currGrpIdx; + SArray* stbUidList; // when group by db_name and/or stable_name } STableCountScanOperatorInfo; typedef struct SOptrBasicInfo { @@ -678,19 +684,19 @@ void setOperatorInfo(SOperatorInfo* pOperator, const char* name, int32 void destroyOperatorInfo(SOperatorInfo* pOperator); int32_t optrDefaultBufFn(SOperatorInfo* pOperator); -void initBasicInfo(SOptrBasicInfo* pInfo, SSDataBlock* pBlock); -void cleanupBasicInfo(SOptrBasicInfo* pInfo); +void initBasicInfo(SOptrBasicInfo* pInfo, SSDataBlock* pBlock); +void cleanupBasicInfo(SOptrBasicInfo* pInfo); int32_t initExprSupp(SExprSupp* pSup, SExprInfo* pExprInfo, int32_t numOfExpr); void cleanupExprSupp(SExprSupp* pSup); -void destroyExprInfo(SExprInfo* pExpr, int32_t numOfExprs); +void destroyExprInfo(SExprInfo* pExpr, int32_t numOfExprs); int32_t initAggSup(SExprSupp* pSup, SAggSupporter* pAggSup, SExprInfo* pExprInfo, int32_t numOfCols, size_t keyBufSize, const char* pkey); void cleanupAggSup(SAggSupporter* pAggSup); -void initResultSizeInfo(SResultInfo* pResultInfo, int32_t numOfRows); +void initResultSizeInfo(SResultInfo* pResultInfo, int32_t numOfRows); void doBuildStreamResBlock(SOperatorInfo* pOperator, SOptrBasicInfo* pbInfo, SGroupResInfo* pGroupResInfo, SDiskbasedBuf* pBuf); @@ -803,10 +809,10 @@ void setInputDataBlock(SExprSupp* pExprSupp, SSDataBlock* pBlock, int32_t order, int32_t checkForQueryBuf(size_t numOfTables); -bool isTaskKilled(SExecTaskInfo* pTaskInfo); -void setTaskKilled(SExecTaskInfo* pTaskInfo, int32_t rspCode); -void doDestroyTask(SExecTaskInfo* pTaskInfo); -void setTaskStatus(SExecTaskInfo* pTaskInfo, int8_t status); +bool isTaskKilled(SExecTaskInfo* pTaskInfo); +void setTaskKilled(SExecTaskInfo* pTaskInfo, int32_t rspCode); +void doDestroyTask(SExecTaskInfo* pTaskInfo); +void setTaskStatus(SExecTaskInfo* pTaskInfo, int8_t status); int32_t createExecTaskInfoImpl(SSubplan* pPlan, SExecTaskInfo** pTaskInfo, SReadHandle* pHandle, uint64_t taskId, char* sql, EOPTR_EXEC_MODEL model); @@ -828,8 +834,8 @@ bool isDeletedWindow(STimeWindow* pWin, uint64_t groupId, SAggSupporter* pSup); bool isDeletedStreamWindow(STimeWindow* pWin, uint64_t groupId, SStreamState* pState, STimeWindowAggSupp* pTwSup); void appendOneRowToStreamSpecialBlock(SSDataBlock* pBlock, TSKEY* pStartTs, TSKEY* pEndTs, uint64_t* pUid, uint64_t* pGp, void* pTbName); -uint64_t calGroupIdByData(SPartitionBySupporter* pParSup, SExprSupp* pExprSup, SSDataBlock* pBlock, int32_t rowId); -void calBlockTbName(SStreamScanInfo* pInfo, SSDataBlock* pBlock); +uint64_t calGroupIdByData(SPartitionBySupporter* pParSup, SExprSupp* pExprSup, SSDataBlock* pBlock, int32_t rowId); +void calBlockTbName(SStreamScanInfo* pInfo, SSDataBlock* pBlock); int32_t finalizeResultRows(SDiskbasedBuf* pBuf, SResultRowPosition* resultRowPosition, SExprSupp* pSup, SSDataBlock* pBlock, SExecTaskInfo* pTaskInfo); diff --git a/source/libs/executor/src/executor.c b/source/libs/executor/src/executor.c index 75de0129470963c34edb9922f5d8e3c6cd9fc40d..f83f938e61c18875fc4998304cfd4bd5d8d78c0b 100644 --- a/source/libs/executor/src/executor.c +++ b/source/libs/executor/src/executor.c @@ -937,6 +937,11 @@ int32_t qStreamRestoreParam(qTaskInfo_t tinfo) { return 0; } +bool qStreamRecoverScanFinished(qTaskInfo_t tinfo) { + SExecTaskInfo* pTaskInfo = (SExecTaskInfo*)tinfo; + return pTaskInfo->streamInfo.recoverScanFinished; +} + void* qExtractReaderFromStreamScanner(void* scanner) { SStreamScanInfo* pInfo = scanner; return (void*)pInfo->tqReader; diff --git a/source/libs/executor/src/scanoperator.c b/source/libs/executor/src/scanoperator.c index 1414d3b4ab310b427491f51f982c60f4ddb21107..175e52565f919cf3e5c2dc104e04b6392184a2ba 100644 --- a/source/libs/executor/src/scanoperator.c +++ b/source/libs/executor/src/scanoperator.c @@ -1785,11 +1785,18 @@ static SSDataBlock* doStreamScan(SOperatorInfo* pOperator) { pTSInfo->scanTimes = 0; pTSInfo->currentGroupId = -1; pTaskInfo->streamInfo.recoverStep = STREAM_RECOVER_STEP__SCAN; + pTaskInfo->streamInfo.recoverScanFinished = false; } if (pTaskInfo->streamInfo.recoverStep == STREAM_RECOVER_STEP__SCAN) { + if (pInfo->blockRecoverContiCnt > 100) { + pInfo->blockRecoverTotCnt += pInfo->blockRecoverContiCnt; + pInfo->blockRecoverContiCnt = 0; + return NULL; + } SSDataBlock* pBlock = doTableScan(pInfo->pTableScanOp); if (pBlock != NULL) { + pInfo->blockRecoverContiCnt++; calBlockTbName(pInfo, pBlock); if (pInfo->pUpdateInfo) { TSKEY maxTs = updateInfoFillBlockData(pInfo->pUpdateInfo, pBlock, pInfo->primaryTsIndex); @@ -1807,6 +1814,7 @@ static SSDataBlock* doStreamScan(SOperatorInfo* pOperator) { pTSInfo->base.cond.startVersion = -1; pTSInfo->base.cond.endVersion = -1; + pTaskInfo->streamInfo.recoverScanFinished = true; return NULL; } diff --git a/source/libs/parser/test/parAlterToBalanceTest.cpp b/source/libs/parser/test/parAlterToBalanceTest.cpp index 51a7bbb0a5e5b78bfaf3499046790b7121f59438..a0de93782ddeffa351cd1700c5447c712a1da967 100644 --- a/source/libs/parser/test/parAlterToBalanceTest.cpp +++ b/source/libs/parser/test/parAlterToBalanceTest.cpp @@ -21,6 +21,25 @@ namespace ParserTest { class ParserInitialATest : public ParserDdlTest {}; +/* + * ALTER ACCOUNT account_name alter_account_options + * + * alter_account_options: + * alter_account_option ... + * + * alter_account_option: { + * PASS value + * | PPS value + * | TSERIES value + * | STORAGE value + * | STREAMS value + * | QTIME value + * | DBS value + * | USERS value + * | CONNS value + * | STATE value + * } + */ TEST_F(ParserInitialATest, alterAccount) { useDb("root", "test"); @@ -48,6 +67,7 @@ TEST_F(ParserInitialATest, alterDnode) { setCheckDdlFunc([&](const SQuery* pQuery, ParserStage stage) { ASSERT_EQ(nodeType(pQuery->pRoot), QUERY_NODE_ALTER_DNODE_STMT); + ASSERT_EQ(pQuery->pCmdMsg->msgType, TDMT_MND_CONFIG_DNODE); SMCfgDnodeReq req = {0}; ASSERT_EQ(tDeserializeSMCfgDnodeReq(pQuery->pCmdMsg->pMsg, pQuery->pCmdMsg->msgLen, &req), TSDB_CODE_SUCCESS); ASSERT_EQ(req.dnodeId, expect.dnodeId); @@ -86,9 +106,8 @@ TEST_F(ParserInitialATest, alterDnode) { * | KEEP {int_value | duration_value} -- rang [1, 365000], default 3650, unit day * | PAGES int_value -- rang [64, INT32_MAX], default 256, unit page * | REPLICA int_value -- todo: enum 1, 3, default 1, unit replica - * | STRICT {'off' | 'on'} -- todo: default 'off' * | WAL_LEVEL int_value -- enum 1, 2, default 1 - * | SST_TRIGGER int_value -- rang [1, 16], default 8 + * | STT_TRIGGER int_value -- rang [1, 16], default 8 * } */ TEST_F(ParserInitialATest, alterDatabase) { @@ -130,10 +149,11 @@ TEST_F(ParserInitialATest, alterDatabase) { auto setAlterDbStrict = [&](int8_t strict) { expect.strict = strict; }; auto setAlterDbCacheModel = [&](int8_t cacheModel) { expect.cacheLast = cacheModel; }; auto setAlterDbReplica = [&](int8_t replications) { expect.replications = replications; }; - auto setAlterDbSstTrigger = [&](int8_t sstTrigger) { expect.sstTrigger = sstTrigger; }; + auto setAlterDbSttTrigger = [&](int8_t sstTrigger) { expect.sstTrigger = sstTrigger; }; setCheckDdlFunc([&](const SQuery* pQuery, ParserStage stage) { ASSERT_EQ(nodeType(pQuery->pRoot), QUERY_NODE_ALTER_DATABASE_STMT); + ASSERT_EQ(pQuery->pCmdMsg->msgType, TDMT_MND_ALTER_DB); SAlterDbReq req = {0}; ASSERT_EQ(tDeserializeSAlterDbReq(pQuery->pCmdMsg->pMsg, pQuery->pCmdMsg->msgLen, &req), TSDB_CODE_SUCCESS); ASSERT_EQ(std::string(req.db), std::string(expect.db)); @@ -161,11 +181,12 @@ TEST_F(ParserInitialATest, alterDatabase) { setAlterDbFsync(200); setAlterDbWal(1); setAlterDbCacheModel(TSDB_CACHE_MODEL_LAST_ROW); - setAlterDbSstTrigger(16); + setAlterDbSttTrigger(16); setAlterDbBuffer(16); setAlterDbPages(128); + setAlterDbReplica(3); run("ALTER DATABASE test BUFFER 16 CACHEMODEL 'last_row' CACHESIZE 32 WAL_FSYNC_PERIOD 200 KEEP 10 PAGES 128 " - "WAL_LEVEL 1 STT_TRIGGER 16"); + "REPLICA 3 WAL_LEVEL 1 STT_TRIGGER 16"); clearAlterDbReq(); initAlterDb("test"); @@ -240,6 +261,22 @@ TEST_F(ParserInitialATest, alterDatabase) { setAlterDbWal(2); run("ALTER DATABASE test WAL_LEVEL 2"); clearAlterDbReq(); + + initAlterDb("test"); + setAlterDbReplica(1); + run("ALTER DATABASE test REPLICA 1"); + setAlterDbReplica(3); + run("ALTER DATABASE test REPLICA 3"); + clearAlterDbReq(); + + initAlterDb("test"); + setAlterDbSttTrigger(1); + run("ALTER DATABASE test STT_TRIGGER 1"); + setAlterDbSttTrigger(4); + run("ALTER DATABASE test STT_TRIGGER 4"); + setAlterDbSttTrigger(16); + run("ALTER DATABASE test STT_TRIGGER 16"); + clearAlterDbReq(); } TEST_F(ParserInitialATest, alterDatabaseSemanticCheck) { @@ -260,6 +297,7 @@ TEST_F(ParserInitialATest, alterDatabaseSemanticCheck) { run("ALTER DATABASE test PAGES 63", TSDB_CODE_PAR_INVALID_DB_OPTION); run("ALTER DATABASE test WAL_LEVEL 0", TSDB_CODE_PAR_INVALID_DB_OPTION); run("ALTER DATABASE test WAL_LEVEL 3", TSDB_CODE_PAR_INVALID_DB_OPTION); + run("ALTER DATABASE test REPLICA 2", TSDB_CODE_PAR_INVALID_DB_OPTION); run("ALTER DATABASE test STT_TRIGGER 0", TSDB_CODE_PAR_INVALID_DB_OPTION); run("ALTER DATABASE test STT_TRIGGER 17", TSDB_CODE_PAR_INVALID_DB_OPTION); // Regardless of the specific sentence @@ -267,7 +305,7 @@ TEST_F(ParserInitialATest, alterDatabaseSemanticCheck) { } /* - * ALTER LOCAL dnode_id 'config' ['value'] + * ALTER LOCAL 'config' ['value'] */ TEST_F(ParserInitialATest, alterLocal) { useDb("root", "test"); @@ -311,19 +349,19 @@ TEST_F(ParserInitialATest, alterLocal) { * | ADD COLUMN col_name column_type * | DROP COLUMN col_name * | MODIFY COLUMN col_name column_type - * | RENAME COLUMN old_col_name new_col_name -- normal table - * | ADD TAG tag_name tag_type -- super table - * | DROP TAG tag_name -- super table - * | MODIFY TAG tag_name tag_type -- super table - * | RENAME TAG old_tag_name new_tag_name -- super table - * | SET TAG tag_name = new_tag_value -- child table + * | RENAME COLUMN old_col_name new_col_name -- only normal table + * | ADD TAG tag_name tag_type -- only super table + * | DROP TAG tag_name -- only super table + * | MODIFY TAG tag_name tag_type -- only super table + * | RENAME TAG old_tag_name new_tag_name -- only super table + * | SET TAG tag_name = new_tag_value -- only child table * } * * alter_table_options: * alter_table_option ... * * alter_table_option: { - * TTL int_value -- child/normal table + * TTL int_value -- only child/normal table * | COMMENT 'string_value' * } */ @@ -379,6 +417,7 @@ TEST_F(ParserInitialATest, alterSTable) { setCheckDdlFunc([&](const SQuery* pQuery, ParserStage stage) { ASSERT_EQ(nodeType(pQuery->pRoot), QUERY_NODE_ALTER_SUPER_TABLE_STMT); + ASSERT_EQ(pQuery->pCmdMsg->msgType, TDMT_MND_ALTER_STB); SMAlterStbReq req = {0}; ASSERT_EQ(tDeserializeSMAlterStbReq(pQuery->pCmdMsg->pMsg, pQuery->pCmdMsg->msgLen, &req), TSDB_CODE_SUCCESS); ASSERT_EQ(std::string(req.name), std::string(expect.name)); @@ -444,136 +483,255 @@ TEST_F(ParserInitialATest, alterSTableSemanticCheck) { run("ALTER STABLE st1 TTL 10", TSDB_CODE_PAR_INVALID_ALTER_TABLE); } +/* + * ALTER TABLE [db_name.]tb_name alter_table_clause + * + * alter_table_clause: { + * alter_table_options + * | ADD COLUMN col_name column_type + * | DROP COLUMN col_name + * | MODIFY COLUMN col_name column_type + * | RENAME COLUMN old_col_name new_col_name -- only normal table + * | ADD TAG tag_name tag_type -- only super table + * | DROP TAG tag_name -- only super table + * | MODIFY TAG tag_name tag_type -- only super table + * | RENAME TAG old_tag_name new_tag_name -- only super table + * | SET TAG tag_name = new_tag_value -- only child table + * } + * + * alter_table_options: + * alter_table_option ... + * + * alter_table_option: { + * TTL int_value -- only child/normal table + * | COMMENT 'string_value' + * } + */ TEST_F(ParserInitialATest, alterTable) { useDb("root", "test"); - SVAlterTbReq expect = {0}; - - auto clearAlterTbReq = [&]() { - free(expect.tbName); - free(expect.colName); - free(expect.colNewName); - free(expect.tagName); - memset(&expect, 0, sizeof(SVAlterTbReq)); - }; - - auto setAlterTableCol = [&](const char* pTbname, int8_t alterType, const char* pColName, int8_t dataType = 0, - int32_t dataBytes = 0, const char* pNewColName = nullptr) { - expect.tbName = strdup(pTbname); - expect.action = alterType; - expect.colName = strdup(pColName); - - switch (alterType) { - case TSDB_ALTER_TABLE_ADD_COLUMN: - expect.type = dataType; - expect.flags = COL_SMA_ON; - expect.bytes = dataBytes > 0 ? dataBytes : (dataType > 0 ? tDataTypes[dataType].bytes : 0); - break; - case TSDB_ALTER_TABLE_UPDATE_COLUMN_BYTES: - expect.colModBytes = dataBytes; - break; - case TSDB_ALTER_TABLE_UPDATE_COLUMN_NAME: - expect.colNewName = strdup(pNewColName); - break; - default: - break; - } - }; - - auto setAlterTableTag = [&](const char* pTbname, const char* pTagName, uint8_t* pNewVal, uint32_t bytes) { - expect.tbName = strdup(pTbname); - expect.action = TSDB_ALTER_TABLE_UPDATE_TAG_VAL; - expect.tagName = strdup(pTagName); - - expect.isNull = (nullptr == pNewVal); - expect.nTagVal = bytes; - expect.pTagVal = pNewVal; - }; - - auto setAlterTableOptions = [&](const char* pTbname, int32_t ttl, char* pComment = nullptr) { - expect.tbName = strdup(pTbname); - expect.action = TSDB_ALTER_TABLE_UPDATE_OPTIONS; - if (-1 != ttl) { - expect.updateTTL = true; - expect.newTTL = ttl; - } - if (nullptr != pComment) { - expect.newCommentLen = strlen(pComment); - expect.newComment = pComment; - } - }; - - setCheckDdlFunc([&](const SQuery* pQuery, ParserStage stage) { - ASSERT_EQ(nodeType(pQuery->pRoot), QUERY_NODE_VNODE_MODIFY_STMT); - SVnodeModifyOpStmt* pStmt = (SVnodeModifyOpStmt*)pQuery->pRoot; - - ASSERT_EQ(pStmt->sqlNodeType, QUERY_NODE_ALTER_TABLE_STMT); - ASSERT_NE(pStmt->pDataBlocks, nullptr); - ASSERT_EQ(taosArrayGetSize(pStmt->pDataBlocks), 1); - SVgDataBlocks* pVgData = (SVgDataBlocks*)taosArrayGetP(pStmt->pDataBlocks, 0); - void* pBuf = POINTER_SHIFT(pVgData->pData, sizeof(SMsgHead)); - SVAlterTbReq req = {0}; - SDecoder coder = {0}; - tDecoderInit(&coder, (uint8_t*)pBuf, pVgData->size); - ASSERT_EQ(tDecodeSVAlterTbReq(&coder, &req), TSDB_CODE_SUCCESS); - - ASSERT_EQ(std::string(req.tbName), std::string(expect.tbName)); - ASSERT_EQ(req.action, expect.action); - if (nullptr != expect.colName) { - ASSERT_EQ(std::string(req.colName), std::string(expect.colName)); - } - ASSERT_EQ(req.type, expect.type); - ASSERT_EQ(req.flags, expect.flags); - ASSERT_EQ(req.bytes, expect.bytes); - ASSERT_EQ(req.colModBytes, expect.colModBytes); - if (nullptr != expect.colNewName) { - ASSERT_EQ(std::string(req.colNewName), std::string(expect.colNewName)); - } - if (nullptr != expect.tagName) { - ASSERT_EQ(std::string(req.tagName), std::string(expect.tagName)); - } - ASSERT_EQ(req.isNull, expect.isNull); - ASSERT_EQ(req.nTagVal, expect.nTagVal); - ASSERT_EQ(memcmp(req.pTagVal, expect.pTagVal, expect.nTagVal), 0); - ASSERT_EQ(req.updateTTL, expect.updateTTL); - ASSERT_EQ(req.newTTL, expect.newTTL); - if (nullptr != expect.newComment) { - ASSERT_EQ(std::string(req.newComment), std::string(expect.newComment)); - ASSERT_EQ(req.newCommentLen, strlen(req.newComment)); - ASSERT_EQ(expect.newCommentLen, strlen(expect.newComment)); - } - - tDecoderClear(&coder); - }); - - setAlterTableOptions("t1", 10, nullptr); - run("ALTER TABLE t1 TTL 10"); - clearAlterTbReq(); - - setAlterTableOptions("t1", -1, (char*)"test"); - run("ALTER TABLE t1 COMMENT 'test'"); - clearAlterTbReq(); - - setAlterTableCol("t1", TSDB_ALTER_TABLE_ADD_COLUMN, "cc1", TSDB_DATA_TYPE_BIGINT); - run("ALTER TABLE t1 ADD COLUMN cc1 BIGINT"); - clearAlterTbReq(); - - setAlterTableCol("t1", TSDB_ALTER_TABLE_DROP_COLUMN, "c1"); - run("ALTER TABLE t1 DROP COLUMN c1"); - clearAlterTbReq(); - - setAlterTableCol("t1", TSDB_ALTER_TABLE_UPDATE_COLUMN_BYTES, "c2", TSDB_DATA_TYPE_VARCHAR, 30 + VARSTR_HEADER_SIZE); - run("ALTER TABLE t1 MODIFY COLUMN c2 VARCHAR(30)"); - clearAlterTbReq(); - - setAlterTableCol("t1", TSDB_ALTER_TABLE_UPDATE_COLUMN_NAME, "c1", 0, 0, "cc1"); - run("ALTER TABLE t1 RENAME COLUMN c1 cc1"); - clearAlterTbReq(); - - int32_t val = 10; - setAlterTableTag("st1s1", "tag1", (uint8_t*)&val, sizeof(val)); - run("ALTER TABLE st1s1 SET TAG tag1=10"); - clearAlterTbReq(); + // normal/child table + { + SVAlterTbReq expect = {0}; + + auto clearAlterTbReq = [&]() { + free(expect.tbName); + free(expect.colName); + free(expect.colNewName); + free(expect.tagName); + memset(&expect, 0, sizeof(SVAlterTbReq)); + }; + + auto setAlterTableCol = [&](const char* pTbname, int8_t alterType, const char* pColName, int8_t dataType = 0, + int32_t dataBytes = 0, const char* pNewColName = nullptr) { + expect.tbName = strdup(pTbname); + expect.action = alterType; + expect.colName = strdup(pColName); + + switch (alterType) { + case TSDB_ALTER_TABLE_ADD_COLUMN: + expect.type = dataType; + expect.flags = COL_SMA_ON; + expect.bytes = dataBytes > 0 ? dataBytes : (dataType > 0 ? tDataTypes[dataType].bytes : 0); + break; + case TSDB_ALTER_TABLE_UPDATE_COLUMN_BYTES: + expect.colModBytes = dataBytes; + break; + case TSDB_ALTER_TABLE_UPDATE_COLUMN_NAME: + expect.colNewName = strdup(pNewColName); + break; + default: + break; + } + }; + + auto setAlterTableTag = [&](const char* pTbname, const char* pTagName, uint8_t* pNewVal, uint32_t bytes) { + expect.tbName = strdup(pTbname); + expect.action = TSDB_ALTER_TABLE_UPDATE_TAG_VAL; + expect.tagName = strdup(pTagName); + + expect.isNull = (nullptr == pNewVal); + expect.nTagVal = bytes; + expect.pTagVal = pNewVal; + }; + + auto setAlterTableOptions = [&](const char* pTbname, int32_t ttl, char* pComment = nullptr) { + expect.tbName = strdup(pTbname); + expect.action = TSDB_ALTER_TABLE_UPDATE_OPTIONS; + if (-1 != ttl) { + expect.updateTTL = true; + expect.newTTL = ttl; + } + if (nullptr != pComment) { + expect.newCommentLen = strlen(pComment); + expect.newComment = pComment; + } + }; + + setCheckDdlFunc([&](const SQuery* pQuery, ParserStage stage) { + ASSERT_EQ(nodeType(pQuery->pRoot), QUERY_NODE_VNODE_MODIFY_STMT); + SVnodeModifyOpStmt* pStmt = (SVnodeModifyOpStmt*)pQuery->pRoot; + + ASSERT_EQ(pStmt->sqlNodeType, QUERY_NODE_ALTER_TABLE_STMT); + ASSERT_NE(pStmt->pDataBlocks, nullptr); + ASSERT_EQ(taosArrayGetSize(pStmt->pDataBlocks), 1); + SVgDataBlocks* pVgData = (SVgDataBlocks*)taosArrayGetP(pStmt->pDataBlocks, 0); + void* pBuf = POINTER_SHIFT(pVgData->pData, sizeof(SMsgHead)); + SVAlterTbReq req = {0}; + SDecoder coder = {0}; + tDecoderInit(&coder, (uint8_t*)pBuf, pVgData->size); + ASSERT_EQ(tDecodeSVAlterTbReq(&coder, &req), TSDB_CODE_SUCCESS); + + ASSERT_EQ(std::string(req.tbName), std::string(expect.tbName)); + ASSERT_EQ(req.action, expect.action); + if (nullptr != expect.colName) { + ASSERT_EQ(std::string(req.colName), std::string(expect.colName)); + } + ASSERT_EQ(req.type, expect.type); + ASSERT_EQ(req.flags, expect.flags); + ASSERT_EQ(req.bytes, expect.bytes); + ASSERT_EQ(req.colModBytes, expect.colModBytes); + if (nullptr != expect.colNewName) { + ASSERT_EQ(std::string(req.colNewName), std::string(expect.colNewName)); + } + if (nullptr != expect.tagName) { + ASSERT_EQ(std::string(req.tagName), std::string(expect.tagName)); + } + ASSERT_EQ(req.isNull, expect.isNull); + ASSERT_EQ(req.nTagVal, expect.nTagVal); + ASSERT_EQ(memcmp(req.pTagVal, expect.pTagVal, expect.nTagVal), 0); + ASSERT_EQ(req.updateTTL, expect.updateTTL); + ASSERT_EQ(req.newTTL, expect.newTTL); + if (nullptr != expect.newComment) { + ASSERT_EQ(std::string(req.newComment), std::string(expect.newComment)); + ASSERT_EQ(req.newCommentLen, strlen(req.newComment)); + ASSERT_EQ(expect.newCommentLen, strlen(expect.newComment)); + } + + tDecoderClear(&coder); + }); + + setAlterTableOptions("t1", 10, nullptr); + run("ALTER TABLE t1 TTL 10"); + clearAlterTbReq(); + + setAlterTableOptions("t1", -1, (char*)"test"); + run("ALTER TABLE t1 COMMENT 'test'"); + clearAlterTbReq(); + + setAlterTableCol("t1", TSDB_ALTER_TABLE_ADD_COLUMN, "cc1", TSDB_DATA_TYPE_BIGINT); + run("ALTER TABLE t1 ADD COLUMN cc1 BIGINT"); + clearAlterTbReq(); + + setAlterTableCol("t1", TSDB_ALTER_TABLE_DROP_COLUMN, "c1"); + run("ALTER TABLE t1 DROP COLUMN c1"); + clearAlterTbReq(); + + setAlterTableCol("t1", TSDB_ALTER_TABLE_UPDATE_COLUMN_BYTES, "c2", TSDB_DATA_TYPE_VARCHAR, 30 + VARSTR_HEADER_SIZE); + run("ALTER TABLE t1 MODIFY COLUMN c2 VARCHAR(30)"); + clearAlterTbReq(); + + setAlterTableCol("t1", TSDB_ALTER_TABLE_UPDATE_COLUMN_NAME, "c1", 0, 0, "cc1"); + run("ALTER TABLE t1 RENAME COLUMN c1 cc1"); + clearAlterTbReq(); + + int32_t val = 10; + setAlterTableTag("st1s1", "tag1", (uint8_t*)&val, sizeof(val)); + run("ALTER TABLE st1s1 SET TAG tag1=10"); + clearAlterTbReq(); + } + + // super table + { + SMAlterStbReq expect = {0}; + + auto clearAlterStbReq = [&]() { + tFreeSMAltertbReq(&expect); + memset(&expect, 0, sizeof(SMAlterStbReq)); + }; + + auto setAlterStbReq = [&](const char* pTbname, int8_t alterType, int32_t numOfFields = 0, + const char* pField1Name = nullptr, int8_t field1Type = 0, int32_t field1Bytes = 0, + const char* pField2Name = nullptr, const char* pComment = nullptr) { + int32_t len = snprintf(expect.name, sizeof(expect.name), "0.test.%s", pTbname); + expect.name[len] = '\0'; + expect.alterType = alterType; + if (nullptr != pComment) { + expect.comment = strdup(pComment); + expect.commentLen = strlen(pComment); + } + + expect.numOfFields = numOfFields; + if (NULL == expect.pFields) { + expect.pFields = taosArrayInit(2, sizeof(TAOS_FIELD)); + TAOS_FIELD field = {0}; + taosArrayPush(expect.pFields, &field); + taosArrayPush(expect.pFields, &field); + } + + TAOS_FIELD* pField = (TAOS_FIELD*)taosArrayGet(expect.pFields, 0); + if (NULL != pField1Name) { + strcpy(pField->name, pField1Name); + pField->name[strlen(pField1Name)] = '\0'; + } else { + memset(pField, 0, sizeof(TAOS_FIELD)); + } + pField->type = field1Type; + pField->bytes = field1Bytes > 0 ? field1Bytes : (field1Type > 0 ? tDataTypes[field1Type].bytes : 0); + + pField = (TAOS_FIELD*)taosArrayGet(expect.pFields, 1); + if (NULL != pField2Name) { + strcpy(pField->name, pField2Name); + pField->name[strlen(pField2Name)] = '\0'; + } else { + memset(pField, 0, sizeof(TAOS_FIELD)); + } + pField->type = 0; + pField->bytes = 0; + }; + + setCheckDdlFunc([&](const SQuery* pQuery, ParserStage stage) { + ASSERT_EQ(nodeType(pQuery->pRoot), QUERY_NODE_ALTER_TABLE_STMT); + ASSERT_EQ(pQuery->pCmdMsg->msgType, TDMT_MND_ALTER_STB); + SMAlterStbReq req = {0}; + ASSERT_EQ(tDeserializeSMAlterStbReq(pQuery->pCmdMsg->pMsg, pQuery->pCmdMsg->msgLen, &req), TSDB_CODE_SUCCESS); + ASSERT_EQ(std::string(req.name), std::string(expect.name)); + ASSERT_EQ(req.alterType, expect.alterType); + ASSERT_EQ(req.numOfFields, expect.numOfFields); + if (expect.numOfFields > 0) { + TAOS_FIELD* pField = (TAOS_FIELD*)taosArrayGet(req.pFields, 0); + TAOS_FIELD* pExpectField = (TAOS_FIELD*)taosArrayGet(expect.pFields, 0); + ASSERT_EQ(std::string(pField->name), std::string(pExpectField->name)); + ASSERT_EQ(pField->type, pExpectField->type); + ASSERT_EQ(pField->bytes, pExpectField->bytes); + } + if (expect.numOfFields > 1) { + TAOS_FIELD* pField = (TAOS_FIELD*)taosArrayGet(req.pFields, 1); + TAOS_FIELD* pExpectField = (TAOS_FIELD*)taosArrayGet(expect.pFields, 1); + ASSERT_EQ(std::string(pField->name), std::string(pExpectField->name)); + ASSERT_EQ(pField->type, pExpectField->type); + ASSERT_EQ(pField->bytes, pExpectField->bytes); + } + tFreeSMAltertbReq(&req); + }); + + setAlterStbReq("st1", TSDB_ALTER_TABLE_ADD_TAG, 1, "tag11", TSDB_DATA_TYPE_BIGINT); + run("ALTER TABLE st1 ADD TAG tag11 BIGINT"); + clearAlterStbReq(); + + setAlterStbReq("st1", TSDB_ALTER_TABLE_DROP_TAG, 1, "tag1"); + run("ALTER TABLE st1 DROP TAG tag1"); + clearAlterStbReq(); + + setAlterStbReq("st1", TSDB_ALTER_TABLE_UPDATE_TAG_BYTES, 1, "tag2", TSDB_DATA_TYPE_VARCHAR, + 30 + VARSTR_HEADER_SIZE); + run("ALTER TABLE st1 MODIFY TAG tag2 VARCHAR(30)"); + clearAlterStbReq(); + + setAlterStbReq("st1", TSDB_ALTER_TABLE_UPDATE_TAG_NAME, 2, "tag1", 0, 0, "tag11"); + run("ALTER TABLE st1 RENAME TAG tag1 tag11"); + clearAlterStbReq(); + } } TEST_F(ParserInitialATest, alterTableSemanticCheck) { @@ -588,7 +746,7 @@ TEST_F(ParserInitialATest, alterTableSemanticCheck) { } /* - * ALTER USER user_name PASS str_value + * ALTER USER user_name alter_user_clause * * alter_user_clause: { * PASS str_value @@ -618,6 +776,7 @@ TEST_F(ParserInitialATest, alterUser) { setCheckDdlFunc([&](const SQuery* pQuery, ParserStage stage) { ASSERT_EQ(nodeType(pQuery->pRoot), QUERY_NODE_ALTER_USER_STMT); + ASSERT_EQ(pQuery->pCmdMsg->msgType, TDMT_MND_ALTER_USER); SAlterUserReq req = {0}; ASSERT_TRUE(TSDB_CODE_SUCCESS == tDeserializeSAlterUserReq(pQuery->pCmdMsg->pMsg, pQuery->pCmdMsg->msgLen, &req)); diff --git a/source/libs/parser/test/parExplainToSyncdbTest.cpp b/source/libs/parser/test/parExplainToSyncdbTest.cpp index f88d6d316b13606ba95226e669a59bcc588bf566..f23685b3058b911f23baf8c37c6608ab989de5c7 100644 --- a/source/libs/parser/test/parExplainToSyncdbTest.cpp +++ b/source/libs/parser/test/parExplainToSyncdbTest.cpp @@ -52,8 +52,8 @@ TEST_F(ParserExplainToSyncdbTest, grant) { ASSERT_EQ(string(req.objname), string(expect.objname)); }); - setAlterUserReq(TSDB_ALTER_USER_ADD_ALL_DB, "wxy", "0.test"); - run("GRANT ALL ON test.* TO wxy"); + setAlterUserReq(TSDB_ALTER_USER_ADD_ALL_DB, "wxy", "0.*"); + run("GRANT ALL ON *.* TO wxy"); setAlterUserReq(TSDB_ALTER_USER_ADD_READ_DB, "wxy", "0.test"); run("GRANT READ ON test.* TO wxy"); @@ -138,10 +138,38 @@ TEST_F(ParserExplainToSyncdbTest, redistributeVgroup) { TEST_F(ParserExplainToSyncdbTest, revoke) { useDb("root", "test"); - run("REVOKE ALL ON test.* FROM wxy"); + SAlterUserReq expect = {0}; + + auto setAlterUserReq = [&](int8_t alterType, const string& user, const string& obj) { + expect.alterType = alterType; + snprintf(expect.user, sizeof(expect.user), "%s", user.c_str()); + snprintf(expect.objname, sizeof(expect.objname), "%s", obj.c_str()); + }; + + setCheckDdlFunc([&](const SQuery* pQuery, ParserStage stage) { + ASSERT_EQ(nodeType(pQuery->pRoot), QUERY_NODE_REVOKE_STMT); + ASSERT_EQ(pQuery->pCmdMsg->msgType, TDMT_MND_ALTER_USER); + SAlterUserReq req = {0}; + ASSERT_EQ(tDeserializeSAlterUserReq(pQuery->pCmdMsg->pMsg, pQuery->pCmdMsg->msgLen, &req), TSDB_CODE_SUCCESS); + ASSERT_EQ(req.alterType, expect.alterType); + ASSERT_EQ(string(req.user), string(expect.user)); + ASSERT_EQ(string(req.objname), string(expect.objname)); + }); + + setAlterUserReq(TSDB_ALTER_USER_REMOVE_ALL_DB, "wxy", "0.*"); + run("REVOKE ALL ON *.* FROM wxy"); + + setAlterUserReq(TSDB_ALTER_USER_REMOVE_READ_DB, "wxy", "0.test"); run("REVOKE READ ON test.* FROM wxy"); + + setAlterUserReq(TSDB_ALTER_USER_REMOVE_WRITE_DB, "wxy", "0.test"); run("REVOKE WRITE ON test.* FROM wxy"); + + setAlterUserReq(TSDB_ALTER_USER_REMOVE_ALL_DB, "wxy", "0.test"); run("REVOKE READ, WRITE ON test.* FROM wxy"); + + setAlterUserReq(TSDB_ALTER_USER_REMOVE_SUBSCRIBE_TOPIC, "wxy", "0.tp1"); + run("REVOKE SUBSCRIBE ON tp1 FROM wxy"); } // todo syncdb diff --git a/source/libs/parser/test/parInitialCTest.cpp b/source/libs/parser/test/parInitialCTest.cpp index 17d02c1cce7084c99d025d89b36c69e223083069..8bdea07150ab3d6d521d4332183819c1144cd3b5 100644 --- a/source/libs/parser/test/parInitialCTest.cpp +++ b/source/libs/parser/test/parInitialCTest.cpp @@ -21,12 +21,35 @@ namespace ParserTest { class ParserInitialCTest : public ParserDdlTest {}; +/* + * CREATE ACCOUNT account_name PASS value [create_account_options] + * + * create_account_options: + * create_account_option ... + * + * create_account_option: { + * PPS value + * | TSERIES value + * | STORAGE value + * | STREAMS value + * | QTIME value + * | DBS value + * | USERS value + * | CONNS value + * | STATE value + * } + */ TEST_F(ParserInitialCTest, createAccount) { useDb("root", "test"); run("CREATE ACCOUNT ac_wxy PASS '123456'", TSDB_CODE_PAR_EXPRIE_STATEMENT, PARSER_STAGE_PARSE); } +/* + * CREATE BNODE ON DNODE dnode_id + * the server does not support it temporarily + */ + /* * CREATE DATABASE [IF NOT EXISTS] db_name [database_options] * @@ -68,7 +91,7 @@ TEST_F(ParserInitialCTest, createDatabase) { memset(&expect, 0, sizeof(SCreateDbReq)); }; - auto setCreateDbReqFunc = [&](const char* pDbname, int8_t igExists = 0) { + auto setCreateDbReq = [&](const char* pDbname, int8_t igExists = 0) { int32_t len = snprintf(expect.db, sizeof(expect.db), "0.%s", pDbname); expect.db[len] = '\0'; expect.ignoreExist = igExists; @@ -102,28 +125,28 @@ TEST_F(ParserInitialCTest, createDatabase) { expect.tsdbPageSize = TSDB_DEFAULT_TSDB_PAGESIZE; }; - auto setDbBufferFunc = [&](int32_t buffer) { expect.buffer = buffer; }; - auto setDbCachelastFunc = [&](int8_t cachelast) { expect.cacheLast = cachelast; }; + auto setDbBuffer = [&](int32_t buffer) { expect.buffer = buffer; }; + auto setDbCachelast = [&](int8_t cachelast) { expect.cacheLast = cachelast; }; auto setDbCachelastSize = [&](int8_t cachelastSize) { expect.cacheLastSize = cachelastSize; }; - auto setDbCompressionFunc = [&](int8_t compressionLevel) { expect.compression = compressionLevel; }; - auto setDbDaysFunc = [&](int32_t daysPerFile) { expect.daysPerFile = daysPerFile; }; - auto setDbFsyncFunc = [&](int32_t fsyncPeriod) { expect.walFsyncPeriod = fsyncPeriod; }; - auto setDbMaxRowsFunc = [&](int32_t maxRowsPerBlock) { expect.maxRows = maxRowsPerBlock; }; - auto setDbMinRowsFunc = [&](int32_t minRowsPerBlock) { expect.minRows = minRowsPerBlock; }; - auto setDbKeepFunc = [&](int32_t keep0, int32_t keep1 = 0, int32_t keep2 = 0) { + auto setDbCompression = [&](int8_t compressionLevel) { expect.compression = compressionLevel; }; + auto setDbDays = [&](int32_t daysPerFile) { expect.daysPerFile = daysPerFile; }; + auto setDbFsync = [&](int32_t fsyncPeriod) { expect.walFsyncPeriod = fsyncPeriod; }; + auto setDbMaxRows = [&](int32_t maxRowsPerBlock) { expect.maxRows = maxRowsPerBlock; }; + auto setDbMinRows = [&](int32_t minRowsPerBlock) { expect.minRows = minRowsPerBlock; }; + auto setDbKeep = [&](int32_t keep0, int32_t keep1 = 0, int32_t keep2 = 0) { expect.daysToKeep0 = keep0; expect.daysToKeep1 = 0 == keep1 ? expect.daysToKeep0 : keep1; expect.daysToKeep2 = 0 == keep2 ? expect.daysToKeep1 : keep2; }; - auto setDbPagesFunc = [&](int32_t pages) { expect.pages = pages; }; - auto setDbPageSizeFunc = [&](int32_t pagesize) { expect.pageSize = pagesize; }; - auto setDbPrecisionFunc = [&](int8_t precision) { expect.precision = precision; }; - auto setDbReplicaFunc = [&](int8_t replica) { expect.replications = replica; }; - auto setDbStrictaFunc = [&](int8_t strict) { expect.strict = strict; }; - auto setDbWalLevelFunc = [&](int8_t walLevel) { expect.walLevel = walLevel; }; - auto setDbVgroupsFunc = [&](int32_t numOfVgroups) { expect.numOfVgroups = numOfVgroups; }; - auto setDbSingleStableFunc = [&](int8_t singleStable) { expect.numOfStables = singleStable; }; - auto addDbRetentionFunc = [&](int64_t freq, int64_t keep, int8_t freqUnit, int8_t keepUnit) { + auto setDbPages = [&](int32_t pages) { expect.pages = pages; }; + auto setDbPageSize = [&](int32_t pagesize) { expect.pageSize = pagesize; }; + auto setDbPrecision = [&](int8_t precision) { expect.precision = precision; }; + auto setDbReplica = [&](int8_t replica) { expect.replications = replica; }; + auto setDbStricta = [&](int8_t strict) { expect.strict = strict; }; + auto setDbWalLevel = [&](int8_t walLevel) { expect.walLevel = walLevel; }; + auto setDbVgroups = [&](int32_t numOfVgroups) { expect.numOfVgroups = numOfVgroups; }; + auto setDbSingleStable = [&](int8_t singleStable) { expect.numOfStables = singleStable; }; + auto addDbRetention = [&](int64_t freq, int64_t keep, int8_t freqUnit, int8_t keepUnit) { SRetention retention = {0}; retention.freq = freq; retention.keep = keep; @@ -135,7 +158,7 @@ TEST_F(ParserInitialCTest, createDatabase) { taosArrayPush(expect.pRetensions, &retention); ++expect.numOfRetensions; }; - auto setDbSchemalessFunc = [&](int8_t schemaless) { expect.schemaless = schemaless; }; + auto setDbSchemaless = [&](int8_t schemaless) { expect.schemaless = schemaless; }; auto setDbWalRetentionPeriod = [&](int32_t walRetentionPeriod) { expect.walRetentionPeriod = walRetentionPeriod; }; auto setDbWalRetentionSize = [&](int32_t walRetentionSize) { expect.walRetentionSize = walRetentionSize; }; auto setDbWalRollPeriod = [&](int32_t walRollPeriod) { expect.walRollPeriod = walRollPeriod; }; @@ -147,6 +170,7 @@ TEST_F(ParserInitialCTest, createDatabase) { setCheckDdlFunc([&](const SQuery* pQuery, ParserStage stage) { ASSERT_EQ(nodeType(pQuery->pRoot), QUERY_NODE_CREATE_DATABASE_STMT); + ASSERT_EQ(pQuery->pCmdMsg->msgType, TDMT_MND_CREATE_DB); SCreateDbReq req = {0}; ASSERT_TRUE(TSDB_CODE_SUCCESS == tDeserializeSCreateDbReq(pQuery->pCmdMsg->pMsg, pQuery->pCmdMsg->msgLen, &req)); @@ -195,32 +219,32 @@ TEST_F(ParserInitialCTest, createDatabase) { tFreeSCreateDbReq(&req); }); - setCreateDbReqFunc("wxy_db"); + setCreateDbReq("wxy_db"); run("CREATE DATABASE wxy_db"); clearCreateDbReq(); - setCreateDbReqFunc("wxy_db", 1); - setDbBufferFunc(64); - setDbCachelastFunc(2); + setCreateDbReq("wxy_db", 1); + setDbBuffer(64); + setDbCachelast(2); setDbCachelastSize(20); - setDbCompressionFunc(1); - setDbDaysFunc(100 * 1440); - setDbFsyncFunc(100); - setDbMaxRowsFunc(1000); - setDbMinRowsFunc(100); - setDbKeepFunc(1440 * 1440); - setDbPagesFunc(96); - setDbPageSizeFunc(8); - setDbPrecisionFunc(TSDB_TIME_PRECISION_NANO); - setDbReplicaFunc(3); - addDbRetentionFunc(15 * MILLISECOND_PER_SECOND, 7 * MILLISECOND_PER_DAY, TIME_UNIT_SECOND, TIME_UNIT_DAY); - addDbRetentionFunc(1 * MILLISECOND_PER_MINUTE, 21 * MILLISECOND_PER_DAY, TIME_UNIT_MINUTE, TIME_UNIT_DAY); - addDbRetentionFunc(15 * MILLISECOND_PER_MINUTE, 500 * MILLISECOND_PER_DAY, TIME_UNIT_MINUTE, TIME_UNIT_DAY); - // setDbStrictaFunc(1); - setDbWalLevelFunc(2); - setDbVgroupsFunc(100); - setDbSingleStableFunc(1); - setDbSchemalessFunc(1); + setDbCompression(1); + setDbDays(100 * 1440); + setDbFsync(100); + setDbMaxRows(1000); + setDbMinRows(100); + setDbKeep(1440 * 1440); + setDbPages(96); + setDbPageSize(8); + setDbPrecision(TSDB_TIME_PRECISION_NANO); + setDbReplica(3); + addDbRetention(15 * MILLISECOND_PER_SECOND, 7 * MILLISECOND_PER_DAY, TIME_UNIT_SECOND, TIME_UNIT_DAY); + addDbRetention(1 * MILLISECOND_PER_MINUTE, 21 * MILLISECOND_PER_DAY, TIME_UNIT_MINUTE, TIME_UNIT_DAY); + addDbRetention(15 * MILLISECOND_PER_MINUTE, 500 * MILLISECOND_PER_DAY, TIME_UNIT_MINUTE, TIME_UNIT_DAY); + // setDbStricta(1); + setDbWalLevel(2); + setDbVgroups(100); + setDbSingleStable(1); + setDbSchemaless(1); setDbWalRetentionPeriod(-1); setDbWalRetentionSize(-1); setDbWalRollPeriod(10); @@ -259,16 +283,16 @@ TEST_F(ParserInitialCTest, createDatabase) { "TSDB_PAGESIZE 32"); clearCreateDbReq(); - setCreateDbReqFunc("wxy_db", 1); - setDbDaysFunc(100); - setDbKeepFunc(1440, 300 * 60, 400 * 1440); + setCreateDbReq("wxy_db", 1); + setDbDays(100); + setDbKeep(1440, 300 * 60, 400 * 1440); run("CREATE DATABASE IF NOT EXISTS wxy_db " "DURATION 100m " "KEEP 1440m,300h,400d "); clearCreateDbReq(); - setCreateDbReqFunc("wxy_db", 1); - setDbReplicaFunc(3); + setCreateDbReq("wxy_db", 1); + setDbReplica(3); setDbWalRetentionPeriod(TSDB_REPS_DEF_DB_WAL_RET_PERIOD); setDbWalRetentionSize(TSDB_REPS_DEF_DB_WAL_RET_SIZE); setDbWalRollPeriod(TSDB_REPS_DEF_DB_WAL_ROLL_PERIOD); @@ -287,6 +311,9 @@ TEST_F(ParserInitialCTest, createDatabaseSemanticCheck) { run("create database db2 retentions 15s:7d,5m:21d,10m:10d", TSDB_CODE_PAR_INVALID_DB_OPTION); } +/* + * CREATE DNODE {dnode_endpoint | dnode_host_name PORT port_val} + */ TEST_F(ParserInitialCTest, createDnode) { useDb("root", "test"); @@ -294,7 +321,7 @@ TEST_F(ParserInitialCTest, createDnode) { auto clearCreateDnodeReq = [&]() { memset(&expect, 0, sizeof(SCreateDnodeReq)); }; - auto setCreateDnodeReqFunc = [&](const char* pFqdn, int32_t port = tsServerPort) { + auto setCreateDnodeReq = [&](const char* pFqdn, int32_t port = tsServerPort) { strcpy(expect.fqdn, pFqdn); expect.port = port; }; @@ -308,39 +335,41 @@ TEST_F(ParserInitialCTest, createDnode) { ASSERT_EQ(req.port, expect.port); }); - setCreateDnodeReqFunc("abc1", 7030); + setCreateDnodeReq("abc1", 7030); run("CREATE DNODE 'abc1' PORT 7030"); clearCreateDnodeReq(); - setCreateDnodeReqFunc("1.1.1.1", 8030); + setCreateDnodeReq("1.1.1.1", 8030); run("CREATE DNODE 1.1.1.1 PORT 8030"); clearCreateDnodeReq(); - setCreateDnodeReqFunc("host1", 9030); + setCreateDnodeReq("host1", 9030); run("CREATE DNODE host1 PORT 9030"); clearCreateDnodeReq(); - setCreateDnodeReqFunc("abc2", 7040); + setCreateDnodeReq("abc2", 7040); run("CREATE DNODE 'abc2:7040'"); clearCreateDnodeReq(); - setCreateDnodeReqFunc("1.1.1.2"); + setCreateDnodeReq("1.1.1.2"); run("CREATE DNODE 1.1.1.2"); clearCreateDnodeReq(); - setCreateDnodeReqFunc("host2"); + setCreateDnodeReq("host2"); run("CREATE DNODE host2"); clearCreateDnodeReq(); } -// CREATE [AGGREGATE] FUNCTION [IF NOT EXISTS] func_name AS library_path OUTPUTTYPE type_name [BUFSIZE value] +/* + * CREATE [AGGREGATE] FUNCTION [IF NOT EXISTS] func_name AS library_path OUTPUTTYPE type_name [BUFSIZE value] + */ TEST_F(ParserInitialCTest, createFunction) { useDb("root", "test"); SCreateFuncReq expect = {0}; - auto setCreateFuncReqFunc = [&](const char* pUdfName, int8_t outputType, int32_t outputBytes = 0, - int8_t funcType = TSDB_FUNC_TYPE_SCALAR, int8_t igExists = 0, int32_t bufSize = 0) { + auto setCreateFuncReq = [&](const char* pUdfName, int8_t outputType, int32_t outputBytes = 0, + int8_t funcType = TSDB_FUNC_TYPE_SCALAR, int8_t igExists = 0, int32_t bufSize = 0) { memset(&expect, 0, sizeof(SCreateFuncReq)); strcpy(expect.name, pUdfName); expect.igExists = igExists; @@ -365,13 +394,69 @@ TEST_F(ParserInitialCTest, createFunction) { ASSERT_EQ(req.bufSize, expect.bufSize); }); - setCreateFuncReqFunc("udf1", TSDB_DATA_TYPE_INT); + setCreateFuncReq("udf1", TSDB_DATA_TYPE_INT); // run("CREATE FUNCTION udf1 AS './build/lib/libudf1.so' OUTPUTTYPE INT"); - setCreateFuncReqFunc("udf2", TSDB_DATA_TYPE_DOUBLE, 0, TSDB_FUNC_TYPE_AGGREGATE, 1, 8); + setCreateFuncReq("udf2", TSDB_DATA_TYPE_DOUBLE, 0, TSDB_FUNC_TYPE_AGGREGATE, 1, 8); // run("CREATE AGGREGATE FUNCTION IF NOT EXISTS udf2 AS './build/lib/libudf2.so' OUTPUTTYPE DOUBLE BUFSIZE 8"); } +/* + * CREATE MNODE ON DNODE dnode_id + */ +TEST_F(ParserInitialCTest, createMnode) { + useDb("root", "test"); + + SMCreateMnodeReq expect = {0}; + + auto setCreateMnodeReq = [&](int32_t dnodeId) { expect.dnodeId = dnodeId; }; + + setCheckDdlFunc([&](const SQuery* pQuery, ParserStage stage) { + ASSERT_EQ(nodeType(pQuery->pRoot), QUERY_NODE_CREATE_MNODE_STMT); + SMCreateMnodeReq req = {0}; + ASSERT_TRUE(TSDB_CODE_SUCCESS == + tDeserializeSCreateDropMQSNodeReq(pQuery->pCmdMsg->pMsg, pQuery->pCmdMsg->msgLen, &req)); + + ASSERT_EQ(req.dnodeId, expect.dnodeId); + }); + + setCreateMnodeReq(1); + run("CREATE MNODE ON DNODE 1"); +} + +/* + * CREATE QNODE ON DNODE dnode_id + */ +TEST_F(ParserInitialCTest, createQnode) { + useDb("root", "test"); + + SMCreateQnodeReq expect = {0}; + + auto setCreateQnodeReq = [&](int32_t dnodeId) { expect.dnodeId = dnodeId; }; + + setCheckDdlFunc([&](const SQuery* pQuery, ParserStage stage) { + ASSERT_EQ(nodeType(pQuery->pRoot), QUERY_NODE_CREATE_QNODE_STMT); + SMCreateQnodeReq req = {0}; + ASSERT_TRUE(TSDB_CODE_SUCCESS == + tDeserializeSCreateDropMQSNodeReq(pQuery->pCmdMsg->pMsg, pQuery->pCmdMsg->msgLen, &req)); + + ASSERT_EQ(req.dnodeId, expect.dnodeId); + }); + + setCreateQnodeReq(1); + run("CREATE QNODE ON DNODE 1"); +} + +/* + * CREATE SMA INDEX index_name ON tb_name index_option + * + * index_option: + * FUNCTION(functions) INTERVAL(interval_val [, interval_offset]) [SLIDING(sliding_val)] + * [WATERMARK(watermark_val)] [MAX_DELAY(max_delay_val)] + * + * functions: + * function [, function] ... + */ TEST_F(ParserInitialCTest, createSmaIndex) { useDb("root", "test"); @@ -439,24 +524,39 @@ TEST_F(ParserInitialCTest, createSmaIndex) { "DELETE_MARK 1000s"); } -TEST_F(ParserInitialCTest, createMnode) { +/* + * CREATE SNODE ON DNODE dnode_id + */ +TEST_F(ParserInitialCTest, createSnode) { useDb("root", "test"); - run("CREATE MNODE ON DNODE 1"); -} + SMCreateSnodeReq expect = {0}; -TEST_F(ParserInitialCTest, createQnode) { - useDb("root", "test"); + auto setCreateSnodeReq = [&](int32_t dnodeId) { expect.dnodeId = dnodeId; }; - run("CREATE QNODE ON DNODE 1"); -} + setCheckDdlFunc([&](const SQuery* pQuery, ParserStage stage) { + ASSERT_EQ(nodeType(pQuery->pRoot), QUERY_NODE_CREATE_SNODE_STMT); + SMCreateSnodeReq req = {0}; + ASSERT_TRUE(TSDB_CODE_SUCCESS == + tDeserializeSCreateDropMQSNodeReq(pQuery->pCmdMsg->pMsg, pQuery->pCmdMsg->msgLen, &req)); -TEST_F(ParserInitialCTest, createSnode) { - useDb("root", "test"); + ASSERT_EQ(req.dnodeId, expect.dnodeId); + }); + setCreateSnodeReq(1); run("CREATE SNODE ON DNODE 1"); } +/* + * CREATE STABLE [IF NOT EXISTS] stb_name (create_definition [, create_definitionn] ...) + * TAGS (create_definition [, create_definition] ...) [table_options] + * + * create_definition: + * col_name column_definition + * + * column_definition: + * type_name [COMMENT 'string_value'] + */ TEST_F(ParserInitialCTest, createStable) { useDb("root", "test"); @@ -467,7 +567,7 @@ TEST_F(ParserInitialCTest, createStable) { memset(&expect, 0, sizeof(SMCreateStbReq)); }; - auto setCreateStbReqFunc = + auto setCreateStbReq = [&](const char* pDbName, const char* pTbName, int8_t igExists = 0, int64_t delay1 = -1, int64_t delay2 = -1, int64_t watermark1 = TSDB_DEFAULT_ROLLUP_WATERMARK, int64_t watermark2 = TSDB_DEFAULT_ROLLUP_WATERMARK, int64_t deleteMark1 = TSDB_DEFAULT_ROLLUP_DELETE_MARK, int64_t deleteMark2 = TSDB_DEFAULT_ROLLUP_DELETE_MARK, @@ -488,8 +588,8 @@ TEST_F(ParserInitialCTest, createStable) { } }; - auto addFieldToCreateStbReqFunc = [&](bool col, const char* pFieldName, uint8_t type, int32_t bytes = 0, - int8_t flags = COL_SMA_ON) { + auto addFieldToCreateStbReq = [&](bool col, const char* pFieldName, uint8_t type, int32_t bytes = 0, + int8_t flags = COL_SMA_ON) { SField field = {0}; strcpy(field.name, pFieldName); field.type = type; @@ -565,46 +665,46 @@ TEST_F(ParserInitialCTest, createStable) { tFreeSMCreateStbReq(&req); }); - setCreateStbReqFunc("test", "t1"); - addFieldToCreateStbReqFunc(true, "ts", TSDB_DATA_TYPE_TIMESTAMP); - addFieldToCreateStbReqFunc(true, "c1", TSDB_DATA_TYPE_INT); - addFieldToCreateStbReqFunc(false, "id", TSDB_DATA_TYPE_INT); + setCreateStbReq("test", "t1"); + addFieldToCreateStbReq(true, "ts", TSDB_DATA_TYPE_TIMESTAMP); + addFieldToCreateStbReq(true, "c1", TSDB_DATA_TYPE_INT); + addFieldToCreateStbReq(false, "id", TSDB_DATA_TYPE_INT); run("CREATE STABLE t1(ts TIMESTAMP, c1 INT) TAGS(id INT)"); clearCreateStbReq(); - setCreateStbReqFunc("rollup_db", "t1", 1, 100 * MILLISECOND_PER_SECOND, 10 * MILLISECOND_PER_MINUTE, 10, - 1 * MILLISECOND_PER_MINUTE, 1000 * MILLISECOND_PER_SECOND, 200 * MILLISECOND_PER_MINUTE, 100, - "test create table"); - addFieldToCreateStbReqFunc(true, "ts", TSDB_DATA_TYPE_TIMESTAMP, 0, 0); - addFieldToCreateStbReqFunc(true, "c1", TSDB_DATA_TYPE_INT); - addFieldToCreateStbReqFunc(true, "c2", TSDB_DATA_TYPE_UINT); - addFieldToCreateStbReqFunc(true, "c3", TSDB_DATA_TYPE_BIGINT); - addFieldToCreateStbReqFunc(true, "c4", TSDB_DATA_TYPE_UBIGINT, 0, 0); - addFieldToCreateStbReqFunc(true, "c5", TSDB_DATA_TYPE_FLOAT, 0, 0); - addFieldToCreateStbReqFunc(true, "c6", TSDB_DATA_TYPE_DOUBLE, 0, 0); - addFieldToCreateStbReqFunc(true, "c7", TSDB_DATA_TYPE_BINARY, 20 + VARSTR_HEADER_SIZE, 0); - addFieldToCreateStbReqFunc(true, "c8", TSDB_DATA_TYPE_SMALLINT, 0, 0); - addFieldToCreateStbReqFunc(true, "c9", TSDB_DATA_TYPE_USMALLINT, 0, 0); - addFieldToCreateStbReqFunc(true, "c10", TSDB_DATA_TYPE_TINYINT, 0, 0); - addFieldToCreateStbReqFunc(true, "c11", TSDB_DATA_TYPE_UTINYINT, 0, 0); - addFieldToCreateStbReqFunc(true, "c12", TSDB_DATA_TYPE_BOOL, 0, 0); - addFieldToCreateStbReqFunc(true, "c13", TSDB_DATA_TYPE_NCHAR, 30 * TSDB_NCHAR_SIZE + VARSTR_HEADER_SIZE, 0); - addFieldToCreateStbReqFunc(true, "c14", TSDB_DATA_TYPE_VARCHAR, 50 + VARSTR_HEADER_SIZE, 0); - addFieldToCreateStbReqFunc(false, "a1", TSDB_DATA_TYPE_TIMESTAMP); - addFieldToCreateStbReqFunc(false, "a2", TSDB_DATA_TYPE_INT); - addFieldToCreateStbReqFunc(false, "a3", TSDB_DATA_TYPE_UINT); - addFieldToCreateStbReqFunc(false, "a4", TSDB_DATA_TYPE_BIGINT); - addFieldToCreateStbReqFunc(false, "a5", TSDB_DATA_TYPE_UBIGINT); - addFieldToCreateStbReqFunc(false, "a6", TSDB_DATA_TYPE_FLOAT); - addFieldToCreateStbReqFunc(false, "a7", TSDB_DATA_TYPE_DOUBLE); - addFieldToCreateStbReqFunc(false, "a8", TSDB_DATA_TYPE_BINARY, 20 + VARSTR_HEADER_SIZE); - addFieldToCreateStbReqFunc(false, "a9", TSDB_DATA_TYPE_SMALLINT); - addFieldToCreateStbReqFunc(false, "a10", TSDB_DATA_TYPE_USMALLINT); - addFieldToCreateStbReqFunc(false, "a11", TSDB_DATA_TYPE_TINYINT); - addFieldToCreateStbReqFunc(false, "a12", TSDB_DATA_TYPE_UTINYINT); - addFieldToCreateStbReqFunc(false, "a13", TSDB_DATA_TYPE_BOOL); - addFieldToCreateStbReqFunc(false, "a14", TSDB_DATA_TYPE_NCHAR, 30 * TSDB_NCHAR_SIZE + VARSTR_HEADER_SIZE); - addFieldToCreateStbReqFunc(false, "a15", TSDB_DATA_TYPE_VARCHAR, 50 + VARSTR_HEADER_SIZE); + setCreateStbReq("rollup_db", "t1", 1, 100 * MILLISECOND_PER_SECOND, 10 * MILLISECOND_PER_MINUTE, 10, + 1 * MILLISECOND_PER_MINUTE, 1000 * MILLISECOND_PER_SECOND, 200 * MILLISECOND_PER_MINUTE, 100, + "test create table"); + addFieldToCreateStbReq(true, "ts", TSDB_DATA_TYPE_TIMESTAMP, 0, 0); + addFieldToCreateStbReq(true, "c1", TSDB_DATA_TYPE_INT); + addFieldToCreateStbReq(true, "c2", TSDB_DATA_TYPE_UINT); + addFieldToCreateStbReq(true, "c3", TSDB_DATA_TYPE_BIGINT); + addFieldToCreateStbReq(true, "c4", TSDB_DATA_TYPE_UBIGINT, 0, 0); + addFieldToCreateStbReq(true, "c5", TSDB_DATA_TYPE_FLOAT, 0, 0); + addFieldToCreateStbReq(true, "c6", TSDB_DATA_TYPE_DOUBLE, 0, 0); + addFieldToCreateStbReq(true, "c7", TSDB_DATA_TYPE_BINARY, 20 + VARSTR_HEADER_SIZE, 0); + addFieldToCreateStbReq(true, "c8", TSDB_DATA_TYPE_SMALLINT, 0, 0); + addFieldToCreateStbReq(true, "c9", TSDB_DATA_TYPE_USMALLINT, 0, 0); + addFieldToCreateStbReq(true, "c10", TSDB_DATA_TYPE_TINYINT, 0, 0); + addFieldToCreateStbReq(true, "c11", TSDB_DATA_TYPE_UTINYINT, 0, 0); + addFieldToCreateStbReq(true, "c12", TSDB_DATA_TYPE_BOOL, 0, 0); + addFieldToCreateStbReq(true, "c13", TSDB_DATA_TYPE_NCHAR, 30 * TSDB_NCHAR_SIZE + VARSTR_HEADER_SIZE, 0); + addFieldToCreateStbReq(true, "c14", TSDB_DATA_TYPE_VARCHAR, 50 + VARSTR_HEADER_SIZE, 0); + addFieldToCreateStbReq(false, "a1", TSDB_DATA_TYPE_TIMESTAMP); + addFieldToCreateStbReq(false, "a2", TSDB_DATA_TYPE_INT); + addFieldToCreateStbReq(false, "a3", TSDB_DATA_TYPE_UINT); + addFieldToCreateStbReq(false, "a4", TSDB_DATA_TYPE_BIGINT); + addFieldToCreateStbReq(false, "a5", TSDB_DATA_TYPE_UBIGINT); + addFieldToCreateStbReq(false, "a6", TSDB_DATA_TYPE_FLOAT); + addFieldToCreateStbReq(false, "a7", TSDB_DATA_TYPE_DOUBLE); + addFieldToCreateStbReq(false, "a8", TSDB_DATA_TYPE_BINARY, 20 + VARSTR_HEADER_SIZE); + addFieldToCreateStbReq(false, "a9", TSDB_DATA_TYPE_SMALLINT); + addFieldToCreateStbReq(false, "a10", TSDB_DATA_TYPE_USMALLINT); + addFieldToCreateStbReq(false, "a11", TSDB_DATA_TYPE_TINYINT); + addFieldToCreateStbReq(false, "a12", TSDB_DATA_TYPE_UTINYINT); + addFieldToCreateStbReq(false, "a13", TSDB_DATA_TYPE_BOOL); + addFieldToCreateStbReq(false, "a14", TSDB_DATA_TYPE_NCHAR, 30 * TSDB_NCHAR_SIZE + VARSTR_HEADER_SIZE); + addFieldToCreateStbReq(false, "a15", TSDB_DATA_TYPE_VARCHAR, 50 + VARSTR_HEADER_SIZE); run("CREATE STABLE IF NOT EXISTS rollup_db.t1(" "ts TIMESTAMP, c1 INT, c2 INT UNSIGNED, c3 BIGINT, c4 BIGINT UNSIGNED, c5 FLOAT, c6 DOUBLE, c7 BINARY(20), " "c8 SMALLINT, c9 SMALLINT UNSIGNED COMMENT 'test column comment', c10 TINYINT, c11 TINYINT UNSIGNED, c12 BOOL, " @@ -630,6 +730,20 @@ TEST_F(ParserInitialCTest, createStableSemanticCheck) { TSDB_CODE_PAR_INVALID_TABLE_OPTION); } +/* + * CREATE STREAM [IF NOT EXISTS] stream_name [stream_options] + * INTO stb_name [TAGS (create_definition [, create_definition] ...)] [SUBTABLE (expr)] AS subquery + * + * stream_options: + * stream_option ... + * + * stream_option: { + * TRIGGER [AT_ONCE | WINDOW_CLOSE | MAX_DELAY time] + * | WATERMARK time + * | IGNORE EXPIRED value + * | FILL_HISTORY value + * } + */ TEST_F(ParserInitialCTest, createStream) { useDb("root", "test"); @@ -734,9 +848,103 @@ TEST_F(ParserInitialCTest, createStreamSemanticCheck) { TSDB_CODE_PAR_STREAM_NOT_ALLOWED_FUNC); } +/* + * CREATE TABLE [IF NOT EXISTS] [db_name.]tb_name (create_definition [, create_definitionn] ...) [table_options] + * + * CREATE TABLE create_subtable_clause + * + * CREATE TABLE [IF NOT EXISTS] [db_name.]tb_name (create_definition [, create_definitionn] ...) + * [TAGS (create_definition [, create_definitionn] ...)] + * [table_options] + * + * create_subtable_clause: { + * create_subtable_clause [create_subtable_clause] ... + * | [IF NOT EXISTS] [db_name.]tb_name USING [db_name.]stb_name [(tag_name [, tag_name] ...)] + * TAGS (tag_value [, tag_value] ...) + * } + * + * create_definition: + * col_name column_definition + * + * column_definition: + * type_name [comment 'string_value'] + * + * table_options: + * table_option ... + * + * table_option: { + * COMMENT 'string_value' + * | WATERMARK duration[,duration] + * | MAX_DELAY duration[,duration] + * | ROLLUP(func_name [, func_name] ...) + * | SMA(col_name [, col_name] ...) + * | TTL value + * } + */ TEST_F(ParserInitialCTest, createTable) { useDb("root", "test"); + SVCreateTbBatchReq expect = {0}; + + auto addCreateTbReq = [&](const char* pName, bool ignoreExists = false, int32_t ttl = TSDB_DEFAULT_TABLE_TTL, + const char* pComment = nullptr) { + SVCreateTbReq req = {0}; + req.name = strdup(pName); + if (ignoreExists) { + req.flags |= TD_CREATE_IF_NOT_EXISTS; + } + req.ttl = ttl; + if (nullptr != pComment) { + req.comment = strdup(pComment); + req.commentLen = strlen(pComment); + } + ++expect.nReqs; + if (nullptr == expect.pArray) { + expect.pArray = taosArrayInit(TARRAY_MIN_SIZE, sizeof(SVCreateTbReq)); + } + taosArrayPush(expect.pArray, &req); + }; + + setCheckDdlFunc([&](const SQuery* pQuery, ParserStage stage) { + return; // todo + ASSERT_EQ(nodeType(pQuery->pRoot), QUERY_NODE_VNODE_MODIFY_STMT); + SVnodeModifyOpStmt* pStmt = (SVnodeModifyOpStmt*)pQuery->pRoot; + + ASSERT_EQ(pStmt->sqlNodeType, QUERY_NODE_CREATE_TABLE_STMT); + ASSERT_NE(pStmt->pDataBlocks, nullptr); + int32_t numOfBlocks = taosArrayGetSize(pStmt->pDataBlocks); + for (int32_t i = 0; i < numOfBlocks; ++i) { + SVgDataBlocks* pVgData = (SVgDataBlocks*)taosArrayGetP(pStmt->pDataBlocks, i); + void* pBuf = POINTER_SHIFT(pVgData->pData, sizeof(SMsgHead)); + SVCreateTbBatchReq req = {0}; + SDecoder coder = {0}; + tDecoderInit(&coder, (uint8_t*)pBuf, pVgData->size); + ASSERT_EQ(tDecodeSVCreateTbBatchReq(&coder, &req), TSDB_CODE_SUCCESS); + ASSERT_EQ(req.nReqs, expect.nReqs); + for (int32_t j = 0; j < req.nReqs; ++j) { + SVCreateTbReq* pReq = req.pReqs + j; + SVCreateTbReq* pExpect = (SVCreateTbReq*)taosArrayGet(expect.pArray, j); + ASSERT_EQ(pReq->flags, pExpect->flags); + ASSERT_EQ(std::string(pReq->name), std::string(pExpect->name)); + ASSERT_EQ(pReq->uid, pExpect->uid); + ASSERT_EQ(pReq->ctime, pExpect->ctime); + ASSERT_EQ(pReq->ttl, pExpect->ttl); + ASSERT_EQ(pReq->commentLen, pExpect->commentLen); + ASSERT_EQ(std::string(pReq->comment), std::string(pExpect->comment)); + ASSERT_EQ(pReq->type, pExpect->type); + if (TD_NORMAL_TABLE == pExpect->type) { + ASSERT_EQ(pReq->ntb.schemaRow.version, pExpect->ntb.schemaRow.version); + ASSERT_EQ(pReq->ntb.schemaRow.nCols, pExpect->ntb.schemaRow.nCols); + } else if (TD_CHILD_TABLE == pExpect->type) { + ASSERT_EQ(std::string(pReq->ctb.stbName), std::string(pExpect->ctb.stbName)); + ASSERT_EQ(pReq->ctb.tagNum, pExpect->ctb.tagNum); + ASSERT_EQ(pReq->ctb.suid, pExpect->ctb.suid); + } + } + tDecoderClear(&coder); + } + }); + run("CREATE TABLE t1(ts TIMESTAMP, c1 INT)"); run("CREATE TABLE IF NOT EXISTS test.t1(" @@ -761,7 +969,7 @@ TEST_F(ParserInitialCTest, createTable) { "IF NOT EXISTS test.t2 USING test.st1 (tag1, tag2) TAGS(2, 'abc') " "IF NOT EXISTS test.t3 USING test.st1 (tag1, tag2) TAGS(3, 'abc') "); - // run("CREATE TABLE IF NOT EXISTS t1 USING st1 TAGS(1, 'wxy', NOW + 1S)"); + run("CREATE TABLE IF NOT EXISTS t1 USING st1 TAGS(1, 'wxy', NOW + 1S)"); } TEST_F(ParserInitialCTest, createTableSemanticCheck) { @@ -779,6 +987,11 @@ TEST_F(ParserInitialCTest, createTableSemanticCheck) { run(sql, TSDB_CODE_PAR_TOO_MANY_COLUMNS); } +/* + * CREATE TOPIC [IF NOT EXISTS] topic_name AS subquery + * + * CREATE TOPIC [IF NOT EXISTS] topic_name [WITH META] AS {DATABASE db_name | STABLE stb_name } + */ TEST_F(ParserInitialCTest, createTopic) { useDb("root", "test"); @@ -786,8 +999,8 @@ TEST_F(ParserInitialCTest, createTopic) { auto clearCreateTopicReq = [&]() { memset(&expect, 0, sizeof(SCMCreateTopicReq)); }; - auto setCreateTopicReqFunc = [&](const char* pTopicName, int8_t igExists, const char* pSql, const char* pAst, - const char* pDbName = nullptr, const char* pTbname = nullptr, int8_t withMeta = 0) { + auto setCreateTopicReq = [&](const char* pTopicName, int8_t igExists, const char* pSql, const char* pAst, + const char* pDbName = nullptr, const char* pTbname = nullptr, int8_t withMeta = 0) { snprintf(expect.name, sizeof(expect.name), "0.%s", pTopicName); expect.igExists = igExists; expect.sql = (char*)pSql; @@ -831,31 +1044,34 @@ TEST_F(ParserInitialCTest, createTopic) { tFreeSCMCreateTopicReq(&req); }); - setCreateTopicReqFunc("tp1", 0, "create topic tp1 as select * from t1", "ast"); + setCreateTopicReq("tp1", 0, "create topic tp1 as select * from t1", "ast"); run("CREATE TOPIC tp1 AS SELECT * FROM t1"); clearCreateTopicReq(); - setCreateTopicReqFunc("tp1", 1, "create topic if not exists tp1 as select ts, ceil(c1) from t1", "ast"); + setCreateTopicReq("tp1", 1, "create topic if not exists tp1 as select ts, ceil(c1) from t1", "ast"); run("CREATE TOPIC IF NOT EXISTS tp1 AS SELECT ts, CEIL(c1) FROM t1"); clearCreateTopicReq(); - setCreateTopicReqFunc("tp1", 0, "create topic tp1 as database test", nullptr, "test"); + setCreateTopicReq("tp1", 0, "create topic tp1 as database test", nullptr, "test"); run("CREATE TOPIC tp1 AS DATABASE test"); clearCreateTopicReq(); - setCreateTopicReqFunc("tp1", 0, "create topic tp1 with meta as database test", nullptr, "test", nullptr, 1); + setCreateTopicReq("tp1", 0, "create topic tp1 with meta as database test", nullptr, "test", nullptr, 1); run("CREATE TOPIC tp1 WITH META AS DATABASE test"); clearCreateTopicReq(); - setCreateTopicReqFunc("tp1", 1, "create topic if not exists tp1 as stable st1", nullptr, "test", "st1"); + setCreateTopicReq("tp1", 1, "create topic if not exists tp1 as stable st1", nullptr, "test", "st1"); run("CREATE TOPIC IF NOT EXISTS tp1 AS STABLE st1"); clearCreateTopicReq(); - setCreateTopicReqFunc("tp1", 1, "create topic if not exists tp1 with meta as stable st1", nullptr, "test", "st1", 1); + setCreateTopicReq("tp1", 1, "create topic if not exists tp1 with meta as stable st1", nullptr, "test", "st1", 1); run("CREATE TOPIC IF NOT EXISTS tp1 WITH META AS STABLE st1"); clearCreateTopicReq(); } +/* + * CREATE USER use_name PASS password [SYSINFO value] + */ TEST_F(ParserInitialCTest, createUser) { useDb("root", "test"); diff --git a/source/libs/parser/test/parInitialDTest.cpp b/source/libs/parser/test/parInitialDTest.cpp index 3ded71242b961ceaf12abbdff44272c7fa6cb32c..3d773d351070fa55f0f658dd093d4f185fa5d4ef 100644 --- a/source/libs/parser/test/parInitialDTest.cpp +++ b/source/libs/parser/test/parInitialDTest.cpp @@ -99,7 +99,7 @@ TEST_F(ParserInitialDTest, dropDnode) { expect.force = force; }; - auto setDropDnodeReqByEndpoint = [&](const char* pFqdn, int32_t port, bool force = false) { + auto setDropDnodeReqByEndpoint = [&](const char* pFqdn, int32_t port = tsServerPort, bool force = false) { strcpy(expect.fqdn, pFqdn); expect.port = port; expect.force = force; @@ -131,6 +131,14 @@ TEST_F(ParserInitialDTest, dropDnode) { setDropDnodeReqByEndpoint("host2", 8030, true); run("DROP DNODE 'host2:8030' FORCE"); clearDropDnodeReq(); + + setDropDnodeReqByEndpoint("host1"); + run("DROP DNODE host1"); + clearDropDnodeReq(); + + setDropDnodeReqByEndpoint("host2", tsServerPort, true); + run("DROP DNODE host2 FORCE"); + clearDropDnodeReq(); } // todo DROP function @@ -174,7 +182,21 @@ TEST_F(ParserInitialDTest, dropMnode) { TEST_F(ParserInitialDTest, dropQnode) { useDb("root", "test"); - run("DROP qnode on dnode 1"); + SMDropQnodeReq expect = {0}; + + auto setDropQnodeReq = [&](int32_t dnodeId) { expect.dnodeId = dnodeId; }; + + setCheckDdlFunc([&](const SQuery* pQuery, ParserStage stage) { + ASSERT_EQ(nodeType(pQuery->pRoot), QUERY_NODE_DROP_QNODE_STMT); + SMDropQnodeReq req = {0}; + ASSERT_TRUE(TSDB_CODE_SUCCESS == + tDeserializeSCreateDropMQSNodeReq(pQuery->pCmdMsg->pMsg, pQuery->pCmdMsg->msgLen, &req)); + + ASSERT_EQ(req.dnodeId, expect.dnodeId); + }); + + setDropQnodeReq(1); + run("DROP QNODE ON DNODE 1"); } TEST_F(ParserInitialDTest, dropSnode) { @@ -237,7 +259,20 @@ TEST_F(ParserInitialDTest, dropUser) { login("root"); useDb("root", "test"); - run("DROP user wxy"); + SDropUserReq expect = {0}; + + auto setDropUserReq = [&](const char* pUser) { sprintf(expect.user, "%s", pUser); }; + + setCheckDdlFunc([&](const SQuery* pQuery, ParserStage stage) { + ASSERT_EQ(nodeType(pQuery->pRoot), QUERY_NODE_DROP_USER_STMT); + SDropUserReq req = {0}; + ASSERT_TRUE(TSDB_CODE_SUCCESS == tDeserializeSDropUserReq(pQuery->pCmdMsg->pMsg, pQuery->pCmdMsg->msgLen, &req)); + + ASSERT_EQ(std::string(req.user), std::string(expect.user)); + }); + + setDropUserReq("wxy"); + run("DROP USER wxy"); } } // namespace ParserTest diff --git a/source/libs/stream/src/streamExec.c b/source/libs/stream/src/streamExec.c index b5bceb9b94fb8e819e0774a477286fd8b14e4a24..415fa41e56f84ef0b25865ebd7ce7a44dbe92727 100644 --- a/source/libs/stream/src/streamExec.c +++ b/source/libs/stream/src/streamExec.c @@ -112,7 +112,11 @@ int32_t streamScanExec(SStreamTask* pTask, int32_t batchSz) { ASSERT(0); } if (output == NULL) { - finished = true; + if (qStreamRecoverScanFinished(exec)) { + finished = true; + } else { + qSetStreamOpOpen(exec); + } break; } diff --git a/source/os/src/osMath.c b/source/os/src/osMath.c index cd2acac2611b4ed2f270c0647d9e06cec334ef8d..dddadd5ff6c187621a1b37efb24882ef84448cb9 100644 --- a/source/os/src/osMath.c +++ b/source/os/src/osMath.c @@ -16,6 +16,7 @@ #define ALLOW_FORBID_FUNC #define _DEFAULT_SOURCE #include "os.h" +#include #ifdef WINDOWS void swapStr(char* j, char* J, int width) { @@ -33,16 +34,5 @@ void swapStr(char* j, char* J, int width) { // todo refactor: 1) move away; 2) use merge sort instead; 3) qsort is not a stable sort actually. void taosSort(void* arr, int64_t sz, int64_t width, __compar_fn_t compar) { -#ifdef WINDOWS - int64_t i, j; - for (i = 0; i < sz - 1; i++) { - for (j = 0; j < sz - 1 - i; j++) { - if (compar((char*)arr + j * width, (char*)arr + (j + 1) * width) > 0.00) { - swapStr((char*)arr + j * width, (char*)arr + (j + 1) * width, width); - } - } - } -#else qsort(arr, sz, width, compar); -#endif }