From 7cacd403d5ecf379c5660718062aa49a9f7744ad Mon Sep 17 00:00:00 2001 From: lichuang Date: Sat, 8 May 2021 16:40:45 +0800 Subject: [PATCH 01/70] add cache last null columns feature --- documentation20/cn/11.administrator/docs.md | 2 +- src/common/src/ttypes.c | 58 +++++++++++++++++++++ src/inc/taosdef.h | 2 +- src/inc/tsdb.h | 6 ++- src/inc/ttype.h | 3 ++ src/tsdb/inc/tsdbMeta.h | 3 ++ src/tsdb/src/tsdbMain.c | 8 +-- src/tsdb/src/tsdbMemTable.c | 57 +++++++++++++++++++- src/tsdb/src/tsdbMeta.c | 7 +++ 9 files changed, 138 insertions(+), 8 deletions(-) diff --git a/documentation20/cn/11.administrator/docs.md b/documentation20/cn/11.administrator/docs.md index bfa0456c7d..b9340210d2 100644 --- a/documentation20/cn/11.administrator/docs.md +++ b/documentation20/cn/11.administrator/docs.md @@ -129,7 +129,7 @@ taosd -C - blocks:每个VNODE(TSDB)中有多少cache大小的内存块。因此一个VNODE的用的内存大小粗略为(cache * blocks)。单位为块,默认值:4。(可通过 alter database 修改) - replica:副本个数,取值范围:1-3。单位为个,默认值:1。(可通过 alter database 修改) - precision:时间戳精度标识,ms表示毫秒,us表示微秒。默认值:ms。 -- cacheLast:是否在内存中缓存子表 last_row,0:关闭;1:开启。默认值:0。(可通过 alter database 修改)(从 2.0.11 版本开始支持此参数) +- cacheLast:是否在内存中缓存子表的最近数据,0:关闭;1:缓存子表最近一行数据;2:缓存子表每一列的最近的非NULL值,设置为3表示同时开启了1和2。默认值:0。(可通过 alter database 修改)(从 2.0.11 版本开始支持此参数) 对于一个应用场景,可能有多种数据特征的数据并存,最佳的设计是将具有相同数据特征的表放在一个库里,这样一个应用有多个库,而每个库可以配置不同的存储参数,从而保证系统有最优的性能。TDengine允许应用在创建库时指定上述存储参数,如果指定,该参数就将覆盖对应的系统配置参数。举例,有下述SQL: diff --git a/src/common/src/ttypes.c b/src/common/src/ttypes.c index 6fa27a029b..77e12e23d2 100644 --- a/src/common/src/ttypes.c +++ b/src/common/src/ttypes.c @@ -417,6 +417,16 @@ void setVardataNull(char* val, int32_t type) { } } +bool isVardataNull(char* val, int32_t type) { + if (type == TSDB_DATA_TYPE_BINARY) { + return *(uint8_t*) varDataVal(val) == TSDB_DATA_BINARY_NULL; + } else if (type == TSDB_DATA_TYPE_NCHAR) { + return *(uint32_t*) varDataVal(val) == TSDB_DATA_NCHAR_NULL; + } else { + assert(0); + } +} + void setNull(char *val, int32_t type, int32_t bytes) { setNullN(val, type, bytes, 1); } void setNullN(char *val, int32_t type, int32_t bytes, int32_t numOfElems) { @@ -492,6 +502,54 @@ void setNullN(char *val, int32_t type, int32_t bytes, int32_t numOfElems) { } } +bool isNullN(char *val, int32_t type) { + switch (type) { + case TSDB_DATA_TYPE_BOOL: + return *(uint8_t *)(val) == TSDB_DATA_BOOL_NULL; + break; + case TSDB_DATA_TYPE_TINYINT: + return *(uint8_t *)(val) == TSDB_DATA_TINYINT_NULL; + break; + case TSDB_DATA_TYPE_SMALLINT: + return *(uint16_t *)(val) == TSDB_DATA_SMALLINT_NULL; + break; + case TSDB_DATA_TYPE_INT: + return *(uint32_t *)(val) == TSDB_DATA_INT_NULL; + break; + case TSDB_DATA_TYPE_BIGINT: + case TSDB_DATA_TYPE_TIMESTAMP: + return *(uint64_t *)(val) == TSDB_DATA_BIGINT_NULL; + break; + case TSDB_DATA_TYPE_UTINYINT: + return *(uint8_t *)(val) == TSDB_DATA_UTINYINT_NULL; + break; + case TSDB_DATA_TYPE_USMALLINT: + return *(uint16_t *)(val) == TSDB_DATA_USMALLINT_NULL; + break; + case TSDB_DATA_TYPE_UINT: + return *(uint32_t *)(val) == TSDB_DATA_UINT_NULL; + break; + case TSDB_DATA_TYPE_UBIGINT: + return *(uint64_t *)(val) == TSDB_DATA_UBIGINT_NULL; + break; + case TSDB_DATA_TYPE_FLOAT: + return *(uint32_t *)(val) == TSDB_DATA_FLOAT_NULL; + break; + case TSDB_DATA_TYPE_DOUBLE: + return *(uint64_t *)(val) == TSDB_DATA_DOUBLE_NULL; + break; + case TSDB_DATA_TYPE_NCHAR: + case TSDB_DATA_TYPE_BINARY: + return isVardataNull(val, type); + break; + default: { + return *(uint32_t *)(val) == TSDB_DATA_INT_NULL; + break; + } + } + +} + static uint8_t nullBool = TSDB_DATA_BOOL_NULL; static uint8_t nullTinyInt = TSDB_DATA_TINYINT_NULL; static uint16_t nullSmallInt = TSDB_DATA_SMALLINT_NULL; diff --git a/src/inc/taosdef.h b/src/inc/taosdef.h index e9170860a6..f6479ea15d 100644 --- a/src/inc/taosdef.h +++ b/src/inc/taosdef.h @@ -299,7 +299,7 @@ do { \ #define TSDB_DEFAULT_DB_UPDATE_OPTION 0 #define TSDB_MIN_DB_CACHE_LAST_ROW 0 -#define TSDB_MAX_DB_CACHE_LAST_ROW 1 +#define TSDB_MAX_DB_CACHE_LAST_ROW 2 #define TSDB_DEFAULT_CACHE_LAST_ROW 0 #define TSDB_MIN_FSYNC_PERIOD 0 diff --git a/src/inc/tsdb.h b/src/inc/tsdb.h index 1ba5131f6d..7c28d3e485 100644 --- a/src/inc/tsdb.h +++ b/src/inc/tsdb.h @@ -69,9 +69,13 @@ typedef struct { int8_t precision; int8_t compression; int8_t update; - int8_t cacheLastRow; + int8_t cacheLastRow; // 0:no cache, 1: cache last row, 2: cache last NULL column } STsdbCfg; +#define CACHE_NO_LAST(c) ((c)->cacheLastRow == 0) +#define CACHE_LAST_ROW(c) (((c)->cacheLastRow & 1) > 0) +#define CACHE_LAST_NULL_COLUMN(c) (((c)->cacheLastRow & 2) > 0) + // --------- TSDB REPOSITORY USAGE STATISTICS typedef struct { int64_t totalStorage; // total bytes occupie diff --git a/src/inc/ttype.h b/src/inc/ttype.h index 662a23bfdb..120667ce6e 100644 --- a/src/inc/ttype.h +++ b/src/inc/ttype.h @@ -176,6 +176,9 @@ void setNull(char *val, int32_t type, int32_t bytes); void setNullN(char *val, int32_t type, int32_t bytes, int32_t numOfElems); void *getNullValue(int32_t type); +bool isVardataNull(char* val, int32_t type); +bool isNullN(char *val, int32_t type); + void assignVal(char *val, const char *src, int32_t len, int32_t type); void tsDataSwap(void *pLeft, void *pRight, int32_t type, int32_t size, void* buf); diff --git a/src/tsdb/inc/tsdbMeta.h b/src/tsdb/inc/tsdbMeta.h index cc916fa689..d339989bb3 100644 --- a/src/tsdb/inc/tsdbMeta.h +++ b/src/tsdb/inc/tsdbMeta.h @@ -36,6 +36,9 @@ typedef struct STable { char* sql; void* cqhandle; SRWLatch latch; // TODO: implementa latch functions + + SDataCol *lastCols; + int32_t lastColNum; T_REF_DECLARE() } STable; diff --git a/src/tsdb/src/tsdbMain.c b/src/tsdb/src/tsdbMain.c index 99929f3542..5a44b03c81 100644 --- a/src/tsdb/src/tsdbMain.c +++ b/src/tsdb/src/tsdbMain.c @@ -447,8 +447,10 @@ static int32_t tsdbCheckAndSetDefaultCfg(STsdbCfg *pCfg) { if (pCfg->update != 0) pCfg->update = 1; // update cacheLastRow - if (pCfg->cacheLastRow != 0) pCfg->cacheLastRow = 1; - + if (pCfg->cacheLastRow != 0) { + if (pCfg->cacheLastRow > 3) + pCfg->cacheLastRow = 1; + } return 0; } @@ -581,7 +583,7 @@ int tsdbRestoreInfo(STsdbRepo *pRepo) { if (pIdx && lastKey < pIdx->maxKey) { pTable->lastKey = pIdx->maxKey; - if (pCfg->cacheLastRow) { + if (CACHE_LAST_ROW(pCfg)) { if (tsdbLoadBlockInfo(&readh, NULL) < 0) { tsdbDestroyReadH(&readh); return -1; diff --git a/src/tsdb/src/tsdbMemTable.c b/src/tsdb/src/tsdbMemTable.c index 20ec426018..18041f0291 100644 --- a/src/tsdb/src/tsdbMemTable.c +++ b/src/tsdb/src/tsdbMemTable.c @@ -955,11 +955,61 @@ static void tsdbFreeRows(STsdbRepo *pRepo, void **rows, int rowCounter) { } } +static void updateTableLatestColumn(STsdbRepo *pRepo, STable *pTable, SDataRow row) { + //tsdbDebug("vgId:%d updateTableLatestColumn, row version:%d", REPO_ID(pRepo), dataRowVersion(row)); + + if (pTable->numOfSchemas <= 0) { + return; + } + STSchema* pSchema = pTable->schema[pTable->numOfSchemas - 1]; + int i = pTable->numOfSchemas - 1; + while ((pSchema == NULL || pSchema->version != dataRowVersion(row)) && i >= 0) { + i -= 1; + pSchema = pTable->schema[i]; + } + if (pSchema == NULL || pSchema->version != dataRowVersion(row)) { + return; + } + + SDataCol *pLatestCols = pTable->lastCols; + + for (int j = 0; j < schemaNCols(pSchema); j++) { + if (j >= pTable->lastColNum) { + pTable->lastCols = realloc(pTable->lastCols, pTable->lastColNum + 10); + for (int i = 0; i < 10; ++i) { + pTable->lastCols[i + pTable->lastColNum].bytes = 0; + pTable->lastCols[i + pTable->lastColNum].pData = NULL; + } + pTable->lastColNum += 10; + } + + STColumn *pTCol = schemaColAt(pSchema, j); + SDataCol *pDataCol = &(pLatestCols[j]); + void* value = tdGetRowDataOfCol(row, (int8_t)pTCol->type, TD_DATA_ROW_HEAD_SIZE + pSchema->columns[j].offset); + if (isNullN(value, pTCol->type)) { + continue; + } + if (pDataCol->pData == NULL) { + pDataCol->pData = malloc(pSchema->columns[j].bytes); + pDataCol->bytes = pSchema->columns[j].bytes; + } else if (pDataCol->bytes < pSchema->columns[j].bytes) { + pDataCol->pData = realloc(pDataCol->pData, pSchema->columns[j].bytes); + pDataCol->bytes = pSchema->columns[j].bytes; + } + + //tsdbDebug("vgId:%d cache column %d for %d,%p", REPO_ID(pRepo), j, pDataCol->bytes, pDataCol->pData); + + memcpy(pDataCol->pData, value, pDataCol->bytes); + } +} + static int tsdbUpdateTableLatestInfo(STsdbRepo *pRepo, STable *pTable, SDataRow row) { STsdbCfg *pCfg = &pRepo->config; + tsdbDebug("vgId:%d tsdbUpdateTableLatestInfo, %ld, %ld, %d", REPO_ID(pRepo), tsdbGetTableLastKeyImpl(pTable), dataRowKey(row), pCfg->cacheLastRow); + if (tsdbGetTableLastKeyImpl(pTable) < dataRowKey(row)) { - if (pCfg->cacheLastRow || pTable->lastRow != NULL) { + if (CACHE_LAST_ROW(pCfg) || pTable->lastRow != NULL) { SDataRow nrow = pTable->lastRow; if (taosTSizeof(nrow) < dataRowLen(row)) { SDataRow orow = nrow; @@ -984,7 +1034,10 @@ static int tsdbUpdateTableLatestInfo(STsdbRepo *pRepo, STable *pTable, SDataRow } else { pTable->lastKey = dataRowKey(row); } - } + if (CACHE_LAST_NULL_COLUMN(pCfg)) { + updateTableLatestColumn(pRepo, pTable, row); + } + } return 0; } diff --git a/src/tsdb/src/tsdbMeta.c b/src/tsdb/src/tsdbMeta.c index 3e6263b9d3..b8e3273664 100644 --- a/src/tsdb/src/tsdbMeta.c +++ b/src/tsdb/src/tsdbMeta.c @@ -14,6 +14,7 @@ */ #include "tsdbint.h" +#define TSDB_LATEST_COLUMN_ARRAY_SIZE 20 #define TSDB_SUPER_TABLE_SL_LEVEL 5 #define DEFAULT_TAG_INDEX_COLUMN 0 @@ -671,6 +672,12 @@ static STable *tsdbNewTable() { } pTable->lastKey = TSKEY_INITIAL_VAL; + pTable->lastCols = (SDataCol*)malloc(TSDB_LATEST_COLUMN_ARRAY_SIZE * sizeof(SDataCol)); + pTable->lastColNum = TSDB_LATEST_COLUMN_ARRAY_SIZE; + for (int i = 0; i < pTable->lastColNum; ++i) { + pTable->lastCols[i].bytes = 0; + pTable->lastCols[i].pData = NULL; + } return pTable; } From 913eb1c71911752378f79c1fa978c09dd8fba83c Mon Sep 17 00:00:00 2001 From: lichuang Date: Sat, 8 May 2021 17:08:29 +0800 Subject: [PATCH 02/70] cache last null columns feature --- src/tsdb/src/tsdbMeta.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/tsdb/src/tsdbMeta.c b/src/tsdb/src/tsdbMeta.c index b8e3273664..9b98ca19fc 100644 --- a/src/tsdb/src/tsdbMeta.c +++ b/src/tsdb/src/tsdbMeta.c @@ -794,6 +794,13 @@ static void tsdbFreeTable(STable *pTable) { tSkipListDestroy(pTable->pIndex); taosTZfree(pTable->lastRow); tfree(pTable->sql); + + for (int i = 0; i < pTable->lastColNum; ++i) { + if (pTable->lastCols[i].pData == NULL) { + continue; + } + free(pTable->lastCols[i].pData); + } free(pTable); } } From f0640ac09ef0af41781fd3daed847b4ff91a1920 Mon Sep 17 00:00:00 2001 From: lichuang Date: Sat, 8 May 2021 18:02:26 +0800 Subject: [PATCH 03/70] disable debug log --- src/tsdb/src/tsdbMemTable.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tsdb/src/tsdbMemTable.c b/src/tsdb/src/tsdbMemTable.c index 18041f0291..d7d1e5ea18 100644 --- a/src/tsdb/src/tsdbMemTable.c +++ b/src/tsdb/src/tsdbMemTable.c @@ -1006,7 +1006,7 @@ static void updateTableLatestColumn(STsdbRepo *pRepo, STable *pTable, SDataRow r static int tsdbUpdateTableLatestInfo(STsdbRepo *pRepo, STable *pTable, SDataRow row) { STsdbCfg *pCfg = &pRepo->config; - tsdbDebug("vgId:%d tsdbUpdateTableLatestInfo, %ld, %ld, %d", REPO_ID(pRepo), tsdbGetTableLastKeyImpl(pTable), dataRowKey(row), pCfg->cacheLastRow); + //tsdbDebug("vgId:%d tsdbUpdateTableLatestInfo, %ld, %ld, %d", REPO_ID(pRepo), tsdbGetTableLastKeyImpl(pTable), dataRowKey(row), pCfg->cacheLastRow); if (tsdbGetTableLastKeyImpl(pTable) < dataRowKey(row)) { if (CACHE_LAST_ROW(pCfg) || pTable->lastRow != NULL) { From 4814df777c8166e1d01f707efdc5e397e1a5ac81 Mon Sep 17 00:00:00 2001 From: lichuang Date: Sat, 8 May 2021 18:40:48 +0800 Subject: [PATCH 04/70] fix compile error --- src/common/src/ttypes.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/common/src/ttypes.c b/src/common/src/ttypes.c index 77e12e23d2..6587a27760 100644 --- a/src/common/src/ttypes.c +++ b/src/common/src/ttypes.c @@ -425,6 +425,8 @@ bool isVardataNull(char* val, int32_t type) { } else { assert(0); } + + return false; } void setNull(char *val, int32_t type, int32_t bytes) { setNullN(val, type, bytes, 1); } @@ -548,6 +550,7 @@ bool isNullN(char *val, int32_t type) { } } + return false; } static uint8_t nullBool = TSDB_DATA_BOOL_NULL; From 8497cdee74ffb87b82157e38bfc837120fdb5eed Mon Sep 17 00:00:00 2001 From: lichuang Date: Mon, 10 May 2021 15:26:33 +0800 Subject: [PATCH 05/70] fix memory leak --- src/tsdb/src/tsdbMeta.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tsdb/src/tsdbMeta.c b/src/tsdb/src/tsdbMeta.c index 9b98ca19fc..f4f555e2df 100644 --- a/src/tsdb/src/tsdbMeta.c +++ b/src/tsdb/src/tsdbMeta.c @@ -793,6 +793,7 @@ static void tsdbFreeTable(STable *pTable) { tSkipListDestroy(pTable->pIndex); taosTZfree(pTable->lastRow); + tfree(pTable->lastCols); tfree(pTable->sql); for (int i = 0; i < pTable->lastColNum; ++i) { From 00836e137cd23c973667c050a5396c01150ba5bd Mon Sep 17 00:00:00 2001 From: lichuang Date: Mon, 10 May 2021 17:01:38 +0800 Subject: [PATCH 06/70] fix memory leak --- src/tsdb/src/tsdbMeta.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/tsdb/src/tsdbMeta.c b/src/tsdb/src/tsdbMeta.c index f4f555e2df..d45f4c2d60 100644 --- a/src/tsdb/src/tsdbMeta.c +++ b/src/tsdb/src/tsdbMeta.c @@ -792,8 +792,7 @@ static void tsdbFreeTable(STable *pTable) { kvRowFree(pTable->tagVal); tSkipListDestroy(pTable->pIndex); - taosTZfree(pTable->lastRow); - tfree(pTable->lastCols); + taosTZfree(pTable->lastRow); tfree(pTable->sql); for (int i = 0; i < pTable->lastColNum; ++i) { @@ -802,6 +801,8 @@ static void tsdbFreeTable(STable *pTable) { } free(pTable->lastCols[i].pData); } + tfree(pTable->lastCols); + free(pTable); } } From 14b699f53bcc07973cb391cb665186d1d30814f1 Mon Sep 17 00:00:00 2001 From: lichuang Date: Thu, 13 May 2021 11:24:18 +0800 Subject: [PATCH 07/70] [TD-4034]refactor cache condition --- documentation20/cn/11.administrator/docs.md | 2 +- src/inc/tsdb.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/documentation20/cn/11.administrator/docs.md b/documentation20/cn/11.administrator/docs.md index b9340210d2..26cfa91beb 100644 --- a/documentation20/cn/11.administrator/docs.md +++ b/documentation20/cn/11.administrator/docs.md @@ -129,7 +129,7 @@ taosd -C - blocks:每个VNODE(TSDB)中有多少cache大小的内存块。因此一个VNODE的用的内存大小粗略为(cache * blocks)。单位为块,默认值:4。(可通过 alter database 修改) - replica:副本个数,取值范围:1-3。单位为个,默认值:1。(可通过 alter database 修改) - precision:时间戳精度标识,ms表示毫秒,us表示微秒。默认值:ms。 -- cacheLast:是否在内存中缓存子表的最近数据,0:关闭;1:缓存子表最近一行数据;2:缓存子表每一列的最近的非NULL值,设置为3表示同时开启了1和2。默认值:0。(可通过 alter database 修改)(从 2.0.11 版本开始支持此参数) +- cacheLast:是否在内存中缓存子表的最近数据,0:关闭;1:缓存子表最近一行数据;2:缓存子表每一列的最近的非NULL值,默认值:0。(可通过 alter database 修改)(从 2.0.11 版本开始支持此参数) 对于一个应用场景,可能有多种数据特征的数据并存,最佳的设计是将具有相同数据特征的表放在一个库里,这样一个应用有多个库,而每个库可以配置不同的存储参数,从而保证系统有最优的性能。TDengine允许应用在创建库时指定上述存储参数,如果指定,该参数就将覆盖对应的系统配置参数。举例,有下述SQL: diff --git a/src/inc/tsdb.h b/src/inc/tsdb.h index 7c28d3e485..d231769c18 100644 --- a/src/inc/tsdb.h +++ b/src/inc/tsdb.h @@ -73,8 +73,8 @@ typedef struct { } STsdbCfg; #define CACHE_NO_LAST(c) ((c)->cacheLastRow == 0) -#define CACHE_LAST_ROW(c) (((c)->cacheLastRow & 1) > 0) -#define CACHE_LAST_NULL_COLUMN(c) (((c)->cacheLastRow & 2) > 0) +#define CACHE_LAST_ROW(c) ((c)->cacheLastRow == 1) +#define CACHE_LAST_NULL_COLUMN(c) ((c)->cacheLastRow == 2) // --------- TSDB REPOSITORY USAGE STATISTICS typedef struct { From 9d3d129fef2ad42747022e5c96dea2363e31e698 Mon Sep 17 00:00:00 2001 From: lichuang Date: Mon, 17 May 2021 13:37:59 +0800 Subject: [PATCH 08/70] [TD-4034]add timestamp in last NULL column --- src/common/inc/tdataformat.h | 1 + src/tsdb/src/tsdbMemTable.c | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/common/inc/tdataformat.h b/src/common/inc/tdataformat.h index 88d5b85010..fcae7a415f 100644 --- a/src/common/inc/tdataformat.h +++ b/src/common/inc/tdataformat.h @@ -234,6 +234,7 @@ typedef struct SDataCol { int len; // column data length VarDataOffsetT *dataOff; // For binary and nchar data, the offset in the data column void * pData; // Actual data pointer + TSKEY ts; // only used in last NULL column } SDataCol; static FORCE_INLINE void dataColReset(SDataCol *pDataCol) { pDataCol->len = 0; } diff --git a/src/tsdb/src/tsdbMemTable.c b/src/tsdb/src/tsdbMemTable.c index 2409536924..e1f6625ffa 100644 --- a/src/tsdb/src/tsdbMemTable.c +++ b/src/tsdb/src/tsdbMemTable.c @@ -985,7 +985,7 @@ static void updateTableLatestColumn(STsdbRepo *pRepo, STable *pTable, SDataRow r for (int j = 0; j < schemaNCols(pSchema); j++) { if (j >= pTable->lastColNum) { pTable->lastCols = realloc(pTable->lastCols, pTable->lastColNum + 10); - for (int i = 0; i < 10; ++i) { + for (i = 0; i < 10; ++i) { pTable->lastCols[i + pTable->lastColNum].bytes = 0; pTable->lastCols[i + pTable->lastColNum].pData = NULL; } @@ -1009,6 +1009,7 @@ static void updateTableLatestColumn(STsdbRepo *pRepo, STable *pTable, SDataRow r //tsdbDebug("vgId:%d cache column %d for %d,%p", REPO_ID(pRepo), j, pDataCol->bytes, pDataCol->pData); memcpy(pDataCol->pData, value, pDataCol->bytes); + pDataCol->ts = dataRowTKey(row); } } From 3b2d5f74ed2d7a34dc2d05154da0353265201029 Mon Sep 17 00:00:00 2001 From: lichuang Date: Mon, 17 May 2021 14:29:36 +0800 Subject: [PATCH 09/70] [TD-4034]check if STColumn is NULL,then ignore cache NULL column --- src/tsdb/src/tsdbMemTable.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/tsdb/src/tsdbMemTable.c b/src/tsdb/src/tsdbMemTable.c index e1f6625ffa..1321d43653 100644 --- a/src/tsdb/src/tsdbMemTable.c +++ b/src/tsdb/src/tsdbMemTable.c @@ -993,6 +993,10 @@ static void updateTableLatestColumn(STsdbRepo *pRepo, STable *pTable, SDataRow r } STColumn *pTCol = schemaColAt(pSchema, j); + if (pTCol == NULL) { + // since schema maybe changed, check if STColumn NULL then ignore + continue; + } SDataCol *pDataCol = &(pLatestCols[j]); void* value = tdGetRowDataOfCol(row, (int8_t)pTCol->type, TD_DATA_ROW_HEAD_SIZE + pSchema->columns[j].offset); if (isNullN(value, pTCol->type)) { From 08848116e5958b41efe85f91426387638d3d9917 Mon Sep 17 00:00:00 2001 From: lichuang Date: Mon, 17 May 2021 16:32:19 +0800 Subject: [PATCH 10/70] [TD-4034]restore last not NULL column --- src/tsdb/src/tsdbMain.c | 45 +++++++++++++++++++++++++++++++++++++ src/tsdb/src/tsdbMemTable.c | 23 +++++++++---------- 2 files changed, 55 insertions(+), 13 deletions(-) diff --git a/src/tsdb/src/tsdbMain.c b/src/tsdb/src/tsdbMain.c index bf195bef33..23556df580 100644 --- a/src/tsdb/src/tsdbMain.c +++ b/src/tsdb/src/tsdbMain.c @@ -645,6 +645,8 @@ int tsdbRestoreInfo(STsdbRepo *pRepo) { STable *pTable = pMeta->tables[i]; if (pTable == NULL) continue; + //tsdbInfo("tsdbRestoreInfo restore vgId:%d,table:%s", REPO_ID(pRepo), pTable->name->data); + if (tsdbSetReadTable(&readh, pTable) < 0) { tsdbDestroyReadH(&readh); return -1; @@ -686,6 +688,49 @@ int tsdbRestoreInfo(STsdbRepo *pRepo) { pCol->offset); } } + + // restore NULL columns + if (CACHE_LAST_NULL_COLUMN(pCfg)) { + STSchema *pSchema = tsdbGetTableSchema(pTable); + int numColumns = schemaNCols(pSchema); + pTable->lastCols = (SDataCol*)malloc(numColumns * sizeof(SDataCol)); + if (pTable->lastCols == NULL) { + terrno = TSDB_CODE_TDB_OUT_OF_MEMORY; + return -1; + } + pTable->lastColNum = numColumns; + + SDataRow row = taosTMalloc(dataRowMaxBytesFromSchema(pSchema)); + if (row == NULL) { + tfree(pTable->lastCols); + pTable->lastColNum = 0; + terrno = TSDB_CODE_TDB_OUT_OF_MEMORY; + return -1; + } + + tdInitDataRow(row, pSchema); + + SDataCol *pLatestCols = pTable->lastCols; + for (i = 0; i < pTable->lastColNum; ++i) { + STColumn *pTCol = schemaColAt(pSchema, i); + + SDataCol *pDataCol = &(pLatestCols[pTCol->colId]); + pDataCol->pData = malloc(pTCol->bytes); + pDataCol->bytes = pTCol->bytes; + + void* value = tdGetRowDataOfCol(row, (int8_t)pTCol->type, TD_DATA_ROW_HEAD_SIZE + pTCol->offset); + if (isNullN(value, pTCol->type)) { + //tsdbInfo("tsdbRestoreInfo restore vgId:%d,table:%s cache column %d NULL", REPO_ID(pRepo), pTable->name->data, pTCol->colId); + continue; + } + + memcpy(pDataCol->pData, value, pDataCol->bytes); + //tsdbInfo("tsdbRestoreInfo restore vgId:%d,table:%s cache column %d for %d,%s", REPO_ID(pRepo), pTable->name->data, pTCol->colId, pDataCol->bytes, (char*)pDataCol->pData); + pDataCol->ts = dataRowTKey(row); + } + + taosTZfree(row); + } } } diff --git a/src/tsdb/src/tsdbMemTable.c b/src/tsdb/src/tsdbMemTable.c index 1321d43653..70e27a5700 100644 --- a/src/tsdb/src/tsdbMemTable.c +++ b/src/tsdb/src/tsdbMemTable.c @@ -965,11 +965,12 @@ static void tsdbFreeRows(STsdbRepo *pRepo, void **rows, int rowCounter) { } static void updateTableLatestColumn(STsdbRepo *pRepo, STable *pTable, SDataRow row) { - //tsdbDebug("vgId:%d updateTableLatestColumn, row version:%d", REPO_ID(pRepo), dataRowVersion(row)); + //tsdbInfo("vgId:%d updateTableLatestColumn, row version:%d", REPO_ID(pRepo), dataRowVersion(row)); if (pTable->numOfSchemas <= 0) { return; } + STSchema* pSchema = pTable->schema[pTable->numOfSchemas - 1]; int i = pTable->numOfSchemas - 1; while ((pSchema == NULL || pSchema->version != dataRowVersion(row)) && i >= 0) { @@ -983,21 +984,18 @@ static void updateTableLatestColumn(STsdbRepo *pRepo, STable *pTable, SDataRow r SDataCol *pLatestCols = pTable->lastCols; for (int j = 0; j < schemaNCols(pSchema); j++) { - if (j >= pTable->lastColNum) { - pTable->lastCols = realloc(pTable->lastCols, pTable->lastColNum + 10); + STColumn *pTCol = schemaColAt(pSchema, j); + + if (pTCol->colId >= pTable->lastColNum) { + pTable->lastCols = realloc(pTable->lastCols, pTCol->colId + 5); for (i = 0; i < 10; ++i) { pTable->lastCols[i + pTable->lastColNum].bytes = 0; pTable->lastCols[i + pTable->lastColNum].pData = NULL; } - pTable->lastColNum += 10; + pTable->lastColNum += pTCol->colId + 5; } - - STColumn *pTCol = schemaColAt(pSchema, j); - if (pTCol == NULL) { - // since schema maybe changed, check if STColumn NULL then ignore - continue; - } - SDataCol *pDataCol = &(pLatestCols[j]); + + SDataCol *pDataCol = &(pLatestCols[pTCol->colId]); void* value = tdGetRowDataOfCol(row, (int8_t)pTCol->type, TD_DATA_ROW_HEAD_SIZE + pSchema->columns[j].offset); if (isNullN(value, pTCol->type)) { continue; @@ -1010,9 +1008,8 @@ static void updateTableLatestColumn(STsdbRepo *pRepo, STable *pTable, SDataRow r pDataCol->bytes = pSchema->columns[j].bytes; } - //tsdbDebug("vgId:%d cache column %d for %d,%p", REPO_ID(pRepo), j, pDataCol->bytes, pDataCol->pData); - memcpy(pDataCol->pData, value, pDataCol->bytes); + //tsdbInfo("updateTableLatestColumn vgId:%d cache column %d for %d,%s", REPO_ID(pRepo), j, pDataCol->bytes, (char*)pDataCol->pData); pDataCol->ts = dataRowTKey(row); } } From 312453705fab3ab91568d420038ff7929ea1c8c4 Mon Sep 17 00:00:00 2001 From: lichuang Date: Mon, 17 May 2021 16:52:33 +0800 Subject: [PATCH 11/70] [TD-4034]restore last not NULL column --- src/tsdb/src/tsdbMain.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/tsdb/src/tsdbMain.c b/src/tsdb/src/tsdbMain.c index 23556df580..44e2bffbe2 100644 --- a/src/tsdb/src/tsdbMain.c +++ b/src/tsdb/src/tsdbMain.c @@ -691,11 +691,24 @@ int tsdbRestoreInfo(STsdbRepo *pRepo) { // restore NULL columns if (CACHE_LAST_NULL_COLUMN(pCfg)) { + if (tsdbLoadBlockInfo(&readh, NULL) < 0) { + tsdbDestroyReadH(&readh); + return -1; + } + + pBlock = readh.pBlkInfo->blocks + pIdx->numOfBlocks - 1; + + if (tsdbLoadBlockData(&readh, pBlock, NULL) < 0) { + tsdbDestroyReadH(&readh); + return -1; + } + STSchema *pSchema = tsdbGetTableSchema(pTable); int numColumns = schemaNCols(pSchema); pTable->lastCols = (SDataCol*)malloc(numColumns * sizeof(SDataCol)); if (pTable->lastCols == NULL) { terrno = TSDB_CODE_TDB_OUT_OF_MEMORY; + tsdbDestroyReadH(&readh); return -1; } pTable->lastColNum = numColumns; @@ -704,11 +717,18 @@ int tsdbRestoreInfo(STsdbRepo *pRepo) { if (row == NULL) { tfree(pTable->lastCols); pTable->lastColNum = 0; + tsdbDestroyReadH(&readh); terrno = TSDB_CODE_TDB_OUT_OF_MEMORY; return -1; } tdInitDataRow(row, pSchema); + for (int icol = 0; icol < schemaNCols(pSchema); icol++) { + STColumn *pCol = schemaColAt(pSchema, icol); + SDataCol *pDataCol = readh.pDCols[0]->cols + icol; + tdAppendColVal(row, tdGetColDataOfRow(pDataCol, pBlock->numOfRows - 1), pCol->type, pCol->bytes, + pCol->offset); + } SDataCol *pLatestCols = pTable->lastCols; for (i = 0; i < pTable->lastColNum; ++i) { From cad6e7ec510378f6909ad172d7c311f9eb6de94f Mon Sep 17 00:00:00 2001 From: lichuang Date: Tue, 18 May 2021 16:29:26 +0800 Subject: [PATCH 12/70] [TD-4034]restore last not NULL column --- src/tsdb/inc/tsdbMeta.h | 1 + src/tsdb/src/tsdbMain.c | 190 +++++++++++++++++++++++++++------------- src/tsdb/src/tsdbMeta.c | 1 + 3 files changed, 129 insertions(+), 63 deletions(-) diff --git a/src/tsdb/inc/tsdbMeta.h b/src/tsdb/inc/tsdbMeta.h index ff47e0cf39..a8c7a6c358 100644 --- a/src/tsdb/inc/tsdbMeta.h +++ b/src/tsdb/inc/tsdbMeta.h @@ -39,6 +39,7 @@ typedef struct STable { SDataCol *lastCols; int32_t lastColNum; + int32_t restoreColumnNum; T_REF_DECLARE() } STable; diff --git a/src/tsdb/src/tsdbMain.c b/src/tsdb/src/tsdbMain.c index 44e2bffbe2..3be78e21dd 100644 --- a/src/tsdb/src/tsdbMain.c +++ b/src/tsdb/src/tsdbMain.c @@ -616,6 +616,118 @@ static void tsdbStopStream(STsdbRepo *pRepo) { } } +static int restoreLastColumns(STsdbRepo *pRepo, STable *pTable, SReadH* pReadh) { + SBlock* pBlock; + int numColumns; + int32_t blockIdx; + SDataStatis* pBlockStatis = NULL; + SDataRow row = NULL; + STSchema *pSchema = tsdbGetTableSchema(pTable); + int err = 0; + + numColumns = schemaNCols(pSchema); + if (numColumns <= pTable->restoreColumnNum) { + return 0; + } + + row = taosTMalloc(dataRowMaxBytesFromSchema(pSchema)); + if (row == NULL) { + terrno = TSDB_CODE_TDB_OUT_OF_MEMORY; + err = -1; + goto out; + } + tdInitDataRow(row, pSchema); + + // first load block index info + if (tsdbLoadBlockInfo(pReadh, NULL) < 0) { + err = -1; + goto out; + } + + pBlockStatis = calloc(numColumns, sizeof(SDataStatis)); + if (pBlockStatis == NULL) { + terrno = TSDB_CODE_TDB_OUT_OF_MEMORY; + err = -1; + goto out; + } + memset(pBlockStatis, 0, numColumns * sizeof(SDataStatis)); + for(int32_t i = 0; i < numColumns; ++i) { + pBlockStatis[i].colId = i; + } + + // load block from backward + SBlockIdx *pIdx = pReadh->pBlkIdx; + blockIdx = (int32_t)(pIdx->numOfBlocks - 1); + + while (numColumns > pTable->restoreColumnNum && blockIdx >= 0) { + bool loadStatisData = false; + pBlock = pReadh->pBlkInfo->blocks + blockIdx; + blockIdx -= 1; + + // load block data + if (tsdbLoadBlockData(pReadh, pBlock, NULL) < 0) { + err = -1; + goto out; + } + + // file block with sub-blocks has no statistics data + if (pBlock->numOfSubBlocks <= 1) { + tsdbLoadBlockStatis(pReadh, pBlock); + tsdbGetBlockStatis(pReadh, pBlockStatis, (int)numColumns); + loadStatisData = true; + } + + for (uint32_t colId = 0; colId < numColumns && numColumns > pTable->restoreColumnNum; ++colId) { + // ignore loaded columns + if (pTable->lastCols[colId].bytes != 0) { + continue; + } + + // ignore block which has no not-null colId column + if (loadStatisData && pBlockStatis[colId].numOfNull == pBlock->numOfRows) { + continue; + } + + // OK,let's load row from backward to get not-null column + STColumn *pCol = schemaColAt(pSchema, colId); + for (int32_t rowId = pBlock->numOfRows - 1; rowId >= 0; rowId--) { + SDataCol *pDataCol = pReadh->pDCols[0]->cols + colId; + tdAppendColVal(row, tdGetColDataOfRow(pDataCol, rowId), pCol->type, pCol->bytes, pCol->offset); + //SDataCol *pDataCol = readh.pDCols[0]->cols + j; + void* value = tdGetRowDataOfCol(row, (int8_t)pCol->type, TD_DATA_ROW_HEAD_SIZE + pCol->offset); + if (isNullN(value, pCol->type)) { + continue; + } + + // save not-null column + SDataCol *pLastCol = &(pTable->lastCols[colId]); + pLastCol->pData = malloc(pCol->bytes); + pLastCol->bytes = pCol->bytes; + pLastCol->offset = pCol->offset; + pLastCol->colId = pCol->colId; + memcpy(pLastCol->pData, value, pCol->bytes); + + // save row ts(in column 0) + pDataCol = pReadh->pDCols[0]->cols + 0; + pCol = schemaColAt(pSchema, 0); + tdAppendColVal(row, tdGetColDataOfRow(pDataCol, rowId), pCol->type, pCol->bytes, pCol->offset); + pLastCol->ts = dataRowTKey(row); + + pTable->restoreColumnNum += 1; + + tsdbInfo("restoreLastColumns restore vgId:%d,table:%s cache column %d, %ld", REPO_ID(pRepo), pTable->name->data, colId, pLastCol->ts); + break; + } + } + } + +out: + taosTZfree(row); + tfree(pBlockStatis); + + return err; +} + int tsdbRestoreInfo(STsdbRepo *pRepo) { SFSIter fsiter; SReadH readh; @@ -630,6 +742,14 @@ int tsdbRestoreInfo(STsdbRepo *pRepo) { tsdbFSIterInit(&fsiter, REPO_FS(pRepo), TSDB_FS_ITER_BACKWARD); + if (CACHE_LAST_NULL_COLUMN(pCfg)) { + for (int i = 1; i < pMeta->maxTables; i++) { + STable *pTable = pMeta->tables[i]; + if (pTable == NULL) continue; + pTable->restoreColumnNum = 0; + } + } + while ((pSet = tsdbFSIterNext(&fsiter)) != NULL) { if (tsdbSetAndOpenReadFSet(&readh, pSet) < 0) { tsdbDestroyReadH(&readh); @@ -688,71 +808,15 @@ int tsdbRestoreInfo(STsdbRepo *pRepo) { pCol->offset); } } - - // restore NULL columns - if (CACHE_LAST_NULL_COLUMN(pCfg)) { - if (tsdbLoadBlockInfo(&readh, NULL) < 0) { - tsdbDestroyReadH(&readh); - return -1; - } - - pBlock = readh.pBlkInfo->blocks + pIdx->numOfBlocks - 1; - - if (tsdbLoadBlockData(&readh, pBlock, NULL) < 0) { - tsdbDestroyReadH(&readh); - return -1; - } - - STSchema *pSchema = tsdbGetTableSchema(pTable); - int numColumns = schemaNCols(pSchema); - pTable->lastCols = (SDataCol*)malloc(numColumns * sizeof(SDataCol)); - if (pTable->lastCols == NULL) { - terrno = TSDB_CODE_TDB_OUT_OF_MEMORY; - tsdbDestroyReadH(&readh); - return -1; - } - pTable->lastColNum = numColumns; - - SDataRow row = taosTMalloc(dataRowMaxBytesFromSchema(pSchema)); - if (row == NULL) { - tfree(pTable->lastCols); - pTable->lastColNum = 0; - tsdbDestroyReadH(&readh); - terrno = TSDB_CODE_TDB_OUT_OF_MEMORY; - return -1; - } - - tdInitDataRow(row, pSchema); - for (int icol = 0; icol < schemaNCols(pSchema); icol++) { - STColumn *pCol = schemaColAt(pSchema, icol); - SDataCol *pDataCol = readh.pDCols[0]->cols + icol; - tdAppendColVal(row, tdGetColDataOfRow(pDataCol, pBlock->numOfRows - 1), pCol->type, pCol->bytes, - pCol->offset); - } - - SDataCol *pLatestCols = pTable->lastCols; - for (i = 0; i < pTable->lastColNum; ++i) { - STColumn *pTCol = schemaColAt(pSchema, i); - - SDataCol *pDataCol = &(pLatestCols[pTCol->colId]); - pDataCol->pData = malloc(pTCol->bytes); - pDataCol->bytes = pTCol->bytes; - - void* value = tdGetRowDataOfCol(row, (int8_t)pTCol->type, TD_DATA_ROW_HEAD_SIZE + pTCol->offset); - if (isNullN(value, pTCol->type)) { - //tsdbInfo("tsdbRestoreInfo restore vgId:%d,table:%s cache column %d NULL", REPO_ID(pRepo), pTable->name->data, pTCol->colId); - continue; - } - - memcpy(pDataCol->pData, value, pDataCol->bytes); - //tsdbInfo("tsdbRestoreInfo restore vgId:%d,table:%s cache column %d for %d,%s", REPO_ID(pRepo), pTable->name->data, pTCol->colId, pDataCol->bytes, (char*)pDataCol->pData); - pDataCol->ts = dataRowTKey(row); - } - - taosTZfree(row); - } } + // restore NULL columns + if (CACHE_LAST_NULL_COLUMN(pCfg)) { + if (restoreLastColumns(pRepo, pTable, &readh) != 0) { + tsdbDestroyReadH(&readh); + return -1; + } + } } } diff --git a/src/tsdb/src/tsdbMeta.c b/src/tsdb/src/tsdbMeta.c index bdf0cfdfad..5a108a5d06 100644 --- a/src/tsdb/src/tsdbMeta.c +++ b/src/tsdb/src/tsdbMeta.c @@ -678,6 +678,7 @@ static STable *tsdbNewTable() { pTable->lastCols[i].bytes = 0; pTable->lastCols[i].pData = NULL; } + pTable->restoreColumnNum = 0; return pTable; } From 6f202d270e66eee02e7d87f314ea2fcc3a281a82 Mon Sep 17 00:00:00 2001 From: lichuang Date: Tue, 18 May 2021 19:50:35 +0800 Subject: [PATCH 13/70] [TD-4034]restore last not NULL column --- src/tsdb/src/tsdbMain.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/tsdb/src/tsdbMain.c b/src/tsdb/src/tsdbMain.c index 3be78e21dd..8e1207b98a 100644 --- a/src/tsdb/src/tsdbMain.c +++ b/src/tsdb/src/tsdbMain.c @@ -652,7 +652,8 @@ static int restoreLastColumns(STsdbRepo *pRepo, STable *pTable, SReadH* pReadh) } memset(pBlockStatis, 0, numColumns * sizeof(SDataStatis)); for(int32_t i = 0; i < numColumns; ++i) { - pBlockStatis[i].colId = i; + STColumn *pCol = schemaColAt(pSchema, i); + pBlockStatis[i].colId = pCol->colId; } // load block from backward @@ -678,6 +679,17 @@ static int restoreLastColumns(STsdbRepo *pRepo, STable *pTable, SReadH* pReadh) } for (uint32_t colId = 0; colId < numColumns && numColumns > pTable->restoreColumnNum; ++colId) { + STColumn *pCol = schemaColAt(pSchema, colId); + + if (colId >= pTable->lastColNum) { + pTable->lastCols = realloc(pTable->lastCols, colId + 5); + for (int m = 0; m < 5; ++m) { + pTable->lastCols[m + pTable->lastColNum].bytes = 0; + pTable->lastCols[m + pTable->lastColNum].pData = NULL; + } + pTable->lastColNum += colId + 5; + } + // ignore loaded columns if (pTable->lastCols[colId].bytes != 0) { continue; @@ -689,7 +701,6 @@ static int restoreLastColumns(STsdbRepo *pRepo, STable *pTable, SReadH* pReadh) } // OK,let's load row from backward to get not-null column - STColumn *pCol = schemaColAt(pSchema, colId); for (int32_t rowId = pBlock->numOfRows - 1; rowId >= 0; rowId--) { SDataCol *pDataCol = pReadh->pDCols[0]->cols + colId; tdAppendColVal(row, tdGetColDataOfRow(pDataCol, rowId), pCol->type, pCol->bytes, pCol->offset); From bec2b58922f5ea25ad9dc6673c533b24bbf10a48 Mon Sep 17 00:00:00 2001 From: lichuang Date: Wed, 19 May 2021 09:16:45 +0800 Subject: [PATCH 14/70] [TD-4034]fix compile error --- src/tsdb/src/tsdbMain.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/tsdb/src/tsdbMain.c b/src/tsdb/src/tsdbMain.c index 8e1207b98a..a7e1efb5ed 100644 --- a/src/tsdb/src/tsdbMain.c +++ b/src/tsdb/src/tsdbMain.c @@ -678,31 +678,31 @@ static int restoreLastColumns(STsdbRepo *pRepo, STable *pTable, SReadH* pReadh) loadStatisData = true; } - for (uint32_t colId = 0; colId < numColumns && numColumns > pTable->restoreColumnNum; ++colId) { - STColumn *pCol = schemaColAt(pSchema, colId); + for (uint32_t i = 0; i < numColumns && numColumns > pTable->restoreColumnNum; ++i) { + STColumn *pCol = schemaColAt(pSchema, i); - if (colId >= pTable->lastColNum) { - pTable->lastCols = realloc(pTable->lastCols, colId + 5); + if (i >= pTable->lastColNum) { + pTable->lastCols = realloc(pTable->lastCols, i + 5); for (int m = 0; m < 5; ++m) { pTable->lastCols[m + pTable->lastColNum].bytes = 0; pTable->lastCols[m + pTable->lastColNum].pData = NULL; } - pTable->lastColNum += colId + 5; + pTable->lastColNum += i + 5; } // ignore loaded columns - if (pTable->lastCols[colId].bytes != 0) { + if (pTable->lastCols[i].bytes != 0) { continue; } // ignore block which has no not-null colId column - if (loadStatisData && pBlockStatis[colId].numOfNull == pBlock->numOfRows) { + if (loadStatisData && pBlockStatis[i].numOfNull == pBlock->numOfRows) { continue; } // OK,let's load row from backward to get not-null column for (int32_t rowId = pBlock->numOfRows - 1; rowId >= 0; rowId--) { - SDataCol *pDataCol = pReadh->pDCols[0]->cols + colId; + SDataCol *pDataCol = pReadh->pDCols[0]->cols + i; tdAppendColVal(row, tdGetColDataOfRow(pDataCol, rowId), pCol->type, pCol->bytes, pCol->offset); //SDataCol *pDataCol = readh.pDCols[0]->cols + j; void* value = tdGetRowDataOfCol(row, (int8_t)pCol->type, TD_DATA_ROW_HEAD_SIZE + pCol->offset); @@ -710,8 +710,8 @@ static int restoreLastColumns(STsdbRepo *pRepo, STable *pTable, SReadH* pReadh) continue; } - // save not-null column - SDataCol *pLastCol = &(pTable->lastCols[colId]); + // save not-null column + SDataCol *pLastCol = &(pTable->lastCols[i]); pLastCol->pData = malloc(pCol->bytes); pLastCol->bytes = pCol->bytes; pLastCol->offset = pCol->offset; @@ -726,7 +726,7 @@ static int restoreLastColumns(STsdbRepo *pRepo, STable *pTable, SReadH* pReadh) pTable->restoreColumnNum += 1; - tsdbInfo("restoreLastColumns restore vgId:%d,table:%s cache column %d, %ld", REPO_ID(pRepo), pTable->name->data, colId, pLastCol->ts); + tsdbInfo("restoreLastColumns restore vgId:%d,table:%s cache column %d, %d", REPO_ID(pRepo), pTable->name->data, pCol->colId, (int32_t)pLastCol->ts); break; } } From e2f1102622a34be4ff8813338a013a1e893fbcc4 Mon Sep 17 00:00:00 2001 From: dapan1121 <89396746@qq.com> Date: Wed, 19 May 2021 15:27:16 +0800 Subject: [PATCH 15/70] init --- src/query/src/qExecutor.c | 33 +++++++ src/tsdb/src/tsdbRead.c | 194 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 217 insertions(+), 10 deletions(-) diff --git a/src/query/src/qExecutor.c b/src/query/src/qExecutor.c index 40759c93c4..b48436a617 100644 --- a/src/query/src/qExecutor.c +++ b/src/query/src/qExecutor.c @@ -1979,6 +1979,37 @@ static bool isFirstLastRowQuery(SQueryAttr *pQueryAttr) { return false; } +static bool isCachedLastQuery(SQueryAttr *pQueryAttr) { + for (int32_t i = 0; i < pQueryAttr->numOfOutput; ++i) { + int32_t functionID = pQueryAttr->pExpr1[i].base.functionId; + if (functionID == TSDB_FUNC_LAST || functionID == TSDB_FUNC_LAST_DST) { + continue; + } + + return false; + } + + if (!TSWINDOW_IS_EQUAL(pQueryAttr->window, TSWINDOW_INITIALIZER)) { + return false; + } + + if (pQueryAttr->groupbyColumn) { + return false; + } + + if (pQueryAttr->interval.interval > 0) { + return false; + } + + if (pQueryAttr->numOfFilterCols > 0 || pQueryAttr->havingNum > 0) { + return false; + } + + return true; +} + + + /** * The following 4 kinds of query are treated as the tags query * tagprj, tid_tag query, count(tbname), 'abc' (user defined constant value column) query @@ -3963,6 +3994,8 @@ static int32_t setupQueryHandle(void* tsdb, SQueryRuntimeEnv* pRuntimeEnv, int64 } } } + } else if (isCachedLastQuery(pQueryAttr)) { + pRuntimeEnv->pQueryHandle = tsdbQueryCacheLast(tsdb, &cond, &pQueryAttr->tableGroupInfo, qId, &pQueryAttr->memRef); } else if (pQueryAttr->pointInterpQuery) { pRuntimeEnv->pQueryHandle = tsdbQueryRowsInExternalWindow(tsdb, &cond, &pQueryAttr->tableGroupInfo, qId, &pQueryAttr->memRef); } else { diff --git a/src/tsdb/src/tsdbRead.c b/src/tsdb/src/tsdbRead.c index 9df25409de..b3460ac3b2 100644 --- a/src/tsdb/src/tsdbRead.c +++ b/src/tsdb/src/tsdbRead.c @@ -62,12 +62,20 @@ typedef struct SLoadCompBlockInfo { int32_t fileId; } SLoadCompBlockInfo; +typedef struct SCacheLastColInfo { + int16_t size; + int16_t num; + int16_t fetchIdx; + int16_t *idx; +} SCacheLastColInfo; + typedef struct STableCheckInfo { STableId tableId; TSKEY lastKey; STable* pTableObj; SBlockInfo* pCompInfo; int32_t compSize; + SCacheLastColInfo cacheLast; // cache last column chosen int32_t numOfBlocks:29; // number of qualified data blocks not the original blocks int8_t chosen:2; // indicate which iterator should move forward bool initBuf; // whether to initialize the in-memory skip list iterator or not @@ -107,7 +115,7 @@ typedef struct STsdbQueryHandle { SArray* pTableCheckInfo; // SArray int32_t activeIndex; bool checkFiles; // check file stage - bool cachelastrow; // check if last row cached + int8_t cachelastrow; // check if last row cached bool loadExternalRow; // load time window external data rows bool currentLoadExternalRows; // current load external rows int32_t loadType; // block load type @@ -512,6 +520,8 @@ void tsdbResetQueryHandleForNewTable(TsdbQueryHandleT queryHandle, STsdbQueryCon pQueryHandle->next = doFreeColumnInfoData(pQueryHandle->next); } + + TsdbQueryHandleT tsdbQueryLastRow(STsdbRepo *tsdb, STsdbQueryCond *pCond, STableGroupInfo *groupList, uint64_t qId, SMemRef* pMemRef) { pCond->twindow = updateLastrowForEachGroup(groupList); @@ -528,10 +538,111 @@ TsdbQueryHandleT tsdbQueryLastRow(STsdbRepo *tsdb, STsdbQueryCond *pCond, STable } assert(pCond->order == TSDB_ORDER_ASC && pCond->twindow.skey <= pCond->twindow.ekey); - pQueryHandle->type = TSDB_QUERY_TYPE_LAST; + if (pQueryHandle->cachelastrow) { + pQueryHandle->type = TSDB_QUERY_TYPE_LAST; + } + return pQueryHandle; } + + +STimeWindow updateCacheLastForEachGroup(STableGroupInfo *groupList) { + STimeWindow window = {INT64_MAX, INT64_MIN}; + + int32_t totalNumOfTable = 0; + + // NOTE: starts from the buffer in case of descending timestamp order check data blocks + size_t numOfGroups = taosArrayGetSize(groupList->pGroupList); + for(int32_t j = 0; j < numOfGroups; ++j) { + SArray* pGroup = taosArrayGetP(groupList->pGroupList, j); + TSKEY key = TSKEY_INITIAL_VAL; + + STableKeyInfo keyInfo = {0}; + + size_t numOfTables = taosArrayGetSize(pGroup); + for(int32_t i = 0; i < numOfTables; ++i) { + STableKeyInfo* pInfo = (STableKeyInfo*) taosArrayGet(pGroup, i); + + // if the lastKey equals to INT64_MIN, there is no data in this table + TSKEY lastKey = ((STable*)(pInfo->pTable))->lastKey; + if (key < lastKey) { + key = lastKey; + + keyInfo.pTable = pInfo->pTable; + keyInfo.lastKey = key; + pInfo->lastKey = key; + + if (key < window.skey) { + window.skey = key; + } + + if (key > window.ekey) { + window.ekey = key; + } + } + } + + // clear current group, unref unused table + for (int32_t i = 0; i < numOfTables; ++i) { + STableKeyInfo* pInfo = (STableKeyInfo*)taosArrayGet(pGroup, i); + + // keyInfo.pTable may be NULL here. + if (pInfo->pTable != keyInfo.pTable) { + tsdbUnRefTable(pInfo->pTable); + } + } + + taosArrayClear(pGroup); + + // more than one table in each group, only one table left for each group + if (keyInfo.pTable != NULL) { + totalNumOfTable++; + taosArrayPush(pGroup, &keyInfo); + } else { + taosArrayDestroy(pGroup); + + taosArrayRemove(groupList->pGroupList, j); + numOfGroups -= 1; + j -= 1; + } + } + + // window does not being updated, so set the original + if (window.skey == INT64_MAX && window.ekey == INT64_MIN) { + window = TSWINDOW_INITIALIZER; + assert(totalNumOfTable == 0 && taosArrayGetSize(groupList->pGroupList) == 0); + } + + groupList->numOfTables = totalNumOfTable; + return window; +} + + +TsdbQueryHandleT tsdbQueryCacheLast(STsdbRepo *tsdb, STsdbQueryCond *pCond, STableGroupInfo *groupList, uint64_t qId, SMemRef* pMemRef) { + pCond->twindow = updateCacheLastForEachGroup(groupList); + + // no qualified table + if (groupList->numOfTables == 0) { + return NULL; + } + + STsdbQueryHandle *pQueryHandle = (STsdbQueryHandle*) tsdbQueryTables(tsdb, pCond, groupList, qId, pMemRef); + int32_t code = checkForCachedLastRow(pQueryHandle, groupList); + if (code != TSDB_CODE_SUCCESS) { // set the numOfTables to be 0 + terrno = code; + return NULL; + } + + assert(pCond->order == TSDB_ORDER_ASC && pCond->twindow.skey <= pCond->twindow.ekey); + if (pQueryHandle->cachelastrow == 2) { + pQueryHandle->type = TSDB_QUERY_TYPE_LAST; + } + + return pQueryHandle; +} + + SArray* tsdbGetQueriedTableList(TsdbQueryHandleT *pHandle) { assert(pHandle != NULL); @@ -2460,6 +2571,58 @@ static bool loadCachedLastRow(STsdbQueryHandle* pQueryHandle) { return false; } + +static bool loadCachedLast(STsdbQueryHandle* pQueryHandle) { + // the last row is cached in buffer, return it directly. + // here note that the pQueryHandle->window must be the TS_INITIALIZER + int32_t numOfCols = (int32_t)(QH_GET_NUM_OF_COLS(pQueryHandle)); + size_t numOfTables = taosArrayGetSize(pQueryHandle->pTableCheckInfo); + assert(numOfTables > 0 && numOfCols > 0); + + SQueryFilePos* cur = &pQueryHandle->cur; + + SDataRow pRow = NULL; + TSKEY key = TSKEY_INITIAL_VAL; + int32_t step = ASCENDING_TRAVERSE(pQueryHandle->order)? 1:-1; + + if (pQueryHandle->activeIndex < 0) { + updateCacheLastForEachGroup(pQueryHandle); + } + + if (pQueryHandle->activeIndex < numOfTables) { + STableCheckInfo* pCheckInfo = taosArrayGet(pQueryHandle->pTableCheckInfo, pQueryHandle->activeIndex); + + if (pQueryHandle->cachelastrow == 1) { + int32_t ret = tsdbGetCachedLastRow(pCheckInfo->pTableObj, &pRow, &key); + if (ret != TSDB_CODE_SUCCESS) { + return false; + } + + copyOneRowFromMem(pQueryHandle, pQueryHandle->outputCapacity, 0, pRow, numOfCols, pCheckInfo->pTableObj, NULL); + tfree(pRow); + + // update the last key value + pCheckInfo->lastKey = key + step; + + cur->rows = 1; // only one row + cur->lastKey = key + step; + cur->mixBlock = true; + cur->win.skey = key; + cur->win.ekey = key; + } else if (pQueryHandle->cachelastrow == 2) { + + } else { + tsdbError("invalid cachelastrow:%d", pQueryHandle->cachelastrow); + return false; + } + + return true; + } + + return false; +} + + static bool loadDataBlockFromTableSeq(STsdbQueryHandle* pQueryHandle) { size_t numOfTables = taosArrayGetSize(pQueryHandle->pTableCheckInfo); assert(numOfTables > 0); @@ -2496,8 +2659,12 @@ bool tsdbNextDataBlock(TsdbQueryHandleT pHandle) { int64_t stime = taosGetTimestampUs(); int64_t elapsedTime = stime; - if (pQueryHandle->type == TSDB_QUERY_TYPE_LAST && pQueryHandle->cachelastrow) { - return loadCachedLastRow(pQueryHandle); + if (pQueryHandle->type == TSDB_QUERY_TYPE_LAST) { + if (pQueryHandle->cachelastrow == 1) { + return loadCachedLastRow(pQueryHandle); + } if (pQueryHandle->cachelastrow == 2) else { + return loadCachedLast(pQueryHandle); + } } if (pQueryHandle->loadType == BLOCK_LOAD_TABLE_SEQ_ORDER) { @@ -2683,7 +2850,7 @@ int32_t tsdbGetCachedLastRow(STable* pTable, SDataRow* pRes, TSKEY* lastKey) { TSDB_RLOCK_TABLE(pTable); *lastKey = pTable->lastKey; - if ((*lastKey) != TSKEY_INITIAL_VAL && pTable->lastRow) { + if ((*lastKey) != TSKEY_INITIAL_VAL && pTable->lastRow == 1) { *pRes = tdDataRowDup(pTable->lastRow); if (*pRes == NULL) { TSDB_RUNLOCK_TABLE(pTable); @@ -2706,12 +2873,19 @@ int32_t checkForCachedLastRow(STsdbQueryHandle* pQueryHandle, STableGroupInfo *g STableKeyInfo* pInfo = (STableKeyInfo*)taosArrayGet(group, 0); - int32_t code = tsdbGetCachedLastRow(pInfo->pTable, &pRow, &key); - if (code != TSDB_CODE_SUCCESS) { - pQueryHandle->cachelastrow = false; - } else { - pQueryHandle->cachelastrow = (pRow != NULL); + int32_t code = 0; + + if (((STable*)pInfo->pTable)->lastRow == 1) { + code = tsdbGetCachedLastRow(pInfo->pTable, &pRow, &key); + if (code != TSDB_CODE_SUCCESS) { + pQueryHandle->cachelastrow = 0; + } else { + pQueryHandle->cachelastrow = ((STable*)pInfo->pTable)->lastRow; + } + } else if (((STable*)pInfo->pTable)->lastCols && ((STable*)pInfo->pTable)->lastColNum > 0 && ((STable*)pInfo->pTable)->lastRow == 2){ + pQueryHandle->cachelastrow = ((STable*)pInfo->pTable)->lastRow; } + // update the tsdb query time range if (pQueryHandle->cachelastrow) { From 865ddbc0268239ea62d0344449e2abdf53557b86 Mon Sep 17 00:00:00 2001 From: lichuang Date: Wed, 19 May 2021 20:40:04 +0800 Subject: [PATCH 16/70] [TD-4034]fix schema change --- src/tsdb/inc/tsdbMeta.h | 11 ++- src/tsdb/src/tsdbMain.c | 45 ++++++------ src/tsdb/src/tsdbMemTable.c | 23 ++++--- src/tsdb/src/tsdbMeta.c | 132 +++++++++++++++++++++++++++++++----- 4 files changed, 161 insertions(+), 50 deletions(-) diff --git a/src/tsdb/inc/tsdbMeta.h b/src/tsdb/inc/tsdbMeta.h index a8c7a6c358..43c85d89cb 100644 --- a/src/tsdb/inc/tsdbMeta.h +++ b/src/tsdb/inc/tsdbMeta.h @@ -38,11 +38,15 @@ typedef struct STable { SRWLatch latch; // TODO: implementa latch functions SDataCol *lastCols; - int32_t lastColNum; - int32_t restoreColumnNum; + int16_t lastColNum; + int16_t maxColumnNum; + int lastColSVersion; T_REF_DECLARE() } STable; +#define TSDB_LATEST_COLUMN_ARRAY_SIZE 20 +#define TSDB_LATEST_COLUMN_ARRAY_ADD_SIZE 5 + typedef struct { pthread_rwlock_t rwLock; @@ -82,6 +86,9 @@ void tsdbUnRefTable(STable* pTable); void tsdbUpdateTableSchema(STsdbRepo* pRepo, STable* pTable, STSchema* pSchema, bool insertAct); int tsdbRestoreTable(STsdbRepo* pRepo, void* cont, int contLen); void tsdbOrgMeta(STsdbRepo* pRepo); +int tsdbInitColIdCacheWithSchema(STable* pTable, STSchema* pSchema); +int16_t tsdbGetLastColumnsIndexByColId(STable* pTable, int16_t colId); +int tsdbUpdateLastColSchema(STable *pTable, STSchema *pNewSchema); static FORCE_INLINE int tsdbCompareSchemaVersion(const void *key1, const void *key2) { if (*(int16_t *)key1 < schemaVersion(*(STSchema **)key2)) { diff --git a/src/tsdb/src/tsdbMain.c b/src/tsdb/src/tsdbMain.c index a7e1efb5ed..3241d617b6 100644 --- a/src/tsdb/src/tsdbMain.c +++ b/src/tsdb/src/tsdbMain.c @@ -617,18 +617,27 @@ static void tsdbStopStream(STsdbRepo *pRepo) { } static int restoreLastColumns(STsdbRepo *pRepo, STable *pTable, SReadH* pReadh) { + if (pTable->numOfSchemas == 0) { + return 0; + } SBlock* pBlock; int numColumns; int32_t blockIdx; SDataStatis* pBlockStatis = NULL; SDataRow row = NULL; - STSchema *pSchema = tsdbGetTableSchema(pTable); + // restore last column data with last schema + STSchema *pSchema = pTable->schema[pTable->numOfSchemas - 1]; int err = 0; numColumns = schemaNCols(pSchema); - if (numColumns <= pTable->restoreColumnNum) { + if (numColumns <= pTable->maxColumnNum) { return 0; } + if (pTable->lastColSVersion != schemaVersion(pSchema)) { + if (tsdbInitColIdCacheWithSchema(pTable, pSchema) < 0) { + return -1; + } + } row = taosTMalloc(dataRowMaxBytesFromSchema(pSchema)); if (row == NULL) { @@ -660,7 +669,7 @@ static int restoreLastColumns(STsdbRepo *pRepo, STable *pTable, SReadH* pReadh) SBlockIdx *pIdx = pReadh->pBlkIdx; blockIdx = (int32_t)(pIdx->numOfBlocks - 1); - while (numColumns > pTable->restoreColumnNum && blockIdx >= 0) { + while (numColumns > pTable->maxColumnNum && blockIdx >= 0) { bool loadStatisData = false; pBlock = pReadh->pBlkInfo->blocks + blockIdx; blockIdx -= 1; @@ -678,18 +687,8 @@ static int restoreLastColumns(STsdbRepo *pRepo, STable *pTable, SReadH* pReadh) loadStatisData = true; } - for (uint32_t i = 0; i < numColumns && numColumns > pTable->restoreColumnNum; ++i) { + for (int16_t i = 0; i < numColumns && numColumns > pTable->maxColumnNum; ++i) { STColumn *pCol = schemaColAt(pSchema, i); - - if (i >= pTable->lastColNum) { - pTable->lastCols = realloc(pTable->lastCols, i + 5); - for (int m = 0; m < 5; ++m) { - pTable->lastCols[m + pTable->lastColNum].bytes = 0; - pTable->lastCols[m + pTable->lastColNum].pData = NULL; - } - pTable->lastColNum += i + 5; - } - // ignore loaded columns if (pTable->lastCols[i].bytes != 0) { continue; @@ -710,11 +709,15 @@ static int restoreLastColumns(STsdbRepo *pRepo, STable *pTable, SReadH* pReadh) continue; } + int16_t idx = tsdbGetLastColumnsIndexByColId(pTable, pCol->colId); + if (idx == -1) { + tsdbError("restoreLastColumns restore vgId:%d,table:%s cache column %d fail", REPO_ID(pRepo), pTable->name->data, pCol->colId); + continue; + } // save not-null column - SDataCol *pLastCol = &(pTable->lastCols[i]); + SDataCol *pLastCol = &(pTable->lastCols[idx]); pLastCol->pData = malloc(pCol->bytes); pLastCol->bytes = pCol->bytes; - pLastCol->offset = pCol->offset; pLastCol->colId = pCol->colId; memcpy(pLastCol->pData, value, pCol->bytes); @@ -722,11 +725,11 @@ static int restoreLastColumns(STsdbRepo *pRepo, STable *pTable, SReadH* pReadh) pDataCol = pReadh->pDCols[0]->cols + 0; pCol = schemaColAt(pSchema, 0); tdAppendColVal(row, tdGetColDataOfRow(pDataCol, rowId), pCol->type, pCol->bytes, pCol->offset); - pLastCol->ts = dataRowTKey(row); + pLastCol->ts = dataRowTKey(row); - pTable->restoreColumnNum += 1; + pTable->maxColumnNum += 1; - tsdbInfo("restoreLastColumns restore vgId:%d,table:%s cache column %d, %d", REPO_ID(pRepo), pTable->name->data, pCol->colId, (int32_t)pLastCol->ts); + tsdbInfo("restoreLastColumns restore vgId:%d,table:%s cache column %d, %" PRId64, REPO_ID(pRepo), pTable->name->data, pLastCol->colId, pLastCol->ts); break; } } @@ -757,7 +760,7 @@ int tsdbRestoreInfo(STsdbRepo *pRepo) { for (int i = 1; i < pMeta->maxTables; i++) { STable *pTable = pMeta->tables[i]; if (pTable == NULL) continue; - pTable->restoreColumnNum = 0; + pTable->maxColumnNum = 0; } } @@ -822,7 +825,7 @@ int tsdbRestoreInfo(STsdbRepo *pRepo) { } // restore NULL columns - if (CACHE_LAST_NULL_COLUMN(pCfg)) { + if (pIdx && CACHE_LAST_NULL_COLUMN(pCfg)) { if (restoreLastColumns(pRepo, pTable, &readh) != 0) { tsdbDestroyReadH(&readh); return -1; diff --git a/src/tsdb/src/tsdbMemTable.c b/src/tsdb/src/tsdbMemTable.c index 70e27a5700..900c034a22 100644 --- a/src/tsdb/src/tsdbMemTable.c +++ b/src/tsdb/src/tsdbMemTable.c @@ -972,7 +972,11 @@ static void updateTableLatestColumn(STsdbRepo *pRepo, STable *pTable, SDataRow r } STSchema* pSchema = pTable->schema[pTable->numOfSchemas - 1]; - int i = pTable->numOfSchemas - 1; + if (tsdbUpdateLastColSchema(pTable, pSchema) < 0) { + return; + } + + int16_t i = pTable->numOfSchemas - 1; while ((pSchema == NULL || pSchema->version != dataRowVersion(row)) && i >= 0) { i -= 1; pSchema = pTable->schema[i]; @@ -983,23 +987,20 @@ static void updateTableLatestColumn(STsdbRepo *pRepo, STable *pTable, SDataRow r SDataCol *pLatestCols = pTable->lastCols; - for (int j = 0; j < schemaNCols(pSchema); j++) { + for (int16_t j = 0; j < schemaNCols(pSchema); j++) { STColumn *pTCol = schemaColAt(pSchema, j); - - if (pTCol->colId >= pTable->lastColNum) { - pTable->lastCols = realloc(pTable->lastCols, pTCol->colId + 5); - for (i = 0; i < 10; ++i) { - pTable->lastCols[i + pTable->lastColNum].bytes = 0; - pTable->lastCols[i + pTable->lastColNum].pData = NULL; - } - pTable->lastColNum += pTCol->colId + 5; + // ignore not exist colId + int16_t idx = tsdbGetLastColumnsIndexByColId(pTable, pTCol->colId); + if (idx == -1) { + continue; } - SDataCol *pDataCol = &(pLatestCols[pTCol->colId]); void* value = tdGetRowDataOfCol(row, (int8_t)pTCol->type, TD_DATA_ROW_HEAD_SIZE + pSchema->columns[j].offset); if (isNullN(value, pTCol->type)) { continue; } + + SDataCol *pDataCol = &(pLatestCols[idx]); if (pDataCol->pData == NULL) { pDataCol->pData = malloc(pSchema->columns[j].bytes); pDataCol->bytes = pSchema->columns[j].bytes; diff --git a/src/tsdb/src/tsdbMeta.c b/src/tsdb/src/tsdbMeta.c index 5a108a5d06..d785d259fa 100644 --- a/src/tsdb/src/tsdbMeta.c +++ b/src/tsdb/src/tsdbMeta.c @@ -14,7 +14,6 @@ */ #include "tsdbint.h" -#define TSDB_LATEST_COLUMN_ARRAY_SIZE 20 #define TSDB_SUPER_TABLE_SL_LEVEL 5 #define DEFAULT_TAG_INDEX_COLUMN 0 @@ -45,6 +44,7 @@ static int tsdbRemoveTableFromStore(STsdbRepo *pRepo, STable *pTable); static int tsdbRmTableFromMeta(STsdbRepo *pRepo, STable *pTable); static int tsdbAdjustMetaTables(STsdbRepo *pRepo, int tid); static int tsdbCheckTableTagVal(SKVRow *pKVRow, STSchema *pSchema); +static void tsdbFreeLastColumns(STable* pTable); // ------------------ OUTER FUNCTIONS ------------------ int tsdbCreateTable(STsdbRepo *repo, STableCfg *pCfg) { @@ -590,6 +590,116 @@ void tsdbUnRefTable(STable *pTable) { } } +static void tsdbFreeLastColumns(STable* pTable) { + if (pTable->lastCols == NULL) { + return; + } + + for (int i = 0; i < pTable->lastColNum; ++i) { + if (pTable->lastCols[i].bytes == 0) { + continue; + } + tfree(pTable->lastCols[i].pData); + pTable->lastCols[i].bytes = 0; + pTable->lastCols[i].pData = NULL; + } + tfree(pTable->lastCols); + pTable->lastCols = NULL; + pTable->lastColNum = 0; +} + +int16_t tsdbGetLastColumnsIndexByColId(STable* pTable, int16_t colId) { + if (pTable->lastCols == NULL) { + return -1; + } + for (int16_t i = 0; i < pTable->lastColNum; ++i) { + if (pTable->lastCols[i].colId == colId) { + return i; + } + } + + return -1; +} + +int tsdbInitColIdCacheWithSchema(STable* pTable, STSchema* pSchema) { + ASSERT(pTable->lastCols == NULL); + + int16_t numOfColumn = pSchema->numOfCols; + + pTable->lastCols = (SDataCol*)malloc(numOfColumn * sizeof(SDataCol)); + if (pTable->lastCols == NULL) { + return -1; + } + + for (int16_t i = 0; i < numOfColumn; ++i) { + STColumn *pCol = schemaColAt(pSchema, i); + SDataCol* pDataCol = &(pTable->lastCols[i]); + pDataCol->bytes = 0; + pDataCol->pData = NULL; + pDataCol->colId = pCol->colId; + } + + pTable->lastColSVersion = schemaVersion(pSchema); + pTable->lastColNum = numOfColumn; + pTable->maxColumnNum = 0; + return 0; +} + +int tsdbUpdateLastColSchema(STable *pTable, STSchema *pNewSchema) { + if (pTable->lastColSVersion == schemaVersion(pNewSchema)) { + return 0; + } + + tsdbInfo("tsdbUpdateLastColSchema:%s,%d->%d", pTable->name->data, pTable->lastColSVersion, schemaVersion(pNewSchema)); + + int16_t numOfCols = pNewSchema->numOfCols; + SDataCol *lastCols = (SDataCol*)malloc(numOfCols * sizeof(SDataCol)); + if (lastCols == NULL) { + return -1; + } + + TSDB_WLOCK_TABLE(pTable); + + int16_t oldIdx = 0; + for (int16_t i = 0; i < numOfCols; ++i) { + STColumn *pCol = schemaColAt(pNewSchema, i); + int16_t idx = tsdbGetLastColumnsIndexByColId(pTable, pCol->colId); + + SDataCol* pDataCol = &(lastCols[i]); + if (idx != -1) { + SDataCol* pOldDataCol = &(pTable->lastCols[idx]); + memcpy(pDataCol, pOldDataCol, sizeof(SDataCol)); + } else { + pDataCol->colId = pCol->colId; + pDataCol->bytes = 0; + pDataCol->pData = NULL; + } + + // free dropped column data + while (oldIdx < idx && oldIdx < pTable->lastColNum) { + SDataCol* pOldDataCol = &(pTable->lastCols[oldIdx]); + if (pOldDataCol->bytes != 0) { + tfree(pOldDataCol->pData); + pOldDataCol->bytes = 0; + } + ++oldIdx; + } + if (idx != -1 && oldIdx == idx) { + oldIdx += 1; + } + } + + // free old schema last column datas + tfree(pTable->lastCols); + + pTable->lastColSVersion = schemaVersion(pNewSchema); + pTable->lastCols = lastCols; + pTable->lastColNum = numOfCols; + + TSDB_WUNLOCK_TABLE(pTable); + return 0; +} + void tsdbUpdateTableSchema(STsdbRepo *pRepo, STable *pTable, STSchema *pSchema, bool insertAct) { ASSERT(TABLE_TYPE(pTable) != TSDB_STREAM_TABLE && TABLE_TYPE(pTable) != TSDB_SUPER_TABLE); STsdbMeta *pMeta = pRepo->tsdbMeta; @@ -672,14 +782,11 @@ static STable *tsdbNewTable() { } pTable->lastKey = TSKEY_INITIAL_VAL; - pTable->lastCols = (SDataCol*)malloc(TSDB_LATEST_COLUMN_ARRAY_SIZE * sizeof(SDataCol)); - pTable->lastColNum = TSDB_LATEST_COLUMN_ARRAY_SIZE; - for (int i = 0; i < pTable->lastColNum; ++i) { - pTable->lastCols[i].bytes = 0; - pTable->lastCols[i].pData = NULL; - } - pTable->restoreColumnNum = 0; + pTable->lastCols = NULL; + pTable->maxColumnNum = 0; + pTable->lastColNum = 0; + pTable->lastColSVersion = -1; return pTable; } @@ -796,14 +903,7 @@ static void tsdbFreeTable(STable *pTable) { taosTZfree(pTable->lastRow); tfree(pTable->sql); - for (int i = 0; i < pTable->lastColNum; ++i) { - if (pTable->lastCols[i].pData == NULL) { - continue; - } - free(pTable->lastCols[i].pData); - } - tfree(pTable->lastCols); - + tsdbFreeLastColumns(pTable); free(pTable); } } From f182495628bfd32ccdbeb56aed15649544181c11 Mon Sep 17 00:00:00 2001 From: lichuang Date: Thu, 20 May 2021 09:29:31 +0800 Subject: [PATCH 17/70] [TD-4034]fix schema change,free not exist column data --- src/inc/tsdb.h | 4 ++-- src/tsdb/src/tsdbMeta.c | 43 +++++++++++++++++++++++++---------------- 2 files changed, 28 insertions(+), 19 deletions(-) diff --git a/src/inc/tsdb.h b/src/inc/tsdb.h index d231769c18..7c28d3e485 100644 --- a/src/inc/tsdb.h +++ b/src/inc/tsdb.h @@ -73,8 +73,8 @@ typedef struct { } STsdbCfg; #define CACHE_NO_LAST(c) ((c)->cacheLastRow == 0) -#define CACHE_LAST_ROW(c) ((c)->cacheLastRow == 1) -#define CACHE_LAST_NULL_COLUMN(c) ((c)->cacheLastRow == 2) +#define CACHE_LAST_ROW(c) (((c)->cacheLastRow & 1) > 0) +#define CACHE_LAST_NULL_COLUMN(c) (((c)->cacheLastRow & 2) > 0) // --------- TSDB REPOSITORY USAGE STATISTICS typedef struct { diff --git a/src/tsdb/src/tsdbMeta.c b/src/tsdb/src/tsdbMeta.c index d785d259fa..fde593b59a 100644 --- a/src/tsdb/src/tsdbMeta.c +++ b/src/tsdb/src/tsdbMeta.c @@ -659,44 +659,53 @@ int tsdbUpdateLastColSchema(STable *pTable, STSchema *pNewSchema) { } TSDB_WLOCK_TABLE(pTable); - - int16_t oldIdx = 0; + for (int16_t i = 0; i < numOfCols; ++i) { STColumn *pCol = schemaColAt(pNewSchema, i); int16_t idx = tsdbGetLastColumnsIndexByColId(pTable, pCol->colId); SDataCol* pDataCol = &(lastCols[i]); if (idx != -1) { + // move col data to new last column array SDataCol* pOldDataCol = &(pTable->lastCols[idx]); memcpy(pDataCol, pOldDataCol, sizeof(SDataCol)); } else { + // init new colid data pDataCol->colId = pCol->colId; pDataCol->bytes = 0; pDataCol->pData = NULL; } - - // free dropped column data - while (oldIdx < idx && oldIdx < pTable->lastColNum) { - SDataCol* pOldDataCol = &(pTable->lastCols[oldIdx]); - if (pOldDataCol->bytes != 0) { - tfree(pOldDataCol->pData); - pOldDataCol->bytes = 0; - } - ++oldIdx; - } - if (idx != -1 && oldIdx == idx) { - oldIdx += 1; - } } - // free old schema last column datas - tfree(pTable->lastCols); + SDataCol *oldLastCols = pTable->lastCols; + int16_t oldLastColNum = pTable->lastColNum; pTable->lastColSVersion = schemaVersion(pNewSchema); pTable->lastCols = lastCols; pTable->lastColNum = numOfCols; + if (oldLastCols == NULL) { + TSDB_WUNLOCK_TABLE(pTable); + return 0; + } + + // free old schema last column datas + for (int16_t i = 0; i < oldLastColNum; ++i) { + SDataCol* pDataCol = &(oldLastCols[i]); + if (pDataCol->bytes == 0) { + continue; + } + int16_t idx = tsdbGetLastColumnsIndexByColId(pTable, pDataCol->colId); + if (idx != -1) { + continue; + } + + // free not exist column data + tfree(pDataCol->pData); + } TSDB_WUNLOCK_TABLE(pTable); + tfree(oldLastCols); + return 0; } From cc50dcec6407e798270a7f12cbcd016ac8a24cf2 Mon Sep 17 00:00:00 2001 From: dapan1121 <89396746@qq.com> Date: Thu, 20 May 2021 10:36:59 +0800 Subject: [PATCH 18/70] update --- src/tsdb/src/tsdbRead.c | 281 ++++++++++++++++++++++------------------ 1 file changed, 154 insertions(+), 127 deletions(-) diff --git a/src/tsdb/src/tsdbRead.c b/src/tsdb/src/tsdbRead.c index b3460ac3b2..a326bd07fc 100644 --- a/src/tsdb/src/tsdbRead.c +++ b/src/tsdb/src/tsdbRead.c @@ -62,12 +62,6 @@ typedef struct SLoadCompBlockInfo { int32_t fileId; } SLoadCompBlockInfo; -typedef struct SCacheLastColInfo { - int16_t size; - int16_t num; - int16_t fetchIdx; - int16_t *idx; -} SCacheLastColInfo; typedef struct STableCheckInfo { STableId tableId; @@ -75,7 +69,6 @@ typedef struct STableCheckInfo { STable* pTableObj; SBlockInfo* pCompInfo; int32_t compSize; - SCacheLastColInfo cacheLast; // cache last column chosen int32_t numOfBlocks:29; // number of qualified data blocks not the original blocks int8_t chosen:2; // indicate which iterator should move forward bool initBuf; // whether to initialize the in-memory skip list iterator or not @@ -101,6 +94,12 @@ typedef struct SIOCostSummary { int64_t checkForNextTime; } SIOCostSummary; + +typedef struct SCacheLastColInfo { + int16_t i; + int16_t j; +} SCacheLastColInfo; + typedef struct STsdbQueryHandle { STsdbRepo* pTsdb; SQueryFilePos cur; // current position @@ -126,6 +125,7 @@ typedef struct STsdbQueryHandle { SReadH rhelper; STableBlockInfo* pDataBlockInfo; + SCacheLastColInfo lastCols; SDataCols *pDataCols; // in order to hold current file data block int32_t allocSize; // allocated data block size SMemRef *pMemRef; @@ -546,98 +546,16 @@ TsdbQueryHandleT tsdbQueryLastRow(STsdbRepo *tsdb, STsdbQueryCond *pCond, STable } - -STimeWindow updateCacheLastForEachGroup(STableGroupInfo *groupList) { - STimeWindow window = {INT64_MAX, INT64_MIN}; - - int32_t totalNumOfTable = 0; - - // NOTE: starts from the buffer in case of descending timestamp order check data blocks - size_t numOfGroups = taosArrayGetSize(groupList->pGroupList); - for(int32_t j = 0; j < numOfGroups; ++j) { - SArray* pGroup = taosArrayGetP(groupList->pGroupList, j); - TSKEY key = TSKEY_INITIAL_VAL; - - STableKeyInfo keyInfo = {0}; - - size_t numOfTables = taosArrayGetSize(pGroup); - for(int32_t i = 0; i < numOfTables; ++i) { - STableKeyInfo* pInfo = (STableKeyInfo*) taosArrayGet(pGroup, i); - - // if the lastKey equals to INT64_MIN, there is no data in this table - TSKEY lastKey = ((STable*)(pInfo->pTable))->lastKey; - if (key < lastKey) { - key = lastKey; - - keyInfo.pTable = pInfo->pTable; - keyInfo.lastKey = key; - pInfo->lastKey = key; - - if (key < window.skey) { - window.skey = key; - } - - if (key > window.ekey) { - window.ekey = key; - } - } - } - - // clear current group, unref unused table - for (int32_t i = 0; i < numOfTables; ++i) { - STableKeyInfo* pInfo = (STableKeyInfo*)taosArrayGet(pGroup, i); - - // keyInfo.pTable may be NULL here. - if (pInfo->pTable != keyInfo.pTable) { - tsdbUnRefTable(pInfo->pTable); - } - } - - taosArrayClear(pGroup); - - // more than one table in each group, only one table left for each group - if (keyInfo.pTable != NULL) { - totalNumOfTable++; - taosArrayPush(pGroup, &keyInfo); - } else { - taosArrayDestroy(pGroup); - - taosArrayRemove(groupList->pGroupList, j); - numOfGroups -= 1; - j -= 1; - } - } - - // window does not being updated, so set the original - if (window.skey == INT64_MAX && window.ekey == INT64_MIN) { - window = TSWINDOW_INITIALIZER; - assert(totalNumOfTable == 0 && taosArrayGetSize(groupList->pGroupList) == 0); - } - - groupList->numOfTables = totalNumOfTable; - return window; -} - - TsdbQueryHandleT tsdbQueryCacheLast(STsdbRepo *tsdb, STsdbQueryCond *pCond, STableGroupInfo *groupList, uint64_t qId, SMemRef* pMemRef) { - pCond->twindow = updateCacheLastForEachGroup(groupList); - - // no qualified table - if (groupList->numOfTables == 0) { - return NULL; - } - STsdbQueryHandle *pQueryHandle = (STsdbQueryHandle*) tsdbQueryTables(tsdb, pCond, groupList, qId, pMemRef); - int32_t code = checkForCachedLastRow(pQueryHandle, groupList); + int32_t code = checkForCachedLast(pQueryHandle, groupList); if (code != TSDB_CODE_SUCCESS) { // set the numOfTables to be 0 terrno = code; return NULL; } assert(pCond->order == TSDB_ORDER_ASC && pCond->twindow.skey <= pCond->twindow.ekey); - if (pQueryHandle->cachelastrow == 2) { - pQueryHandle->type = TSDB_QUERY_TYPE_LAST; - } + pQueryHandle->type = TSDB_QUERY_TYPE_LAST; return pQueryHandle; } @@ -2572,6 +2490,115 @@ static bool loadCachedLastRow(STsdbQueryHandle* pQueryHandle) { } +static int32_t copyColsFromCacheMem(STsdbQueryHandle* pQueryHandle, int32_t capacity, int32_t numOfRows, STable* pTable) { + char* pData = NULL; + + STSchema* pSchema = tsdbGetTableSchema(pTable); + int32_t numOfCols = schemaNCols(pSchema); + int32_t tgNumOfCols = QH_GET_NUM_OF_COLS(pQueryHandle); + + assert(numOfCols == pTable->restoreColumnNum); + assert(pTable->lastCols != NULL); + + int32_t i = pQueryHandle->lastCols.i, j = pQueryHandle->lastCols.j; + while(i < tgNumOfCols && j < numOfCols) { + SColumnInfoData* pColInfo = taosArrayGet(pQueryHandle->pColumns, i); + if (pTable->lastCols[j].colId < pColInfo->info.colId) { + j++; + continue; + } else if (pTable->lastCols[j].colId > pColInfo->info.colId) { + i++; + continue; + } + + if (ASCENDING_TRAVERSE(pQueryHandle->order)) { + pData = (char*)pColInfo->pData + numOfRows * pColInfo->info.bytes; + } else { + pData = (char*)pColInfo->pData + (capacity - numOfRows - 1) * pColInfo->info.bytes; + } + + if (pTable->lastCols[j].bytes > 0) { + void* value = pTable->lastCols[j].pData; + switch (pColInfo->info.type) { + case TSDB_DATA_TYPE_BINARY: + case TSDB_DATA_TYPE_NCHAR: + memcpy(pData, value, varDataTLen(value)); + break; + case TSDB_DATA_TYPE_NULL: + case TSDB_DATA_TYPE_BOOL: + case TSDB_DATA_TYPE_TINYINT: + case TSDB_DATA_TYPE_UTINYINT: + *(uint8_t *)pData = *(uint8_t *)value; + break; + case TSDB_DATA_TYPE_SMALLINT: + case TSDB_DATA_TYPE_USMALLINT: + *(uint16_t *)pData = *(uint16_t *)value; + break; + case TSDB_DATA_TYPE_INT: + case TSDB_DATA_TYPE_UINT: + *(uint32_t *)pData = *(uint32_t *)value; + break; + case TSDB_DATA_TYPE_BIGINT: + case TSDB_DATA_TYPE_UBIGINT: + *(uint64_t *)pData = *(uint64_t *)value; + break; + case TSDB_DATA_TYPE_FLOAT: + SET_FLOAT_PTR(pData, value); + break; + case TSDB_DATA_TYPE_DOUBLE: + SET_DOUBLE_PTR(pData, value); + break; + case TSDB_DATA_TYPE_TIMESTAMP: + if (pColInfo->info.colId == PRIMARYKEY_TIMESTAMP_COL_INDEX) { + *(TSKEY *)pData = tdGetKey(*(TKEY *)value); + } else { + *(TSKEY *)pData = *(TSKEY *)value; + } + break; + default: + memcpy(pData, value, pColInfo->info.bytes); + } + + for (int32_t n = 0; n < tgNumOfCols; ++n) { + if (n == i) { + continue; + } + + SColumnInfoData* pColInfo = taosArrayGet(pQueryHandle->pColumns, i); + if (pColInfo->info.type == TSDB_DATA_TYPE_BINARY || pColInfo->info.type == TSDB_DATA_TYPE_NCHAR) { + setVardataNull(pData, pColInfo->info.type); + } else { + setNull(pData, pColInfo->info.type, pColInfo->info.bytes); + } + } + + ++i; + ++j; + + if (i >= tgNumOfCols || j >= numOfCols) { + pQueryHandle->lastCols.i = 0; + pQueryHandle->lastCols.j = 0; + pQueryHandle->activeIndex++; + } else { + pQueryHandle->lastCols.i = i; + pQueryHandle->lastCols.j = j; + } + + return 1; + } + + i++; + j++; + } + + pQueryHandle->lastCols.i = 0; + pQueryHandle->lastCols.j = 0; + pQueryHandle->activeIndex++; + + return 0; +} + + static bool loadCachedLast(STsdbQueryHandle* pQueryHandle) { // the last row is cached in buffer, return it directly. // here note that the pQueryHandle->window must be the TS_INITIALIZER @@ -2581,42 +2608,15 @@ static bool loadCachedLast(STsdbQueryHandle* pQueryHandle) { SQueryFilePos* cur = &pQueryHandle->cur; - SDataRow pRow = NULL; TSKEY key = TSKEY_INITIAL_VAL; int32_t step = ASCENDING_TRAVERSE(pQueryHandle->order)? 1:-1; - if (pQueryHandle->activeIndex < 0) { - updateCacheLastForEachGroup(pQueryHandle); - } - - if (pQueryHandle->activeIndex < numOfTables) { + while (pQueryHandle->activeIndex < numOfTables) { STableCheckInfo* pCheckInfo = taosArrayGet(pQueryHandle->pTableCheckInfo, pQueryHandle->activeIndex); - if (pQueryHandle->cachelastrow == 1) { - int32_t ret = tsdbGetCachedLastRow(pCheckInfo->pTableObj, &pRow, &key); - if (ret != TSDB_CODE_SUCCESS) { - return false; - } - - copyOneRowFromMem(pQueryHandle, pQueryHandle->outputCapacity, 0, pRow, numOfCols, pCheckInfo->pTableObj, NULL); - tfree(pRow); - - // update the last key value - pCheckInfo->lastKey = key + step; - - cur->rows = 1; // only one row - cur->lastKey = key + step; - cur->mixBlock = true; - cur->win.skey = key; - cur->win.ekey = key; - } else if (pQueryHandle->cachelastrow == 2) { - - } else { - tsdbError("invalid cachelastrow:%d", pQueryHandle->cachelastrow); - return false; + if (copyColsFromCacheMem(pQueryHandle, pQueryHandle->outputCapacity, 0, numOfCols, pCheckInfo->pTableObj, NULL)) { + return true; } - - return true; } return false; @@ -2662,7 +2662,7 @@ bool tsdbNextDataBlock(TsdbQueryHandleT pHandle) { if (pQueryHandle->type == TSDB_QUERY_TYPE_LAST) { if (pQueryHandle->cachelastrow == 1) { return loadCachedLastRow(pQueryHandle); - } if (pQueryHandle->cachelastrow == 2) else { + } else if (pQueryHandle->cachelastrow == 2) { return loadCachedLast(pQueryHandle); } } @@ -2875,17 +2875,14 @@ int32_t checkForCachedLastRow(STsdbQueryHandle* pQueryHandle, STableGroupInfo *g int32_t code = 0; - if (((STable*)pInfo->pTable)->lastRow == 1) { + if (((STable*)pInfo->pTable)->lastRow) { code = tsdbGetCachedLastRow(pInfo->pTable, &pRow, &key); if (code != TSDB_CODE_SUCCESS) { pQueryHandle->cachelastrow = 0; } else { - pQueryHandle->cachelastrow = ((STable*)pInfo->pTable)->lastRow; + pQueryHandle->cachelastrow = 1; } - } else if (((STable*)pInfo->pTable)->lastCols && ((STable*)pInfo->pTable)->lastColNum > 0 && ((STable*)pInfo->pTable)->lastRow == 2){ - pQueryHandle->cachelastrow = ((STable*)pInfo->pTable)->lastRow; } - // update the tsdb query time range if (pQueryHandle->cachelastrow) { @@ -2898,6 +2895,36 @@ int32_t checkForCachedLastRow(STsdbQueryHandle* pQueryHandle, STableGroupInfo *g return code; } +int32_t checkForCachedLast(STsdbQueryHandle* pQueryHandle, STableGroupInfo *groupList) { + assert(pQueryHandle != NULL && groupList != NULL); + + SDataRow pRow = NULL; + TSKEY key = TSKEY_INITIAL_VAL; + + SArray* group = taosArrayGetP(groupList->pGroupList, 0); + assert(group != NULL); + + STableKeyInfo* pInfo = (STableKeyInfo*)taosArrayGet(group, 0); + + int32_t code = 0; + + if (((STable*)pInfo->pTable)->lastCols && ((STable*)pInfo->pTable)->lastColNum > 0){ + pQueryHandle->cachelastrow = 2; + } + + + // update the tsdb query time range + if (pQueryHandle->cachelastrow) { + pQueryHandle->window = TSWINDOW_INITIALIZER; + pQueryHandle->checkFiles = false; + pQueryHandle->activeIndex = 0; // start from -1 + } + + tfree(pRow); + return code; +} + + STimeWindow updateLastrowForEachGroup(STableGroupInfo *groupList) { STimeWindow window = {INT64_MAX, INT64_MIN}; From 61b2473bf927f16d31b319e309fc904ca1e6f086 Mon Sep 17 00:00:00 2001 From: lichuang Date: Thu, 20 May 2021 13:35:06 +0800 Subject: [PATCH 19/70] [TD-4034]fix Data column ts type --- src/common/inc/tdataformat.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/inc/tdataformat.h b/src/common/inc/tdataformat.h index fcae7a415f..9bb997ddcc 100644 --- a/src/common/inc/tdataformat.h +++ b/src/common/inc/tdataformat.h @@ -234,7 +234,7 @@ typedef struct SDataCol { int len; // column data length VarDataOffsetT *dataOff; // For binary and nchar data, the offset in the data column void * pData; // Actual data pointer - TSKEY ts; // only used in last NULL column + TKEY ts; // only used in last NULL column } SDataCol; static FORCE_INLINE void dataColReset(SDataCol *pDataCol) { pDataCol->len = 0; } From cf8be044de5f3ed4b0a6733183700beb3c7b7903 Mon Sep 17 00:00:00 2001 From: dapan1121 <89396746@qq.com> Date: Thu, 20 May 2021 14:41:21 +0800 Subject: [PATCH 20/70] fix bug --- src/inc/taosdef.h | 2 + src/inc/tsdb.h | 4 + src/query/src/qExecutor.c | 4 +- src/tsdb/src/tsdbRead.c | 238 ++++++++++++++++++-------------------- 4 files changed, 119 insertions(+), 129 deletions(-) diff --git a/src/inc/taosdef.h b/src/inc/taosdef.h index 2882faf7be..1c63a9a05d 100644 --- a/src/inc/taosdef.h +++ b/src/inc/taosdef.h @@ -33,6 +33,8 @@ extern "C" { #endif #define TSWINDOW_INITIALIZER ((STimeWindow) {INT64_MIN, INT64_MAX}) +#define TSWINDOW_DESC_INITIALIZER ((STimeWindow) {INT64_MAX, INT64_MIN}) + #define TSKEY_INITIAL_VAL INT64_MIN // Bytes for each type. diff --git a/src/inc/tsdb.h b/src/inc/tsdb.h index 7c28d3e485..468c5ab271 100644 --- a/src/inc/tsdb.h +++ b/src/inc/tsdb.h @@ -265,6 +265,10 @@ TsdbQueryHandleT *tsdbQueryTables(STsdbRepo *tsdb, STsdbQueryCond *pCond, STable TsdbQueryHandleT tsdbQueryLastRow(STsdbRepo *tsdb, STsdbQueryCond *pCond, STableGroupInfo *tableInfo, uint64_t qId, SMemRef *pRef); + +TsdbQueryHandleT tsdbQueryCacheLast(STsdbRepo *tsdb, STsdbQueryCond *pCond, STableGroupInfo *groupList, uint64_t qId, SMemRef* pMemRef); + + /** * get the queried table object list * @param pHandle diff --git a/src/query/src/qExecutor.c b/src/query/src/qExecutor.c index b48436a617..c2a4c7febe 100644 --- a/src/query/src/qExecutor.c +++ b/src/query/src/qExecutor.c @@ -33,6 +33,8 @@ #define SET_MASTER_SCAN_FLAG(runtime) ((runtime)->scanFlag = MASTER_SCAN) #define SET_REVERSE_SCAN_FLAG(runtime) ((runtime)->scanFlag = REVERSE_SCAN) +#define TSWINDOW_IS_EQUAL(t1, t2) (((t1).skey == (t2).skey) && ((t1).ekey == (t2).ekey)) + #define SWITCH_ORDER(n) (((n) = ((n) == TSDB_ORDER_ASC) ? TSDB_ORDER_DESC : TSDB_ORDER_ASC)) #define SDATA_BLOCK_INITIALIZER (SDataBlockInfo) {{0}, 0} @@ -1989,7 +1991,7 @@ static bool isCachedLastQuery(SQueryAttr *pQueryAttr) { return false; } - if (!TSWINDOW_IS_EQUAL(pQueryAttr->window, TSWINDOW_INITIALIZER)) { + if (pQueryAttr->order.order != TSDB_ORDER_DESC || !TSWINDOW_IS_EQUAL(pQueryAttr->window, TSWINDOW_DESC_INITIALIZER)) { return false; } diff --git a/src/tsdb/src/tsdbRead.c b/src/tsdb/src/tsdbRead.c index a326bd07fc..54833e5e78 100644 --- a/src/tsdb/src/tsdbRead.c +++ b/src/tsdb/src/tsdbRead.c @@ -94,12 +94,6 @@ typedef struct SIOCostSummary { int64_t checkForNextTime; } SIOCostSummary; - -typedef struct SCacheLastColInfo { - int16_t i; - int16_t j; -} SCacheLastColInfo; - typedef struct STsdbQueryHandle { STsdbRepo* pTsdb; SQueryFilePos cur; // current position @@ -124,8 +118,6 @@ typedef struct STsdbQueryHandle { SFSIter fileIter; SReadH rhelper; STableBlockInfo* pDataBlockInfo; - - SCacheLastColInfo lastCols; SDataCols *pDataCols; // in order to hold current file data block int32_t allocSize; // allocated data block size SMemRef *pMemRef; @@ -146,6 +138,7 @@ typedef struct STableGroupSupporter { static STimeWindow updateLastrowForEachGroup(STableGroupInfo *groupList); static int32_t checkForCachedLastRow(STsdbQueryHandle* pQueryHandle, STableGroupInfo *groupList); +static int32_t checkForCachedLast(STsdbQueryHandle* pQueryHandle, STableGroupInfo *groupList); static int32_t tsdbGetCachedLastRow(STable* pTable, SDataRow* pRes, TSKEY* lastKey); static void changeQueryHandleForInterpQuery(TsdbQueryHandleT pHandle); @@ -554,7 +547,6 @@ TsdbQueryHandleT tsdbQueryCacheLast(STsdbRepo *tsdb, STsdbQueryCond *pCond, STab return NULL; } - assert(pCond->order == TSDB_ORDER_ASC && pCond->twindow.skey <= pCond->twindow.ekey); pQueryHandle->type = TSDB_QUERY_TYPE_LAST; return pQueryHandle; @@ -2490,133 +2482,124 @@ static bool loadCachedLastRow(STsdbQueryHandle* pQueryHandle) { } -static int32_t copyColsFromCacheMem(STsdbQueryHandle* pQueryHandle, int32_t capacity, int32_t numOfRows, STable* pTable) { - char* pData = NULL; - - STSchema* pSchema = tsdbGetTableSchema(pTable); - int32_t numOfCols = schemaNCols(pSchema); - int32_t tgNumOfCols = QH_GET_NUM_OF_COLS(pQueryHandle); - - assert(numOfCols == pTable->restoreColumnNum); - assert(pTable->lastCols != NULL); - - int32_t i = pQueryHandle->lastCols.i, j = pQueryHandle->lastCols.j; - while(i < tgNumOfCols && j < numOfCols) { - SColumnInfoData* pColInfo = taosArrayGet(pQueryHandle->pColumns, i); - if (pTable->lastCols[j].colId < pColInfo->info.colId) { - j++; - continue; - } else if (pTable->lastCols[j].colId > pColInfo->info.colId) { - i++; - continue; - } - - if (ASCENDING_TRAVERSE(pQueryHandle->order)) { - pData = (char*)pColInfo->pData + numOfRows * pColInfo->info.bytes; - } else { - pData = (char*)pColInfo->pData + (capacity - numOfRows - 1) * pColInfo->info.bytes; - } - - if (pTable->lastCols[j].bytes > 0) { - void* value = pTable->lastCols[j].pData; - switch (pColInfo->info.type) { - case TSDB_DATA_TYPE_BINARY: - case TSDB_DATA_TYPE_NCHAR: - memcpy(pData, value, varDataTLen(value)); - break; - case TSDB_DATA_TYPE_NULL: - case TSDB_DATA_TYPE_BOOL: - case TSDB_DATA_TYPE_TINYINT: - case TSDB_DATA_TYPE_UTINYINT: - *(uint8_t *)pData = *(uint8_t *)value; - break; - case TSDB_DATA_TYPE_SMALLINT: - case TSDB_DATA_TYPE_USMALLINT: - *(uint16_t *)pData = *(uint16_t *)value; - break; - case TSDB_DATA_TYPE_INT: - case TSDB_DATA_TYPE_UINT: - *(uint32_t *)pData = *(uint32_t *)value; - break; - case TSDB_DATA_TYPE_BIGINT: - case TSDB_DATA_TYPE_UBIGINT: - *(uint64_t *)pData = *(uint64_t *)value; - break; - case TSDB_DATA_TYPE_FLOAT: - SET_FLOAT_PTR(pData, value); - break; - case TSDB_DATA_TYPE_DOUBLE: - SET_DOUBLE_PTR(pData, value); - break; - case TSDB_DATA_TYPE_TIMESTAMP: - if (pColInfo->info.colId == PRIMARYKEY_TIMESTAMP_COL_INDEX) { - *(TSKEY *)pData = tdGetKey(*(TKEY *)value); - } else { - *(TSKEY *)pData = *(TSKEY *)value; - } - break; - default: - memcpy(pData, value, pColInfo->info.bytes); - } - - for (int32_t n = 0; n < tgNumOfCols; ++n) { - if (n == i) { - continue; - } - - SColumnInfoData* pColInfo = taosArrayGet(pQueryHandle->pColumns, i); - if (pColInfo->info.type == TSDB_DATA_TYPE_BINARY || pColInfo->info.type == TSDB_DATA_TYPE_NCHAR) { - setVardataNull(pData, pColInfo->info.type); - } else { - setNull(pData, pColInfo->info.type, pColInfo->info.bytes); - } - } - - ++i; - ++j; - - if (i >= tgNumOfCols || j >= numOfCols) { - pQueryHandle->lastCols.i = 0; - pQueryHandle->lastCols.j = 0; - pQueryHandle->activeIndex++; - } else { - pQueryHandle->lastCols.i = i; - pQueryHandle->lastCols.j = j; - } - - return 1; - } - - i++; - j++; - } - - pQueryHandle->lastCols.i = 0; - pQueryHandle->lastCols.j = 0; - pQueryHandle->activeIndex++; - - return 0; -} - static bool loadCachedLast(STsdbQueryHandle* pQueryHandle) { // the last row is cached in buffer, return it directly. // here note that the pQueryHandle->window must be the TS_INITIALIZER - int32_t numOfCols = (int32_t)(QH_GET_NUM_OF_COLS(pQueryHandle)); + int32_t tgNumOfCols = QH_GET_NUM_OF_COLS(pQueryHandle); size_t numOfTables = taosArrayGetSize(pQueryHandle->pTableCheckInfo); - assert(numOfTables > 0 && numOfCols > 0); - - SQueryFilePos* cur = &pQueryHandle->cur; - - TSKEY key = TSKEY_INITIAL_VAL; - int32_t step = ASCENDING_TRAVERSE(pQueryHandle->order)? 1:-1; + int32_t numOfRows = 0; + assert(numOfTables > 0 && tgNumOfCols > 0); while (pQueryHandle->activeIndex < numOfTables) { STableCheckInfo* pCheckInfo = taosArrayGet(pQueryHandle->pTableCheckInfo, pQueryHandle->activeIndex); + STable* pTable = pCheckInfo->pTableObj; + char* pData = NULL; + + int32_t numOfCols = pTable->lastColNum; - if (copyColsFromCacheMem(pQueryHandle, pQueryHandle->outputCapacity, 0, numOfCols, pCheckInfo->pTableObj, NULL)) { - return true; + if (pTable->lastCols == NULL || pTable->lastColNum <= 0) { + tsdbWarn("no last cached for table, uid:%" PRIu64 ",tid:%d", pTable->tableId.uid, pTable->tableId.tid); + pQueryHandle->activeIndex++; + continue; } + + int32_t i = 0, j = 0; + while(i < tgNumOfCols && j < numOfCols) { + SColumnInfoData* pColInfo = taosArrayGet(pQueryHandle->pColumns, i); + if (pTable->lastCols[j].colId < pColInfo->info.colId) { + j++; + continue; + } else if (pTable->lastCols[j].colId > pColInfo->info.colId) { + i++; + continue; + } + + if (ASCENDING_TRAVERSE(pQueryHandle->order)) { + pData = (char*)pColInfo->pData + numOfRows * pColInfo->info.bytes;; + } else { + pData = (char*)pColInfo->pData + (pQueryHandle->outputCapacity + numOfRows - 1) * pColInfo->info.bytes; + } + + if (pTable->lastCols[j].bytes > 0) { + void* value = pTable->lastCols[j].pData; + switch (pColInfo->info.type) { + case TSDB_DATA_TYPE_BINARY: + case TSDB_DATA_TYPE_NCHAR: + memcpy(pData, value, varDataTLen(value)); + break; + case TSDB_DATA_TYPE_NULL: + case TSDB_DATA_TYPE_BOOL: + case TSDB_DATA_TYPE_TINYINT: + case TSDB_DATA_TYPE_UTINYINT: + *(uint8_t *)pData = *(uint8_t *)value; + break; + case TSDB_DATA_TYPE_SMALLINT: + case TSDB_DATA_TYPE_USMALLINT: + *(uint16_t *)pData = *(uint16_t *)value; + break; + case TSDB_DATA_TYPE_INT: + case TSDB_DATA_TYPE_UINT: + *(uint32_t *)pData = *(uint32_t *)value; + break; + case TSDB_DATA_TYPE_BIGINT: + case TSDB_DATA_TYPE_UBIGINT: + *(uint64_t *)pData = *(uint64_t *)value; + break; + case TSDB_DATA_TYPE_FLOAT: + SET_FLOAT_PTR(pData, value); + break; + case TSDB_DATA_TYPE_DOUBLE: + SET_DOUBLE_PTR(pData, value); + break; + case TSDB_DATA_TYPE_TIMESTAMP: + if (pColInfo->info.colId == PRIMARYKEY_TIMESTAMP_COL_INDEX) { + *(TSKEY *)pData = tdGetKey(*(TKEY *)value); + } else { + *(TSKEY *)pData = *(TSKEY *)value; + } + break; + default: + memcpy(pData, value, pColInfo->info.bytes); + } + + for (int32_t n = 0; n < tgNumOfCols; ++n) { + if (n == i) { + continue; + } + + SColumnInfoData* pColInfo = taosArrayGet(pQueryHandle->pColumns, i); + if (ASCENDING_TRAVERSE(pQueryHandle->order)) { + pData = (char*)pColInfo->pData + numOfRows * pColInfo->info.bytes;; + } else { + pData = (char*)pColInfo->pData + (pQueryHandle->outputCapacity + numOfRows - 1) * pColInfo->info.bytes; + } + + if (n == 0) { + *(TSKEY *)pData = pTable->lastCols[j].ts; + continue; + } + + if (pColInfo->info.type == TSDB_DATA_TYPE_BINARY || pColInfo->info.type == TSDB_DATA_TYPE_NCHAR) { + setVardataNull(pData, pColInfo->info.type); + } else { + setNull(pData, pColInfo->info.type, pColInfo->info.bytes); + } + } + + numOfRows++; + assert(numOfRows < pQueryHandle->outputCapacity); + } + + i++; + j++; + } + + pQueryHandle->activeIndex++; + + if (numOfRows > 0) { + return true; + } } return false; @@ -2850,7 +2833,7 @@ int32_t tsdbGetCachedLastRow(STable* pTable, SDataRow* pRes, TSKEY* lastKey) { TSDB_RLOCK_TABLE(pTable); *lastKey = pTable->lastKey; - if ((*lastKey) != TSKEY_INITIAL_VAL && pTable->lastRow == 1) { + if ((*lastKey) != TSKEY_INITIAL_VAL && pTable->lastRow) { *pRes = tdDataRowDup(pTable->lastRow); if (*pRes == NULL) { TSDB_RUNLOCK_TABLE(pTable); @@ -2899,7 +2882,6 @@ int32_t checkForCachedLast(STsdbQueryHandle* pQueryHandle, STableGroupInfo *grou assert(pQueryHandle != NULL && groupList != NULL); SDataRow pRow = NULL; - TSKEY key = TSKEY_INITIAL_VAL; SArray* group = taosArrayGetP(groupList->pGroupList, 0); assert(group != NULL); From e51fd4bf77b4aa7d9904adcd53fcc592902d3e58 Mon Sep 17 00:00:00 2001 From: lichuang Date: Thu, 20 May 2021 15:32:25 +0800 Subject: [PATCH 21/70] [TD-4034]get latest schema from super table --- src/tsdb/src/tsdbMain.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/tsdb/src/tsdbMain.c b/src/tsdb/src/tsdbMain.c index 3241d617b6..29842c0c16 100644 --- a/src/tsdb/src/tsdbMain.c +++ b/src/tsdb/src/tsdbMain.c @@ -616,17 +616,34 @@ static void tsdbStopStream(STsdbRepo *pRepo) { } } +static STSchema* getTableLatestSchema(STable *pTable) { + if (pTable->numOfSchemas > 0) { + return pTable->schema[pTable->numOfSchemas - 1]; + } + + if (pTable->type == TSDB_CHILD_TABLE) { + if (pTable->pSuper && pTable->pSuper->numOfSchemas) { + tsdbInfo("getTableLatestSchema of table %s from super table", pTable->name->data); + return pTable->pSuper->schema[pTable->pSuper->numOfSchemas - 1]; + } + } + return NULL; +} + static int restoreLastColumns(STsdbRepo *pRepo, STable *pTable, SReadH* pReadh) { - if (pTable->numOfSchemas == 0) { + STSchema *pSchema = getTableLatestSchema(pTable); + if (pSchema == NULL) { + tsdbError("getTableLatestSchema of table %s fail", pTable->name->data); return 0; } + SBlock* pBlock; int numColumns; int32_t blockIdx; SDataStatis* pBlockStatis = NULL; SDataRow row = NULL; // restore last column data with last schema - STSchema *pSchema = pTable->schema[pTable->numOfSchemas - 1]; + int err = 0; numColumns = schemaNCols(pSchema); From 220bc3502a023cb7c8a79a5e640798632e379858 Mon Sep 17 00:00:00 2001 From: lichuang Date: Thu, 20 May 2021 15:36:44 +0800 Subject: [PATCH 22/70] [TD-4034]get latest schema from super table --- src/tsdb/src/tsdbMain.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tsdb/src/tsdbMain.c b/src/tsdb/src/tsdbMain.c index 29842c0c16..8e31ae5022 100644 --- a/src/tsdb/src/tsdbMain.c +++ b/src/tsdb/src/tsdbMain.c @@ -623,7 +623,7 @@ static STSchema* getTableLatestSchema(STable *pTable) { if (pTable->type == TSDB_CHILD_TABLE) { if (pTable->pSuper && pTable->pSuper->numOfSchemas) { - tsdbInfo("getTableLatestSchema of table %s from super table", pTable->name->data); + tsdbDebug("getTableLatestSchema of table %s from super table %s", pTable->name->data, pTable->pSuper->name->data); return pTable->pSuper->schema[pTable->pSuper->numOfSchemas - 1]; } } From 308639a9e333a083ee693ced95d66dbd0b014c56 Mon Sep 17 00:00:00 2001 From: dapan1121 <89396746@qq.com> Date: Thu, 20 May 2021 15:37:38 +0800 Subject: [PATCH 23/70] fix bug --- src/tsdb/src/tsdbRead.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/tsdb/src/tsdbRead.c b/src/tsdb/src/tsdbRead.c index 54833e5e78..cf2ab0cc3f 100644 --- a/src/tsdb/src/tsdbRead.c +++ b/src/tsdb/src/tsdbRead.c @@ -2491,7 +2491,7 @@ static bool loadCachedLast(STsdbQueryHandle* pQueryHandle) { int32_t numOfRows = 0; assert(numOfTables > 0 && tgNumOfCols > 0); - while (pQueryHandle->activeIndex < numOfTables) { + while (++pQueryHandle->activeIndex < numOfTables) { STableCheckInfo* pCheckInfo = taosArrayGet(pQueryHandle->pTableCheckInfo, pQueryHandle->activeIndex); STable* pTable = pCheckInfo->pTableObj; char* pData = NULL; @@ -2500,7 +2500,6 @@ static bool loadCachedLast(STsdbQueryHandle* pQueryHandle) { if (pTable->lastCols == NULL || pTable->lastColNum <= 0) { tsdbWarn("no last cached for table, uid:%" PRIu64 ",tid:%d", pTable->tableId.uid, pTable->tableId.tid); - pQueryHandle->activeIndex++; continue; } @@ -2595,8 +2594,6 @@ static bool loadCachedLast(STsdbQueryHandle* pQueryHandle) { j++; } - pQueryHandle->activeIndex++; - if (numOfRows > 0) { return true; } @@ -2899,7 +2896,7 @@ int32_t checkForCachedLast(STsdbQueryHandle* pQueryHandle, STableGroupInfo *grou if (pQueryHandle->cachelastrow) { pQueryHandle->window = TSWINDOW_INITIALIZER; pQueryHandle->checkFiles = false; - pQueryHandle->activeIndex = 0; // start from -1 + pQueryHandle->activeIndex = -1; // start from -1 } tfree(pRow); From fcfd4d29d1df853599f73200cf8a6ddc3c254827 Mon Sep 17 00:00:00 2001 From: lichuang Date: Thu, 20 May 2021 16:14:16 +0800 Subject: [PATCH 24/70] [TD-4034]fix Data column ts type --- src/common/inc/tdataformat.h | 2 +- src/tsdb/src/tsdbMain.c | 2 +- src/tsdb/src/tsdbMemTable.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/common/inc/tdataformat.h b/src/common/inc/tdataformat.h index 9bb997ddcc..fcae7a415f 100644 --- a/src/common/inc/tdataformat.h +++ b/src/common/inc/tdataformat.h @@ -234,7 +234,7 @@ typedef struct SDataCol { int len; // column data length VarDataOffsetT *dataOff; // For binary and nchar data, the offset in the data column void * pData; // Actual data pointer - TKEY ts; // only used in last NULL column + TSKEY ts; // only used in last NULL column } SDataCol; static FORCE_INLINE void dataColReset(SDataCol *pDataCol) { pDataCol->len = 0; } diff --git a/src/tsdb/src/tsdbMain.c b/src/tsdb/src/tsdbMain.c index 8e31ae5022..d593997d3c 100644 --- a/src/tsdb/src/tsdbMain.c +++ b/src/tsdb/src/tsdbMain.c @@ -742,7 +742,7 @@ static int restoreLastColumns(STsdbRepo *pRepo, STable *pTable, SReadH* pReadh) pDataCol = pReadh->pDCols[0]->cols + 0; pCol = schemaColAt(pSchema, 0); tdAppendColVal(row, tdGetColDataOfRow(pDataCol, rowId), pCol->type, pCol->bytes, pCol->offset); - pLastCol->ts = dataRowTKey(row); + pLastCol->ts = dataRowKey(row); pTable->maxColumnNum += 1; diff --git a/src/tsdb/src/tsdbMemTable.c b/src/tsdb/src/tsdbMemTable.c index 900c034a22..156bd29ee1 100644 --- a/src/tsdb/src/tsdbMemTable.c +++ b/src/tsdb/src/tsdbMemTable.c @@ -1011,7 +1011,7 @@ static void updateTableLatestColumn(STsdbRepo *pRepo, STable *pTable, SDataRow r memcpy(pDataCol->pData, value, pDataCol->bytes); //tsdbInfo("updateTableLatestColumn vgId:%d cache column %d for %d,%s", REPO_ID(pRepo), j, pDataCol->bytes, (char*)pDataCol->pData); - pDataCol->ts = dataRowTKey(row); + pDataCol->ts = dataRowKey(row); } } From 80cd7963cd2389a8dcf857dedffaa129932ce68d Mon Sep 17 00:00:00 2001 From: dapan1121 <89396746@qq.com> Date: Thu, 20 May 2021 16:16:58 +0800 Subject: [PATCH 25/70] fix bug --- src/tsdb/src/tsdbRead.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/tsdb/src/tsdbRead.c b/src/tsdb/src/tsdbRead.c index cf2ab0cc3f..29d400fd56 100644 --- a/src/tsdb/src/tsdbRead.c +++ b/src/tsdb/src/tsdbRead.c @@ -2490,6 +2490,7 @@ static bool loadCachedLast(STsdbQueryHandle* pQueryHandle) { size_t numOfTables = taosArrayGetSize(pQueryHandle->pTableCheckInfo); int32_t numOfRows = 0; assert(numOfTables > 0 && tgNumOfCols > 0); + SQueryFilePos* cur = &pQueryHandle->cur; while (++pQueryHandle->activeIndex < numOfTables) { STableCheckInfo* pCheckInfo = taosArrayGet(pQueryHandle->pTableCheckInfo, pQueryHandle->activeIndex); @@ -2517,7 +2518,7 @@ static bool loadCachedLast(STsdbQueryHandle* pQueryHandle) { if (ASCENDING_TRAVERSE(pQueryHandle->order)) { pData = (char*)pColInfo->pData + numOfRows * pColInfo->info.bytes;; } else { - pData = (char*)pColInfo->pData + (pQueryHandle->outputCapacity + numOfRows - 1) * pColInfo->info.bytes; + pData = (char*)pColInfo->pData + (pQueryHandle->outputCapacity - numOfRows - 1) * pColInfo->info.bytes; } if (pTable->lastCols[j].bytes > 0) { @@ -2567,11 +2568,11 @@ static bool loadCachedLast(STsdbQueryHandle* pQueryHandle) { continue; } - SColumnInfoData* pColInfo = taosArrayGet(pQueryHandle->pColumns, i); + SColumnInfoData* pColInfo = taosArrayGet(pQueryHandle->pColumns, n); if (ASCENDING_TRAVERSE(pQueryHandle->order)) { pData = (char*)pColInfo->pData + numOfRows * pColInfo->info.bytes;; } else { - pData = (char*)pColInfo->pData + (pQueryHandle->outputCapacity + numOfRows - 1) * pColInfo->info.bytes; + pData = (char*)pColInfo->pData + (pQueryHandle->outputCapacity - numOfRows - 1) * pColInfo->info.bytes; } if (n == 0) { @@ -2595,6 +2596,9 @@ static bool loadCachedLast(STsdbQueryHandle* pQueryHandle) { } if (numOfRows > 0) { + cur->rows = numOfRows; + cur->mixBlock = true; + return true; } } From 4beb0b4d076b1c2f01d7d086186804013f26db97 Mon Sep 17 00:00:00 2001 From: lichuang Date: Thu, 20 May 2021 19:16:12 +0800 Subject: [PATCH 26/70] [TD-4034]fix super table bug --- src/tsdb/inc/tsdbMeta.h | 1 + src/tsdb/src/tsdbMain.c | 27 ++++++++------------------- src/tsdb/src/tsdbMemTable.c | 16 ++++------------ src/tsdb/src/tsdbMeta.c | 4 ++++ 4 files changed, 17 insertions(+), 31 deletions(-) diff --git a/src/tsdb/inc/tsdbMeta.h b/src/tsdb/inc/tsdbMeta.h index 43c85d89cb..45868c002d 100644 --- a/src/tsdb/inc/tsdbMeta.h +++ b/src/tsdb/inc/tsdbMeta.h @@ -89,6 +89,7 @@ void tsdbOrgMeta(STsdbRepo* pRepo); int tsdbInitColIdCacheWithSchema(STable* pTable, STSchema* pSchema); int16_t tsdbGetLastColumnsIndexByColId(STable* pTable, int16_t colId); int tsdbUpdateLastColSchema(STable *pTable, STSchema *pNewSchema); +STSchema* tsdbGetTableLatestSchema(STable *pTable); static FORCE_INLINE int tsdbCompareSchemaVersion(const void *key1, const void *key2) { if (*(int16_t *)key1 < schemaVersion(*(STSchema **)key2)) { diff --git a/src/tsdb/src/tsdbMain.c b/src/tsdb/src/tsdbMain.c index d593997d3c..1e6f9eac12 100644 --- a/src/tsdb/src/tsdbMain.c +++ b/src/tsdb/src/tsdbMain.c @@ -26,6 +26,7 @@ static STsdbRepo *tsdbNewRepo(STsdbCfg *pCfg, STsdbAppH *pAppH); static void tsdbFreeRepo(STsdbRepo *pRepo); static void tsdbStartStream(STsdbRepo *pRepo); static void tsdbStopStream(STsdbRepo *pRepo); +static int tsdbRestoreLastColumns(STsdbRepo *pRepo, STable *pTable, SReadH* pReadh); // Function declaration int32_t tsdbCreateRepo(int repoid) { @@ -616,24 +617,12 @@ static void tsdbStopStream(STsdbRepo *pRepo) { } } -static STSchema* getTableLatestSchema(STable *pTable) { - if (pTable->numOfSchemas > 0) { - return pTable->schema[pTable->numOfSchemas - 1]; - } +static int tsdbRestoreLastColumns(STsdbRepo *pRepo, STable *pTable, SReadH* pReadh) { + //tsdbInfo("tsdbRestoreLastColumns of table %s", pTable->name->data); - if (pTable->type == TSDB_CHILD_TABLE) { - if (pTable->pSuper && pTable->pSuper->numOfSchemas) { - tsdbDebug("getTableLatestSchema of table %s from super table %s", pTable->name->data, pTable->pSuper->name->data); - return pTable->pSuper->schema[pTable->pSuper->numOfSchemas - 1]; - } - } - return NULL; -} - -static int restoreLastColumns(STsdbRepo *pRepo, STable *pTable, SReadH* pReadh) { - STSchema *pSchema = getTableLatestSchema(pTable); + STSchema *pSchema = tsdbGetTableLatestSchema(pTable); if (pSchema == NULL) { - tsdbError("getTableLatestSchema of table %s fail", pTable->name->data); + tsdbError("tsdbGetTableLatestSchema of table %s fail", pTable->name->data); return 0; } @@ -728,7 +717,7 @@ static int restoreLastColumns(STsdbRepo *pRepo, STable *pTable, SReadH* pReadh) int16_t idx = tsdbGetLastColumnsIndexByColId(pTable, pCol->colId); if (idx == -1) { - tsdbError("restoreLastColumns restore vgId:%d,table:%s cache column %d fail", REPO_ID(pRepo), pTable->name->data, pCol->colId); + tsdbError("tsdbRestoreLastColumns restore vgId:%d,table:%s cache column %d fail", REPO_ID(pRepo), pTable->name->data, pCol->colId); continue; } // save not-null column @@ -746,7 +735,7 @@ static int restoreLastColumns(STsdbRepo *pRepo, STable *pTable, SReadH* pReadh) pTable->maxColumnNum += 1; - tsdbInfo("restoreLastColumns restore vgId:%d,table:%s cache column %d, %" PRId64, REPO_ID(pRepo), pTable->name->data, pLastCol->colId, pLastCol->ts); + tsdbInfo("tsdbRestoreLastColumns restore vgId:%d,table:%s cache column %d, %" PRId64, REPO_ID(pRepo), pTable->name->data, pLastCol->colId, pLastCol->ts); break; } } @@ -843,7 +832,7 @@ int tsdbRestoreInfo(STsdbRepo *pRepo) { // restore NULL columns if (pIdx && CACHE_LAST_NULL_COLUMN(pCfg)) { - if (restoreLastColumns(pRepo, pTable, &readh) != 0) { + if (tsdbRestoreLastColumns(pRepo, pTable, &readh) != 0) { tsdbDestroyReadH(&readh); return -1; } diff --git a/src/tsdb/src/tsdbMemTable.c b/src/tsdb/src/tsdbMemTable.c index 156bd29ee1..ff2a870f3f 100644 --- a/src/tsdb/src/tsdbMemTable.c +++ b/src/tsdb/src/tsdbMemTable.c @@ -965,23 +965,15 @@ static void tsdbFreeRows(STsdbRepo *pRepo, void **rows, int rowCounter) { } static void updateTableLatestColumn(STsdbRepo *pRepo, STable *pTable, SDataRow row) { - //tsdbInfo("vgId:%d updateTableLatestColumn, row version:%d", REPO_ID(pRepo), dataRowVersion(row)); + tsdbInfo("vgId:%d updateTableLatestColumn, %s row version:%d", REPO_ID(pRepo), pTable->name->data, dataRowVersion(row)); - if (pTable->numOfSchemas <= 0) { - return; - } - - STSchema* pSchema = pTable->schema[pTable->numOfSchemas - 1]; + STSchema* pSchema = tsdbGetTableLatestSchema(pTable); if (tsdbUpdateLastColSchema(pTable, pSchema) < 0) { return; } - int16_t i = pTable->numOfSchemas - 1; - while ((pSchema == NULL || pSchema->version != dataRowVersion(row)) && i >= 0) { - i -= 1; - pSchema = pTable->schema[i]; - } - if (pSchema == NULL || pSchema->version != dataRowVersion(row)) { + pSchema = tsdbGetTableSchemaByVersion(pTable, dataRowVersion(row)); + if (pSchema == NULL) { return; } diff --git a/src/tsdb/src/tsdbMeta.c b/src/tsdb/src/tsdbMeta.c index fde593b59a..5717d52eea 100644 --- a/src/tsdb/src/tsdbMeta.c +++ b/src/tsdb/src/tsdbMeta.c @@ -645,6 +645,10 @@ int tsdbInitColIdCacheWithSchema(STable* pTable, STSchema* pSchema) { return 0; } +STSchema* tsdbGetTableLatestSchema(STable *pTable) { + return tsdbGetTableSchemaByVersion(pTable, -1); +} + int tsdbUpdateLastColSchema(STable *pTable, STSchema *pNewSchema) { if (pTable->lastColSVersion == schemaVersion(pNewSchema)) { return 0; From 5507e88752614360abb66ab29e2802d4d42205ea Mon Sep 17 00:00:00 2001 From: dapan1121 <89396746@qq.com> Date: Fri, 21 May 2021 08:26:29 +0800 Subject: [PATCH 27/70] move ts to last row --- src/tsdb/src/tsdbRead.c | 52 ++++++++++++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 13 deletions(-) diff --git a/src/tsdb/src/tsdbRead.c b/src/tsdb/src/tsdbRead.c index 29d400fd56..c78739d7ce 100644 --- a/src/tsdb/src/tsdbRead.c +++ b/src/tsdb/src/tsdbRead.c @@ -2491,6 +2491,8 @@ static bool loadCachedLast(STsdbQueryHandle* pQueryHandle) { int32_t numOfRows = 0; assert(numOfTables > 0 && tgNumOfCols > 0); SQueryFilePos* cur = &pQueryHandle->cur; + TSKEY priKey = TSKEY_INITIAL_VAL; + int32_t priIdx = -1; while (++pQueryHandle->activeIndex < numOfTables) { STableCheckInfo* pCheckInfo = taosArrayGet(pQueryHandle->pTableCheckInfo, pQueryHandle->activeIndex); @@ -2515,13 +2517,9 @@ static bool loadCachedLast(STsdbQueryHandle* pQueryHandle) { continue; } - if (ASCENDING_TRAVERSE(pQueryHandle->order)) { - pData = (char*)pColInfo->pData + numOfRows * pColInfo->info.bytes;; - } else { - pData = (char*)pColInfo->pData + (pQueryHandle->outputCapacity - numOfRows - 1) * pColInfo->info.bytes; - } + pData = (char*)pColInfo->pData + numOfRows * pColInfo->info.bytes; - if (pTable->lastCols[j].bytes > 0) { + if (pTable->lastCols[j].bytes > 0) { void* value = pTable->lastCols[j].pData; switch (pColInfo->info.type) { case TSDB_DATA_TYPE_BINARY: @@ -2554,7 +2552,12 @@ static bool loadCachedLast(STsdbQueryHandle* pQueryHandle) { break; case TSDB_DATA_TYPE_TIMESTAMP: if (pColInfo->info.colId == PRIMARYKEY_TIMESTAMP_COL_INDEX) { - *(TSKEY *)pData = tdGetKey(*(TKEY *)value); + priKey = tdGetKey(*(TKEY *)value); + priIdx = i; + + i++; + j++; + continue; } else { *(TSKEY *)pData = *(TSKEY *)value; } @@ -2569,13 +2572,9 @@ static bool loadCachedLast(STsdbQueryHandle* pQueryHandle) { } SColumnInfoData* pColInfo = taosArrayGet(pQueryHandle->pColumns, n); - if (ASCENDING_TRAVERSE(pQueryHandle->order)) { - pData = (char*)pColInfo->pData + numOfRows * pColInfo->info.bytes;; - } else { - pData = (char*)pColInfo->pData + (pQueryHandle->outputCapacity - numOfRows - 1) * pColInfo->info.bytes; - } + pData = (char*)pColInfo->pData + numOfRows * pColInfo->info.bytes;; - if (n == 0) { + if (pColInfo->info.colId == PRIMARYKEY_TIMESTAMP_COL_INDEX) { *(TSKEY *)pData = pTable->lastCols[j].ts; continue; } @@ -2595,6 +2594,33 @@ static bool loadCachedLast(STsdbQueryHandle* pQueryHandle) { j++; } + // leave the real ts column as the last row, because last function only (not stable) use the last row as res + if (priKey != TSKEY_INITIAL_VAL) { + SColumnInfoData* pColInfo = taosArrayGet(pQueryHandle->pColumns, priIdx); + pData = (char*)pColInfo->pData + numOfRows * pColInfo->info.bytes; + + *(TSKEY *)pData = priKey; + + for (int32_t n = 0; n < tgNumOfCols; ++n) { + if (n == priIdx) { + continue; + } + + SColumnInfoData* pColInfo = taosArrayGet(pQueryHandle->pColumns, n); + pData = (char*)pColInfo->pData + numOfRows * pColInfo->info.bytes;; + + assert (pColInfo->info.colId != PRIMARYKEY_TIMESTAMP_COL_INDEX); + + if (pColInfo->info.type == TSDB_DATA_TYPE_BINARY || pColInfo->info.type == TSDB_DATA_TYPE_NCHAR) { + setVardataNull(pData, pColInfo->info.type); + } else { + setNull(pData, pColInfo->info.type, pColInfo->info.bytes); + } + } + + numOfRows++; + } + if (numOfRows > 0) { cur->rows = numOfRows; cur->mixBlock = true; From 2f1c18b6c1eff8505968efe82a8dbeeb7db6ca0c Mon Sep 17 00:00:00 2001 From: dapan1121 <89396746@qq.com> Date: Fri, 21 May 2021 14:16:03 +0800 Subject: [PATCH 28/70] add test case --- tests/script/general/parser/last_cache.sim | 71 +++ .../general/parser/last_cache_query.sim | 416 ++++++++++++++++++ tests/script/general/parser/testSuite.sim | 2 + 3 files changed, 489 insertions(+) create mode 100644 tests/script/general/parser/last_cache.sim create mode 100644 tests/script/general/parser/last_cache_query.sim diff --git a/tests/script/general/parser/last_cache.sim b/tests/script/general/parser/last_cache.sim new file mode 100644 index 0000000000..9d7da9ddba --- /dev/null +++ b/tests/script/general/parser/last_cache.sim @@ -0,0 +1,71 @@ +system sh/stop_dnodes.sh +system sh/deploy.sh -n dnode1 -i 1 +system sh/cfg.sh -n dnode1 -c walLevel -v 0 +system sh/cfg.sh -n dnode1 -c maxtablesPerVnode -v 4 +system sh/exec.sh -n dnode1 -s start + +sleep 100 +sql connect +print ======================== dnode1 start + +$db = testdb + +sql create database $db cachelast 2 +sql use $db + +sql create stable st2 (ts timestamp, f1 int, f2 double, f3 binary(10), f4 timestamp) tags (id int) + +sql create table tb1 using st2 tags (1); +sql create table tb2 using st2 tags (2); +sql create table tb3 using st2 tags (3); +sql create table tb4 using st2 tags (4); +sql create table tb5 using st2 tags (1); +sql create table tb6 using st2 tags (2); +sql create table tb7 using st2 tags (3); +sql create table tb8 using st2 tags (4); +sql create table tb9 using st2 tags (5); +sql create table tba using st2 tags (5); +sql create table tbb using st2 tags (5); +sql create table tbc using st2 tags (5); +sql create table tbd using st2 tags (5); +sql create table tbe using st2 tags (5); + +sql insert into tb1 values ("2021-05-09 10:10:10", 1, 2.0, '3', -1000) +sql insert into tb1 values ("2021-05-10 10:10:11", 4, 5.0, NULL, -2000) +sql insert into tb1 values ("2021-05-12 10:10:12", 6,NULL, NULL, -3000) + +sql insert into tb2 values ("2021-05-09 10:11:13",-1,-2.0,'-3', -1001) +sql insert into tb2 values ("2021-05-10 10:11:14",-4,-5.0, NULL, -2001) +sql insert into tb2 values ("2021-05-11 10:11:15",-6, -7, '-8', -3001) + +sql insert into tb3 values ("2021-05-09 10:12:17", 7, 8.0, '9' , -1002) +sql insert into tb3 values ("2021-05-09 10:12:17",10,11.0, NULL, -2002) +sql insert into tb3 values ("2021-05-09 10:12:18",12,NULL, NULL, -3002) + +sql insert into tb4 values ("2021-05-09 10:12:19",13,14.0,'15' , -1003) +sql insert into tb4 values ("2021-05-10 10:12:20",16,17.0, NULL, -2003) +sql insert into tb4 values ("2021-05-11 10:12:21",18,NULL, NULL, -3003) + +sql insert into tb5 values ("2021-05-09 10:12:22",19, 20, '21', -1004) +sql insert into tb6 values ("2021-05-11 10:12:23",22, 23, NULL, -2004) +sql insert into tb7 values ("2021-05-10 10:12:24",24,NULL, '25', -3004) +sql insert into tb8 values ("2021-05-11 10:12:25",26,NULL, '27', -4004) + +sql insert into tb9 values ("2021-05-09 10:12:26",28, 29, '30', -1005) +sql insert into tba values ("2021-05-10 10:12:27",31, 32, NULL, -2005) +sql insert into tbb values ("2021-05-10 10:12:28",33,NULL, '35', -3005) +sql insert into tbc values ("2021-05-11 10:12:29",36, 37, NULL, -4005) +sql insert into tbd values ("2021-05-11 10:12:29",NULL,NULL,NULL,NULL ) + +run general/parser/last_cache_query.sim + +system sh/exec.sh -n dnode1 -s stop -x SIGINT + +system sh/exec.sh -n dnode1 -s start + +run general/parser/last_cache_query.sim + +system sh/exec.sh -n dnode1 -s stop -x SIGINT + + + diff --git a/tests/script/general/parser/last_cache_query.sim b/tests/script/general/parser/last_cache_query.sim new file mode 100644 index 0000000000..2acd000585 --- /dev/null +++ b/tests/script/general/parser/last_cache_query.sim @@ -0,0 +1,416 @@ + +sleep 100 +sql connect + +$db = testdb + +sql use $db + +print "test tb1" + +sql select last(ts) from tb1 +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-12 10:10:12.000@ then + print $data00 + return -1 +endi + + +sql select last(f1) from tb1 +if $rows != 1 then + return -1 +endi +if $data00 != 6 then + print $data00 + return -1 +endi + +sql select last(*) from tb1 +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-12 10:10:12.000@ then + print $data00 + return -1 +endi +if $data01 != 6 then + return -1 +endi +if $data02 != 5.000000000 then + print $data02 + return -1 +endi +if $data03 != 3 then + return -1 +endi +if $data04 != @70-01-01 07:59:57.000@ then + return -1 +endi + + +sql select last(tb1.*,ts,f4) from tb1 +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-12 10:10:12.000@ then + print $data00 + return -1 +endi +if $data01 != 6 then + return -1 +endi +if $data02 != 5.000000000 then + print $data02 + return -1 +endi +if $data03 != 3 then + return -1 +endi +if $data04 != @70-01-01 07:59:57.000@ then + return -1 +endi +if $data05 != @21-05-12 10:10:12.000@ then + print $data00 + return -1 +endi +if $data06 != @70-01-01 07:59:57.000@ then + return -1 +endi + + + + +print "test tb2" + +sql select last(ts) from tb2 +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-11 10:11:15.000@ then + print $data00 + return -1 +endi + + +sql select last(f1) from tb2 +if $rows != 1 then + return -1 +endi +if $data00 != -6 then + print $data00 + return -1 +endi + +sql select last(*) from tb2 +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-11 10:11:15.000@ then + print $data00 + return -1 +endi +if $data01 != -6 then + return -1 +endi +if $data02 != -7.000000000 then + print $data02 + return -1 +endi +if $data03 != -8 then + return -1 +endi +if $data04 != @70-01-01 07:59:56.999@ then + if $data04 != @70-01-01 07:59:57.-01@ then + return -1 + endi +endi + + +sql select last(tb2.*,ts,f4) from tb2 +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-11 10:11:15.000@ then + print $data00 + return -1 +endi +if $data01 != -6 then + return -1 +endi +if $data02 != -7.000000000 then + print $data02 + return -1 +endi +if $data03 != -8 then + return -1 +endi +if $data04 != @70-01-01 07:59:56.999@ then + if $data04 != @70-01-01 07:59:57.-01@ then + return -1 + endi +endi +if $data05 != @21-05-11 10:11:15.000@ then + print $data00 + return -1 +endi +if $data06 != @70-01-01 07:59:56.999@ then + if $data04 != @70-01-01 07:59:57.-01@ then + return -1 + endi +endi + + + + + + + +print "test tbd" +sql select last(*) from tbd +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-11 10:12:29.000@ then + print $data00 + return -1 +endi +if $data01 != NULL then + return -1 +endi +if $data02 != NULL then + print $data02 + return -1 +endi +if $data03 != NULL then + return -1 +endi +if $data04 != NULL then + return -1 +endi + + + +print "test tbe" +sql select last(*) from tbe +if $rows != 0 then + return -1 +endi + + + + + +print "test stable" +sql select last(ts) from st2 +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-12 10:10:12.000@ then + print $data00 + return -1 +endi + + +sql select last(f1) from st2 +if $rows != 1 then + return -1 +endi +if $data00 != 6 then + print $data00 + return -1 +endi + +sql select last(*) from st2 +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-12 10:10:12.000@ then + print $data00 + return -1 +endi +if $data01 != 6 then + return -1 +endi +if $data02 != 37.000000000 then + print $data02 + return -1 +endi +if $data03 != 27 then + return -1 +endi +if $data04 != @70-01-01 07:59:57.000@ then + return -1 +endi + + +sql select last(st2.*,ts,f4) from st2 +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-12 10:10:12.000@ then + print $data00 + return -1 +endi +if $data01 != 6 then + return -1 +endi +if $data02 != 37.000000000 then + print $data02 + return -1 +endi +if $data03 != 27 then + return -1 +endi +if $data04 != @70-01-01 07:59:57.000@ then + return -1 +endi +if $data05 != @21-05-12 10:10:12.000@ then + print $data00 + return -1 +endi +if $data06 != @70-01-01 07:59:57.000@ then + return -1 +endi + + +sql select last(*) from st2 group by id +if $rows != 5 then + return -1 +endi +if $data00 != @21-05-12 10:10:12.000@ then + return -1 +endi +if $data01 != 6 then + return -1 +endi +if $data02 != 5.000000000 then + print $data02 + return -1 +endi +if $data03 != 21 then + return -1 +endi +if $data04 != @70-01-01 07:59:57.000@ then + return -1 +endi +if $data05 != 1 then + return -1 +endi +if $data10 != @21-05-11 10:12:23.000@ then + return -1 +endi +if $data11 != 22 then + return -1 +endi +if $data12 != 23.000000000 then + print $data02 + return -1 +endi +if $data13 != -8 then + return -1 +endi +if $data14 != @70-01-01 07:59:57.996@ then +if $data14 != @70-01-01 07:59:58.-04@ then + print $data14 + return -1 +endi +endi +if $data15 != 2 then + return -1 +endi +if $data20 != @21-05-10 10:12:24.000@ then + return -1 +endi +if $data21 != 24 then + return -1 +endi +if $data22 != 8.000000000 then + print $data02 + return -1 +endi +if $data23 != 25 then + return -1 +endi +if $data24 != @70-01-01 07:59:56.996@ then +if $data24 != @70-01-01 07:59:57.-04@ then + return -1 +endi +endi +if $data25 != 3 then + return -1 +endi +if $data30 != @21-05-11 10:12:25.000@ then + return -1 +endi +if $data31 != 26 then + return -1 +endi +if $data32 != 17.000000000 then + print $data02 + return -1 +endi +if $data33 != 27 then + return -1 +endi +if $data34 != @70-01-01 07:59:55.996@ then +if $data34 != @70-01-01 07:59:56.-04@ then + return -1 +endi +endi +if $data35 != 4 then + return -1 +endi +if $data40 != @21-05-11 10:12:29.000@ then + return -1 +endi +if $data41 != 36 then + return -1 +endi +if $data42 != 37.000000000 then + print $data02 + return -1 +endi +if $data43 != 35 then + return -1 +endi +if $data44 != @70-01-01 07:59:55.995@ then +if $data44 != @70-01-01 07:59:56.-05@ then + return -1 +endi +endi +if $data45 != 5 then + return -1 +endi + + +print "test tbn" +sql create table tbn (ts timestamp, f1 int, f2 double, f3 binary(10), f4 timestamp) +sql insert into tbn values ("2021-05-09 10:10:10", 1, 2.0, '3', -1000) +sql insert into tbn values ("2021-05-10 10:10:11", 4, 5.0, NULL, -2000) +sql insert into tbn values ("2021-05-12 10:10:12", 6,NULL, NULL, -3000) +sql insert into tbn values ("2021-05-13 10:10:12", NULL,NULL, NULL,NULL) + +sql select last(*) from tbn; +if $rows != 1 then + return -1 +endi +if $data00 != @21-05-13 10:10:12.000@ then + print $data00 + return -1 +endi +if $data01 != 6 then + return -1 +endi +if $data02 != 5.000000000 then + print $data02 + return -1 +endi +if $data03 != 3 then + return -1 +endi +if $data04 != @70-01-01 07:59:57.000@ then + return -1 +endi + diff --git a/tests/script/general/parser/testSuite.sim b/tests/script/general/parser/testSuite.sim index 1294b093c2..6a3b71e773 100644 --- a/tests/script/general/parser/testSuite.sim +++ b/tests/script/general/parser/testSuite.sim @@ -59,4 +59,6 @@ run general/parser/having.sim run general/parser/having_child.sim run general/parser/slimit_alter_tags.sim run general/parser/binary_escapeCharacter.sim +run general/parser/between_and.sim +run general/parser/last_cache.sim From 210c0ae3f85b182b18237ae53541c95a7fe085fb Mon Sep 17 00:00:00 2001 From: lichuang Date: Fri, 21 May 2021 15:08:17 +0800 Subject: [PATCH 29/70] [TD-4034]fix cache last valid range --- documentation20/cn/11.administrator/docs.md | 2 +- src/inc/taosdef.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/documentation20/cn/11.administrator/docs.md b/documentation20/cn/11.administrator/docs.md index 26cfa91beb..ee2f34ff11 100644 --- a/documentation20/cn/11.administrator/docs.md +++ b/documentation20/cn/11.administrator/docs.md @@ -129,7 +129,7 @@ taosd -C - blocks:每个VNODE(TSDB)中有多少cache大小的内存块。因此一个VNODE的用的内存大小粗略为(cache * blocks)。单位为块,默认值:4。(可通过 alter database 修改) - replica:副本个数,取值范围:1-3。单位为个,默认值:1。(可通过 alter database 修改) - precision:时间戳精度标识,ms表示毫秒,us表示微秒。默认值:ms。 -- cacheLast:是否在内存中缓存子表的最近数据,0:关闭;1:缓存子表最近一行数据;2:缓存子表每一列的最近的非NULL值,默认值:0。(可通过 alter database 修改)(从 2.0.11 版本开始支持此参数) +- cacheLast:是否在内存中缓存子表的最近数据,0:关闭;1:缓存子表最近一行数据;2:缓存子表每一列的最近的非NULL值,3:同时打开缓存最近行和列功能,默认值:0。(可通过 alter database 修改)(从 2.0.11 版本开始支持此参数) 对于一个应用场景,可能有多种数据特征的数据并存,最佳的设计是将具有相同数据特征的表放在一个库里,这样一个应用有多个库,而每个库可以配置不同的存储参数,从而保证系统有最优的性能。TDengine允许应用在创建库时指定上述存储参数,如果指定,该参数就将覆盖对应的系统配置参数。举例,有下述SQL: diff --git a/src/inc/taosdef.h b/src/inc/taosdef.h index 2882faf7be..f888d037b3 100644 --- a/src/inc/taosdef.h +++ b/src/inc/taosdef.h @@ -298,7 +298,7 @@ do { \ #define TSDB_DEFAULT_DB_UPDATE_OPTION 0 #define TSDB_MIN_DB_CACHE_LAST_ROW 0 -#define TSDB_MAX_DB_CACHE_LAST_ROW 2 +#define TSDB_MAX_DB_CACHE_LAST_ROW 3 #define TSDB_DEFAULT_CACHE_LAST_ROW 0 #define TSDB_MIN_FSYNC_PERIOD 0 From 23313ecf677314f3d9fd373bd5808e6d32fc0c25 Mon Sep 17 00:00:00 2001 From: dapan1121 <89396746@qq.com> Date: Fri, 21 May 2021 15:14:36 +0800 Subject: [PATCH 30/70] fix bug --- src/tsdb/src/tsdbRead.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tsdb/src/tsdbRead.c b/src/tsdb/src/tsdbRead.c index c78739d7ce..f40c496bf4 100644 --- a/src/tsdb/src/tsdbRead.c +++ b/src/tsdb/src/tsdbRead.c @@ -2571,7 +2571,7 @@ static bool loadCachedLast(STsdbQueryHandle* pQueryHandle) { continue; } - SColumnInfoData* pColInfo = taosArrayGet(pQueryHandle->pColumns, n); + pColInfo = taosArrayGet(pQueryHandle->pColumns, n); pData = (char*)pColInfo->pData + numOfRows * pColInfo->info.bytes;; if (pColInfo->info.colId == PRIMARYKEY_TIMESTAMP_COL_INDEX) { @@ -2596,7 +2596,7 @@ static bool loadCachedLast(STsdbQueryHandle* pQueryHandle) { // leave the real ts column as the last row, because last function only (not stable) use the last row as res if (priKey != TSKEY_INITIAL_VAL) { - SColumnInfoData* pColInfo = taosArrayGet(pQueryHandle->pColumns, priIdx); + pColInfo = taosArrayGet(pQueryHandle->pColumns, priIdx); pData = (char*)pColInfo->pData + numOfRows * pColInfo->info.bytes; *(TSKEY *)pData = priKey; From 9be55c32b127f343457458cc23c4c58a7c7830de Mon Sep 17 00:00:00 2001 From: dapan1121 <89396746@qq.com> Date: Fri, 21 May 2021 15:16:53 +0800 Subject: [PATCH 31/70] fix bug --- src/tsdb/src/tsdbRead.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/tsdb/src/tsdbRead.c b/src/tsdb/src/tsdbRead.c index f40c496bf4..491a4b2db0 100644 --- a/src/tsdb/src/tsdbRead.c +++ b/src/tsdb/src/tsdbRead.c @@ -2493,6 +2493,7 @@ static bool loadCachedLast(STsdbQueryHandle* pQueryHandle) { SQueryFilePos* cur = &pQueryHandle->cur; TSKEY priKey = TSKEY_INITIAL_VAL; int32_t priIdx = -1; + SColumnInfoData* pColInfo = NULL; while (++pQueryHandle->activeIndex < numOfTables) { STableCheckInfo* pCheckInfo = taosArrayGet(pQueryHandle->pTableCheckInfo, pQueryHandle->activeIndex); @@ -2508,7 +2509,7 @@ static bool loadCachedLast(STsdbQueryHandle* pQueryHandle) { int32_t i = 0, j = 0; while(i < tgNumOfCols && j < numOfCols) { - SColumnInfoData* pColInfo = taosArrayGet(pQueryHandle->pColumns, i); + pColInfo = taosArrayGet(pQueryHandle->pColumns, i); if (pTable->lastCols[j].colId < pColInfo->info.colId) { j++; continue; @@ -2606,7 +2607,7 @@ static bool loadCachedLast(STsdbQueryHandle* pQueryHandle) { continue; } - SColumnInfoData* pColInfo = taosArrayGet(pQueryHandle->pColumns, n); + pColInfo = taosArrayGet(pQueryHandle->pColumns, n); pData = (char*)pColInfo->pData + numOfRows * pColInfo->info.bytes;; assert (pColInfo->info.colId != PRIMARYKEY_TIMESTAMP_COL_INDEX); From fbb160572efa96495a91a1a60abe5a11425b4f19 Mon Sep 17 00:00:00 2001 From: lichuang Date: Sat, 22 May 2021 10:09:29 +0800 Subject: [PATCH 32/70] [TD-4034]debug log --- src/tsdb/src/tsdbMain.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tsdb/src/tsdbMain.c b/src/tsdb/src/tsdbMain.c index 1e6f9eac12..880400dd9f 100644 --- a/src/tsdb/src/tsdbMain.c +++ b/src/tsdb/src/tsdbMain.c @@ -735,7 +735,7 @@ static int tsdbRestoreLastColumns(STsdbRepo *pRepo, STable *pTable, SReadH* pRea pTable->maxColumnNum += 1; - tsdbInfo("tsdbRestoreLastColumns restore vgId:%d,table:%s cache column %d, %" PRId64, REPO_ID(pRepo), pTable->name->data, pLastCol->colId, pLastCol->ts); + tsdbDebug("tsdbRestoreLastColumns restore vgId:%d,table:%s cache column %d, %" PRId64, REPO_ID(pRepo), pTable->name->data, pLastCol->colId, pLastCol->ts); break; } } From 6eeb539807eda232ad6300afe1b27c0b1ce5e2a1 Mon Sep 17 00:00:00 2001 From: dapan1121 <89396746@qq.com> Date: Sat, 22 May 2021 15:04:59 +0800 Subject: [PATCH 33/70] fix bug --- src/inc/tsdb.h | 2 ++ src/query/src/qExecutor.c | 2 +- src/tsdb/src/tsdbRead.c | 9 +++++++-- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/inc/tsdb.h b/src/inc/tsdb.h index 468c5ab271..7c8819777d 100644 --- a/src/inc/tsdb.h +++ b/src/inc/tsdb.h @@ -268,6 +268,8 @@ TsdbQueryHandleT tsdbQueryLastRow(STsdbRepo *tsdb, STsdbQueryCond *pCond, STable TsdbQueryHandleT tsdbQueryCacheLast(STsdbRepo *tsdb, STsdbQueryCond *pCond, STableGroupInfo *groupList, uint64_t qId, SMemRef* pMemRef); +bool isTsdbCacheLastRow(TsdbQueryHandleT* pQueryHandle); + /** * get the queried table object list diff --git a/src/query/src/qExecutor.c b/src/query/src/qExecutor.c index c2a4c7febe..1d41bc42b0 100644 --- a/src/query/src/qExecutor.c +++ b/src/query/src/qExecutor.c @@ -4243,7 +4243,7 @@ static SSDataBlock* doTableScan(void* param, bool *newgroup) { } if (++pTableScanInfo->current >= pTableScanInfo->times) { - if (pTableScanInfo->reverseTimes <= 0) { + if (pTableScanInfo->reverseTimes <= 0 || isTsdbCacheLastRow(pTableScanInfo->pQueryHandle)) { return NULL; } else { break; diff --git a/src/tsdb/src/tsdbRead.c b/src/tsdb/src/tsdbRead.c index 491a4b2db0..626602576f 100644 --- a/src/tsdb/src/tsdbRead.c +++ b/src/tsdb/src/tsdbRead.c @@ -547,7 +547,9 @@ TsdbQueryHandleT tsdbQueryCacheLast(STsdbRepo *tsdb, STsdbQueryCond *pCond, STab return NULL; } - pQueryHandle->type = TSDB_QUERY_TYPE_LAST; + if (pQueryHandle->cachelastrow) { + pQueryHandle->type = TSDB_QUERY_TYPE_LAST; + } return pQueryHandle; } @@ -2873,6 +2875,10 @@ int32_t tsdbGetCachedLastRow(STable* pTable, SDataRow* pRes, TSKEY* lastKey) { return TSDB_CODE_SUCCESS; } +bool isTsdbCacheLastRow(TsdbQueryHandleT* pQueryHandle) { + return ((STsdbQueryHandle *)pQueryHandle)->cachelastrow > 0; +} + int32_t checkForCachedLastRow(STsdbQueryHandle* pQueryHandle, STableGroupInfo *groupList) { assert(pQueryHandle != NULL && groupList != NULL); @@ -2921,7 +2927,6 @@ int32_t checkForCachedLast(STsdbQueryHandle* pQueryHandle, STableGroupInfo *grou if (((STable*)pInfo->pTable)->lastCols && ((STable*)pInfo->pTable)->lastColNum > 0){ pQueryHandle->cachelastrow = 2; } - // update the tsdb query time range if (pQueryHandle->cachelastrow) { From 89fd502625adf7b6af1779c9ee341d2116854e69 Mon Sep 17 00:00:00 2001 From: Elias Soong Date: Wed, 26 May 2021 13:51:06 +0800 Subject: [PATCH 34/70] [TD-3948] : column names can be away from table name in insert. --- documentation20/cn/12.taos-sql/docs.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/documentation20/cn/12.taos-sql/docs.md b/documentation20/cn/12.taos-sql/docs.md index bcf80d8fa2..186287515f 100644 --- a/documentation20/cn/12.taos-sql/docs.md +++ b/documentation20/cn/12.taos-sql/docs.md @@ -399,7 +399,12 @@ TDengine 缺省的时间戳是毫秒精度,但通过修改配置参数 enableM INSERT INTO tb1_name (tb1_field1_name, ...) [USING stb1_name TAGS (tag_value1, ...)] VALUES (field1_value1, ...) (field1_value2, ...) ... tb2_name (tb2_field1_name, ...) [USING stb2_name TAGS (tag_value2, ...)] VALUES (field1_value1, ...) (field1_value2, ...) ...; ``` - 以自动建表的方式,同时向表tb1_name和tb2_name中按列分别插入多条记录。 + 以自动建表的方式,同时向表tb1_name和tb2_name中按列分别插入多条记录。 + 从 2.0.20.5 版本开始,子表的列名可以不跟在子表名称后面,而是可以放在 TAGS 和 VALUES 之间,例如像下面这样写: + ```mysql + INSERT INTO tb1_name [USING stb1_name TAGS (tag_value1, ...)] (tb1_field1_name, ...) VALUES (field1_value1, ...) (field1_value2, ...) ...; + ``` + 注意:虽然两种写法都可以,但并不能在一条 SQL 语句中混用,否则会报语法错误。 **历史记录写入**:可使用IMPORT或者INSERT命令,IMPORT的语法,功能与INSERT完全一样。 From ede8a4a6f040fb0710f7022da77ff08f7031bb51 Mon Sep 17 00:00:00 2001 From: Elias Soong Date: Wed, 26 May 2021 15:08:53 +0800 Subject: [PATCH 35/70] [TD-4089] : stopping taosd service may take remarkable time. --- documentation20/cn/02.getting-started/docs.md | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/documentation20/cn/02.getting-started/docs.md b/documentation20/cn/02.getting-started/docs.md index a98159d8c4..6eb58a1433 100644 --- a/documentation20/cn/02.getting-started/docs.md +++ b/documentation20/cn/02.getting-started/docs.md @@ -24,7 +24,7 @@ TDengine的安装非常简单,从下载到安装成功仅仅只要几秒钟。 ## 轻松启动 -安装成功后,用户可使用`systemctl`命令来启动TDengine的服务进程。 +安装成功后,用户可使用 `systemctl` 命令来启动 TDengine 的服务进程。 ```bash $ systemctl start taosd @@ -35,21 +35,22 @@ $ systemctl start taosd $ systemctl status taosd ``` -如果TDengine服务正常工作,那么您可以通过TDengine的命令行程序`taos`来访问并体验TDengine。 +如果 TDengine 服务正常工作,那么您可以通过 TDengine 的命令行程序 `taos` 来访问并体验 TDengine。 **注意:** -- systemctl命令需要 _root_ 权限来运行,如果您非 _root_ 用户,请在命令前添加 sudo -- 为更好的获得产品反馈,改善产品,TDengine会采集基本的使用信息,但您可以修改系统配置文件taos.cfg里的配置参数telemetryReporting, 将其设为0,就可将其关闭。 -- TDengine采用FQDN(一般就是hostname)作为节点的ID,为保证正常运行,需要给运行taosd的服务器配置好hostname,在客户端应用运行的机器配置好DNS服务或hosts文件,保证FQDN能够解析。 +- systemctl 命令需要 _root_ 权限来运行,如果您非 _root_ 用户,请在命令前添加 sudo 。 +- 为更好的获得产品反馈,改善产品,TDengine 会采集基本的使用信息,但您可以修改系统配置文件 taos.cfg 里的配置参数 telemetryReporting, 将其设为 0,就可将其关闭。 +- TDengine 采用 FQDN (一般就是 hostname )作为节点的 ID,为保证正常运行,需要给运行 taosd 的服务器配置好 hostname,在客户端应用运行的机器配置好 DNS 服务或 hosts 文件,保证 FQDN 能够解析。 +- `systemctl stop taosd` 指令在执行后并不会马上停止 TDengine 服务,而是会等待系统中必要的落盘工作正常完成。在数据量很大的情况下,这可能会消耗较长时间。 -* TDengine 支持在使用[`systemd`](https://en.wikipedia.org/wiki/Systemd)做进程服务管理的linux系统上安装,用`which systemctl`命令来检测系统中是否存在`systemd`包: +* TDengine 支持在使用 [`systemd`](https://en.wikipedia.org/wiki/Systemd) 做进程服务管理的 linux 系统上安装,用 `which systemctl` 命令来检测系统中是否存在 `systemd` 包: ```bash $ which systemctl ``` - 如果系统中不支持systemd,也可以用手动运行 /usr/local/taos/bin/taosd 方式启动 TDengine 服务。 + 如果系统中不支持 systemd,也可以用手动运行 /usr/local/taos/bin/taosd 方式启动 TDengine 服务。 ## TDengine命令行程序 From 0a38b29c3d12ee12942432a2bcf8fc215a958966 Mon Sep 17 00:00:00 2001 From: Elias Soong Date: Wed, 26 May 2021 16:06:38 +0800 Subject: [PATCH 36/70] [TD-3963] : allow alter some database parameters without reboot server. --- documentation20/cn/12.taos-sql/docs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation20/cn/12.taos-sql/docs.md b/documentation20/cn/12.taos-sql/docs.md index 186287515f..b130e0544c 100644 --- a/documentation20/cn/12.taos-sql/docs.md +++ b/documentation20/cn/12.taos-sql/docs.md @@ -126,7 +126,7 @@ TDengine 缺省的时间戳是毫秒精度,但通过修改配置参数 enableM ```mysql ALTER DATABASE db_name CACHELAST 0; ``` - CACHELAST 参数控制是否在内存中缓存数据子表的 last_row。缺省值为 0,取值范围 [0, 1]。其中 0 表示不启用、1 表示启用。(从 2.0.11 版本开始支持,修改后需要重启服务器生效。) + CACHELAST 参数控制是否在内存中缓存数据子表的 last_row。缺省值为 0,取值范围 [0, 1]。其中 0 表示不启用、1 表示启用。(从 2.0.11.0 版本开始支持。从 2.1.1.0 版本开始,修改此参数后无需重启服务器即可生效。) **Tips**: 以上所有参数修改后都可以用show databases来确认是否修改成功。 From 1062357eeee0cb3eb04064c20c98a3f356f51ad0 Mon Sep 17 00:00:00 2001 From: lichuang Date: Wed, 26 May 2021 17:36:51 +0800 Subject: [PATCH 37/70] [TD-4034]when cacheLast option changed,restore or free cache last data --- src/tsdb/inc/tsdbMeta.h | 6 +- src/tsdb/inc/tsdbint.h | 4 + src/tsdb/src/tsdbCommitQueue.c | 22 +++-- src/tsdb/src/tsdbMain.c | 172 ++++++++++++++++++++++++++++++++- src/tsdb/src/tsdbMeta.c | 23 ++--- 5 files changed, 203 insertions(+), 24 deletions(-) diff --git a/src/tsdb/inc/tsdbMeta.h b/src/tsdb/inc/tsdbMeta.h index 45868c002d..14d5a41768 100644 --- a/src/tsdb/inc/tsdbMeta.h +++ b/src/tsdb/inc/tsdbMeta.h @@ -38,8 +38,9 @@ typedef struct STable { SRWLatch latch; // TODO: implementa latch functions SDataCol *lastCols; - int16_t lastColNum; - int16_t maxColumnNum; + int16_t maxColNum; + int16_t restoreColumnNum; + bool hasRestoreLastColumn; int lastColSVersion; T_REF_DECLARE() } STable; @@ -90,6 +91,7 @@ int tsdbInitColIdCacheWithSchema(STable* pTable, STSchema* pSchema); int16_t tsdbGetLastColumnsIndexByColId(STable* pTable, int16_t colId); int tsdbUpdateLastColSchema(STable *pTable, STSchema *pNewSchema); STSchema* tsdbGetTableLatestSchema(STable *pTable); +void tsdbFreeLastColumns(STable* pTable); static FORCE_INLINE int tsdbCompareSchemaVersion(const void *key1, const void *key2) { if (*(int16_t *)key1 < schemaVersion(*(STSchema **)key2)) { diff --git a/src/tsdb/inc/tsdbint.h b/src/tsdb/inc/tsdbint.h index 4d62164df9..e74c3238e2 100644 --- a/src/tsdb/inc/tsdbint.h +++ b/src/tsdb/inc/tsdbint.h @@ -75,6 +75,9 @@ struct STsdbRepo { STsdbCfg save_config; // save apply config bool config_changed; // config changed flag pthread_mutex_t save_mutex; // protect save config + + uint8_t hasCachedLastRow; + uint8_t hasCachedLastColumn; STsdbAppH appH; STsdbStat stat; @@ -100,6 +103,7 @@ int tsdbUnlockRepo(STsdbRepo* pRepo); STsdbMeta* tsdbGetMeta(STsdbRepo* pRepo); int tsdbCheckCommit(STsdbRepo* pRepo); int tsdbRestoreInfo(STsdbRepo* pRepo); +int tsdbCacheLastData(STsdbRepo *pRepo, STsdbCfg* oldCfg); void tsdbGetRootDir(int repoid, char dirName[]); void tsdbGetDataDir(int repoid, char dirName[]); diff --git a/src/tsdb/src/tsdbCommitQueue.c b/src/tsdb/src/tsdbCommitQueue.c index e753a3211e..abea79bc4f 100644 --- a/src/tsdb/src/tsdbCommitQueue.c +++ b/src/tsdb/src/tsdbCommitQueue.c @@ -113,11 +113,15 @@ int tsdbScheduleCommit(STsdbRepo *pRepo) { } static void tsdbApplyRepoConfig(STsdbRepo *pRepo) { + pthread_mutex_lock(&pRepo->save_mutex); + pRepo->config_changed = false; STsdbCfg * pSaveCfg = &pRepo->save_config; - + STsdbCfg oldCfg; int32_t oldTotalBlocks = pRepo->config.totalBlocks; + memcpy(&oldCfg, &(pRepo->config), sizeof(STsdbCfg)); + pRepo->config.compression = pRepo->save_config.compression; pRepo->config.keep = pRepo->save_config.keep; pRepo->config.keep1 = pRepo->save_config.keep1; @@ -125,10 +129,12 @@ static void tsdbApplyRepoConfig(STsdbRepo *pRepo) { pRepo->config.cacheLastRow = pRepo->save_config.cacheLastRow; pRepo->config.totalBlocks = pRepo->save_config.totalBlocks; - tsdbInfo("vgId:%d apply new config: compression(%d), keep(%d,%d,%d), totalBlocks(%d), cacheLastRow(%d),totalBlocks(%d)", + pthread_mutex_unlock(&pRepo->save_mutex); + + tsdbInfo("vgId:%d apply new config: compression(%d), keep(%d,%d,%d), totalBlocks(%d), cacheLastRow(%d->%d),totalBlocks(%d->%d)", REPO_ID(pRepo), pSaveCfg->compression, pSaveCfg->keep,pSaveCfg->keep1, pSaveCfg->keep2, - pSaveCfg->totalBlocks, pSaveCfg->cacheLastRow, pSaveCfg->totalBlocks); + pSaveCfg->totalBlocks, oldCfg.cacheLastRow, pSaveCfg->cacheLastRow, oldTotalBlocks, pSaveCfg->totalBlocks); int err = tsdbExpendPool(pRepo, oldTotalBlocks); if (!TAOS_SUCCEEDED(err)) { @@ -136,6 +142,12 @@ static void tsdbApplyRepoConfig(STsdbRepo *pRepo) { REPO_ID(pRepo), oldTotalBlocks, pSaveCfg->totalBlocks, tstrerror(err)); } + if (oldCfg.cacheLastRow != pRepo->config.cacheLastRow) { + if (tsdbLockRepo(pRepo) < 0) return; + tsdbCacheLastData(pRepo, &oldCfg); + tsdbUnlockRepo(pRepo); + } + } static void *tsdbLoopCommit(void *arg) { @@ -165,10 +177,8 @@ static void *tsdbLoopCommit(void *arg) { pRepo = ((SCommitReq *)pNode->data)->pRepo; // check if need to apply new config - if (pRepo->config_changed) { - pthread_mutex_lock(&pRepo->save_mutex); + if (pRepo->config_changed) { tsdbApplyRepoConfig(pRepo); - pthread_mutex_unlock(&pRepo->save_mutex); } tsdbCommitData(pRepo); diff --git a/src/tsdb/src/tsdbMain.c b/src/tsdb/src/tsdbMain.c index 880400dd9f..a8bbd0d69e 100644 --- a/src/tsdb/src/tsdbMain.c +++ b/src/tsdb/src/tsdbMain.c @@ -548,6 +548,8 @@ static STsdbRepo *tsdbNewRepo(STsdbCfg *pCfg, STsdbAppH *pAppH) { return NULL; } pRepo->config_changed = false; + atomic_store_8(&pRepo->hasCachedLastRow, 0); + atomic_store_8(&pRepo->hasCachedLastColumn, 0); code = tsem_init(&(pRepo->readyToCommit), 0, 1); if (code != 0) { @@ -636,7 +638,7 @@ static int tsdbRestoreLastColumns(STsdbRepo *pRepo, STable *pTable, SReadH* pRea int err = 0; numColumns = schemaNCols(pSchema); - if (numColumns <= pTable->maxColumnNum) { + if (numColumns <= pTable->restoreColumnNum) { return 0; } if (pTable->lastColSVersion != schemaVersion(pSchema)) { @@ -675,7 +677,7 @@ static int tsdbRestoreLastColumns(STsdbRepo *pRepo, STable *pTable, SReadH* pRea SBlockIdx *pIdx = pReadh->pBlkIdx; blockIdx = (int32_t)(pIdx->numOfBlocks - 1); - while (numColumns > pTable->maxColumnNum && blockIdx >= 0) { + while (numColumns > pTable->restoreColumnNum && blockIdx >= 0) { bool loadStatisData = false; pBlock = pReadh->pBlkInfo->blocks + blockIdx; blockIdx -= 1; @@ -693,7 +695,7 @@ static int tsdbRestoreLastColumns(STsdbRepo *pRepo, STable *pTable, SReadH* pRea loadStatisData = true; } - for (int16_t i = 0; i < numColumns && numColumns > pTable->maxColumnNum; ++i) { + for (int16_t i = 0; i < numColumns && numColumns > pTable->restoreColumnNum; ++i) { STColumn *pCol = schemaColAt(pSchema, i); // ignore loaded columns if (pTable->lastCols[i].bytes != 0) { @@ -733,7 +735,7 @@ static int tsdbRestoreLastColumns(STsdbRepo *pRepo, STable *pTable, SReadH* pRea tdAppendColVal(row, tdGetColDataOfRow(pDataCol, rowId), pCol->type, pCol->bytes, pCol->offset); pLastCol->ts = dataRowKey(row); - pTable->maxColumnNum += 1; + pTable->restoreColumnNum += 1; tsdbDebug("tsdbRestoreLastColumns restore vgId:%d,table:%s cache column %d, %" PRId64, REPO_ID(pRepo), pTable->name->data, pLastCol->colId, pLastCol->ts); break; @@ -766,7 +768,7 @@ int tsdbRestoreInfo(STsdbRepo *pRepo) { for (int i = 1; i < pMeta->maxTables; i++) { STable *pTable = pMeta->tables[i]; if (pTable == NULL) continue; - pTable->maxColumnNum = 0; + pTable->restoreColumnNum = 0; } } @@ -841,5 +843,165 @@ int tsdbRestoreInfo(STsdbRepo *pRepo) { } tsdbDestroyReadH(&readh); + if (CACHE_LAST_ROW(pCfg)) { + atomic_store_8(&pRepo->hasCachedLastRow, 1); + } + if (CACHE_LAST_NULL_COLUMN(pCfg)) { + atomic_store_8(&pRepo->hasCachedLastColumn, 1); + } + return 0; } + +int tsdbCacheLastData(STsdbRepo *pRepo, STsdbCfg* oldCfg) { + bool cacheLastRow = false, cacheLastCol = false; + SFSIter fsiter; + SReadH readh; + SDFileSet *pSet; + STsdbMeta *pMeta = pRepo->tsdbMeta; + //STsdbCfg * pCfg = REPO_CFG(pRepo); + SBlock * pBlock; + int tableNum = 0; + int maxTableIdx = 0; + int cacheLastRowTableNum = 0; + int cacheLastColTableNum = 0; + + bool need_free_last_row = CACHE_LAST_ROW(oldCfg) && !CACHE_LAST_ROW(&(pRepo->config)); + bool need_free_last_col = CACHE_LAST_NULL_COLUMN(oldCfg) && !CACHE_LAST_NULL_COLUMN(&(pRepo->config)); + + if (CACHE_LAST_ROW(&(pRepo->config)) || CACHE_LAST_NULL_COLUMN(&(pRepo->config))) { + tsdbInfo("tsdbCacheLastData cache last data since cacheLast option changed"); + cacheLastRow = !CACHE_LAST_ROW(oldCfg) && CACHE_LAST_ROW(&(pRepo->config)); + cacheLastCol = !CACHE_LAST_NULL_COLUMN(oldCfg) && CACHE_LAST_NULL_COLUMN(&(pRepo->config)); + } + + // calc max table idx and table num + for (int i = 1; i < pMeta->maxTables; i++) { + STable *pTable = pMeta->tables[i]; + if (pTable == NULL) continue; + tableNum += 1; + maxTableIdx = i; + if (cacheLastCol) { + pTable->restoreColumnNum = 0; + } + } + + // if close last option,need to free data + if (need_free_last_row || need_free_last_col) { + if (need_free_last_row) { + atomic_store_8(&pRepo->hasCachedLastRow, 0); + } + if (need_free_last_col) { + atomic_store_8(&pRepo->hasCachedLastColumn, 0); + } + tsdbInfo("free cache last data since cacheLast option changed"); + for (int i = 1; i < maxTableIdx; i++) { + STable *pTable = pMeta->tables[i]; + if (pTable == NULL) continue; + if (need_free_last_row) { + taosTZfree(pTable->lastRow); + pTable->lastRow = NULL; + pTable->lastKey = TSKEY_INITIAL_VAL; + } + if (need_free_last_col) { + tsdbFreeLastColumns(pTable); + } + } + } + + if (!cacheLastRow && !cacheLastCol) { + return 0; + } + + cacheLastRowTableNum = cacheLastRow ? tableNum : 0; + cacheLastColTableNum = cacheLastCol ? tableNum : 0; + + if (tsdbInitReadH(&readh, pRepo) < 0) { + return -1; + } + + tsdbFSIterInit(&fsiter, REPO_FS(pRepo), TSDB_FS_ITER_BACKWARD); + + while ((pSet = tsdbFSIterNext(&fsiter)) != NULL && (cacheLastRowTableNum > 0 || cacheLastColTableNum > 0)) { + if (tsdbSetAndOpenReadFSet(&readh, pSet) < 0) { + tsdbDestroyReadH(&readh); + return -1; + } + + if (tsdbLoadBlockIdx(&readh) < 0) { + tsdbDestroyReadH(&readh); + return -1; + } + + for (int i = 1; i <= maxTableIdx; i++) { + STable *pTable = pMeta->tables[i]; + if (pTable == NULL) continue; + + //tsdbInfo("tsdbRestoreInfo restore vgId:%d,table:%s", REPO_ID(pRepo), pTable->name->data); + + if (tsdbSetReadTable(&readh, pTable) < 0) { + tsdbDestroyReadH(&readh); + return -1; + } + + SBlockIdx *pIdx = readh.pBlkIdx; + + if (pIdx && cacheLastRowTableNum > 0 && pTable->lastRow == NULL) { + pTable->lastKey = pIdx->maxKey; + + if (tsdbLoadBlockInfo(&readh, NULL) < 0) { + tsdbDestroyReadH(&readh); + return -1; + } + + pBlock = readh.pBlkInfo->blocks + pIdx->numOfBlocks - 1; + + if (tsdbLoadBlockData(&readh, pBlock, NULL) < 0) { + tsdbDestroyReadH(&readh); + return -1; + } + + // Get the data in row + ASSERT(pTable->lastRow == NULL); + STSchema *pSchema = tsdbGetTableSchema(pTable); + pTable->lastRow = taosTMalloc(dataRowMaxBytesFromSchema(pSchema)); + if (pTable->lastRow == NULL) { + terrno = TSDB_CODE_TDB_OUT_OF_MEMORY; + tsdbDestroyReadH(&readh); + return -1; + } + + tdInitDataRow(pTable->lastRow, pSchema); + for (int icol = 0; icol < schemaNCols(pSchema); icol++) { + STColumn *pCol = schemaColAt(pSchema, icol); + SDataCol *pDataCol = readh.pDCols[0]->cols + icol; + tdAppendColVal(pTable->lastRow, tdGetColDataOfRow(pDataCol, pBlock->numOfRows - 1), pCol->type, pCol->bytes, + pCol->offset); + } + cacheLastRowTableNum -= 1; + } + + // restore NULL columns + if (pIdx && cacheLastColTableNum > 0 && !pTable->hasRestoreLastColumn) { + if (tsdbRestoreLastColumns(pRepo, pTable, &readh) != 0) { + tsdbDestroyReadH(&readh); + return -1; + } + if (pTable->hasRestoreLastColumn) { + cacheLastColTableNum -= 1; + } + } + } + } + + tsdbDestroyReadH(&readh); + + if (cacheLastRow) { + atomic_store_8(&pRepo->hasCachedLastRow, 1); + } + if (cacheLastCol) { + atomic_store_8(&pRepo->hasCachedLastColumn, 1); + } + + return 0; +} \ No newline at end of file diff --git a/src/tsdb/src/tsdbMeta.c b/src/tsdb/src/tsdbMeta.c index 5717d52eea..324a7c79c5 100644 --- a/src/tsdb/src/tsdbMeta.c +++ b/src/tsdb/src/tsdbMeta.c @@ -44,7 +44,6 @@ static int tsdbRemoveTableFromStore(STsdbRepo *pRepo, STable *pTable); static int tsdbRmTableFromMeta(STsdbRepo *pRepo, STable *pTable); static int tsdbAdjustMetaTables(STsdbRepo *pRepo, int tid); static int tsdbCheckTableTagVal(SKVRow *pKVRow, STSchema *pSchema); -static void tsdbFreeLastColumns(STable* pTable); // ------------------ OUTER FUNCTIONS ------------------ int tsdbCreateTable(STsdbRepo *repo, STableCfg *pCfg) { @@ -590,12 +589,12 @@ void tsdbUnRefTable(STable *pTable) { } } -static void tsdbFreeLastColumns(STable* pTable) { +void tsdbFreeLastColumns(STable* pTable) { if (pTable->lastCols == NULL) { return; } - for (int i = 0; i < pTable->lastColNum; ++i) { + for (int i = 0; i < pTable->maxColNum; ++i) { if (pTable->lastCols[i].bytes == 0) { continue; } @@ -605,14 +604,16 @@ static void tsdbFreeLastColumns(STable* pTable) { } tfree(pTable->lastCols); pTable->lastCols = NULL; - pTable->lastColNum = 0; + pTable->maxColNum = 0; + pTable->lastColSVersion = -1; + pTable->restoreColumnNum = 0; } int16_t tsdbGetLastColumnsIndexByColId(STable* pTable, int16_t colId) { if (pTable->lastCols == NULL) { return -1; } - for (int16_t i = 0; i < pTable->lastColNum; ++i) { + for (int16_t i = 0; i < pTable->maxColNum; ++i) { if (pTable->lastCols[i].colId == colId) { return i; } @@ -640,8 +641,8 @@ int tsdbInitColIdCacheWithSchema(STable* pTable, STSchema* pSchema) { } pTable->lastColSVersion = schemaVersion(pSchema); - pTable->lastColNum = numOfColumn; - pTable->maxColumnNum = 0; + pTable->maxColNum = numOfColumn; + pTable->restoreColumnNum = 0; return 0; } @@ -682,11 +683,11 @@ int tsdbUpdateLastColSchema(STable *pTable, STSchema *pNewSchema) { } SDataCol *oldLastCols = pTable->lastCols; - int16_t oldLastColNum = pTable->lastColNum; + int16_t oldLastColNum = pTable->maxColNum; pTable->lastColSVersion = schemaVersion(pNewSchema); pTable->lastCols = lastCols; - pTable->lastColNum = numOfCols; + pTable->maxColNum = numOfCols; if (oldLastCols == NULL) { TSDB_WUNLOCK_TABLE(pTable); @@ -797,8 +798,8 @@ static STable *tsdbNewTable() { pTable->lastKey = TSKEY_INITIAL_VAL; pTable->lastCols = NULL; - pTable->maxColumnNum = 0; - pTable->lastColNum = 0; + pTable->restoreColumnNum = 0; + pTable->maxColNum = 0; pTable->lastColSVersion = -1; return pTable; } From da4b78f1bad71b606461c46066a759249ac50d28 Mon Sep 17 00:00:00 2001 From: lichuang Date: Wed, 26 May 2021 18:27:04 +0800 Subject: [PATCH 38/70] [TD-4034]when config changed,apply a commit msg then config will be applied --- src/tsdb/src/tsdbCommit.c | 3 +++ src/tsdb/src/tsdbMain.c | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/src/tsdb/src/tsdbCommit.c b/src/tsdb/src/tsdbCommit.c index 24f1c11628..c43b35492d 100644 --- a/src/tsdb/src/tsdbCommit.c +++ b/src/tsdb/src/tsdbCommit.c @@ -90,6 +90,9 @@ static int tsdbApplyRtn(STsdbRepo *pRepo); static int tsdbApplyRtnOnFSet(STsdbRepo *pRepo, SDFileSet *pSet, SRtn *pRtn); void *tsdbCommitData(STsdbRepo *pRepo) { + if (pRepo->imem == NULL) { + return NULL; + } tsdbStartCommit(pRepo); // Commit to update meta file diff --git a/src/tsdb/src/tsdbMain.c b/src/tsdb/src/tsdbMain.c index a8bbd0d69e..d4bc712275 100644 --- a/src/tsdb/src/tsdbMain.c +++ b/src/tsdb/src/tsdbMain.c @@ -268,6 +268,12 @@ int32_t tsdbConfigRepo(STsdbRepo *repo, STsdbCfg *pCfg) { repo->config_changed = true; pthread_mutex_unlock(&repo->save_mutex); + + // schedule a commit msg then the new config will be applyed immediatly + if (tsdbLockRepo(repo) < 0) return -1; + tsdbScheduleCommit(repo); + if (tsdbUnlockRepo(repo) < 0) return -1; + return 0; #if 0 STsdbRepo *pRepo = (STsdbRepo *)repo; From 6213438f2e9056d6e234e711b02c7a724f9451dd Mon Sep 17 00:00:00 2001 From: lichuang Date: Wed, 26 May 2021 18:27:22 +0800 Subject: [PATCH 39/70] [TD-4034]when config changed,apply a commit msg then config will be applied --- src/tsdb/src/tsdbMain.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tsdb/src/tsdbMain.c b/src/tsdb/src/tsdbMain.c index d4bc712275..cc2fca420c 100644 --- a/src/tsdb/src/tsdbMain.c +++ b/src/tsdb/src/tsdbMain.c @@ -269,7 +269,7 @@ int32_t tsdbConfigRepo(STsdbRepo *repo, STsdbCfg *pCfg) { pthread_mutex_unlock(&repo->save_mutex); - // schedule a commit msg then the new config will be applyed immediatly + // schedule a commit msg then the new config will be applied immediatly if (tsdbLockRepo(repo) < 0) return -1; tsdbScheduleCommit(repo); if (tsdbUnlockRepo(repo) < 0) return -1; From ca4e75b69a6926fe5cc5c741d3f0da70bcdaa776 Mon Sep 17 00:00:00 2001 From: dapan1121 <89396746@qq.com> Date: Wed, 26 May 2021 18:30:31 +0800 Subject: [PATCH 40/70] fix bug --- src/tsdb/src/tsdbRead.c | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/src/tsdb/src/tsdbRead.c b/src/tsdb/src/tsdbRead.c index 626602576f..50acda0d95 100644 --- a/src/tsdb/src/tsdbRead.c +++ b/src/tsdb/src/tsdbRead.c @@ -138,7 +138,7 @@ typedef struct STableGroupSupporter { static STimeWindow updateLastrowForEachGroup(STableGroupInfo *groupList); static int32_t checkForCachedLastRow(STsdbQueryHandle* pQueryHandle, STableGroupInfo *groupList); -static int32_t checkForCachedLast(STsdbQueryHandle* pQueryHandle, STableGroupInfo *groupList); +static int32_t checkForCachedLast(STsdbQueryHandle* pQueryHandle); static int32_t tsdbGetCachedLastRow(STable* pTable, SDataRow* pRes, TSKEY* lastKey); static void changeQueryHandleForInterpQuery(TsdbQueryHandleT pHandle); @@ -541,7 +541,7 @@ TsdbQueryHandleT tsdbQueryLastRow(STsdbRepo *tsdb, STsdbQueryCond *pCond, STable TsdbQueryHandleT tsdbQueryCacheLast(STsdbRepo *tsdb, STsdbQueryCond *pCond, STableGroupInfo *groupList, uint64_t qId, SMemRef* pMemRef) { STsdbQueryHandle *pQueryHandle = (STsdbQueryHandle*) tsdbQueryTables(tsdb, pCond, groupList, qId, pMemRef); - int32_t code = checkForCachedLast(pQueryHandle, groupList); + int32_t code = checkForCachedLast(pQueryHandle); if (code != TSDB_CODE_SUCCESS) { // set the numOfTables to be 0 terrno = code; return NULL; @@ -2502,9 +2502,9 @@ static bool loadCachedLast(STsdbQueryHandle* pQueryHandle) { STable* pTable = pCheckInfo->pTableObj; char* pData = NULL; - int32_t numOfCols = pTable->lastColNum; + int32_t numOfCols = pTable->maxColNum; - if (pTable->lastCols == NULL || pTable->lastColNum <= 0) { + if (pTable->lastCols == NULL || pTable->maxColNum <= 0) { tsdbWarn("no last cached for table, uid:%" PRIu64 ",tid:%d", pTable->tableId.uid, pTable->tableId.tid); continue; } @@ -2912,19 +2912,12 @@ int32_t checkForCachedLastRow(STsdbQueryHandle* pQueryHandle, STableGroupInfo *g return code; } -int32_t checkForCachedLast(STsdbQueryHandle* pQueryHandle, STableGroupInfo *groupList) { - assert(pQueryHandle != NULL && groupList != NULL); - - SDataRow pRow = NULL; - - SArray* group = taosArrayGetP(groupList->pGroupList, 0); - assert(group != NULL); - - STableKeyInfo* pInfo = (STableKeyInfo*)taosArrayGet(group, 0); +int32_t checkForCachedLast(STsdbQueryHandle* pQueryHandle) { + assert(pQueryHandle != NULL); int32_t code = 0; - if (((STable*)pInfo->pTable)->lastCols && ((STable*)pInfo->pTable)->lastColNum > 0){ + if (pQueryHandle->pTsdb && atomic_load_8(&pQueryHandle->pTsdb->hasCachedLastColumn)){ pQueryHandle->cachelastrow = 2; } @@ -2935,7 +2928,6 @@ int32_t checkForCachedLast(STsdbQueryHandle* pQueryHandle, STableGroupInfo *grou pQueryHandle->activeIndex = -1; // start from -1 } - tfree(pRow); return code; } From d66b6e2d850431eb5b98a579952f964b0309e0fe Mon Sep 17 00:00:00 2001 From: lichuang Date: Wed, 26 May 2021 19:35:47 +0800 Subject: [PATCH 41/70] [TD-4034]refactor code --- src/common/src/ttypes.c | 61 -------------------- src/inc/tsdb.h | 2 +- src/inc/ttype.h | 3 - src/tsdb/inc/tsdbMeta.h | 3 - src/tsdb/src/tsdbMain.c | 109 +++++++++++++++--------------------- src/tsdb/src/tsdbMemTable.c | 6 +- 6 files changed, 49 insertions(+), 135 deletions(-) diff --git a/src/common/src/ttypes.c b/src/common/src/ttypes.c index 6587a27760..6fa27a029b 100644 --- a/src/common/src/ttypes.c +++ b/src/common/src/ttypes.c @@ -417,18 +417,6 @@ void setVardataNull(char* val, int32_t type) { } } -bool isVardataNull(char* val, int32_t type) { - if (type == TSDB_DATA_TYPE_BINARY) { - return *(uint8_t*) varDataVal(val) == TSDB_DATA_BINARY_NULL; - } else if (type == TSDB_DATA_TYPE_NCHAR) { - return *(uint32_t*) varDataVal(val) == TSDB_DATA_NCHAR_NULL; - } else { - assert(0); - } - - return false; -} - void setNull(char *val, int32_t type, int32_t bytes) { setNullN(val, type, bytes, 1); } void setNullN(char *val, int32_t type, int32_t bytes, int32_t numOfElems) { @@ -504,55 +492,6 @@ void setNullN(char *val, int32_t type, int32_t bytes, int32_t numOfElems) { } } -bool isNullN(char *val, int32_t type) { - switch (type) { - case TSDB_DATA_TYPE_BOOL: - return *(uint8_t *)(val) == TSDB_DATA_BOOL_NULL; - break; - case TSDB_DATA_TYPE_TINYINT: - return *(uint8_t *)(val) == TSDB_DATA_TINYINT_NULL; - break; - case TSDB_DATA_TYPE_SMALLINT: - return *(uint16_t *)(val) == TSDB_DATA_SMALLINT_NULL; - break; - case TSDB_DATA_TYPE_INT: - return *(uint32_t *)(val) == TSDB_DATA_INT_NULL; - break; - case TSDB_DATA_TYPE_BIGINT: - case TSDB_DATA_TYPE_TIMESTAMP: - return *(uint64_t *)(val) == TSDB_DATA_BIGINT_NULL; - break; - case TSDB_DATA_TYPE_UTINYINT: - return *(uint8_t *)(val) == TSDB_DATA_UTINYINT_NULL; - break; - case TSDB_DATA_TYPE_USMALLINT: - return *(uint16_t *)(val) == TSDB_DATA_USMALLINT_NULL; - break; - case TSDB_DATA_TYPE_UINT: - return *(uint32_t *)(val) == TSDB_DATA_UINT_NULL; - break; - case TSDB_DATA_TYPE_UBIGINT: - return *(uint64_t *)(val) == TSDB_DATA_UBIGINT_NULL; - break; - case TSDB_DATA_TYPE_FLOAT: - return *(uint32_t *)(val) == TSDB_DATA_FLOAT_NULL; - break; - case TSDB_DATA_TYPE_DOUBLE: - return *(uint64_t *)(val) == TSDB_DATA_DOUBLE_NULL; - break; - case TSDB_DATA_TYPE_NCHAR: - case TSDB_DATA_TYPE_BINARY: - return isVardataNull(val, type); - break; - default: { - return *(uint32_t *)(val) == TSDB_DATA_INT_NULL; - break; - } - } - - return false; -} - static uint8_t nullBool = TSDB_DATA_BOOL_NULL; static uint8_t nullTinyInt = TSDB_DATA_TINYINT_NULL; static uint16_t nullSmallInt = TSDB_DATA_SMALLINT_NULL; diff --git a/src/inc/tsdb.h b/src/inc/tsdb.h index 7c28d3e485..5f2d866fdb 100644 --- a/src/inc/tsdb.h +++ b/src/inc/tsdb.h @@ -69,7 +69,7 @@ typedef struct { int8_t precision; int8_t compression; int8_t update; - int8_t cacheLastRow; // 0:no cache, 1: cache last row, 2: cache last NULL column + int8_t cacheLastRow; // 0:no cache, 1: cache last row, 2: cache last NULL column 3: 1&2 } STsdbCfg; #define CACHE_NO_LAST(c) ((c)->cacheLastRow == 0) diff --git a/src/inc/ttype.h b/src/inc/ttype.h index 43dbeb7640..9949f31c59 100644 --- a/src/inc/ttype.h +++ b/src/inc/ttype.h @@ -178,9 +178,6 @@ void setNull(char *val, int32_t type, int32_t bytes); void setNullN(char *val, int32_t type, int32_t bytes, int32_t numOfElems); void *getNullValue(int32_t type); -bool isVardataNull(char* val, int32_t type); -bool isNullN(char *val, int32_t type); - void assignVal(char *val, const char *src, int32_t len, int32_t type); void tsDataSwap(void *pLeft, void *pRight, int32_t type, int32_t size, void* buf); diff --git a/src/tsdb/inc/tsdbMeta.h b/src/tsdb/inc/tsdbMeta.h index 14d5a41768..45bbd5a7c6 100644 --- a/src/tsdb/inc/tsdbMeta.h +++ b/src/tsdb/inc/tsdbMeta.h @@ -45,9 +45,6 @@ typedef struct STable { T_REF_DECLARE() } STable; -#define TSDB_LATEST_COLUMN_ARRAY_SIZE 20 -#define TSDB_LATEST_COLUMN_ARRAY_ADD_SIZE 5 - typedef struct { pthread_rwlock_t rwLock; diff --git a/src/tsdb/src/tsdbMain.c b/src/tsdb/src/tsdbMain.c index cc2fca420c..afbedd5b2f 100644 --- a/src/tsdb/src/tsdbMain.c +++ b/src/tsdb/src/tsdbMain.c @@ -27,6 +27,7 @@ static void tsdbFreeRepo(STsdbRepo *pRepo); static void tsdbStartStream(STsdbRepo *pRepo); static void tsdbStopStream(STsdbRepo *pRepo); static int tsdbRestoreLastColumns(STsdbRepo *pRepo, STable *pTable, SReadH* pReadh); +static int tsdbRestoreLastRow(STsdbRepo *pRepo, STable *pTable, SReadH* pReadh, SBlockIdx *pIdx); // Function declaration int32_t tsdbCreateRepo(int repoid) { @@ -270,9 +271,7 @@ int32_t tsdbConfigRepo(STsdbRepo *repo, STsdbCfg *pCfg) { pthread_mutex_unlock(&repo->save_mutex); // schedule a commit msg then the new config will be applied immediatly - if (tsdbLockRepo(repo) < 0) return -1; - tsdbScheduleCommit(repo); - if (tsdbUnlockRepo(repo) < 0) return -1; + tsdbAsyncCommit(repo); return 0; #if 0 @@ -645,6 +644,7 @@ static int tsdbRestoreLastColumns(STsdbRepo *pRepo, STable *pTable, SReadH* pRea numColumns = schemaNCols(pSchema); if (numColumns <= pTable->restoreColumnNum) { + pTable->hasRestoreLastColumn = true; return 0; } if (pTable->lastColSVersion != schemaVersion(pSchema)) { @@ -719,7 +719,7 @@ static int tsdbRestoreLastColumns(STsdbRepo *pRepo, STable *pTable, SReadH* pRea tdAppendColVal(row, tdGetColDataOfRow(pDataCol, rowId), pCol->type, pCol->bytes, pCol->offset); //SDataCol *pDataCol = readh.pDCols[0]->cols + j; void* value = tdGetRowDataOfCol(row, (int8_t)pCol->type, TD_DATA_ROW_HEAD_SIZE + pCol->offset); - if (isNullN(value, pCol->type)) { + if (isNull(value, pCol->type)) { continue; } @@ -753,16 +753,51 @@ out: taosTZfree(row); tfree(pBlockStatis); + if (err == 0 && numColumns <= pTable->restoreColumnNum) { + pTable->hasRestoreLastColumn = true; + } + return err; } +static int tsdbRestoreLastRow(STsdbRepo *pRepo, STable *pTable, SReadH* pReadh, SBlockIdx *pIdx) { + ASSERT(pTable->lastRow == NULL); + if (tsdbLoadBlockInfo(pReadh, NULL) < 0) { + return -1; + } + + SBlock* pBlock = pReadh->pBlkInfo->blocks + pIdx->numOfBlocks - 1; + + if (tsdbLoadBlockData(pReadh, pBlock, NULL) < 0) { + return -1; + } + + // Get the data in row + + STSchema *pSchema = tsdbGetTableSchema(pTable); + pTable->lastRow = taosTMalloc(dataRowMaxBytesFromSchema(pSchema)); + if (pTable->lastRow == NULL) { + terrno = TSDB_CODE_TDB_OUT_OF_MEMORY; + return -1; + } + + tdInitDataRow(pTable->lastRow, pSchema); + for (int icol = 0; icol < schemaNCols(pSchema); icol++) { + STColumn *pCol = schemaColAt(pSchema, icol); + SDataCol *pDataCol = pReadh->pDCols[0]->cols + icol; + tdAppendColVal(pTable->lastRow, tdGetColDataOfRow(pDataCol, pBlock->numOfRows - 1), pCol->type, pCol->bytes, + pCol->offset); + } + + return 0; +} + int tsdbRestoreInfo(STsdbRepo *pRepo) { SFSIter fsiter; SReadH readh; SDFileSet *pSet; STsdbMeta *pMeta = pRepo->tsdbMeta; STsdbCfg * pCfg = REPO_CFG(pRepo); - SBlock * pBlock; if (tsdbInitReadH(&readh, pRepo) < 0) { return -1; @@ -805,41 +840,14 @@ int tsdbRestoreInfo(STsdbRepo *pRepo) { if (pIdx && lastKey < pIdx->maxKey) { pTable->lastKey = pIdx->maxKey; - if (CACHE_LAST_ROW(pCfg)) { - if (tsdbLoadBlockInfo(&readh, NULL) < 0) { - tsdbDestroyReadH(&readh); - return -1; - } - - pBlock = readh.pBlkInfo->blocks + pIdx->numOfBlocks - 1; - - if (tsdbLoadBlockData(&readh, pBlock, NULL) < 0) { - tsdbDestroyReadH(&readh); - return -1; - } - - // Get the data in row - ASSERT(pTable->lastRow == NULL); - STSchema *pSchema = tsdbGetTableSchema(pTable); - pTable->lastRow = taosTMalloc(dataRowMaxBytesFromSchema(pSchema)); - if (pTable->lastRow == NULL) { - terrno = TSDB_CODE_TDB_OUT_OF_MEMORY; - tsdbDestroyReadH(&readh); - return -1; - } - - tdInitDataRow(pTable->lastRow, pSchema); - for (int icol = 0; icol < schemaNCols(pSchema); icol++) { - STColumn *pCol = schemaColAt(pSchema, icol); - SDataCol *pDataCol = readh.pDCols[0]->cols + icol; - tdAppendColVal(pTable->lastRow, tdGetColDataOfRow(pDataCol, pBlock->numOfRows - 1), pCol->type, pCol->bytes, - pCol->offset); - } + if (CACHE_LAST_ROW(pCfg) && tsdbRestoreLastRow(pRepo, pTable, &readh, pIdx) != 0) { + tsdbDestroyReadH(&readh); + return -1; } } // restore NULL columns - if (pIdx && CACHE_LAST_NULL_COLUMN(pCfg)) { + if (pIdx && CACHE_LAST_NULL_COLUMN(pCfg) && !pTable->hasRestoreLastColumn) { if (tsdbRestoreLastColumns(pRepo, pTable, &readh) != 0) { tsdbDestroyReadH(&readh); return -1; @@ -865,8 +873,6 @@ int tsdbCacheLastData(STsdbRepo *pRepo, STsdbCfg* oldCfg) { SReadH readh; SDFileSet *pSet; STsdbMeta *pMeta = pRepo->tsdbMeta; - //STsdbCfg * pCfg = REPO_CFG(pRepo); - SBlock * pBlock; int tableNum = 0; int maxTableIdx = 0; int cacheLastRowTableNum = 0; @@ -955,35 +961,10 @@ int tsdbCacheLastData(STsdbRepo *pRepo, STsdbCfg* oldCfg) { if (pIdx && cacheLastRowTableNum > 0 && pTable->lastRow == NULL) { pTable->lastKey = pIdx->maxKey; - if (tsdbLoadBlockInfo(&readh, NULL) < 0) { + if (tsdbRestoreLastRow(pRepo, pTable, &readh, pIdx) != 0) { tsdbDestroyReadH(&readh); return -1; } - - pBlock = readh.pBlkInfo->blocks + pIdx->numOfBlocks - 1; - - if (tsdbLoadBlockData(&readh, pBlock, NULL) < 0) { - tsdbDestroyReadH(&readh); - return -1; - } - - // Get the data in row - ASSERT(pTable->lastRow == NULL); - STSchema *pSchema = tsdbGetTableSchema(pTable); - pTable->lastRow = taosTMalloc(dataRowMaxBytesFromSchema(pSchema)); - if (pTable->lastRow == NULL) { - terrno = TSDB_CODE_TDB_OUT_OF_MEMORY; - tsdbDestroyReadH(&readh); - return -1; - } - - tdInitDataRow(pTable->lastRow, pSchema); - for (int icol = 0; icol < schemaNCols(pSchema); icol++) { - STColumn *pCol = schemaColAt(pSchema, icol); - SDataCol *pDataCol = readh.pDCols[0]->cols + icol; - tdAppendColVal(pTable->lastRow, tdGetColDataOfRow(pDataCol, pBlock->numOfRows - 1), pCol->type, pCol->bytes, - pCol->offset); - } cacheLastRowTableNum -= 1; } diff --git a/src/tsdb/src/tsdbMemTable.c b/src/tsdb/src/tsdbMemTable.c index ff2a870f3f..79dbb8be5d 100644 --- a/src/tsdb/src/tsdbMemTable.c +++ b/src/tsdb/src/tsdbMemTable.c @@ -274,7 +274,7 @@ void *tsdbAllocBytes(STsdbRepo *pRepo, int bytes) { int tsdbAsyncCommit(STsdbRepo *pRepo) { tsem_wait(&(pRepo->readyToCommit)); - ASSERT(pRepo->imem == NULL); + //ASSERT(pRepo->imem == NULL); if (pRepo->mem == NULL) { tsem_post(&(pRepo->readyToCommit)); return 0; @@ -965,7 +965,7 @@ static void tsdbFreeRows(STsdbRepo *pRepo, void **rows, int rowCounter) { } static void updateTableLatestColumn(STsdbRepo *pRepo, STable *pTable, SDataRow row) { - tsdbInfo("vgId:%d updateTableLatestColumn, %s row version:%d", REPO_ID(pRepo), pTable->name->data, dataRowVersion(row)); + tsdbDebug("vgId:%d updateTableLatestColumn, %s row version:%d", REPO_ID(pRepo), pTable->name->data, dataRowVersion(row)); STSchema* pSchema = tsdbGetTableLatestSchema(pTable); if (tsdbUpdateLastColSchema(pTable, pSchema) < 0) { @@ -988,7 +988,7 @@ static void updateTableLatestColumn(STsdbRepo *pRepo, STable *pTable, SDataRow r } void* value = tdGetRowDataOfCol(row, (int8_t)pTCol->type, TD_DATA_ROW_HEAD_SIZE + pSchema->columns[j].offset); - if (isNullN(value, pTCol->type)) { + if (isNull(value, pTCol->type)) { continue; } From 11026023e237bc6f3e039e4fdd3dfa34e952901f Mon Sep 17 00:00:00 2001 From: dapan1121 <89396746@qq.com> Date: Thu, 27 May 2021 11:52:02 +0800 Subject: [PATCH 42/70] fix windows compile error --- src/tsdb/src/tsdbRead.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tsdb/src/tsdbRead.c b/src/tsdb/src/tsdbRead.c index 50acda0d95..0a39dba021 100644 --- a/src/tsdb/src/tsdbRead.c +++ b/src/tsdb/src/tsdbRead.c @@ -2488,7 +2488,7 @@ static bool loadCachedLastRow(STsdbQueryHandle* pQueryHandle) { static bool loadCachedLast(STsdbQueryHandle* pQueryHandle) { // the last row is cached in buffer, return it directly. // here note that the pQueryHandle->window must be the TS_INITIALIZER - int32_t tgNumOfCols = QH_GET_NUM_OF_COLS(pQueryHandle); + int32_t tgNumOfCols = (int32_t)QH_GET_NUM_OF_COLS(pQueryHandle); size_t numOfTables = taosArrayGetSize(pQueryHandle->pTableCheckInfo); int32_t numOfRows = 0; assert(numOfTables > 0 && tgNumOfCols > 0); From 683c4d58700aace3255296610354d394b48fbcf3 Mon Sep 17 00:00:00 2001 From: Kaili Xu Date: Thu, 27 May 2021 13:28:19 +0800 Subject: [PATCH 43/70] [TD-4324] skip expired files during init and sync --- src/tsdb/inc/tsdbCommit.h | 1 + src/tsdb/inc/tsdbint.h | 1 + src/tsdb/src/tsdbCommit.c | 3 +- src/tsdb/src/tsdbFS.c | 83 ++++++++++++++++++++++++++++++++++++--- src/tsdb/src/tsdbSync.c | 43 +++++++++++++++----- 5 files changed, 115 insertions(+), 16 deletions(-) diff --git a/src/tsdb/inc/tsdbCommit.h b/src/tsdb/inc/tsdbCommit.h index 5e740081d1..6bd5dc4325 100644 --- a/src/tsdb/inc/tsdbCommit.h +++ b/src/tsdb/inc/tsdbCommit.h @@ -33,6 +33,7 @@ void tsdbGetRtnSnap(STsdbRepo *pRepo, SRtn *pRtn); int tsdbEncodeKVRecord(void **buf, SKVRecord *pRecord); void *tsdbDecodeKVRecord(void *buf, SKVRecord *pRecord); void *tsdbCommitData(STsdbRepo *pRepo); +int tsdbApplyRtn(STsdbRepo *pRepo); static FORCE_INLINE int tsdbGetFidLevel(int fid, SRtn *pRtn) { if (fid >= pRtn->maxFid) { diff --git a/src/tsdb/inc/tsdbint.h b/src/tsdb/inc/tsdbint.h index 4d62164df9..324d25d8cd 100644 --- a/src/tsdb/inc/tsdbint.h +++ b/src/tsdb/inc/tsdbint.h @@ -83,6 +83,7 @@ struct STsdbRepo { SMemTable* mem; SMemTable* imem; STsdbFS* fs; + SRtn rtn; tsem_t readyToCommit; pthread_mutex_t mutex; bool repoLocked; diff --git a/src/tsdb/src/tsdbCommit.c b/src/tsdb/src/tsdbCommit.c index 24f1c11628..88dad3c642 100644 --- a/src/tsdb/src/tsdbCommit.c +++ b/src/tsdb/src/tsdbCommit.c @@ -86,7 +86,6 @@ static void tsdbCloseCommitFile(SCommitH *pCommith, bool hasError); static bool tsdbCanAddSubBlock(SCommitH *pCommith, SBlock *pBlock, SMergeInfo *pInfo); static void tsdbLoadAndMergeFromCache(SDataCols *pDataCols, int *iter, SCommitIter *pCommitIter, SDataCols *pTarget, TSKEY maxKey, int maxRows, int8_t update); -static int tsdbApplyRtn(STsdbRepo *pRepo); static int tsdbApplyRtnOnFSet(STsdbRepo *pRepo, SDFileSet *pSet, SRtn *pRtn); void *tsdbCommitData(STsdbRepo *pRepo) { @@ -1428,7 +1427,7 @@ static bool tsdbCanAddSubBlock(SCommitH *pCommith, SBlock *pBlock, SMergeInfo *p return false; } -static int tsdbApplyRtn(STsdbRepo *pRepo) { +int tsdbApplyRtn(STsdbRepo *pRepo) { SRtn rtn; SFSIter fsiter; STsdbFS * pfs = REPO_FS(pRepo); diff --git a/src/tsdb/src/tsdbFS.c b/src/tsdb/src/tsdbFS.c index fd9b5e77e3..fd4fa5f139 100644 --- a/src/tsdb/src/tsdbFS.c +++ b/src/tsdb/src/tsdbFS.c @@ -33,7 +33,9 @@ static int tsdbScanDataDir(STsdbRepo *pRepo); static bool tsdbIsTFileInFS(STsdbFS *pfs, const TFILE *pf); static int tsdbRestoreCurrent(STsdbRepo *pRepo); static int tsdbComparTFILE(const void *arg1, const void *arg2); -static void tsdbScanAndTryFixDFilesHeader(STsdbRepo *pRepo); +static void tsdbScanAndTryFixDFilesHeader(STsdbRepo *pRepo, int32_t *nExpired); +static int tsdbProcessExpiredFS(STsdbRepo *pRepo); +static int tsdbCreateMeta(STsdbRepo *pRepo); // ================== CURRENT file header info static int tsdbEncodeFSHeader(void **buf, SFSHeader *pHeader) { @@ -212,6 +214,8 @@ STsdbFS *tsdbNewFS(STsdbCfg *pCfg) { return NULL; } + pfs->intxn = false; + pfs->nstatus = tsdbNewFSStatus(maxFSet); if (pfs->nstatus == NULL) { tsdbFreeFS(pfs); @@ -234,22 +238,84 @@ void *tsdbFreeFS(STsdbFS *pfs) { return NULL; } +static int tsdbProcessExpiredFS(STsdbRepo *pRepo) { + tsdbStartFSTxn(pRepo, 0, 0); + if (tsdbCreateMeta(pRepo) < 0) { + tsdbError("vgId:%d failed to apply rtn since %s", REPO_ID(pRepo), tstrerror(terrno)); + return -1; + } + + if (tsdbApplyRtn(pRepo) < 0) { + tsdbEndFSTxnWithError(REPO_FS(pRepo)); + tsdbError("vgId:%d failed to apply rtn since %s", REPO_ID(pRepo), tstrerror(terrno)); + return -1; + } + if (tsdbEndFSTxn(pRepo) < 0) { + tsdbError("vgId:%d failed to end fs txn since %s", REPO_ID(pRepo), tstrerror(terrno)); + return -1; + } + return 0; +} + +static int tsdbCreateMeta(STsdbRepo *pRepo) { + STsdbFS *pfs = REPO_FS(pRepo); + SMFile * pOMFile = pfs->cstatus->pmf; + SMFile mf; + SDiskID did; + + if (pOMFile != NULL) { + // keep the old meta file + tsdbUpdateMFile(pfs, pOMFile); + return 0; + } + + // Create a new meta file + did.level = TFS_PRIMARY_LEVEL; + did.id = TFS_PRIMARY_ID; + tsdbInitMFile(&mf, did, REPO_ID(pRepo), FS_TXN_VERSION(REPO_FS(pRepo))); + + if (tsdbCreateMFile(&mf, true) < 0) { + tsdbError("vgId:%d failed to create META file since %s", REPO_ID(pRepo), tstrerror(terrno)); + return -1; + } + + tsdbInfo("vgId:%d meta file %s is created", REPO_ID(pRepo), TSDB_FILE_FULL_NAME(&mf)); + + if (tsdbUpdateMFileHeader(&mf) < 0) { + tsdbError("vgId:%d failed to update META file header since %s, revert it", REPO_ID(pRepo), tstrerror(terrno)); + tsdbApplyMFileChange(&mf, pOMFile); + return -1; + } + + TSDB_FILE_FSYNC(&mf); + tsdbCloseMFile(&mf); + tsdbUpdateMFile(pfs, &mf); + + return 0; +} + int tsdbOpenFS(STsdbRepo *pRepo) { STsdbFS *pfs = REPO_FS(pRepo); char current[TSDB_FILENAME_LEN] = "\0"; + int nExpired = 0; ASSERT(pfs != NULL); tsdbGetTxnFname(REPO_ID(pRepo), TSDB_TXN_CURR_FILE, current); + tsdbGetRtnSnap(pRepo, &pRepo->rtn); if (access(current, F_OK) == 0) { if (tsdbOpenFSFromCurrent(pRepo) < 0) { tsdbError("vgId:%d failed to open FS since %s", REPO_ID(pRepo), tstrerror(terrno)); return -1; } - - tsdbScanAndTryFixDFilesHeader(pRepo); + + tsdbScanAndTryFixDFilesHeader(pRepo, &nExpired); + if (nExpired > 0) { + tsdbProcessExpiredFS(pRepo); + } } else { + // should skip expired fileset inside of the function if (tsdbRestoreCurrent(pRepo) < 0) { tsdbError("vgId:%d failed to restore current file since %s", REPO_ID(pRepo), tstrerror(terrno)); return -1; @@ -1110,6 +1176,11 @@ static int tsdbRestoreDFileSet(STsdbRepo *pRepo) { ASSERT(tvid == REPO_ID(pRepo)); + if (tfid < pRepo->rtn.minFid) { // skip file expired + ++index; + continue; + } + if (ftype == 0) { fset.fid = tfid; } else { @@ -1206,7 +1277,7 @@ static int tsdbComparTFILE(const void *arg1, const void *arg2) { } } -static void tsdbScanAndTryFixDFilesHeader(STsdbRepo *pRepo) { +static void tsdbScanAndTryFixDFilesHeader(STsdbRepo *pRepo, int32_t *nExpired) { STsdbFS * pfs = REPO_FS(pRepo); SFSStatus *pStatus = pfs->cstatus; SDFInfo info; @@ -1214,7 +1285,9 @@ static void tsdbScanAndTryFixDFilesHeader(STsdbRepo *pRepo) { for (size_t i = 0; i < taosArrayGetSize(pStatus->df); i++) { SDFileSet fset; tsdbInitDFileSetEx(&fset, (SDFileSet *)taosArrayGet(pStatus->df, i)); - + if (fset.fid < pRepo->rtn.minFid) { + ++*nExpired; + } tsdbDebug("vgId:%d scan DFileSet %d header", REPO_ID(pRepo), fset.fid); if (tsdbOpenDFileSet(&fset, O_RDWR) < 0) { diff --git a/src/tsdb/src/tsdbSync.c b/src/tsdb/src/tsdbSync.c index 5a2756537e..e9f069c64f 100644 --- a/src/tsdb/src/tsdbSync.c +++ b/src/tsdb/src/tsdbSync.c @@ -424,24 +424,42 @@ static int32_t tsdbSyncRecvDFileSetArray(SSyncH *pSynch) { } if (tsdbSendDecision(pSynch, false) < 0) { - tsdbError("vgId:%d, filed to send decision since %s", REPO_ID(pRepo), tstrerror(terrno)); + tsdbError("vgId:%d, failed to send decision since %s", REPO_ID(pRepo), tstrerror(terrno)); return -1; } } else { // Need to copy from remote - tsdbInfo("vgId:%d, fileset:%d will be received", REPO_ID(pRepo), pSynch->pdf->fid); - - // Notify remote to send there file here - if (tsdbSendDecision(pSynch, true) < 0) { - tsdbError("vgId:%d, failed to send decision since %s", REPO_ID(pRepo), tstrerror(terrno)); - return -1; + int fidLevel = tsdbGetFidLevel(pSynch->pdf->fid, &(pSynch->rtn)); + if (fidLevel < 0) { // expired fileset + tsdbInfo("vgId:%d, fileset:%d will be skipped as expired", REPO_ID(pRepo), pSynch->pdf->fid); + if (tsdbSendDecision(pSynch, false) < 0) { + tsdbError("vgId:%d, failed to send decision since %s", REPO_ID(pRepo), tstrerror(terrno)); + return -1; + } + // Move forward + if (tsdbRecvDFileSetInfo(pSynch) < 0) { + tsdbError("vgId:%d, failed to recv fileset since %s", REPO_ID(pRepo), tstrerror(terrno)); + return -1; + } + if (pLSet) { + pLSet = tsdbFSIterNext(&fsiter); + } + // Next loop + continue; + } else { + tsdbInfo("vgId:%d, fileset:%d will be received", REPO_ID(pRepo), pSynch->pdf->fid); + // Notify remote to send there file here + if (tsdbSendDecision(pSynch, true) < 0) { + tsdbError("vgId:%d, failed to send decision since %s", REPO_ID(pRepo), tstrerror(terrno)); + return -1; + } } // Create local files and copy from remote SDiskID did; SDFileSet fset; - tfsAllocDisk(tsdbGetFidLevel(pSynch->pdf->fid, &(pSynch->rtn)), &(did.level), &(did.id)); + tfsAllocDisk(fidLevel, &(did.level), &(did.id)); if (did.level == TFS_UNDECIDED_LEVEL) { terrno = TSDB_CODE_TDB_NO_AVAIL_DISK; tsdbError("vgId:%d, failed allc disk since %s", REPO_ID(pRepo), tstrerror(terrno)); @@ -548,12 +566,19 @@ static int32_t tsdbSyncSendDFileSet(SSyncH *pSynch, SDFileSet *pSet) { STsdbRepo *pRepo = pSynch->pRepo; bool toSend = false; + // skip expired fileset + if (pSet && tsdbGetFidLevel(pSet->fid, &(pSynch->rtn)) < 0) { + tsdbInfo("vgId:%d, don't sync send since fileset:%d smaller than minFid:%d", REPO_ID(pRepo), pSet->fid, + pSynch->rtn.minFid); + return 0; + } + if (tsdbSendDFileSetInfo(pSynch, pSet) < 0) { tsdbError("vgId:%d, failed to send fileset:%d info since %s", REPO_ID(pRepo), pSet ? pSet->fid : -1, tstrerror(terrno)); return -1; } - // No file any more, no need to send file, just return + // No file any more, no need to send file, just return if (pSet == NULL) { return 0; } From b5fa8bf617a13fd9e0ed3665a368ee88da0e6a56 Mon Sep 17 00:00:00 2001 From: Kaili Xu Date: Thu, 27 May 2021 13:37:41 +0800 Subject: [PATCH 44/70] update logs --- src/tsdb/src/tsdbFS.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tsdb/src/tsdbFS.c b/src/tsdb/src/tsdbFS.c index fd4fa5f139..54372ae8c2 100644 --- a/src/tsdb/src/tsdbFS.c +++ b/src/tsdb/src/tsdbFS.c @@ -241,7 +241,7 @@ void *tsdbFreeFS(STsdbFS *pfs) { static int tsdbProcessExpiredFS(STsdbRepo *pRepo) { tsdbStartFSTxn(pRepo, 0, 0); if (tsdbCreateMeta(pRepo) < 0) { - tsdbError("vgId:%d failed to apply rtn since %s", REPO_ID(pRepo), tstrerror(terrno)); + tsdbError("vgId:%d failed to create meta since %s", REPO_ID(pRepo), tstrerror(terrno)); return -1; } @@ -309,7 +309,7 @@ int tsdbOpenFS(STsdbRepo *pRepo) { tsdbError("vgId:%d failed to open FS since %s", REPO_ID(pRepo), tstrerror(terrno)); return -1; } - + tsdbScanAndTryFixDFilesHeader(pRepo, &nExpired); if (nExpired > 0) { tsdbProcessExpiredFS(pRepo); From f1f7d5564f809afffc83bb71c7384f84ce6246d2 Mon Sep 17 00:00:00 2001 From: lichuang Date: Thu, 27 May 2021 16:02:57 +0800 Subject: [PATCH 45/70] [TD-1920]add mnode_bak and mnode_tmp dir exist check when start up --- src/dnode/src/dnodeMain.c | 10 ++++++++-- src/os/inc/osDir.h | 1 + src/os/src/detail/osDir.c | 4 ++++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/dnode/src/dnodeMain.c b/src/dnode/src/dnodeMain.c index ee4dfcf852..cce382b15f 100644 --- a/src/dnode/src/dnodeMain.c +++ b/src/dnode/src/dnodeMain.c @@ -219,14 +219,20 @@ static int32_t dnodeInitStorage() { if (tsCompactMnodeWal == 1) { sprintf(tsMnodeTmpDir, "%s/mnode_tmp", tsDataDir); - tfsRmdir(tsMnodeTmpDir); + if (taosDirExist(tsMnodeTmpDir)) { + dError("mnode_tmp dir already exist in %s,quit compact job", tsMnodeTmpDir); + return -1; + } if (dnodeCreateDir(tsMnodeTmpDir) < 0) { dError("failed to create dir: %s, reason: %s", tsMnodeTmpDir, strerror(errno)); return -1; } sprintf(tsMnodeBakDir, "%s/mnode_bak", tsDataDir); - //tfsRmdir(tsMnodeBakDir); + if (taosDirExist(tsMnodeBakDir)) { + dError("mnode_bak dir already exist in %s,quit compact job", tsMnodeBakDir); + return -1; + } } //TODO(dengyihao): no need to init here if (dnodeCreateDir(tsMnodeDir) < 0) { diff --git a/src/os/inc/osDir.h b/src/os/inc/osDir.h index bdc65e4520..7afe126451 100644 --- a/src/os/inc/osDir.h +++ b/src/os/inc/osDir.h @@ -21,6 +21,7 @@ extern "C" { #endif void taosRemoveDir(char *rootDir); +bool taosDirExist(const char* dirname); int32_t taosMkDir(const char *pathname, mode_t mode); void taosRemoveOldLogFiles(char *rootDir, int32_t keepDays); int32_t taosRename(char *oldName, char *newName); diff --git a/src/os/src/detail/osDir.c b/src/os/src/detail/osDir.c index 2a2e2519b5..c467c64872 100644 --- a/src/os/src/detail/osDir.c +++ b/src/os/src/detail/osDir.c @@ -45,6 +45,10 @@ void taosRemoveDir(char *rootDir) { uInfo("dir:%s is removed", rootDir); } +bool taosDirExist(const char* dirname) { + return access(dirname, F_OK) == 0; +} + int taosMkDir(const char *path, mode_t mode) { int code = mkdir(path, 0755); if (code < 0 && errno == EEXIST) code = 0; From 16378507da99a02747fdd9ff9b82b30a250b254a Mon Sep 17 00:00:00 2001 From: dapan1121 <89396746@qq.com> Date: Thu, 27 May 2021 17:01:57 +0800 Subject: [PATCH 46/70] support auto create table --- src/client/inc/tscUtil.h | 2 + src/client/src/tscPrepare.c | 236 ++++++- src/client/src/tscUtil.c | 61 ++ src/inc/taos.h | 1 + tests/script/api/batchprepare.c | 1166 ++++++++++++++++++++++++++++++- 5 files changed, 1413 insertions(+), 53 deletions(-) diff --git a/src/client/inc/tscUtil.h b/src/client/inc/tscUtil.h index 0348606d6b..c444456337 100644 --- a/src/client/inc/tscUtil.h +++ b/src/client/inc/tscUtil.h @@ -99,6 +99,8 @@ static FORCE_INLINE SQueryInfo* tscGetQueryInfo(SSqlCmd* pCmd, int32_t subClause return pCmd->pQueryInfo[subClauseIndex]; } +int32_t converToStr(char *str, int type, void *buf, int32_t bufSize, int32_t *len); + SQueryInfo* tscGetActiveQueryInfo(SSqlCmd* pCmd); int32_t tscCreateDataBlock(size_t initialSize, int32_t rowSize, int32_t startOffset, SName* name, STableMeta* pTableMeta, STableDataBlocks** dataBlocks); diff --git a/src/client/src/tscPrepare.c b/src/client/src/tscPrepare.c index 7794e3190c..cfa822ad4d 100644 --- a/src/client/src/tscPrepare.c +++ b/src/client/src/tscPrepare.c @@ -46,9 +46,13 @@ typedef struct SNormalStmt { typedef struct SMultiTbStmt { bool nameSet; + bool tagSet; uint64_t currentUid; uint32_t tbNum; SStrToken tbname; + SStrToken stbname; + SStrToken values; + SArray *tags; SHashObj *pTableHash; SHashObj *pTableBlockHashList; // data block for each table } SMultiTbStmt; @@ -1201,6 +1205,185 @@ static int insertBatchStmtExecute(STscStmt* pStmt) { return pStmt->pSql->res.code; } + +int stmtParseInsertTbTags(SSqlObj* pSql, STscStmt* pStmt) { + SSqlCmd *pCmd = &pSql->cmd; + int32_t ret = TSDB_CODE_SUCCESS; + + if ((ret = tsInsertInitialCheck(pSql)) != TSDB_CODE_SUCCESS) { + return ret; + } + + int32_t index = 0; + SStrToken sToken = tStrGetToken(pCmd->curSql, &index, false); + + if (sToken.n == 0) { + return TSDB_CODE_TSC_INVALID_SQL; + } + + if (sToken.n == 1 && sToken.type == TK_QUESTION) { + pStmt->multiTbInsert = true; + pStmt->mtb.tbname = sToken; + pStmt->mtb.nameSet = false; + if (pStmt->mtb.pTableHash == NULL) { + pStmt->mtb.pTableHash = taosHashInit(16, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, false); + } + + if (pStmt->mtb.pTableBlockHashList == NULL) { + pStmt->mtb.pTableBlockHashList = taosHashInit(16, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), true, false); + } + + pStmt->mtb.tagSet = true; + + sToken = tStrGetToken(pCmd->curSql, &index, false); + if (sToken.n > 0 && sToken.type == TK_VALUES) { + return TSDB_CODE_SUCCESS; + } + + if (sToken.n <= 0 || sToken.type != TK_USING) { + return TSDB_CODE_TSC_INVALID_SQL; + } + + sToken = tStrGetToken(pCmd->curSql, &index, false); + if (sToken.n <= 0 || ((sToken.type != TK_ID) && (sToken.type != TK_STRING))) { + return TSDB_CODE_TSC_INVALID_SQL; + } + pStmt->mtb.stbname = sToken; + + sToken = tStrGetToken(pCmd->curSql, &index, false); + if (sToken.n <= 0 || sToken.type != TK_TAGS) { + return TSDB_CODE_TSC_INVALID_SQL; + } + + sToken = tStrGetToken(pCmd->curSql, &index, false); + if (sToken.n <= 0 || sToken.type != TK_LP) { + return TSDB_CODE_TSC_INVALID_SQL; + } + + pStmt->mtb.tags = taosArrayInit(4, sizeof(SStrToken)); + + int32_t loopCont = 1; + + while (loopCont) { + sToken = tStrGetToken(pCmd->curSql, &index, false); + if (sToken.n <= 0) { + return TSDB_CODE_TSC_INVALID_SQL; + } + + switch (sToken.type) { + case TK_RP: + loopCont = 0; + break; + case TK_VALUES: + return TSDB_CODE_TSC_INVALID_SQL; + case TK_QUESTION: + pStmt->mtb.tagSet = false; //continue + default: + taosArrayPush(pStmt->mtb.tags, &sToken); + break; + } + } + + if (taosArrayGetSize(pStmt->mtb.tags) <= 0) { + return TSDB_CODE_TSC_INVALID_SQL; + } + + sToken = tStrGetToken(pCmd->curSql, &index, false); + if (sToken.n <= 0 || sToken.type != TK_VALUES) { + return TSDB_CODE_TSC_INVALID_SQL; + } + + pStmt->mtb.values = sToken; + } + + return TSDB_CODE_SUCCESS; +} + + + + +int stmtGenInsertStatement(SSqlObj* pSql, STscStmt* pStmt, const char* name, TAOS_BIND* tags) { + size_t tagNum = taosArrayGetSize(pStmt->mtb.tags); + size_t size = 1048576; + char *str = calloc(1, size); + size_t len = 0; + int32_t ret = 0; + int32_t j = 0; + + while (1) { + len = (size_t)snprintf(str, size - 1, "insert into %s using %.*s tags(", name, pStmt->mtb.stbname.n, pStmt->mtb.stbname.z); + if (len >= (size -1)) { + size *= 2; + free(str); + str = calloc(1, size); + continue; + } + + j = 0; + + for (size_t i = 0; i < tagNum && len < (size - 1); ++i) { + SStrToken *t = taosArrayGet(pStmt->mtb.tags, i); + if (t->type == TK_QUESTION) { + int32_t l = 0; + if (i > 0) { + str[len++] = ','; + } + + if (tags[j].is_null && (*tags[j].is_null)) { + ret = converToStr(str + len, TSDB_DATA_TYPE_NULL, NULL, -1, &l); + } else { + if (tags[j].buffer == NULL) { + free(str); + tscError("empty"); + return TSDB_CODE_TSC_APP_ERROR; + } + + ret = converToStr(str + len, tags[j].buffer_type, tags[j].buffer, tags[j].length ? *tags[j].length : -1, &l); + } + + ++j; + + if (ret) { + free(str); + return ret; + } + + len += l; + } else { + len += (size_t)snprintf(str + len, size - len - 1, i > 0 ? ",%.*s" : "%.*s", t->n, t->z); + } + } + + if (len >= (size - 1)) { + size *= 2; + free(str); + str = calloc(1, size); + continue; + } + + strcat(str, ") "); + len += 2; + + if ((len + strlen(pStmt->mtb.values.z)) >= (size - 1)) { + size *= 2; + free(str); + str = calloc(1, size); + continue; + } + + strcat(str, pStmt->mtb.values.z); + + break; + } + + free(pSql->sqlstr); + pSql->sqlstr = str; + + return TSDB_CODE_SUCCESS; +} + + + //////////////////////////////////////////////////////////////////////////////// // interface functions @@ -1292,34 +1475,15 @@ int taos_stmt_prepare(TAOS_STMT* stmt, const char* sql, unsigned long length) { registerSqlObj(pSql); - int32_t ret = TSDB_CODE_SUCCESS; - - if ((ret = tsInsertInitialCheck(pSql)) != TSDB_CODE_SUCCESS) { + int32_t ret = stmtParseInsertTbTags(pSql, pStmt); + if (ret != TSDB_CODE_SUCCESS) { return ret; } - - int32_t index = 0; - SStrToken sToken = tStrGetToken(pCmd->curSql, &index, false); - if (sToken.n == 0) { - return TSDB_CODE_TSC_INVALID_SQL; + if (pStmt->multiTbInsert) { + return TSDB_CODE_SUCCESS; } - if (sToken.n == 1 && sToken.type == TK_QUESTION) { - pStmt->multiTbInsert = true; - pStmt->mtb.tbname = sToken; - pStmt->mtb.nameSet = false; - if (pStmt->mtb.pTableHash == NULL) { - pStmt->mtb.pTableHash = taosHashInit(16, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, false); - } - if (pStmt->mtb.pTableBlockHashList == NULL) { - pStmt->mtb.pTableBlockHashList = taosHashInit(16, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), true, false); - } - - return TSDB_CODE_SUCCESS; - } - - pStmt->multiTbInsert = false; memset(&pStmt->mtb, 0, sizeof(pStmt->mtb)); int32_t code = tsParseSql(pSql, true); @@ -1337,7 +1501,8 @@ int taos_stmt_prepare(TAOS_STMT* stmt, const char* sql, unsigned long length) { } -int taos_stmt_set_tbname(TAOS_STMT* stmt, const char* name) { + +int taos_stmt_set_tbname_tags(TAOS_STMT* stmt, const char* name, TAOS_BIND* tags) { STscStmt* pStmt = (STscStmt*)stmt; SSqlObj* pSql = pStmt->pSql; SSqlCmd* pCmd = &pSql->cmd; @@ -1384,9 +1549,23 @@ int taos_stmt_set_tbname(TAOS_STMT* stmt, const char* name) { tscDebug("0x%"PRIx64" table:%s is already prepared, uid:%" PRIu64, pSql->self, name, pStmt->mtb.currentUid); return TSDB_CODE_SUCCESS; } + + if (pStmt->mtb.tagSet) { + pStmt->mtb.tbname = tscReplaceStrToken(&pSql->sqlstr, &pStmt->mtb.tbname, name); + } else { + if (tags == NULL) { + tscError("No tags set"); + return TSDB_CODE_TSC_APP_ERROR; + } + + int32_t ret = stmtGenInsertStatement(pSql, pStmt, name, tags); + if (ret != TSDB_CODE_SUCCESS) { + return ret; + } + } - pStmt->mtb.tbname = tscReplaceStrToken(&pSql->sqlstr, &pStmt->mtb.tbname, name); pStmt->mtb.nameSet = true; + pStmt->mtb.tagSet = true; tscDebug("0x%"PRIx64" SQL: %s", pSql->self, pSql->sqlstr); @@ -1435,6 +1614,12 @@ int taos_stmt_set_tbname(TAOS_STMT* stmt, const char* name) { return code; } + +int taos_stmt_set_tbname(TAOS_STMT* stmt, const char* name) { + return taos_stmt_set_tbname_tags(stmt, name, NULL); +} + + int taos_stmt_close(TAOS_STMT* stmt) { STscStmt* pStmt = (STscStmt*)stmt; if (!pStmt->isInsert) { @@ -1453,6 +1638,7 @@ int taos_stmt_close(TAOS_STMT* stmt) { pStmt->mtb.pTableBlockHashList = tscDestroyBlockHashTable(pStmt->mtb.pTableBlockHashList, true); taosHashCleanup(pStmt->pSql->cmd.pTableBlockHashList); pStmt->pSql->cmd.pTableBlockHashList = NULL; + taosArrayDestroy(pStmt->mtb.tags); } } diff --git a/src/client/src/tscUtil.c b/src/client/src/tscUtil.c index 37e836dc1c..0ecfbe229a 100644 --- a/src/client/src/tscUtil.c +++ b/src/client/src/tscUtil.c @@ -32,6 +32,67 @@ static void freeQueryInfoImpl(SQueryInfo* pQueryInfo); static void clearAllTableMetaInfo(SQueryInfo* pQueryInfo, bool removeMeta); +int32_t converToStr(char *str, int type, void *buf, int32_t bufSize, int32_t *len) { + int32_t n = 0; + + switch (type) { + case TSDB_DATA_TYPE_NULL: + n = sprintf(str, "null"); + break; + + case TSDB_DATA_TYPE_BOOL: + n = sprintf(str, (*(int8_t*)buf) ? "true" : "false"); + break; + + case TSDB_DATA_TYPE_TINYINT: + n = sprintf(str, "%d", *(int8_t*)buf); + break; + + case TSDB_DATA_TYPE_SMALLINT: + n = sprintf(str, "%d", *(int16_t*)buf); + break; + + case TSDB_DATA_TYPE_INT: + n = sprintf(str, "%d", *(int32_t*)buf); + break; + + case TSDB_DATA_TYPE_BIGINT: + case TSDB_DATA_TYPE_TIMESTAMP: + n = sprintf(str, "%" PRId64, *(int64_t*)buf); + break; + + case TSDB_DATA_TYPE_FLOAT: + n = sprintf(str, "%f", GET_FLOAT_VAL(buf)); + break; + + case TSDB_DATA_TYPE_DOUBLE: + n = sprintf(str, "%f", GET_DOUBLE_VAL(buf)); + break; + + case TSDB_DATA_TYPE_BINARY: + case TSDB_DATA_TYPE_NCHAR: + if (bufSize < 0) { + tscError("invalid buf size"); + return TSDB_CODE_TSC_INVALID_VALUE; + } + + *str = '"'; + memcpy(str + 1, buf, bufSize); + *(str + bufSize + 1) = '"'; + n = bufSize + 2; + break; + + default: + tscError("unsupported type:%d", type); + return TSDB_CODE_TSC_INVALID_VALUE; + } + + *len = n; + + return TSDB_CODE_SUCCESS; +} + + static void tscStrToLower(char *str, int32_t n) { if (str == NULL || n <= 0) { return;} for (int32_t i = 0; i < n; i++) { diff --git a/src/inc/taos.h b/src/inc/taos.h index 6dd695b320..d27828fc36 100644 --- a/src/inc/taos.h +++ b/src/inc/taos.h @@ -112,6 +112,7 @@ typedef struct TAOS_MULTI_BIND { TAOS_STMT *taos_stmt_init(TAOS *taos); int taos_stmt_prepare(TAOS_STMT *stmt, const char *sql, unsigned long length); +int taos_stmt_set_tbname_tags(TAOS_STMT* stmt, const char* name, TAOS_BIND* tags); int taos_stmt_set_tbname(TAOS_STMT* stmt, const char* name); int taos_stmt_is_insert(TAOS_STMT *stmt, int *insert); int taos_stmt_num_params(TAOS_STMT *stmt, int *nums); diff --git a/tests/script/api/batchprepare.c b/tests/script/api/batchprepare.c index db48632cb7..603bc35492 100644 --- a/tests/script/api/batchprepare.c +++ b/tests/script/api/batchprepare.c @@ -840,6 +840,1021 @@ int stmt_func3(TAOS_STMT *stmt) { } + +//1 tables 10 records +int stmt_funcb_autoctb1(TAOS_STMT *stmt) { + struct { + int64_t *ts; + int8_t b[10]; + int8_t v1[10]; + int16_t v2[10]; + int32_t v4[10]; + int64_t v8[10]; + float f4[10]; + double f8[10]; + char bin[10][40]; + } v = {0}; + + v.ts = malloc(sizeof(int64_t) * 1 * 10); + + int *lb = malloc(10 * sizeof(int)); + + TAOS_BIND *tags = calloc(1, sizeof(TAOS_BIND) * 9 * 1); + TAOS_MULTI_BIND *params = calloc(1, sizeof(TAOS_MULTI_BIND) * 1*10); + +// int one_null = 1; + int one_not_null = 0; + + char* is_null = malloc(sizeof(char) * 10); + char* no_null = malloc(sizeof(char) * 10); + + for (int i = 0; i < 10; ++i) { + lb[i] = 40; + no_null[i] = 0; + is_null[i] = (i % 10 == 2) ? 1 : 0; + v.b[i] = (int8_t)(i % 2); + v.v1[i] = (int8_t)((i+1) % 2); + v.v2[i] = (int16_t)i; + v.v4[i] = (int32_t)(i+1); + v.v8[i] = (int64_t)(i+2); + v.f4[i] = (float)(i+3); + v.f8[i] = (double)(i+4); + memset(v.bin[i], '0'+i%10, 40); + } + + for (int i = 0; i < 10; i+=10) { + params[i+0].buffer_type = TSDB_DATA_TYPE_TIMESTAMP; + params[i+0].buffer_length = sizeof(int64_t); + params[i+0].buffer = &v.ts[10*i/10]; + params[i+0].length = NULL; + params[i+0].is_null = no_null; + params[i+0].num = 10; + + params[i+1].buffer_type = TSDB_DATA_TYPE_BOOL; + params[i+1].buffer_length = sizeof(int8_t); + params[i+1].buffer = v.b; + params[i+1].length = NULL; + params[i+1].is_null = is_null; + params[i+1].num = 10; + + params[i+2].buffer_type = TSDB_DATA_TYPE_TINYINT; + params[i+2].buffer_length = sizeof(int8_t); + params[i+2].buffer = v.v1; + params[i+2].length = NULL; + params[i+2].is_null = is_null; + params[i+2].num = 10; + + params[i+3].buffer_type = TSDB_DATA_TYPE_SMALLINT; + params[i+3].buffer_length = sizeof(int16_t); + params[i+3].buffer = v.v2; + params[i+3].length = NULL; + params[i+3].is_null = is_null; + params[i+3].num = 10; + + params[i+4].buffer_type = TSDB_DATA_TYPE_INT; + params[i+4].buffer_length = sizeof(int32_t); + params[i+4].buffer = v.v4; + params[i+4].length = NULL; + params[i+4].is_null = is_null; + params[i+4].num = 10; + + params[i+5].buffer_type = TSDB_DATA_TYPE_BIGINT; + params[i+5].buffer_length = sizeof(int64_t); + params[i+5].buffer = v.v8; + params[i+5].length = NULL; + params[i+5].is_null = is_null; + params[i+5].num = 10; + + params[i+6].buffer_type = TSDB_DATA_TYPE_FLOAT; + params[i+6].buffer_length = sizeof(float); + params[i+6].buffer = v.f4; + params[i+6].length = NULL; + params[i+6].is_null = is_null; + params[i+6].num = 10; + + params[i+7].buffer_type = TSDB_DATA_TYPE_DOUBLE; + params[i+7].buffer_length = sizeof(double); + params[i+7].buffer = v.f8; + params[i+7].length = NULL; + params[i+7].is_null = is_null; + params[i+7].num = 10; + + params[i+8].buffer_type = TSDB_DATA_TYPE_BINARY; + params[i+8].buffer_length = 40; + params[i+8].buffer = v.bin; + params[i+8].length = lb; + params[i+8].is_null = is_null; + params[i+8].num = 10; + + params[i+9].buffer_type = TSDB_DATA_TYPE_BINARY; + params[i+9].buffer_length = 40; + params[i+9].buffer = v.bin; + params[i+9].length = lb; + params[i+9].is_null = is_null; + params[i+9].num = 10; + + } + + int64_t tts = 1591060628000; + for (int i = 0; i < 10; ++i) { + v.ts[i] = tts + i; + } + + + for (int i = 0; i < 1; ++i) { + tags[i+0].buffer_type = TSDB_DATA_TYPE_INT; + tags[i+0].buffer = v.v4; + tags[i+0].is_null = &one_not_null; + tags[i+0].length = NULL; + + tags[i+1].buffer_type = TSDB_DATA_TYPE_BOOL; + tags[i+1].buffer = v.b; + tags[i+1].is_null = &one_not_null; + tags[i+1].length = NULL; + + tags[i+2].buffer_type = TSDB_DATA_TYPE_TINYINT; + tags[i+2].buffer = v.v1; + tags[i+2].is_null = &one_not_null; + tags[i+2].length = NULL; + + tags[i+3].buffer_type = TSDB_DATA_TYPE_SMALLINT; + tags[i+3].buffer = v.v2; + tags[i+3].is_null = &one_not_null; + tags[i+3].length = NULL; + + tags[i+4].buffer_type = TSDB_DATA_TYPE_BIGINT; + tags[i+4].buffer = v.v8; + tags[i+4].is_null = &one_not_null; + tags[i+4].length = NULL; + + tags[i+5].buffer_type = TSDB_DATA_TYPE_FLOAT; + tags[i+5].buffer = v.f4; + tags[i+5].is_null = &one_not_null; + tags[i+5].length = NULL; + + tags[i+6].buffer_type = TSDB_DATA_TYPE_DOUBLE; + tags[i+6].buffer = v.f8; + tags[i+6].is_null = &one_not_null; + tags[i+6].length = NULL; + + tags[i+7].buffer_type = TSDB_DATA_TYPE_BINARY; + tags[i+7].buffer = v.bin; + tags[i+7].is_null = &one_not_null; + tags[i+7].length = (uintptr_t *)lb; + + tags[i+8].buffer_type = TSDB_DATA_TYPE_NCHAR; + tags[i+8].buffer = v.bin; + tags[i+8].is_null = &one_not_null; + tags[i+8].length = (uintptr_t *)lb; + } + + + unsigned long long starttime = getCurrentTime(); + + char *sql = "insert into ? using stb1 tags(?,?,?,?,?,?,?,?,?) values(?,?,?,?,?,?,?,?,?,?)"; + int code = taos_stmt_prepare(stmt, sql, 0); + if (code != 0){ + printf("failed to execute taos_stmt_prepare. code:0x%x\n", code); + exit(1); + } + + int id = 0; + for (int zz = 0; zz < 1; zz++) { + char buf[32]; + sprintf(buf, "m%d", zz); + code = taos_stmt_set_tbname_tags(stmt, buf, tags); + if (code != 0){ + printf("failed to execute taos_stmt_set_tbname_tags. code:0x%x\n", code); + } + + taos_stmt_bind_param_batch(stmt, params + id * 10); + taos_stmt_add_batch(stmt); + } + + if (taos_stmt_execute(stmt) != 0) { + printf("failed to execute insert statement.\n"); + exit(1); + } + + ++id; + + unsigned long long endtime = getCurrentTime(); + printf("insert total %d records, used %u seconds, avg:%u useconds\n", 10, (endtime-starttime)/1000000UL, (endtime-starttime)/(10)); + + free(v.ts); + free(lb); + free(params); + free(is_null); + free(no_null); + + return 0; +} + + + + +//1 tables 10 records +int stmt_funcb_autoctb2(TAOS_STMT *stmt) { + struct { + int64_t *ts; + int8_t b[10]; + int8_t v1[10]; + int16_t v2[10]; + int32_t v4[10]; + int64_t v8[10]; + float f4[10]; + double f8[10]; + char bin[10][40]; + } v = {0}; + + v.ts = malloc(sizeof(int64_t) * 1 * 10); + + int *lb = malloc(10 * sizeof(int)); + + TAOS_BIND *tags = calloc(1, sizeof(TAOS_BIND) * 9 * 1); + TAOS_MULTI_BIND *params = calloc(1, sizeof(TAOS_MULTI_BIND) * 1*10); + +// int one_null = 1; + int one_not_null = 0; + + char* is_null = malloc(sizeof(char) * 10); + char* no_null = malloc(sizeof(char) * 10); + + for (int i = 0; i < 10; ++i) { + lb[i] = 40; + no_null[i] = 0; + is_null[i] = (i % 10 == 2) ? 1 : 0; + v.b[i] = (int8_t)(i % 2); + v.v1[i] = (int8_t)((i+1) % 2); + v.v2[i] = (int16_t)i; + v.v4[i] = (int32_t)(i+1); + v.v8[i] = (int64_t)(i+2); + v.f4[i] = (float)(i+3); + v.f8[i] = (double)(i+4); + memset(v.bin[i], '0'+i%10, 40); + } + + for (int i = 0; i < 10; i+=10) { + params[i+0].buffer_type = TSDB_DATA_TYPE_TIMESTAMP; + params[i+0].buffer_length = sizeof(int64_t); + params[i+0].buffer = &v.ts[10*i/10]; + params[i+0].length = NULL; + params[i+0].is_null = no_null; + params[i+0].num = 10; + + params[i+1].buffer_type = TSDB_DATA_TYPE_BOOL; + params[i+1].buffer_length = sizeof(int8_t); + params[i+1].buffer = v.b; + params[i+1].length = NULL; + params[i+1].is_null = is_null; + params[i+1].num = 10; + + params[i+2].buffer_type = TSDB_DATA_TYPE_TINYINT; + params[i+2].buffer_length = sizeof(int8_t); + params[i+2].buffer = v.v1; + params[i+2].length = NULL; + params[i+2].is_null = is_null; + params[i+2].num = 10; + + params[i+3].buffer_type = TSDB_DATA_TYPE_SMALLINT; + params[i+3].buffer_length = sizeof(int16_t); + params[i+3].buffer = v.v2; + params[i+3].length = NULL; + params[i+3].is_null = is_null; + params[i+3].num = 10; + + params[i+4].buffer_type = TSDB_DATA_TYPE_INT; + params[i+4].buffer_length = sizeof(int32_t); + params[i+4].buffer = v.v4; + params[i+4].length = NULL; + params[i+4].is_null = is_null; + params[i+4].num = 10; + + params[i+5].buffer_type = TSDB_DATA_TYPE_BIGINT; + params[i+5].buffer_length = sizeof(int64_t); + params[i+5].buffer = v.v8; + params[i+5].length = NULL; + params[i+5].is_null = is_null; + params[i+5].num = 10; + + params[i+6].buffer_type = TSDB_DATA_TYPE_FLOAT; + params[i+6].buffer_length = sizeof(float); + params[i+6].buffer = v.f4; + params[i+6].length = NULL; + params[i+6].is_null = is_null; + params[i+6].num = 10; + + params[i+7].buffer_type = TSDB_DATA_TYPE_DOUBLE; + params[i+7].buffer_length = sizeof(double); + params[i+7].buffer = v.f8; + params[i+7].length = NULL; + params[i+7].is_null = is_null; + params[i+7].num = 10; + + params[i+8].buffer_type = TSDB_DATA_TYPE_BINARY; + params[i+8].buffer_length = 40; + params[i+8].buffer = v.bin; + params[i+8].length = lb; + params[i+8].is_null = is_null; + params[i+8].num = 10; + + params[i+9].buffer_type = TSDB_DATA_TYPE_BINARY; + params[i+9].buffer_length = 40; + params[i+9].buffer = v.bin; + params[i+9].length = lb; + params[i+9].is_null = is_null; + params[i+9].num = 10; + + } + + int64_t tts = 1591060628000; + for (int i = 0; i < 10; ++i) { + v.ts[i] = tts + i; + } + + + for (int i = 0; i < 1; ++i) { + tags[i+0].buffer_type = TSDB_DATA_TYPE_INT; + tags[i+0].buffer = v.v4; + tags[i+0].is_null = &one_not_null; + tags[i+0].length = NULL; + + tags[i+1].buffer_type = TSDB_DATA_TYPE_BOOL; + tags[i+1].buffer = v.b; + tags[i+1].is_null = &one_not_null; + tags[i+1].length = NULL; + + tags[i+2].buffer_type = TSDB_DATA_TYPE_TINYINT; + tags[i+2].buffer = v.v1; + tags[i+2].is_null = &one_not_null; + tags[i+2].length = NULL; + + tags[i+3].buffer_type = TSDB_DATA_TYPE_SMALLINT; + tags[i+3].buffer = v.v2; + tags[i+3].is_null = &one_not_null; + tags[i+3].length = NULL; + + tags[i+4].buffer_type = TSDB_DATA_TYPE_BIGINT; + tags[i+4].buffer = v.v8; + tags[i+4].is_null = &one_not_null; + tags[i+4].length = NULL; + + tags[i+5].buffer_type = TSDB_DATA_TYPE_FLOAT; + tags[i+5].buffer = v.f4; + tags[i+5].is_null = &one_not_null; + tags[i+5].length = NULL; + + tags[i+6].buffer_type = TSDB_DATA_TYPE_DOUBLE; + tags[i+6].buffer = v.f8; + tags[i+6].is_null = &one_not_null; + tags[i+6].length = NULL; + + tags[i+7].buffer_type = TSDB_DATA_TYPE_BINARY; + tags[i+7].buffer = v.bin; + tags[i+7].is_null = &one_not_null; + tags[i+7].length = (uintptr_t *)lb; + + tags[i+8].buffer_type = TSDB_DATA_TYPE_NCHAR; + tags[i+8].buffer = v.bin; + tags[i+8].is_null = &one_not_null; + tags[i+8].length = (uintptr_t *)lb; + } + + + unsigned long long starttime = getCurrentTime(); + + char *sql = "insert into ? using stb1 tags(1,true,2,3,4,5.0,6.0,'a','b') values(?,?,?,?,?,?,?,?,?,?)"; + int code = taos_stmt_prepare(stmt, sql, 0); + if (code != 0){ + printf("failed to execute taos_stmt_prepare. code:0x%x\n", code); + exit(1); + } + + int id = 0; + for (int zz = 0; zz < 1; zz++) { + char buf[32]; + sprintf(buf, "m%d", zz); + code = taos_stmt_set_tbname_tags(stmt, buf, tags); + if (code != 0){ + printf("failed to execute taos_stmt_set_tbname_tags. code:0x%x\n", code); + } + + taos_stmt_bind_param_batch(stmt, params + id * 10); + taos_stmt_add_batch(stmt); + } + + if (taos_stmt_execute(stmt) != 0) { + printf("failed to execute insert statement.\n"); + exit(1); + } + + ++id; + + unsigned long long endtime = getCurrentTime(); + printf("insert total %d records, used %u seconds, avg:%u useconds\n", 10, (endtime-starttime)/1000000UL, (endtime-starttime)/(10)); + + free(v.ts); + free(lb); + free(params); + free(is_null); + free(no_null); + + return 0; +} + + + + + +//1 tables 10 records +int stmt_funcb_autoctb3(TAOS_STMT *stmt) { + struct { + int64_t *ts; + int8_t b[10]; + int8_t v1[10]; + int16_t v2[10]; + int32_t v4[10]; + int64_t v8[10]; + float f4[10]; + double f8[10]; + char bin[10][40]; + } v = {0}; + + v.ts = malloc(sizeof(int64_t) * 1 * 10); + + int *lb = malloc(10 * sizeof(int)); + + TAOS_BIND *tags = calloc(1, sizeof(TAOS_BIND) * 9 * 1); + TAOS_MULTI_BIND *params = calloc(1, sizeof(TAOS_MULTI_BIND) * 1*10); + +// int one_null = 1; + int one_not_null = 0; + + char* is_null = malloc(sizeof(char) * 10); + char* no_null = malloc(sizeof(char) * 10); + + for (int i = 0; i < 10; ++i) { + lb[i] = 40; + no_null[i] = 0; + is_null[i] = (i % 10 == 2) ? 1 : 0; + v.b[i] = (int8_t)(i % 2); + v.v1[i] = (int8_t)((i+1) % 2); + v.v2[i] = (int16_t)i; + v.v4[i] = (int32_t)(i+1); + v.v8[i] = (int64_t)(i+2); + v.f4[i] = (float)(i+3); + v.f8[i] = (double)(i+4); + memset(v.bin[i], '0'+i%10, 40); + } + + for (int i = 0; i < 10; i+=10) { + params[i+0].buffer_type = TSDB_DATA_TYPE_TIMESTAMP; + params[i+0].buffer_length = sizeof(int64_t); + params[i+0].buffer = &v.ts[10*i/10]; + params[i+0].length = NULL; + params[i+0].is_null = no_null; + params[i+0].num = 10; + + params[i+1].buffer_type = TSDB_DATA_TYPE_BOOL; + params[i+1].buffer_length = sizeof(int8_t); + params[i+1].buffer = v.b; + params[i+1].length = NULL; + params[i+1].is_null = is_null; + params[i+1].num = 10; + + params[i+2].buffer_type = TSDB_DATA_TYPE_TINYINT; + params[i+2].buffer_length = sizeof(int8_t); + params[i+2].buffer = v.v1; + params[i+2].length = NULL; + params[i+2].is_null = is_null; + params[i+2].num = 10; + + params[i+3].buffer_type = TSDB_DATA_TYPE_SMALLINT; + params[i+3].buffer_length = sizeof(int16_t); + params[i+3].buffer = v.v2; + params[i+3].length = NULL; + params[i+3].is_null = is_null; + params[i+3].num = 10; + + params[i+4].buffer_type = TSDB_DATA_TYPE_INT; + params[i+4].buffer_length = sizeof(int32_t); + params[i+4].buffer = v.v4; + params[i+4].length = NULL; + params[i+4].is_null = is_null; + params[i+4].num = 10; + + params[i+5].buffer_type = TSDB_DATA_TYPE_BIGINT; + params[i+5].buffer_length = sizeof(int64_t); + params[i+5].buffer = v.v8; + params[i+5].length = NULL; + params[i+5].is_null = is_null; + params[i+5].num = 10; + + params[i+6].buffer_type = TSDB_DATA_TYPE_FLOAT; + params[i+6].buffer_length = sizeof(float); + params[i+6].buffer = v.f4; + params[i+6].length = NULL; + params[i+6].is_null = is_null; + params[i+6].num = 10; + + params[i+7].buffer_type = TSDB_DATA_TYPE_DOUBLE; + params[i+7].buffer_length = sizeof(double); + params[i+7].buffer = v.f8; + params[i+7].length = NULL; + params[i+7].is_null = is_null; + params[i+7].num = 10; + + params[i+8].buffer_type = TSDB_DATA_TYPE_BINARY; + params[i+8].buffer_length = 40; + params[i+8].buffer = v.bin; + params[i+8].length = lb; + params[i+8].is_null = is_null; + params[i+8].num = 10; + + params[i+9].buffer_type = TSDB_DATA_TYPE_BINARY; + params[i+9].buffer_length = 40; + params[i+9].buffer = v.bin; + params[i+9].length = lb; + params[i+9].is_null = is_null; + params[i+9].num = 10; + + } + + int64_t tts = 1591060628000; + for (int i = 0; i < 10; ++i) { + v.ts[i] = tts + i; + } + + + for (int i = 0; i < 1; ++i) { + tags[i+0].buffer_type = TSDB_DATA_TYPE_BOOL; + tags[i+0].buffer = v.b; + tags[i+0].is_null = &one_not_null; + tags[i+0].length = NULL; + + tags[i+1].buffer_type = TSDB_DATA_TYPE_SMALLINT; + tags[i+1].buffer = v.v2; + tags[i+1].is_null = &one_not_null; + tags[i+1].length = NULL; + + tags[i+2].buffer_type = TSDB_DATA_TYPE_FLOAT; + tags[i+2].buffer = v.f4; + tags[i+2].is_null = &one_not_null; + tags[i+2].length = NULL; + + tags[i+3].buffer_type = TSDB_DATA_TYPE_BINARY; + tags[i+3].buffer = v.bin; + tags[i+3].is_null = &one_not_null; + tags[i+3].length = (uintptr_t *)lb; + } + + + unsigned long long starttime = getCurrentTime(); + + char *sql = "insert into ? using stb1 tags(1,?,2,?,4,?,6.0,?,'b') values(?,?,?,?,?,?,?,?,?,?)"; + int code = taos_stmt_prepare(stmt, sql, 0); + if (code != 0){ + printf("failed to execute taos_stmt_prepare. code:0x%x\n", code); + exit(1); + } + + int id = 0; + for (int zz = 0; zz < 1; zz++) { + char buf[32]; + sprintf(buf, "m%d", zz); + code = taos_stmt_set_tbname_tags(stmt, buf, tags); + if (code != 0){ + printf("failed to execute taos_stmt_set_tbname_tags. code:0x%x\n", code); + } + + taos_stmt_bind_param_batch(stmt, params + id * 10); + taos_stmt_add_batch(stmt); + } + + if (taos_stmt_execute(stmt) != 0) { + printf("failed to execute insert statement.\n"); + exit(1); + } + + ++id; + + unsigned long long endtime = getCurrentTime(); + printf("insert total %d records, used %u seconds, avg:%u useconds\n", 10, (endtime-starttime)/1000000UL, (endtime-starttime)/(10)); + + free(v.ts); + free(lb); + free(params); + free(is_null); + free(no_null); + + return 0; +} + + + + + + +//1 tables 10 records +int stmt_funcb_autoctb_e1(TAOS_STMT *stmt) { + struct { + int64_t *ts; + int8_t b[10]; + int8_t v1[10]; + int16_t v2[10]; + int32_t v4[10]; + int64_t v8[10]; + float f4[10]; + double f8[10]; + char bin[10][40]; + } v = {0}; + + v.ts = malloc(sizeof(int64_t) * 1 * 10); + + int *lb = malloc(10 * sizeof(int)); + + TAOS_BIND *tags = calloc(1, sizeof(TAOS_BIND) * 9 * 1); + TAOS_MULTI_BIND *params = calloc(1, sizeof(TAOS_MULTI_BIND) * 1*10); + +// int one_null = 1; + int one_not_null = 0; + + char* is_null = malloc(sizeof(char) * 10); + char* no_null = malloc(sizeof(char) * 10); + + for (int i = 0; i < 10; ++i) { + lb[i] = 40; + no_null[i] = 0; + is_null[i] = (i % 10 == 2) ? 1 : 0; + v.b[i] = (int8_t)(i % 2); + v.v1[i] = (int8_t)((i+1) % 2); + v.v2[i] = (int16_t)i; + v.v4[i] = (int32_t)(i+1); + v.v8[i] = (int64_t)(i+2); + v.f4[i] = (float)(i+3); + v.f8[i] = (double)(i+4); + memset(v.bin[i], '0'+i%10, 40); + } + + for (int i = 0; i < 10; i+=10) { + params[i+0].buffer_type = TSDB_DATA_TYPE_TIMESTAMP; + params[i+0].buffer_length = sizeof(int64_t); + params[i+0].buffer = &v.ts[10*i/10]; + params[i+0].length = NULL; + params[i+0].is_null = no_null; + params[i+0].num = 10; + + params[i+1].buffer_type = TSDB_DATA_TYPE_BOOL; + params[i+1].buffer_length = sizeof(int8_t); + params[i+1].buffer = v.b; + params[i+1].length = NULL; + params[i+1].is_null = is_null; + params[i+1].num = 10; + + params[i+2].buffer_type = TSDB_DATA_TYPE_TINYINT; + params[i+2].buffer_length = sizeof(int8_t); + params[i+2].buffer = v.v1; + params[i+2].length = NULL; + params[i+2].is_null = is_null; + params[i+2].num = 10; + + params[i+3].buffer_type = TSDB_DATA_TYPE_SMALLINT; + params[i+3].buffer_length = sizeof(int16_t); + params[i+3].buffer = v.v2; + params[i+3].length = NULL; + params[i+3].is_null = is_null; + params[i+3].num = 10; + + params[i+4].buffer_type = TSDB_DATA_TYPE_INT; + params[i+4].buffer_length = sizeof(int32_t); + params[i+4].buffer = v.v4; + params[i+4].length = NULL; + params[i+4].is_null = is_null; + params[i+4].num = 10; + + params[i+5].buffer_type = TSDB_DATA_TYPE_BIGINT; + params[i+5].buffer_length = sizeof(int64_t); + params[i+5].buffer = v.v8; + params[i+5].length = NULL; + params[i+5].is_null = is_null; + params[i+5].num = 10; + + params[i+6].buffer_type = TSDB_DATA_TYPE_FLOAT; + params[i+6].buffer_length = sizeof(float); + params[i+6].buffer = v.f4; + params[i+6].length = NULL; + params[i+6].is_null = is_null; + params[i+6].num = 10; + + params[i+7].buffer_type = TSDB_DATA_TYPE_DOUBLE; + params[i+7].buffer_length = sizeof(double); + params[i+7].buffer = v.f8; + params[i+7].length = NULL; + params[i+7].is_null = is_null; + params[i+7].num = 10; + + params[i+8].buffer_type = TSDB_DATA_TYPE_BINARY; + params[i+8].buffer_length = 40; + params[i+8].buffer = v.bin; + params[i+8].length = lb; + params[i+8].is_null = is_null; + params[i+8].num = 10; + + params[i+9].buffer_type = TSDB_DATA_TYPE_BINARY; + params[i+9].buffer_length = 40; + params[i+9].buffer = v.bin; + params[i+9].length = lb; + params[i+9].is_null = is_null; + params[i+9].num = 10; + + } + + int64_t tts = 1591060628000; + for (int i = 0; i < 10; ++i) { + v.ts[i] = tts + i; + } + + + for (int i = 0; i < 1; ++i) { + tags[i+0].buffer_type = TSDB_DATA_TYPE_BOOL; + tags[i+0].buffer = v.b; + tags[i+0].is_null = &one_not_null; + tags[i+0].length = NULL; + + tags[i+1].buffer_type = TSDB_DATA_TYPE_SMALLINT; + tags[i+1].buffer = v.v2; + tags[i+1].is_null = &one_not_null; + tags[i+1].length = NULL; + + tags[i+2].buffer_type = TSDB_DATA_TYPE_FLOAT; + tags[i+2].buffer = v.f4; + tags[i+2].is_null = &one_not_null; + tags[i+2].length = NULL; + + tags[i+3].buffer_type = TSDB_DATA_TYPE_BINARY; + tags[i+3].buffer = v.bin; + tags[i+3].is_null = &one_not_null; + tags[i+3].length = (uintptr_t *)lb; + } + + + unsigned long long starttime = getCurrentTime(); + + char *sql = "insert into ? using stb1 (id1,id2,id3,id4,id5,id6,id7,id8,id9) tags(1,?,2,?,4,?,6.0,?,'b') values(?,?,?,?,?,?,?,?,?,?)"; + int code = taos_stmt_prepare(stmt, sql, 0); + if (code != 0){ + printf("failed to execute taos_stmt_prepare. code:0x%x\n", code); + exit(1); + } + + int id = 0; + for (int zz = 0; zz < 1; zz++) { + char buf[32]; + sprintf(buf, "m%d", zz); + code = taos_stmt_set_tbname_tags(stmt, buf, tags); + if (code != 0){ + printf("failed to execute taos_stmt_set_tbname_tags. code:0x%x\n", code); + } + + taos_stmt_bind_param_batch(stmt, params + id * 10); + taos_stmt_add_batch(stmt); + } + + if (taos_stmt_execute(stmt) != 0) { + printf("failed to execute insert statement.\n"); + exit(1); + } + + ++id; + + unsigned long long endtime = getCurrentTime(); + printf("insert total %d records, used %u seconds, avg:%u useconds\n", 10, (endtime-starttime)/1000000UL, (endtime-starttime)/(10)); + + free(v.ts); + free(lb); + free(params); + free(is_null); + free(no_null); + + return 0; +} + + + + + +//1 tables 10 records +int stmt_funcb_autoctb_e2(TAOS_STMT *stmt) { + struct { + int64_t *ts; + int8_t b[10]; + int8_t v1[10]; + int16_t v2[10]; + int32_t v4[10]; + int64_t v8[10]; + float f4[10]; + double f8[10]; + char bin[10][40]; + } v = {0}; + + v.ts = malloc(sizeof(int64_t) * 1 * 10); + + int *lb = malloc(10 * sizeof(int)); + + TAOS_BIND *tags = calloc(1, sizeof(TAOS_BIND) * 9 * 1); + TAOS_MULTI_BIND *params = calloc(1, sizeof(TAOS_MULTI_BIND) * 1*10); + +// int one_null = 1; + int one_not_null = 0; + + char* is_null = malloc(sizeof(char) * 10); + char* no_null = malloc(sizeof(char) * 10); + + for (int i = 0; i < 10; ++i) { + lb[i] = 40; + no_null[i] = 0; + is_null[i] = (i % 10 == 2) ? 1 : 0; + v.b[i] = (int8_t)(i % 2); + v.v1[i] = (int8_t)((i+1) % 2); + v.v2[i] = (int16_t)i; + v.v4[i] = (int32_t)(i+1); + v.v8[i] = (int64_t)(i+2); + v.f4[i] = (float)(i+3); + v.f8[i] = (double)(i+4); + memset(v.bin[i], '0'+i%10, 40); + } + + for (int i = 0; i < 10; i+=10) { + params[i+0].buffer_type = TSDB_DATA_TYPE_TIMESTAMP; + params[i+0].buffer_length = sizeof(int64_t); + params[i+0].buffer = &v.ts[10*i/10]; + params[i+0].length = NULL; + params[i+0].is_null = no_null; + params[i+0].num = 10; + + params[i+1].buffer_type = TSDB_DATA_TYPE_BOOL; + params[i+1].buffer_length = sizeof(int8_t); + params[i+1].buffer = v.b; + params[i+1].length = NULL; + params[i+1].is_null = is_null; + params[i+1].num = 10; + + params[i+2].buffer_type = TSDB_DATA_TYPE_TINYINT; + params[i+2].buffer_length = sizeof(int8_t); + params[i+2].buffer = v.v1; + params[i+2].length = NULL; + params[i+2].is_null = is_null; + params[i+2].num = 10; + + params[i+3].buffer_type = TSDB_DATA_TYPE_SMALLINT; + params[i+3].buffer_length = sizeof(int16_t); + params[i+3].buffer = v.v2; + params[i+3].length = NULL; + params[i+3].is_null = is_null; + params[i+3].num = 10; + + params[i+4].buffer_type = TSDB_DATA_TYPE_INT; + params[i+4].buffer_length = sizeof(int32_t); + params[i+4].buffer = v.v4; + params[i+4].length = NULL; + params[i+4].is_null = is_null; + params[i+4].num = 10; + + params[i+5].buffer_type = TSDB_DATA_TYPE_BIGINT; + params[i+5].buffer_length = sizeof(int64_t); + params[i+5].buffer = v.v8; + params[i+5].length = NULL; + params[i+5].is_null = is_null; + params[i+5].num = 10; + + params[i+6].buffer_type = TSDB_DATA_TYPE_FLOAT; + params[i+6].buffer_length = sizeof(float); + params[i+6].buffer = v.f4; + params[i+6].length = NULL; + params[i+6].is_null = is_null; + params[i+6].num = 10; + + params[i+7].buffer_type = TSDB_DATA_TYPE_DOUBLE; + params[i+7].buffer_length = sizeof(double); + params[i+7].buffer = v.f8; + params[i+7].length = NULL; + params[i+7].is_null = is_null; + params[i+7].num = 10; + + params[i+8].buffer_type = TSDB_DATA_TYPE_BINARY; + params[i+8].buffer_length = 40; + params[i+8].buffer = v.bin; + params[i+8].length = lb; + params[i+8].is_null = is_null; + params[i+8].num = 10; + + params[i+9].buffer_type = TSDB_DATA_TYPE_BINARY; + params[i+9].buffer_length = 40; + params[i+9].buffer = v.bin; + params[i+9].length = lb; + params[i+9].is_null = is_null; + params[i+9].num = 10; + + } + + int64_t tts = 1591060628000; + for (int i = 0; i < 10; ++i) { + v.ts[i] = tts + i; + } + + + for (int i = 0; i < 1; ++i) { + tags[i+0].buffer_type = TSDB_DATA_TYPE_INT; + tags[i+0].buffer = v.v4; + tags[i+0].is_null = &one_not_null; + tags[i+0].length = NULL; + + tags[i+1].buffer_type = TSDB_DATA_TYPE_BOOL; + tags[i+1].buffer = v.b; + tags[i+1].is_null = &one_not_null; + tags[i+1].length = NULL; + + tags[i+2].buffer_type = TSDB_DATA_TYPE_TINYINT; + tags[i+2].buffer = v.v1; + tags[i+2].is_null = &one_not_null; + tags[i+2].length = NULL; + + tags[i+3].buffer_type = TSDB_DATA_TYPE_SMALLINT; + tags[i+3].buffer = v.v2; + tags[i+3].is_null = &one_not_null; + tags[i+3].length = NULL; + + tags[i+4].buffer_type = TSDB_DATA_TYPE_BIGINT; + tags[i+4].buffer = v.v8; + tags[i+4].is_null = &one_not_null; + tags[i+4].length = NULL; + + tags[i+5].buffer_type = TSDB_DATA_TYPE_FLOAT; + tags[i+5].buffer = v.f4; + tags[i+5].is_null = &one_not_null; + tags[i+5].length = NULL; + + tags[i+6].buffer_type = TSDB_DATA_TYPE_DOUBLE; + tags[i+6].buffer = v.f8; + tags[i+6].is_null = &one_not_null; + tags[i+6].length = NULL; + + tags[i+7].buffer_type = TSDB_DATA_TYPE_BINARY; + tags[i+7].buffer = v.bin; + tags[i+7].is_null = &one_not_null; + tags[i+7].length = (uintptr_t *)lb; + + tags[i+8].buffer_type = TSDB_DATA_TYPE_NCHAR; + tags[i+8].buffer = v.bin; + tags[i+8].is_null = &one_not_null; + tags[i+8].length = (uintptr_t *)lb; + } + + + unsigned long long starttime = getCurrentTime(); + + char *sql = "insert into ? using stb1 tags(?,?,?,?,?,?,?,?,?) values(?,?,?,?,?,?,?,?,?,?)"; + int code = taos_stmt_prepare(stmt, sql, 0); + if (code != 0){ + printf("failed to execute taos_stmt_prepare. code:0x%x\n", code); + exit(1); + } + + int id = 0; + for (int zz = 0; zz < 1; zz++) { + char buf[32]; + sprintf(buf, "m%d", zz); + code = taos_stmt_set_tbname_tags(stmt, buf, NULL); + if (code != 0){ + printf("failed to execute taos_stmt_set_tbname_tags. code:0x%x\n", code); + exit(1); + } + + taos_stmt_bind_param_batch(stmt, params + id * 10); + taos_stmt_add_batch(stmt); + } + + if (taos_stmt_execute(stmt) != 0) { + printf("failed to execute insert statement.\n"); + exit(1); + } + + ++id; + + unsigned long long endtime = getCurrentTime(); + printf("insert total %d records, used %u seconds, avg:%u useconds\n", 10, (endtime-starttime)/1000000UL, (endtime-starttime)/(10)); + + free(v.ts); + free(lb); + free(params); + free(is_null); + free(no_null); + + return 0; +} + + + //300 tables 60 records int stmt_funcb1(TAOS_STMT *stmt) { struct { @@ -2540,7 +3555,7 @@ int sql_s_perf1(TAOS *taos) { } -void prepare(TAOS *taos, int bigsize) { +void prepare(TAOS *taos, int bigsize, int createChildTable) { TAOS_RES *result; int code; @@ -2558,15 +3573,34 @@ void prepare(TAOS *taos, int bigsize) { result = taos_query(taos, "use demo"); taos_free_result(result); - - // create table - for (int i = 0 ; i < 300; i++) { + + if (createChildTable) { + // create table + for (int i = 0 ; i < 300; i++) { + char buf[1024]; + if (bigsize) { + sprintf(buf, "create table m%d (ts timestamp, b bool, v1 tinyint, v2 smallint, v4 int, v8 bigint, f4 float, f8 double, bin binary(40), bin2 binary(40))", i) ; + } else { + sprintf(buf, "create table m%d (ts timestamp, b int)", i) ; + } + result = taos_query(taos, buf); + code = taos_errno(result); + if (code != 0) { + printf("failed to create table, reason:%s\n", taos_errstr(result)); + taos_free_result(result); + exit(1); + } + taos_free_result(result); + } + } else { char buf[1024]; if (bigsize) { - sprintf(buf, "create table m%d (ts timestamp, b bool, v1 tinyint, v2 smallint, v4 int, v8 bigint, f4 float, f8 double, bin binary(40), bin2 binary(40))", i) ; + sprintf(buf, "create stable stb1 (ts timestamp, b bool, v1 tinyint, v2 smallint, v4 int, v8 bigint, f4 float, f8 double, bin binary(40), bin2 binary(40))" + " tags(id1 int, id2 bool, id3 tinyint, id4 smallint, id5 bigint, id6 float, id7 double, id8 binary(40), id9 nchar(40))") ; } else { - sprintf(buf, "create table m%d (ts timestamp, b int)", i) ; + sprintf(buf, "create stable stb1 (ts timestamp, b int) tags(id1 int, id2 bool, id3 tinyint, id4 smallint, id5 bigint, id6 float, id7 double, id8 binary(40), id9 nchar(40))") ; } + result = taos_query(taos, buf); code = taos_errno(result); if (code != 0) { @@ -2640,8 +3674,8 @@ void* runcase(void *par) { (void)idx; -#if 0 - prepare(taos, 1); +#if 1 + prepare(taos, 1, 1); stmt = taos_stmt_init(taos); @@ -2664,8 +3698,8 @@ void* runcase(void *par) { #endif -#if 0 - prepare(taos, 1); +#if 1 + prepare(taos, 1, 1); stmt = taos_stmt_init(taos); @@ -2679,8 +3713,8 @@ void* runcase(void *par) { #endif -#if 0 - prepare(taos, 1); +#if 1 + prepare(taos, 1, 1); stmt = taos_stmt_init(taos); @@ -2699,7 +3733,7 @@ void* runcase(void *par) { #endif #if 1 - prepare(taos, 1); + prepare(taos, 1, 1); stmt = taos_stmt_init(taos); @@ -2720,12 +3754,11 @@ void* runcase(void *par) { printf("check result end\n"); taos_stmt_close(stmt); - return NULL; #endif #if 1 - prepare(taos, 1); + prepare(taos, 1, 1); stmt = taos_stmt_init(taos); @@ -2749,7 +3782,7 @@ void* runcase(void *par) { #endif #if 1 - prepare(taos, 1); + prepare(taos, 1, 1); stmt = taos_stmt_init(taos); @@ -2773,7 +3806,7 @@ void* runcase(void *par) { #endif #if 1 - prepare(taos, 1); + prepare(taos, 1, 1); stmt = taos_stmt_init(taos); @@ -2798,7 +3831,7 @@ void* runcase(void *par) { #if 1 - prepare(taos, 1); + prepare(taos, 1, 1); stmt = taos_stmt_init(taos); @@ -2813,11 +3846,88 @@ void* runcase(void *par) { check_result(taos, "m299", 0, 180000); printf("check result end\n"); taos_stmt_close(stmt); + +#endif + +#if 1 + prepare(taos, 1, 0); + + stmt = taos_stmt_init(taos); + + printf("1t+10r+bm+autoctb start\n"); + stmt_funcb_autoctb1(stmt); + printf("1t+10r+bm+autoctb end\n"); + printf("check result start\n"); + check_result(taos, "m0", 1, 10); + printf("check result end\n"); + taos_stmt_close(stmt); + +#endif + +#if 1 + prepare(taos, 1, 0); + + stmt = taos_stmt_init(taos); + + printf("1t+10r+bm+autoctb start\n"); + stmt_funcb_autoctb2(stmt); + printf("1t+10r+bm+autoctb end\n"); + printf("check result start\n"); + check_result(taos, "m0", 1, 10); + printf("check result end\n"); + taos_stmt_close(stmt); + +#endif + + +#if 1 + prepare(taos, 1, 0); + + stmt = taos_stmt_init(taos); + + printf("1t+10r+bm+autoctb start\n"); + stmt_funcb_autoctb3(stmt); + printf("1t+10r+bm+autoctb end\n"); + printf("check result start\n"); + check_result(taos, "m0", 1, 10); + printf("check result end\n"); + taos_stmt_close(stmt); + +#endif + +#if 1 + prepare(taos, 1, 0); + + stmt = taos_stmt_init(taos); + + printf("1t+10r+bm+autoctb+e1 start\n"); + stmt_funcb_autoctb_e1(stmt); + printf("1t+10r+bm+autoctb+e1 end\n"); + printf("check result start\n"); + check_result(taos, "m0", 1, 10); + printf("check result end\n"); + taos_stmt_close(stmt); + +#endif + +#if 1 + prepare(taos, 1, 0); + + stmt = taos_stmt_init(taos); + + printf("1t+10r+bm+autoctb+e2 start\n"); + stmt_funcb_autoctb_e2(stmt); + printf("1t+10r+bm+autoctb+e2 end\n"); + printf("check result start\n"); + check_result(taos, "m0", 1, 10); + printf("check result end\n"); + taos_stmt_close(stmt); + #endif #if 1 - prepare(taos, 1); + prepare(taos, 1, 1); stmt = taos_stmt_init(taos); @@ -2836,7 +3946,7 @@ void* runcase(void *par) { #endif #if 1 - prepare(taos, 1); + prepare(taos, 1, 1); stmt = taos_stmt_init(taos); @@ -2856,7 +3966,7 @@ void* runcase(void *par) { #if 1 - prepare(taos, 1); + prepare(taos, 1, 1); stmt = taos_stmt_init(taos); @@ -2874,7 +3984,7 @@ void* runcase(void *par) { #endif #if 1 - prepare(taos, 1); + prepare(taos, 1, 1); stmt = taos_stmt_init(taos); @@ -2890,7 +4000,7 @@ void* runcase(void *par) { #if 1 - prepare(taos, 1); + prepare(taos, 1, 1); stmt = taos_stmt_init(taos); @@ -2908,7 +4018,7 @@ void* runcase(void *par) { #endif #if 1 - prepare(taos, 1); + prepare(taos, 1, 1); stmt = taos_stmt_init(taos); @@ -2927,7 +4037,7 @@ void* runcase(void *par) { #endif #if 1 - prepare(taos, 1); + prepare(taos, 1, 1); stmt = taos_stmt_init(taos); @@ -2952,7 +4062,7 @@ void* runcase(void *par) { #if 1 - prepare(taos, 1); + prepare(taos, 1, 1); stmt = taos_stmt_init(taos); @@ -2972,7 +4082,7 @@ void* runcase(void *par) { #if 1 - prepare(taos, 1); + prepare(taos, 1, 1); (void)stmt; printf("120t+60r+sql start\n"); @@ -2988,7 +4098,7 @@ void* runcase(void *par) { #endif #if 1 - prepare(taos, 1); + prepare(taos, 1, 1); (void)stmt; printf("1t+60r+sql start\n"); From 0e97b397879e5e843a2a1775e7eda64e662b96d9 Mon Sep 17 00:00:00 2001 From: Elias Soong Date: Thu, 27 May 2021 17:10:17 +0800 Subject: [PATCH 47/70] [TD-4387] : fix broken link to server config doc. --- documentation20/cn/12.taos-sql/docs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation20/cn/12.taos-sql/docs.md b/documentation20/cn/12.taos-sql/docs.md index b130e0544c..af78074eb2 100644 --- a/documentation20/cn/12.taos-sql/docs.md +++ b/documentation20/cn/12.taos-sql/docs.md @@ -76,7 +76,7 @@ TDengine 缺省的时间戳是毫秒精度,但通过修改配置参数 enableM 4) 一条SQL 语句的最大长度为65480个字符; - 5) 数据库还有更多与存储相关的配置参数,请参见 [服务端配置](https://www.taosdata.com/cn/documentation/taos-sql#management) 章节。 + 5) 数据库还有更多与存储相关的配置参数,请参见 [服务端配置](https://www.taosdata.com/cn/documentation/administrator#config) 章节。 - **显示系统当前参数** From 0dcff322e5b886448b9d74a82b39b87f8e781f8e Mon Sep 17 00:00:00 2001 From: dapan1121 <89396746@qq.com> Date: Thu, 27 May 2021 17:51:09 +0800 Subject: [PATCH 48/70] fix bug --- tests/script/api/batchprepare.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/script/api/batchprepare.c b/tests/script/api/batchprepare.c index 603bc35492..262076bafc 100644 --- a/tests/script/api/batchprepare.c +++ b/tests/script/api/batchprepare.c @@ -1604,7 +1604,7 @@ int stmt_funcb_autoctb_e1(TAOS_STMT *stmt) { int code = taos_stmt_prepare(stmt, sql, 0); if (code != 0){ printf("failed to execute taos_stmt_prepare. code:0x%x\n", code); - exit(1); + return -1; } int id = 0; @@ -1827,7 +1827,7 @@ int stmt_funcb_autoctb_e2(TAOS_STMT *stmt) { code = taos_stmt_set_tbname_tags(stmt, buf, NULL); if (code != 0){ printf("failed to execute taos_stmt_set_tbname_tags. code:0x%x\n", code); - exit(1); + return -1; } taos_stmt_bind_param_batch(stmt, params + id * 10); @@ -3904,7 +3904,7 @@ void* runcase(void *par) { stmt_funcb_autoctb_e1(stmt); printf("1t+10r+bm+autoctb+e1 end\n"); printf("check result start\n"); - check_result(taos, "m0", 1, 10); + check_result(taos, "m0", 1, 0); printf("check result end\n"); taos_stmt_close(stmt); @@ -3919,7 +3919,7 @@ void* runcase(void *par) { stmt_funcb_autoctb_e2(stmt); printf("1t+10r+bm+autoctb+e2 end\n"); printf("check result start\n"); - check_result(taos, "m0", 1, 10); + check_result(taos, "m0", 1, 0); printf("check result end\n"); taos_stmt_close(stmt); From 5592f1ec0bd74cdd972670c00816a52b9aecfb1b Mon Sep 17 00:00:00 2001 From: dapan1121 <89396746@qq.com> Date: Thu, 27 May 2021 18:06:40 +0800 Subject: [PATCH 49/70] fix case issue --- tests/script/api/batchprepare.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/script/api/batchprepare.c b/tests/script/api/batchprepare.c index 262076bafc..1d29ca6dad 100644 --- a/tests/script/api/batchprepare.c +++ b/tests/script/api/batchprepare.c @@ -3904,7 +3904,7 @@ void* runcase(void *par) { stmt_funcb_autoctb_e1(stmt); printf("1t+10r+bm+autoctb+e1 end\n"); printf("check result start\n"); - check_result(taos, "m0", 1, 0); + //check_result(taos, "m0", 1, 0); printf("check result end\n"); taos_stmt_close(stmt); @@ -3919,7 +3919,7 @@ void* runcase(void *par) { stmt_funcb_autoctb_e2(stmt); printf("1t+10r+bm+autoctb+e2 end\n"); printf("check result start\n"); - check_result(taos, "m0", 1, 0); + //check_result(taos, "m0", 1, 0); printf("check result end\n"); taos_stmt_close(stmt); From 7b602ab65872a481bbe162b4bcf63f1dde8c70d2 Mon Sep 17 00:00:00 2001 From: dapan1121 <89396746@qq.com> Date: Thu, 27 May 2021 18:36:08 +0800 Subject: [PATCH 50/70] fix case issue --- tests/script/api/batchprepare.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/script/api/batchprepare.c b/tests/script/api/batchprepare.c index 1d29ca6dad..92253be78c 100644 --- a/tests/script/api/batchprepare.c +++ b/tests/script/api/batchprepare.c @@ -3562,7 +3562,7 @@ void prepare(TAOS *taos, int bigsize, int createChildTable) { result = taos_query(taos, "drop database demo"); taos_free_result(result); - result = taos_query(taos, "create database demo"); + result = taos_query(taos, "create database demo keep 36500"); code = taos_errno(result); if (code != 0) { printf("failed to create database, reason:%s\n", taos_errstr(result)); @@ -3627,7 +3627,7 @@ void preparem(TAOS *taos, int bigsize, int idx) { result = taos_query(taos, sql); taos_free_result(result); - sprintf(sql, "create database %s", dbname); + sprintf(sql, "create database %s keep 36500", dbname); result = taos_query(taos, sql); code = taos_errno(result); if (code != 0) { From 703cc9a5e187040bcd4957ef35aa426c0a6a0380 Mon Sep 17 00:00:00 2001 From: Shuduo Sang Date: Fri, 28 May 2021 00:00:00 +0800 Subject: [PATCH 51/70] [TD-4382]: taosdemo query result file is null. (#6263) Co-authored-by: Shuduo Sang --- src/kit/taosdemo/taosdemo.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/kit/taosdemo/taosdemo.c b/src/kit/taosdemo/taosdemo.c index 888dc4a04e..2d1e4c03d6 100644 --- a/src/kit/taosdemo/taosdemo.c +++ b/src/kit/taosdemo/taosdemo.c @@ -6642,7 +6642,7 @@ static void *specifiedTableQuery(void *sarg) { uint64_t lastPrintTime = taosGetTimestampMs(); uint64_t startTs = taosGetTimestampMs(); - if (g_queryInfo.specifiedQueryInfo.result[pThreadInfo->querySeq] != NULL) { + if (g_queryInfo.specifiedQueryInfo.result[pThreadInfo->querySeq][0] != '\0') { sprintf(pThreadInfo->filePath, "%s-%d", g_queryInfo.specifiedQueryInfo.result[pThreadInfo->querySeq], pThreadInfo->threadID); @@ -6743,7 +6743,7 @@ static void *superTableQuery(void *sarg) { for (int j = 0; j < g_queryInfo.superQueryInfo.sqlCount; j++) { memset(sqlstr,0,sizeof(sqlstr)); replaceChildTblName(g_queryInfo.superQueryInfo.sql[j], sqlstr, i); - if (g_queryInfo.superQueryInfo.result[j] != NULL) { + if (g_queryInfo.superQueryInfo.result[j][0] != '\0') { sprintf(pThreadInfo->filePath, "%s-%d", g_queryInfo.superQueryInfo.result[j], pThreadInfo->threadID); @@ -7174,7 +7174,7 @@ static void *specifiedSubscribe(void *sarg) { "taosdemo-subscribe-%"PRIu64"-%d", pThreadInfo->querySeq, pThreadInfo->threadID); - if (g_queryInfo.specifiedQueryInfo.result[pThreadInfo->querySeq] != NULL) { + if (g_queryInfo.specifiedQueryInfo.result[pThreadInfo->querySeq][0] != '\0') { sprintf(pThreadInfo->filePath, "%s-%d", g_queryInfo.specifiedQueryInfo.result[pThreadInfo->querySeq], pThreadInfo->threadID); From dae5a07488cd5183a57b23077cf7ce9c04d02921 Mon Sep 17 00:00:00 2001 From: Shuduo Sang Date: Fri, 28 May 2021 00:00:26 +0800 Subject: [PATCH 52/70] Feature/sangshuduo/td 4068 taosdemo stmt (#6250) * merge with develop branch. change query/tests/CMakeLists.txt to allow unused function and variable. * refactor data generating. * refactor. * refactor. * refactor. * refactor. * refactor * add prepare stmt function. * refactor get rand timestamp. * fix windows compile error. * copy logic of generate data for stmt. * insert data basically works now. * fix windows compile issue. * [TD-4068]: taosdemo stmt interface. stb batch insert works. * [TD-4068]: taosdemo support stmt. normal table insert works. * [TD-4068]: taosdemo support stmt. interlace write works. Co-authored-by: Shuduo Sang --- src/kit/taosdemo/taosdemo.c | 686 ++++++++++++++++++++++-------------- 1 file changed, 417 insertions(+), 269 deletions(-) diff --git a/src/kit/taosdemo/taosdemo.c b/src/kit/taosdemo/taosdemo.c index 2d1e4c03d6..6ad5fadf7c 100644 --- a/src/kit/taosdemo/taosdemo.c +++ b/src/kit/taosdemo/taosdemo.c @@ -1054,6 +1054,19 @@ static void parse_args(int argc, char *argv[], SArguments *arguments) { } } + int columnCount; + for (columnCount = 0; columnCount < MAX_NUM_DATATYPE; columnCount ++) { + if (g_args.datatype[columnCount] == NULL) { + break; + } + } + + if (0 == columnCount) { + perror("data type error!"); + exit(-1); + } + g_args.num_of_CPR = columnCount; + if (((arguments->debug_print) && (arguments->metaFile == NULL)) || arguments->verbose_print) { printf("###################################################################\n"); @@ -1076,7 +1089,7 @@ static void parse_args(int argc, char *argv[], SArguments *arguments) { } printf("# Insertion interval: %"PRIu64"\n", arguments->insert_interval); - printf("# Number of records per req: %ud\n", + printf("# Number of records per req: %u\n", arguments->num_of_RPR); printf("# Max SQL length: %"PRIu64"\n", arguments->max_sql_len); @@ -1368,7 +1381,7 @@ static int printfInsertMeta() { g_Dbs.threadCountByCreateTbl); printf("top insert interval: \033[33m%"PRIu64"\033[0m\n", g_args.insert_interval); - printf("number of records per req: \033[33m%ud\033[0m\n", + printf("number of records per req: \033[33m%u\033[0m\n", g_args.num_of_RPR); printf("max sql length: \033[33m%"PRIu64"\033[0m\n", g_args.max_sql_len); @@ -1494,7 +1507,7 @@ static int printfInsertMeta() { printf(" multiThreadWriteOneTbl: \033[33myes\033[0m\n"); } */ - printf(" interlaceRows: \033[33m%ud\033[0m\n", + printf(" interlaceRows: \033[33m%u\033[0m\n", g_Dbs.db[i].superTbls[j].interlaceRows); if (g_Dbs.db[i].superTbls[j].interlaceRows > 0) { @@ -1572,7 +1585,7 @@ static void printfInsertMetaToFile(FILE* fp) { fprintf(fp, "resultFile: %s\n", g_Dbs.resultFile); fprintf(fp, "thread num of insert data: %d\n", g_Dbs.threadCount); fprintf(fp, "thread num of create table: %d\n", g_Dbs.threadCountByCreateTbl); - fprintf(fp, "number of records per req: %ud\n", g_args.num_of_RPR); + fprintf(fp, "number of records per req: %u\n", g_args.num_of_RPR); fprintf(fp, "max sql length: %"PRIu64"\n", g_args.max_sql_len); fprintf(fp, "database count: %d\n", g_Dbs.dbCount); @@ -1669,7 +1682,7 @@ static void printfInsertMetaToFile(FILE* fp) { (g_Dbs.db[i].superTbls[j].iface==REST_IFACE)?"rest":"stmt"); fprintf(fp, " insertRows: %"PRId64"\n", g_Dbs.db[i].superTbls[j].insertRows); - fprintf(fp, " interlace rows: %ud\n", + fprintf(fp, " interlace rows: %u\n", g_Dbs.db[i].superTbls[j].interlaceRows); if (g_Dbs.db[i].superTbls[j].interlaceRows > 0) { fprintf(fp, " stable insert interval: %"PRIu64"\n", @@ -1682,7 +1695,7 @@ static void printfInsertMetaToFile(FILE* fp) { fprintf(fp, " multiThreadWriteOneTbl: yes\n"); } */ - fprintf(fp, " interlaceRows: %ud\n", + fprintf(fp, " interlaceRows: %u\n", g_Dbs.db[i].superTbls[j].interlaceRows); fprintf(fp, " disorderRange: %d\n", g_Dbs.db[i].superTbls[j].disorderRange); @@ -3075,11 +3088,14 @@ static void createChildTables() { // normal table len = snprintf(tblColsBuf, MAX_SQL_SIZE, "(TS TIMESTAMP"); for (int j = 0; j < g_args.num_of_CPR; j++) { - if ((strncasecmp(g_args.datatype[j], "BINARY", strlen("BINARY")) == 0) + if (g_args.datatype[j] + && ((strncasecmp(g_args.datatype[j], + "BINARY", strlen("BINARY")) == 0) || (strncasecmp(g_args.datatype[j], - "NCHAR", strlen("NCHAR")) == 0)) { + "NCHAR", strlen("NCHAR")) == 0))) { snprintf(tblColsBuf + len, MAX_SQL_SIZE - len, - ", COL%d %s(%d)", j, g_args.datatype[j], g_args.len_of_binary); + ", COL%d %s(%d)", j, g_args.datatype[j], + g_args.len_of_binary); } else { snprintf(tblColsBuf + len, MAX_SQL_SIZE - len, ", COL%d %s", j, g_args.datatype[j]); @@ -3561,9 +3577,9 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { // rows per table need be less than insert batch if (g_args.interlace_rows > g_args.num_of_RPR) { - printf("NOTICE: interlace rows value %ud > num_of_records_per_req %ud\n\n", + printf("NOTICE: interlace rows value %u > num_of_records_per_req %u\n\n", g_args.interlace_rows, g_args.num_of_RPR); - printf(" interlace rows value will be set to num_of_records_per_req %ud\n\n", + printf(" interlace rows value will be set to num_of_records_per_req %u\n\n", g_args.num_of_RPR); prompt(); g_args.interlace_rows = g_args.num_of_RPR; @@ -4030,10 +4046,10 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { g_Dbs.db[i].superTbls[j].interlaceRows = stbInterlaceRows->valueint; // rows per table need be less than insert batch if (g_Dbs.db[i].superTbls[j].interlaceRows > g_args.num_of_RPR) { - printf("NOTICE: db[%d].superTbl[%d]'s interlace rows value %ud > num_of_records_per_req %ud\n\n", + printf("NOTICE: db[%d].superTbl[%d]'s interlace rows value %u > num_of_records_per_req %u\n\n", i, j, g_Dbs.db[i].superTbls[j].interlaceRows, g_args.num_of_RPR); - printf(" interlace rows value will be set to num_of_records_per_req %ud\n\n", + printf(" interlace rows value will be set to num_of_records_per_req %u\n\n", g_args.num_of_RPR); prompt(); g_Dbs.db[i].superTbls[j].interlaceRows = g_args.num_of_RPR; @@ -4773,44 +4789,34 @@ static int64_t generateData(char *recBuf, char **data_type, memset(recBuf, 0, MAX_DATA_SIZE); char *pstr = recBuf; pstr += sprintf(pstr, "(%" PRId64, timestamp); - int c = 0; - for (; c < MAX_NUM_DATATYPE; c++) { - if (data_type[c] == NULL) { - break; - } - } + int columnCount = g_args.num_of_CPR; - if (0 == c) { - perror("data type error!"); - exit(-1); - } - - for (int i = 0; i < c; i++) { - if (strcasecmp(data_type[i % c], "TINYINT") == 0) { + for (int i = 0; i < columnCount; i++) { + if (strcasecmp(data_type[i % columnCount], "TINYINT") == 0) { pstr += sprintf(pstr, ",%d", rand_tinyint() ); - } else if (strcasecmp(data_type[i % c], "SMALLINT") == 0) { + } else if (strcasecmp(data_type[i % columnCount], "SMALLINT") == 0) { pstr += sprintf(pstr, ",%d", rand_smallint()); - } else if (strcasecmp(data_type[i % c], "INT") == 0) { + } else if (strcasecmp(data_type[i % columnCount], "INT") == 0) { pstr += sprintf(pstr, ",%d", rand_int()); - } else if (strcasecmp(data_type[i % c], "BIGINT") == 0) { + } else if (strcasecmp(data_type[i % columnCount], "BIGINT") == 0) { pstr += sprintf(pstr, ",%" PRId64, rand_bigint()); - } else if (strcasecmp(data_type[i % c], "TIMESTAMP") == 0) { + } else if (strcasecmp(data_type[i % columnCount], "TIMESTAMP") == 0) { pstr += sprintf(pstr, ",%" PRId64, rand_bigint()); - } else if (strcasecmp(data_type[i % c], "FLOAT") == 0) { + } else if (strcasecmp(data_type[i % columnCount], "FLOAT") == 0) { pstr += sprintf(pstr, ",%10.4f", rand_float()); - } else if (strcasecmp(data_type[i % c], "DOUBLE") == 0) { + } else if (strcasecmp(data_type[i % columnCount], "DOUBLE") == 0) { double t = rand_double(); pstr += sprintf(pstr, ",%20.8f", t); - } else if (strcasecmp(data_type[i % c], "BOOL") == 0) { + } else if (strcasecmp(data_type[i % columnCount], "BOOL") == 0) { bool b = rand_bool() & 1; pstr += sprintf(pstr, ",%s", b ? "true" : "false"); - } else if (strcasecmp(data_type[i % c], "BINARY") == 0) { + } else if (strcasecmp(data_type[i % columnCount], "BINARY") == 0) { char *s = malloc(lenOfBinary); rand_string(s, lenOfBinary); pstr += sprintf(pstr, ",\"%s\"", s); free(s); - } else if (strcasecmp(data_type[i % c], "NCHAR") == 0) { + } else if (strcasecmp(data_type[i % columnCount], "NCHAR") == 0) { char *s = malloc(lenOfBinary); rand_string(s, lenOfBinary); pstr += sprintf(pstr, ",\"%s\"", s); @@ -4857,46 +4863,60 @@ static int prepareSampleDataForSTable(SSuperTable *superTblInfo) { return 0; } -static int64_t execInsert(threadInfo *pThreadInfo, uint64_t k) +static int32_t execInsert(threadInfo *pThreadInfo, uint32_t k) { - int affectedRows; - SSuperTable* superTblInfo = pThreadInfo->superTblInfo; + int32_t affectedRows; + SSuperTable* superTblInfo = pThreadInfo->superTblInfo; - verbosePrint("[%d] %s() LN%d %s\n", pThreadInfo->threadID, + verbosePrint("[%d] %s() LN%d %s\n", pThreadInfo->threadID, __func__, __LINE__, pThreadInfo->buffer); - if (superTblInfo) { - if (superTblInfo->iface == TAOSC_IFACE) { - affectedRows = queryDbExec( - pThreadInfo->taos, - pThreadInfo->buffer, INSERT_TYPE, false); - } else if (superTblInfo->iface == REST_IFACE) { - if (0 != postProceSql(g_Dbs.host, &g_Dbs.serv_addr, g_Dbs.port, - pThreadInfo->buffer, NULL /* not set result file */)) { - affectedRows = -1; - printf("========restful return fail, threadID[%d]\n", - pThreadInfo->threadID); - } else { - affectedRows = k; - } - } else if (superTblInfo->iface == STMT_IFACE) { - debugPrint("%s() LN%d, stmt=%p", __func__, __LINE__, pThreadInfo->stmt); - if (0 != taos_stmt_execute(pThreadInfo->stmt)) { - errorPrint("%s() LN%d, failied to execute insert statement\n", - __func__, __LINE__); - exit(-1); - } - affectedRows = k; - } else { - errorPrint("%s() LN%d: unknown insert mode: %d\n", - __func__, __LINE__, superTblInfo->iface); - affectedRows = 0; + uint16_t iface; + if (superTblInfo) + iface = superTblInfo->iface; + else + iface = g_args.iface; + + debugPrint("[%d] %s() LN%d %s\n", pThreadInfo->threadID, + __func__, __LINE__, + (g_args.iface==TAOSC_IFACE)? + "taosc":(g_args.iface==REST_IFACE)?"rest":"stmt"); + + switch(iface) { + case TAOSC_IFACE: + affectedRows = queryDbExec( + pThreadInfo->taos, + pThreadInfo->buffer, INSERT_TYPE, false); + break; + + case REST_IFACE: + if (0 != postProceSql(g_Dbs.host, &g_Dbs.serv_addr, g_Dbs.port, + pThreadInfo->buffer, NULL /* not set result file */)) { + affectedRows = -1; + printf("========restful return fail, threadID[%d]\n", + pThreadInfo->threadID); + } else { + affectedRows = k; + } + break; + + case STMT_IFACE: + debugPrint("%s() LN%d, stmt=%p", __func__, __LINE__, pThreadInfo->stmt); + if (0 != taos_stmt_execute(pThreadInfo->stmt)) { + errorPrint("%s() LN%d, failied to execute insert statement\n", + __func__, __LINE__); + exit(-1); + } + affectedRows = k; + break; + + default: + errorPrint("%s() LN%d: unknown insert mode: %d\n", + __func__, __LINE__, superTblInfo->iface); + affectedRows = 0; } - } else { - affectedRows = queryDbExec(pThreadInfo->taos, pThreadInfo->buffer, INSERT_TYPE, false); - } - return affectedRows; + return affectedRows; } static void getTableName(char *pTblName, @@ -4924,7 +4944,7 @@ static void getTableName(char *pTblName, } } -static int64_t generateDataTailWithoutStb( +static int32_t generateDataTailWithoutStb( uint32_t batch, char* buffer, int64_t remainderBufLen, int64_t insertRows, uint64_t recordFrom, int64_t startTime, @@ -4935,7 +4955,7 @@ static int64_t generateDataTailWithoutStb( verbosePrint("%s() LN%d batch=%d\n", __func__, __LINE__, batch); - int64_t k = 0; + int32_t k = 0; for (k = 0; k < batch;) { char data[MAX_DATA_SIZE]; memset(data, 0, MAX_DATA_SIZE); @@ -4947,7 +4967,7 @@ static int64_t generateDataTailWithoutStb( retLen = generateData(data, data_type, startTime + getTSRandTail( - (int64_t)DEFAULT_TIMESTAMP_STEP, k, + (int64_t) DEFAULT_TIMESTAMP_STEP, k, g_args.disorderRatio, g_args.disorderRange), lenOfBinary); @@ -4960,7 +4980,7 @@ static int64_t generateDataTailWithoutStb( len += retLen; remainderBufLen -= retLen; - verbosePrint("%s() LN%d len=%"PRIu64" k=%"PRIu64" \nbuffer=%s\n", + verbosePrint("%s() LN%d len=%"PRIu64" k=%d \nbuffer=%s\n", __func__, __LINE__, len, k, buffer); recordFrom ++; @@ -5006,7 +5026,7 @@ static int32_t generateStbDataTail( } else { tsRand = false; } - verbosePrint("%s() LN%d batch=%ud\n", __func__, __LINE__, batch); + verbosePrint("%s() LN%d batch=%u\n", __func__, __LINE__, batch); int32_t k = 0; for (k = 0; k < batch;) { @@ -5040,7 +5060,7 @@ static int32_t generateStbDataTail( len += retLen; remainderBufLen -= retLen; - verbosePrint("%s() LN%d len=%"PRIu64" k=%ud \nbuffer=%s\n", + verbosePrint("%s() LN%d len=%"PRIu64" k=%u \nbuffer=%s\n", __func__, __LINE__, len, k, buffer); recordFrom ++; @@ -5168,7 +5188,7 @@ static int32_t generateStbInterlaceData( int64_t dataLen = 0; - verbosePrint("[%d] %s() LN%d i=%"PRIu64" batchPerTblTimes=%ud batchPerTbl = %ud\n", + verbosePrint("[%d] %s() LN%d i=%"PRIu64" batchPerTblTimes=%u batchPerTbl = %u\n", pThreadInfo->threadID, __func__, __LINE__, i, batchPerTblTimes, batchPerTbl); @@ -5186,7 +5206,7 @@ static int32_t generateStbInterlaceData( pstr += dataLen; *pRemainderBufLen -= dataLen; } else { - debugPrint("%s() LN%d, generated data tail: %ud, not equal batch per table: %ud\n", + debugPrint("%s() LN%d, generated data tail: %u, not equal batch per table: %u\n", __func__, __LINE__, k, batchPerTbl); pstr -= headLen; pstr[0] = '\0'; @@ -5197,10 +5217,11 @@ static int32_t generateStbInterlaceData( } static int64_t generateInterlaceDataWithoutStb( - char *tableName, uint32_t batchPerTbl, + char *tableName, uint32_t batch, uint64_t tableSeq, char *dbName, char *buffer, int64_t insertRows, + int64_t startTime, uint64_t *pRemainderBufLen) { assert(buffer); @@ -5219,18 +5240,17 @@ static int64_t generateInterlaceDataWithoutStb( int64_t dataLen = 0; - int64_t startTime = 1500000000000; - int64_t k = generateDataTailWithoutStb( - batchPerTbl, pstr, *pRemainderBufLen, insertRows, 0, + int32_t k = generateDataTailWithoutStb( + batch, pstr, *pRemainderBufLen, insertRows, 0, startTime, &dataLen); - if (k == batchPerTbl) { + if (k == batch) { pstr += dataLen; *pRemainderBufLen -= dataLen; } else { - debugPrint("%s() LN%d, generated data tail: %"PRIu64", not equal batch per table: %ud\n", - __func__, __LINE__, k, batchPerTbl); + debugPrint("%s() LN%d, generated data tail: %d, not equal batch per table: %u\n", + __func__, __LINE__, k, batch); pstr -= headLen; pstr[0] = '\0'; k = 0; @@ -5239,32 +5259,237 @@ static int64_t generateInterlaceDataWithoutStb( return k; } +static int32_t prepareStmtBindArrayByType(TAOS_BIND *bind, + char *dataType, int32_t dataLen, char **ptr) +{ + if (0 == strncasecmp(dataType, + "BINARY", strlen("BINARY"))) { + if (dataLen > TSDB_MAX_BINARY_LEN) { + errorPrint( "binary length overflow, max size:%u\n", + (uint32_t)TSDB_MAX_BINARY_LEN); + return -1; + } + char *bind_binary = (char *)*ptr; + rand_string(bind_binary, dataLen); + + bind->buffer_type = TSDB_DATA_TYPE_BINARY; + bind->buffer_length = dataLen; + bind->buffer = bind_binary; + bind->length = &bind->buffer_length; + bind->is_null = NULL; + + *ptr += bind->buffer_length; + } else if (0 == strncasecmp(dataType, + "NCHAR", strlen("NCHAR"))) { + if (dataLen > TSDB_MAX_BINARY_LEN) { + errorPrint( "nchar length overflow, max size:%u\n", + (uint32_t)TSDB_MAX_BINARY_LEN); + return -1; + } + char *bind_nchar = (char *)*ptr; + rand_string(bind_nchar, dataLen); + + bind->buffer_type = TSDB_DATA_TYPE_NCHAR; + bind->buffer_length = strlen(bind_nchar); + bind->buffer = bind_nchar; + bind->length = &bind->buffer_length; + bind->is_null = NULL; + + *ptr += bind->buffer_length; + } else if (0 == strncasecmp(dataType, + "INT", strlen("INT"))) { + int32_t *bind_int = (int32_t *)*ptr; + + *bind_int = rand_int(); + bind->buffer_type = TSDB_DATA_TYPE_INT; + bind->buffer_length = sizeof(int32_t); + bind->buffer = bind_int; + bind->length = &bind->buffer_length; + bind->is_null = NULL; + + *ptr += bind->buffer_length; + } else if (0 == strncasecmp(dataType, + "BIGINT", strlen("BIGINT"))) { + int64_t *bind_bigint = (int64_t *)*ptr; + + *bind_bigint = rand_bigint(); + bind->buffer_type = TSDB_DATA_TYPE_BIGINT; + bind->buffer_length = sizeof(int64_t); + bind->buffer = bind_bigint; + bind->length = &bind->buffer_length; + bind->is_null = NULL; + + *ptr += bind->buffer_length; + } else if (0 == strncasecmp(dataType, + "FLOAT", strlen("FLOAT"))) { + float *bind_float = (float *) *ptr; + + *bind_float = rand_float(); + bind->buffer_type = TSDB_DATA_TYPE_FLOAT; + bind->buffer_length = sizeof(float); + bind->buffer = bind_float; + bind->length = &bind->buffer_length; + bind->is_null = NULL; + + *ptr += bind->buffer_length; + } else if (0 == strncasecmp(dataType, + "DOUBLE", strlen("DOUBLE"))) { + double *bind_double = (double *)*ptr; + + *bind_double = rand_double(); + bind->buffer_type = TSDB_DATA_TYPE_DOUBLE; + bind->buffer_length = sizeof(double); + bind->buffer = bind_double; + bind->length = &bind->buffer_length; + bind->is_null = NULL; + + *ptr += bind->buffer_length; + } else if (0 == strncasecmp(dataType, + "SMALLINT", strlen("SMALLINT"))) { + int16_t *bind_smallint = (int16_t *)*ptr; + + *bind_smallint = rand_smallint(); + bind->buffer_type = TSDB_DATA_TYPE_SMALLINT; + bind->buffer_length = sizeof(int16_t); + bind->buffer = bind_smallint; + bind->length = &bind->buffer_length; + bind->is_null = NULL; + + *ptr += bind->buffer_length; + } else if (0 == strncasecmp(dataType, + "TINYINT", strlen("TINYINT"))) { + int8_t *bind_tinyint = (int8_t *)*ptr; + + *bind_tinyint = rand_tinyint(); + bind->buffer_type = TSDB_DATA_TYPE_TINYINT; + bind->buffer_length = sizeof(int8_t); + bind->buffer = bind_tinyint; + bind->length = &bind->buffer_length; + bind->is_null = NULL; + *ptr += bind->buffer_length; + } else if (0 == strncasecmp(dataType, + "BOOL", strlen("BOOL"))) { + int8_t *bind_bool = (int8_t *)*ptr; + + *bind_bool = rand_bool(); + bind->buffer_type = TSDB_DATA_TYPE_BOOL; + bind->buffer_length = sizeof(int8_t); + bind->buffer = bind_bool; + bind->length = &bind->buffer_length; + bind->is_null = NULL; + + *ptr += bind->buffer_length; + } else if (0 == strncasecmp(dataType, + "TIMESTAMP", strlen("TIMESTAMP"))) { + int64_t *bind_ts2 = (int64_t *) *ptr; + + *bind_ts2 = rand_bigint(); + bind->buffer_type = TSDB_DATA_TYPE_TIMESTAMP; + bind->buffer_length = sizeof(int64_t); + bind->buffer = bind_ts2; + bind->length = &bind->buffer_length; + bind->is_null = NULL; + + *ptr += bind->buffer_length; + } else { + errorPrint( "No support data type: %s\n", + dataType); + return -1; + } + + return 0; +} + +static int32_t prepareStmtWithoutStb( + TAOS_STMT *stmt, + char *tableName, + uint32_t batch, + int64_t insertRows, + int64_t recordFrom, + int64_t startTime) +{ + int ret = taos_stmt_set_tbname(stmt, tableName); + if (ret != 0) { + errorPrint("failed to execute taos_stmt_set_tbname(%s). return 0x%x. reason: %s\n", + tableName, ret, taos_errstr(NULL)); + return ret; + } + + char **data_type = g_args.datatype; + + char *bindArray = malloc(sizeof(TAOS_BIND) * (g_args.num_of_CPR + 1)); + if (bindArray == NULL) { + errorPrint("Failed to allocate %d bind params\n", + (g_args.num_of_CPR + 1)); + return -1; + } + + int32_t k = 0; + for (k = 0; k < batch;) { + /* columnCount + 1 (ts) */ + char data[MAX_DATA_SIZE]; + memset(data, 0, MAX_DATA_SIZE); + + char *ptr = data; + TAOS_BIND *bind = (TAOS_BIND *)(bindArray + 0); + + int64_t *bind_ts; + + bind_ts = (int64_t *)ptr; + bind->buffer_type = TSDB_DATA_TYPE_TIMESTAMP; + *bind_ts = startTime + getTSRandTail( + (int64_t)DEFAULT_TIMESTAMP_STEP, k, + g_args.disorderRatio, + g_args.disorderRange); + bind->buffer_length = sizeof(int64_t); + bind->buffer = bind_ts; + bind->length = &bind->buffer_length; + bind->is_null = NULL; + + ptr += bind->buffer_length; + + for (int i = 0; i < g_args.num_of_CPR; i ++) { + bind = (TAOS_BIND *)((char *)bindArray + (sizeof(TAOS_BIND) * (i + 1))); + if ( -1 == prepareStmtBindArrayByType( + bind, + data_type[i], + g_args.len_of_binary, + &ptr)) { + return -1; + } + } + taos_stmt_bind_param(stmt, (TAOS_BIND *)bindArray); + // if msg > 3MB, break + taos_stmt_add_batch(stmt); + + k++; + recordFrom ++; + if (recordFrom >= insertRows) { + break; + } + } + + return k; +} + static int32_t prepareStbStmt(SSuperTable *stbInfo, TAOS_STMT *stmt, - char *tableName, uint32_t batch, uint64_t insertRows, + char *tableName, uint32_t batch, + uint64_t insertRows, uint64_t recordFrom, int64_t startTime, char *buffer) { - uint32_t k; - int ret; - char *pstr = buffer; - pstr += sprintf(pstr, "INSERT INTO %s values(?", tableName); - - for (int i = 0; i < stbInfo->columnCount; i++) { - pstr += sprintf(pstr, ",?"); - } - pstr += sprintf(pstr, ")"); - - ret = taos_stmt_prepare(stmt, buffer, 0); - if (ret != 0){ - errorPrint("failed to execute taos_stmt_prepare. return 0x%x. reason: %s\n", - ret, taos_errstr(NULL)); + int ret = taos_stmt_set_tbname(stmt, tableName); + if (ret != 0) { + errorPrint("failed to execute taos_stmt_set_tbname(%s). return 0x%x. reason: %s\n", + tableName, ret, taos_errstr(NULL)); return ret; } char *bindArray = malloc(sizeof(TAOS_BIND) * (stbInfo->columnCount + 1)); if (bindArray == NULL) { - errorPrint("Failed to allocate %d bind params\n", batch); + errorPrint("Failed to allocate %d bind params\n", + (stbInfo->columnCount + 1)); return -1; } @@ -5274,6 +5499,8 @@ static int32_t prepareStbStmt(SSuperTable *stbInfo, } else { tsRand = false; } + + uint32_t k; for (k = 0; k < batch;) { /* columnCount + 1 (ts) */ char data[MAX_DATA_SIZE]; @@ -5303,135 +5530,12 @@ static int32_t prepareStbStmt(SSuperTable *stbInfo, for (int i = 0; i < stbInfo->columnCount; i ++) { bind = (TAOS_BIND *)((char *)bindArray + (sizeof(TAOS_BIND) * (i + 1))); - if (0 == strncasecmp(stbInfo->columns[i].dataType, - "BINARY", strlen("BINARY"))) { - if (stbInfo->columns[i].dataLen > TSDB_MAX_BINARY_LEN) { - errorPrint( "binary length overflow, max size:%u\n", - (uint32_t)TSDB_MAX_BINARY_LEN); - return -1; - } - char *bind_binary = (char *)ptr; - rand_string(bind_binary, stbInfo->columns[i].dataLen); - - bind->buffer_type = TSDB_DATA_TYPE_BINARY; - bind->buffer_length = stbInfo->columns[i].dataLen; - bind->buffer = bind_binary; - bind->length = &bind->buffer_length; - bind->is_null = NULL; - - ptr += bind->buffer_length; - } else if (0 == strncasecmp(stbInfo->columns[i].dataType, - "NCHAR", strlen("NCHAR"))) { - if (stbInfo->columns[i].dataLen > TSDB_MAX_BINARY_LEN) { - errorPrint( "nchar length overflow, max size:%u\n", - (uint32_t)TSDB_MAX_BINARY_LEN); - return -1; - } - char *bind_nchar = (char *)ptr; - rand_string(bind_nchar, stbInfo->columns[i].dataLen); - - bind->buffer_type = TSDB_DATA_TYPE_NCHAR; - bind->buffer_length = strlen(bind_nchar); - bind->buffer = bind_nchar; - bind->length = &bind->buffer_length; - bind->is_null = NULL; - - ptr += bind->buffer_length; - } else if (0 == strncasecmp(stbInfo->columns[i].dataType, - "INT", strlen("INT"))) { - int32_t *bind_int = (int32_t *)ptr; - - *bind_int = rand_int(); - bind->buffer_type = TSDB_DATA_TYPE_INT; - bind->buffer_length = sizeof(int32_t); - bind->buffer = bind_int; - bind->length = &bind->buffer_length; - bind->is_null = NULL; - - ptr += bind->buffer_length; - } else if (0 == strncasecmp(stbInfo->columns[i].dataType, - "BIGINT", strlen("BIGINT"))) { - int64_t *bind_bigint = (int64_t *)ptr; - - *bind_bigint = rand_bigint(); - bind->buffer_type = TSDB_DATA_TYPE_BIGINT; - bind->buffer_length = sizeof(int64_t); - bind->buffer = bind_bigint; - bind->length = &bind->buffer_length; - bind->is_null = NULL; - ptr += bind->buffer_length; - } else if (0 == strncasecmp(stbInfo->columns[i].dataType, - "FLOAT", strlen("FLOAT"))) { - float *bind_float = (float *)ptr; - - *bind_float = rand_float(); - bind->buffer_type = TSDB_DATA_TYPE_FLOAT; - bind->buffer_length = sizeof(float); - bind->buffer = bind_float; - bind->length = &bind->buffer_length; - bind->is_null = NULL; - ptr += bind->buffer_length; - } else if (0 == strncasecmp(stbInfo->columns[i].dataType, - "DOUBLE", strlen("DOUBLE"))) { - double *bind_double = (double *)ptr; - - *bind_double = rand_double(); - bind->buffer_type = TSDB_DATA_TYPE_DOUBLE; - bind->buffer_length = sizeof(double); - bind->buffer = bind_double; - bind->length = &bind->buffer_length; - bind->is_null = NULL; - ptr += bind->buffer_length; - } else if (0 == strncasecmp(stbInfo->columns[i].dataType, - "SMALLINT", strlen("SMALLINT"))) { - int16_t *bind_smallint = (int16_t *)ptr; - - *bind_smallint = rand_smallint(); - bind->buffer_type = TSDB_DATA_TYPE_SMALLINT; - bind->buffer_length = sizeof(int16_t); - bind->buffer = bind_smallint; - bind->length = &bind->buffer_length; - bind->is_null = NULL; - ptr += bind->buffer_length; - } else if (0 == strncasecmp(stbInfo->columns[i].dataType, - "TINYINT", strlen("TINYINT"))) { - int8_t *bind_tinyint = (int8_t *)ptr; - - *bind_tinyint = rand_tinyint(); - bind->buffer_type = TSDB_DATA_TYPE_TINYINT; - bind->buffer_length = sizeof(int8_t); - bind->buffer = bind_tinyint; - bind->length = &bind->buffer_length; - bind->is_null = NULL; - ptr += bind->buffer_length; - } else if (0 == strncasecmp(stbInfo->columns[i].dataType, - "BOOL", strlen("BOOL"))) { - int8_t *bind_bool = (int8_t *)ptr; - - *bind_bool = rand_bool(); - bind->buffer_type = TSDB_DATA_TYPE_BOOL; - bind->buffer_length = sizeof(int8_t); - bind->buffer = bind_bool; - bind->length = &bind->buffer_length; - bind->is_null = NULL; - - ptr += bind->buffer_length; - } else if (0 == strncasecmp(stbInfo->columns[i].dataType, - "TIMESTAMP", strlen("TIMESTAMP"))) { - int64_t *bind_ts2 = (int64_t *)ptr; - - *bind_ts2 = rand_bigint(); - bind->buffer_type = TSDB_DATA_TYPE_TIMESTAMP; - bind->buffer_length = sizeof(int64_t); - bind->buffer = bind_ts2; - bind->length = &bind->buffer_length; - bind->is_null = NULL; - - ptr += bind->buffer_length; - } else { - errorPrint( "No support data type: %s\n", - stbInfo->columns[i].dataType); - return -1; + if ( -1 == prepareStmtBindArrayByType( + bind, + stbInfo->columns[i].dataType, + stbInfo->columns[i].dataLen, + &ptr)) { + return -1; } } taos_stmt_bind_param(stmt, (TAOS_BIND *)bindArray); @@ -5482,12 +5586,7 @@ static int32_t generateStbProgressiveData( pSamplePos, &dataLen); } -static int64_t prepareStmtWithoutStb(char *tableName) -{ - return -1; -} - -static int64_t generateProgressiveDataWithoutStb( +static int32_t generateProgressiveDataWithoutStb( char *tableName, /* int64_t tableSeq, */ threadInfo *pThreadInfo, char *buffer, @@ -5520,7 +5619,7 @@ static int64_t generateProgressiveDataWithoutStb( static void printStatPerThread(threadInfo *pThreadInfo) { - fprintf(stderr, "====thread[%d] completed total inserted rows: %"PRIu64 ", total affected rows: %"PRIu64". %.2f records/second====\n", + fprintf(stderr, "====thread[%d] completed total inserted rows: %"PRIu64 ", total affected rows: %"PRIu64". %.2f records/second====\n", pThreadInfo->threadID, pThreadInfo->totalInsertRows, pThreadInfo->totalAffectedRows, @@ -5638,22 +5737,45 @@ static void* syncWriteInterlace(threadInfo *pThreadInfo) { int32_t generated; if (superTblInfo) { - generated = generateStbInterlaceData( - superTblInfo, - tableName, batchPerTbl, i, - batchPerTblTimes, - tableSeq, - pThreadInfo, pstr, - insertRows, - startTime, - &remainderBufLen); + if (superTblInfo->iface == STMT_IFACE) { + generated = prepareStbStmt(superTblInfo, + pThreadInfo->stmt, + tableName, + batchPerTbl, + insertRows, i, + startTime, + pThreadInfo->buffer); + } else { + generated = generateStbInterlaceData( + superTblInfo, + tableName, batchPerTbl, i, + batchPerTblTimes, + tableSeq, + pThreadInfo, pstr, + insertRows, + startTime, + &remainderBufLen); + } } else { - generated = generateInterlaceDataWithoutStb( - tableName, batchPerTbl, - tableSeq, - pThreadInfo->db_name, pstr, - insertRows, - &remainderBufLen); + if (g_args.iface == STMT_IFACE) { + debugPrint("[%d] %s() LN%d, tableName:%s, batch:%d startTime:%"PRId64"\n", + pThreadInfo->threadID, + __func__, __LINE__, + tableName, batchPerTbl, startTime); + generated = prepareStmtWithoutStb( + pThreadInfo->stmt, tableName, + batchPerTbl, + insertRows, i, + startTime); + } else { + generated = generateInterlaceDataWithoutStb( + tableName, batchPerTbl, + tableSeq, + pThreadInfo->db_name, pstr, + insertRows, + startTime, + &remainderBufLen); + } } debugPrint("[%d] %s() LN%d, generated records is %d\n", @@ -5668,9 +5790,10 @@ static void* syncWriteInterlace(threadInfo *pThreadInfo) { tableSeq ++; recOfBatch += batchPerTbl; + pstr += (oldRemainderLen - remainderBufLen); -// startTime += batchPerTbl * superTblInfo->timeStampStep; pThreadInfo->totalInsertRows += batchPerTbl; + verbosePrint("[%d] %s() LN%d batchPerTbl=%d recOfBatch=%d\n", pThreadInfo->threadID, __func__, __LINE__, batchPerTbl, recOfBatch); @@ -5824,9 +5947,11 @@ static void* syncWriteProgressive(threadInfo *pThreadInfo) { int32_t generated; if (superTblInfo) { if (superTblInfo->iface == STMT_IFACE) { - generated = prepareStbStmt(superTblInfo, + generated = prepareStbStmt( + superTblInfo, pThreadInfo->stmt, - tableName, g_args.num_of_RPR, + tableName, + g_args.num_of_RPR, insertRows, i, start_time, pstr); } else { generated = generateStbProgressiveData( @@ -5838,7 +5963,12 @@ static void* syncWriteProgressive(threadInfo *pThreadInfo) { } } else { if (g_args.iface == STMT_IFACE) { - generated = prepareStmtWithoutStb(tableName); + generated = prepareStmtWithoutStb( + pThreadInfo->stmt, + tableName, + g_args.num_of_RPR, + insertRows, i, + start_time); } else { generated = generateProgressiveDataWithoutStb( tableName, @@ -5859,13 +5989,13 @@ static void* syncWriteProgressive(threadInfo *pThreadInfo) { startTs = taosGetTimestampMs(); - int64_t affectedRows = execInsert(pThreadInfo, generated); + int32_t affectedRows = execInsert(pThreadInfo, generated); endTs = taosGetTimestampMs(); uint64_t delay = endTs - startTs; performancePrint("%s() LN%d, insert execution time is %"PRId64"ms\n", __func__, __LINE__, delay); - verbosePrint("[%d] %s() LN%d affectedRows=%"PRId64"\n", + verbosePrint("[%d] %s() LN%d affectedRows=%d\n", pThreadInfo->threadID, __func__, __LINE__, affectedRows); @@ -5875,7 +6005,7 @@ static void* syncWriteProgressive(threadInfo *pThreadInfo) { pThreadInfo->totalDelay += delay; if (affectedRows < 0) { - errorPrint("%s() LN%d, affected rows: %"PRId64"\n", + errorPrint("%s() LN%d, affected rows: %d\n", __func__, __LINE__, affectedRows); goto free_of_progressive; } @@ -6045,15 +6175,6 @@ static int convertHostToServAddr(char *host, uint16_t port, struct sockaddr_in * static void startMultiThreadInsertData(int threads, char* db_name, char* precision,SSuperTable* superTblInfo) { - //TAOS* taos; - //if (0 == strncasecmp(superTblInfo->iface, "taosc", 5)) { - // taos = taos_connect(g_Dbs.host, g_Dbs.user, g_Dbs.password, db_name, g_Dbs.port); - // if (NULL == taos) { - // printf("connect to server fail, reason: %s\n", taos_errstr(NULL)); - // exit(-1); - // } - //} - int32_t timePrec = TSDB_TIME_PRECISION_MILLI; if (0 != precision[0]) { if (0 == strncasecmp(precision, "ms", 2)) { @@ -6232,7 +6353,16 @@ static void startMultiThreadInsertData(int threads, char* db_name, exit(-1); } - if ((superTblInfo) && (superTblInfo->iface == STMT_IFACE)) { + if ((g_args.iface == STMT_IFACE) + || ((superTblInfo) && (superTblInfo->iface == STMT_IFACE))) { + + int columnCount; + if (superTblInfo) { + columnCount = superTblInfo->columnCount; + } else { + columnCount = g_args.num_of_CPR; + } + pThreadInfo->stmt = taos_stmt_init(pThreadInfo->taos); if (NULL == pThreadInfo->stmt) { errorPrint( @@ -6243,6 +6373,24 @@ static void startMultiThreadInsertData(int threads, char* db_name, free(infos); exit(-1); } + + char buffer[3000]; + char *pstr = buffer; + pstr += sprintf(pstr, "INSERT INTO ? values(?"); + + for (int col = 0; col < columnCount; col ++) { + pstr += sprintf(pstr, ",?"); + } + pstr += sprintf(pstr, ")"); + + int ret = taos_stmt_prepare(pThreadInfo->stmt, buffer, 0); + if (ret != 0){ + errorPrint("failed to execute taos_stmt_prepare. return 0x%x. reason: %s\n", + ret, taos_errstr(NULL)); + free(pids); + free(infos); + exit(-1); + } } } else { pThreadInfo->taos = NULL; @@ -6563,7 +6711,7 @@ static int insertTestProcess() { } } - taosMsleep(1000); + // taosMsleep(1000); // create sub threads for inserting data //start = taosGetTimestampMs(); for (int i = 0; i < g_Dbs.dbCount; i++) { From 5789abb8be5502522c811e6fc90ea70de4df574d Mon Sep 17 00:00:00 2001 From: dapan1121 <89396746@qq.com> Date: Fri, 28 May 2021 10:00:20 +0800 Subject: [PATCH 53/70] fix windows compile error --- src/client/src/tscPrepare.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/src/tscPrepare.c b/src/client/src/tscPrepare.c index cfa822ad4d..c95003fc4d 100644 --- a/src/client/src/tscPrepare.c +++ b/src/client/src/tscPrepare.c @@ -1338,7 +1338,7 @@ int stmtGenInsertStatement(SSqlObj* pSql, STscStmt* pStmt, const char* name, TAO return TSDB_CODE_TSC_APP_ERROR; } - ret = converToStr(str + len, tags[j].buffer_type, tags[j].buffer, tags[j].length ? *tags[j].length : -1, &l); + ret = converToStr(str + len, tags[j].buffer_type, tags[j].buffer, tags[j].length ? (int32_t)*tags[j].length : -1, &l); } ++j; From 25e3bde26490b353f7d75c39e23c2152c58bde69 Mon Sep 17 00:00:00 2001 From: XYWang Date: Fri, 28 May 2021 15:14:20 +0800 Subject: [PATCH 54/70] [TD-4384]: fixed an uninitialized bug --- src/plugins/http/src/httpUtil.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/plugins/http/src/httpUtil.c b/src/plugins/http/src/httpUtil.c index 399a33954d..a8031d3fd8 100644 --- a/src/plugins/http/src/httpUtil.c +++ b/src/plugins/http/src/httpUtil.c @@ -237,6 +237,11 @@ void httpFreeMultiCmds(HttpContext *pContext) { JsonBuf *httpMallocJsonBuf(HttpContext *pContext) { if (pContext->jsonBuf == NULL) { pContext->jsonBuf = (JsonBuf *)malloc(sizeof(JsonBuf)); + if (pContext->jsonBuf == NULL) { + return NULL; + } + + memset(pContext->jsonBuf, 0, sizeof(JsonBuf)); } if (!pContext->jsonBuf->pContext) { From 35e2285328b4ec77d0ee3a88598de3e72038dbcd Mon Sep 17 00:00:00 2001 From: lichuang Date: Fri, 28 May 2021 19:37:47 +0800 Subject: [PATCH 55/70] [TD-1920]load mininal modules,and disable sync wal when compact mnode wal --- src/dnode/src/dnodeMain.c | 29 +++++++++++++++++++++++++---- src/mnode/src/mnodeMain.c | 2 +- src/mnode/src/mnodeSdb.c | 6 ++++-- src/wal/src/walWrite.c | 3 +++ 4 files changed, 33 insertions(+), 7 deletions(-) diff --git a/src/dnode/src/dnodeMain.c b/src/dnode/src/dnodeMain.c index cce382b15f..64da11f312 100644 --- a/src/dnode/src/dnodeMain.c +++ b/src/dnode/src/dnodeMain.c @@ -86,6 +86,17 @@ static SStep tsDnodeSteps[] = { {"dnode-telemetry", dnodeInitTelemetry, dnodeCleanupTelemetry}, }; +static SStep tsDnodeCompactSteps[] = { + {"dnode-tfile", tfInit, tfCleanup}, + {"dnode-storage", dnodeInitStorage, dnodeCleanupStorage}, + {"dnode-eps", dnodeInitEps, dnodeCleanupEps}, + {"dnode-wal", walInit, walCleanUp}, + {"dnode-mread", dnodeInitMRead, NULL}, + {"dnode-mwrite", dnodeInitMWrite, NULL}, + {"dnode-mpeer", dnodeInitMPeer, NULL}, + {"dnode-modules", dnodeInitModules, dnodeCleanupModules}, +}; + static int dnodeCreateDir(const char *dir) { if (mkdir(dir, 0755) != 0 && errno != EEXIST) { return -1; @@ -95,13 +106,23 @@ static int dnodeCreateDir(const char *dir) { } static void dnodeCleanupComponents() { - int32_t stepSize = sizeof(tsDnodeSteps) / sizeof(SStep); - dnodeStepCleanup(tsDnodeSteps, stepSize); + if (!tsCompactMnodeWal) { + int32_t stepSize = sizeof(tsDnodeSteps) / sizeof(SStep); + dnodeStepCleanup(tsDnodeSteps, stepSize); + } else { + int32_t stepSize = sizeof(tsDnodeCompactSteps) / sizeof(SStep); + dnodeStepCleanup(tsDnodeCompactSteps, stepSize); + } } static int32_t dnodeInitComponents() { - int32_t stepSize = sizeof(tsDnodeSteps) / sizeof(SStep); - return dnodeStepInit(tsDnodeSteps, stepSize); + if (!tsCompactMnodeWal) { + int32_t stepSize = sizeof(tsDnodeSteps) / sizeof(SStep); + return dnodeStepInit(tsDnodeSteps, stepSize); + } else { + int32_t stepSize = sizeof(tsDnodeCompactSteps) / sizeof(SStep); + return dnodeStepInit(tsDnodeCompactSteps, stepSize); + } } static int32_t dnodeInitTmr() { diff --git a/src/mnode/src/mnodeMain.c b/src/mnode/src/mnodeMain.c index d3511a4e62..8ce798c8ec 100644 --- a/src/mnode/src/mnodeMain.c +++ b/src/mnode/src/mnodeMain.c @@ -121,7 +121,7 @@ int32_t mnodeStartSystem() { int32_t mnodeInitSystem() { mnodeInitTimer(); - if (mnodeNeedStart()) { + if (mnodeNeedStart() || tsCompactMnodeWal) { return mnodeStartSystem(); } return 0; diff --git a/src/mnode/src/mnodeSdb.c b/src/mnode/src/mnodeSdb.c index 84e4f33ca7..ac3e5d86ec 100644 --- a/src/mnode/src/mnodeSdb.c +++ b/src/mnode/src/mnodeSdb.c @@ -690,7 +690,7 @@ static int32_t sdbProcessWrite(void *wparam, void *hparam, int32_t qtype, void * pthread_mutex_unlock(&tsSdbMgmt.mutex); // from app, row is created - if (pRow != NULL) { + if (pRow != NULL && tsCompactMnodeWal != 1) { // forward to peers pRow->processedCount = 0; int32_t syncCode = syncForwardToPeer(tsSdbMgmt.sync, pHead, pRow, TAOS_QTYPE_RPC, false); @@ -713,7 +713,9 @@ static int32_t sdbProcessWrite(void *wparam, void *hparam, int32_t qtype, void * actStr[action], sdbGetKeyStr(pTable, pHead->cont), pHead->version); // even it is WAL/FWD, it shall be called to update version in sync - syncForwardToPeer(tsSdbMgmt.sync, pHead, pRow, TAOS_QTYPE_RPC, false); + if (tsCompactMnodeWal != 1) { + syncForwardToPeer(tsSdbMgmt.sync, pHead, pRow, TAOS_QTYPE_RPC, false); + } // from wal or forward msg, row not created, should add into hash if (action == SDB_ACTION_INSERT) { diff --git a/src/wal/src/walWrite.c b/src/wal/src/walWrite.c index f865870d47..09a03de048 100644 --- a/src/wal/src/walWrite.c +++ b/src/wal/src/walWrite.c @@ -383,6 +383,7 @@ static int32_t walRestoreWalFile(SWal *pWal, void *pVnode, FWalWrite writeFp, ch wError("vgId:%d, file:%s, wal whole cksum is messed up, hver:%" PRIu64 " len:%d offset:%" PRId64, pWal->vgId, name, pHead->version, pHead->len, offset); code = walSkipCorruptedRecord(pWal, pHead, tfd, &offset); + break; if (code != TSDB_CODE_SUCCESS) { walFtruncate(pWal, tfd, offset); break; @@ -430,6 +431,8 @@ static int32_t walRestoreWalFile(SWal *pWal, void *pVnode, FWalWrite writeFp, ch pWal->vgId, fileId, pHead->version, pWal->version, pHead->len, offset); pWal->version = pHead->version; + + //wInfo("writeFp: %ld", offset); (*writeFp)(pVnode, pHead, TAOS_QTYPE_WAL, NULL); } From 9050532645e01b33e75cf9fbf87ac0d988efba5c Mon Sep 17 00:00:00 2001 From: lichuang Date: Fri, 28 May 2021 19:40:43 +0800 Subject: [PATCH 56/70] [TD-1920]revert debug code --- src/wal/src/walWrite.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/wal/src/walWrite.c b/src/wal/src/walWrite.c index 09a03de048..b884546a08 100644 --- a/src/wal/src/walWrite.c +++ b/src/wal/src/walWrite.c @@ -383,7 +383,6 @@ static int32_t walRestoreWalFile(SWal *pWal, void *pVnode, FWalWrite writeFp, ch wError("vgId:%d, file:%s, wal whole cksum is messed up, hver:%" PRIu64 " len:%d offset:%" PRId64, pWal->vgId, name, pHead->version, pHead->len, offset); code = walSkipCorruptedRecord(pWal, pHead, tfd, &offset); - break; if (code != TSDB_CODE_SUCCESS) { walFtruncate(pWal, tfd, offset); break; From f0fea88d4f2107589f0265a3006aae36de9f92e1 Mon Sep 17 00:00:00 2001 From: Shuduo Sang Date: Fri, 28 May 2021 19:51:00 +0800 Subject: [PATCH 57/70] Feature/sangshuduo/td 4068 taosdemo stmt (#6274) * merge with develop branch. change query/tests/CMakeLists.txt to allow unused function and variable. * refactor data generating. * refactor. * refactor. * refactor. * refactor. * refactor * add prepare stmt function. * refactor get rand timestamp. * fix windows compile error. * copy logic of generate data for stmt. * insert data basically works now. * fix windows compile issue. * [TD-4068]: taosdemo stmt interface. stb batch insert works. * [TD-4068]: taosdemo support stmt. normal table insert works. * [TD-4068]: taosdemo support stmt. interlace write works. * add compile macro to make taosdemo same with master branch. * fix clang compile error. Co-authored-by: Shuduo Sang --- src/kit/taosdemo/taosdemo.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/kit/taosdemo/taosdemo.c b/src/kit/taosdemo/taosdemo.c index 6ad5fadf7c..b7b2fe0e52 100644 --- a/src/kit/taosdemo/taosdemo.c +++ b/src/kit/taosdemo/taosdemo.c @@ -53,6 +53,8 @@ #include "taoserror.h" #include "tutil.h" +#define STMT_IFACE_ENABLED 1 + #define REQ_EXTRA_BUF_LEN 1024 #define RESP_BUF_LEN 4096 @@ -5259,6 +5261,7 @@ static int64_t generateInterlaceDataWithoutStb( return k; } +#if STMT_IFACE_ENABLED == 1 static int32_t prepareStmtBindArrayByType(TAOS_BIND *bind, char *dataType, int32_t dataLen, char **ptr) { @@ -5551,6 +5554,7 @@ static int32_t prepareStbStmt(SSuperTable *stbInfo, return k; } +#endif static int32_t generateStbProgressiveData( SSuperTable *superTblInfo, @@ -5738,6 +5742,7 @@ static void* syncWriteInterlace(threadInfo *pThreadInfo) { int32_t generated; if (superTblInfo) { if (superTblInfo->iface == STMT_IFACE) { +#if STMT_IFACE_ENABLED == 1 generated = prepareStbStmt(superTblInfo, pThreadInfo->stmt, tableName, @@ -5745,6 +5750,9 @@ static void* syncWriteInterlace(threadInfo *pThreadInfo) { insertRows, i, startTime, pThreadInfo->buffer); +#else + generated = -1; +#endif } else { generated = generateStbInterlaceData( superTblInfo, @@ -5762,11 +5770,15 @@ static void* syncWriteInterlace(threadInfo *pThreadInfo) { pThreadInfo->threadID, __func__, __LINE__, tableName, batchPerTbl, startTime); +#if STMT_IFACE_ENABLED == 1 generated = prepareStmtWithoutStb( pThreadInfo->stmt, tableName, batchPerTbl, insertRows, i, startTime); +#else + generated = -1; +#endif } else { generated = generateInterlaceDataWithoutStb( tableName, batchPerTbl, @@ -5947,12 +5959,16 @@ static void* syncWriteProgressive(threadInfo *pThreadInfo) { int32_t generated; if (superTblInfo) { if (superTblInfo->iface == STMT_IFACE) { +#if STMT_IFACE_ENABLED == 1 generated = prepareStbStmt( superTblInfo, pThreadInfo->stmt, tableName, g_args.num_of_RPR, insertRows, i, start_time, pstr); +#else + generated = -1; +#endif } else { generated = generateStbProgressiveData( superTblInfo, @@ -5963,12 +5979,16 @@ static void* syncWriteProgressive(threadInfo *pThreadInfo) { } } else { if (g_args.iface == STMT_IFACE) { +#if STMT_IFACE_ENABLED == 1 generated = prepareStmtWithoutStb( pThreadInfo->stmt, tableName, g_args.num_of_RPR, insertRows, i, start_time); +#else + generated = -1; +#endif } else { generated = generateProgressiveDataWithoutStb( tableName, From c56825984039798c90b2c9184eb19477755c4707 Mon Sep 17 00:00:00 2001 From: Shuduo Sang Date: Sat, 29 May 2021 00:24:53 +0800 Subject: [PATCH 58/70] Hotfix/sangshuduo/td 3913 mips compile support for develop (#6278) * [TD-3913]: mips compile support. * [TD-3913]: mips64 support. * fix osSignal.c * fix tcrc32c.c * fix cmake. * fix osInc.h * fix gcc 4.8 compile error. * fix clang compile error. Co-authored-by: Shuduo Sang --- src/os/src/detail/osTime.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/os/src/detail/osTime.c b/src/os/src/detail/osTime.c index d9d070218e..67e0c2642e 100644 --- a/src/os/src/detail/osTime.c +++ b/src/os/src/detail/osTime.c @@ -87,12 +87,12 @@ static int32_t (*parseLocaltimeFp[]) (char* timestr, int64_t* time, int32_t time int32_t taosGetTimestampSec() { return (int32_t)time(NULL); } -int32_t taosParseTime(char* timestr, int64_t* time, int32_t len, int32_t timePrec, int8_t daylight) { +int32_t taosParseTime(char* timestr, int64_t* time, int32_t len, int32_t timePrec, int8_t day_light) { /* parse datatime string in with tz */ if (strnchr(timestr, 'T', len, false) != NULL) { return parseTimeWithTz(timestr, time, timePrec); } else { - return (*parseLocaltimeFp[daylight])(timestr, time, timePrec); + return (*parseLocaltimeFp[day_light])(timestr, time, timePrec); } } From 88f3e7aad8f02907c0632d2a5cd47a17f8963978 Mon Sep 17 00:00:00 2001 From: Shuduo Sang Date: Sat, 29 May 2021 09:04:13 +0800 Subject: [PATCH 59/70] [TD-4353]: taosdemo resub if resubAfterConsume != -1 (#6286) Co-authored-by: Shuduo Sang --- src/kit/taosdemo/taosdemo.c | 72 +++++++++++++++++++++++++------------ 1 file changed, 50 insertions(+), 22 deletions(-) diff --git a/src/kit/taosdemo/taosdemo.c b/src/kit/taosdemo/taosdemo.c index b7b2fe0e52..004ea280c4 100644 --- a/src/kit/taosdemo/taosdemo.c +++ b/src/kit/taosdemo/taosdemo.c @@ -379,7 +379,7 @@ typedef struct SDbs_S { typedef struct SpecifiedQueryInfo_S { uint64_t queryInterval; // 0: unlimit > 0 loop/s uint32_t concurrent; - uint64_t sqlCount; + int sqlCount; uint32_t asyncMode; // 0: sync, 1: async uint64_t subscribeInterval; // ms uint64_t queryTimes; @@ -388,6 +388,7 @@ typedef struct SpecifiedQueryInfo_S { char sql[MAX_QUERY_SQL_COUNT][MAX_QUERY_SQL_LENGTH+1]; char result[MAX_QUERY_SQL_COUNT][MAX_FILE_NAME_LEN+1]; int resubAfterConsume[MAX_QUERY_SQL_COUNT]; + int endAfterConsume[MAX_QUERY_SQL_COUNT]; TAOS_SUB* tsub[MAX_QUERY_SQL_COUNT]; char topic[MAX_QUERY_SQL_COUNT][32]; int consumed[MAX_QUERY_SQL_COUNT]; @@ -406,10 +407,11 @@ typedef struct SuperQueryInfo_S { uint64_t queryTimes; int64_t childTblCount; char childTblPrefix[MAX_TB_NAME_SIZE]; - uint64_t sqlCount; + int sqlCount; char sql[MAX_QUERY_SQL_COUNT][MAX_QUERY_SQL_LENGTH+1]; char result[MAX_QUERY_SQL_COUNT][MAX_FILE_NAME_LEN+1]; int resubAfterConsume; + int endAfterConsume; TAOS_SUB* tsub[MAX_QUERY_SQL_COUNT]; char* childTblName; @@ -1773,7 +1775,7 @@ static void printfQueryMeta() { if ((SUBSCRIBE_TEST == g_args.test_mode) || (QUERY_TEST == g_args.test_mode)) { printf("specified table query info: \n"); - printf("sqlCount: \033[33m%"PRIu64"\033[0m\n", + printf("sqlCount: \033[33m%d\033[0m\n", g_queryInfo.specifiedQueryInfo.sqlCount); if (g_queryInfo.specifiedQueryInfo.sqlCount > 0) { printf("specified tbl query times:\n"); @@ -1793,15 +1795,15 @@ static void printfQueryMeta() { printf("keepProgress: \033[33m%d\033[0m\n", g_queryInfo.specifiedQueryInfo.subscribeKeepProgress); - for (uint64_t i = 0; i < g_queryInfo.specifiedQueryInfo.sqlCount; i++) { - printf(" sql[%"PRIu64"]: \033[33m%s\033[0m\n", + for (int i = 0; i < g_queryInfo.specifiedQueryInfo.sqlCount; i++) { + printf(" sql[%d]: \033[33m%s\033[0m\n", i, g_queryInfo.specifiedQueryInfo.sql[i]); } printf("\n"); } printf("super table query info:\n"); - printf("sqlCount: \033[33m%"PRIu64"\033[0m\n", + printf("sqlCount: \033[33m%d\033[0m\n", g_queryInfo.superQueryInfo.sqlCount); if (g_queryInfo.superQueryInfo.sqlCount > 0) { @@ -4268,7 +4270,7 @@ static bool getMetaFromQueryJsonFile(cJSON* root) { if (concurrent && concurrent->type == cJSON_Number) { if (concurrent->valueint <= 0) { errorPrint( - "%s() LN%d, query sqlCount %"PRIu64" or concurrent %d is not correct.\n", + "%s() LN%d, query sqlCount %d or concurrent %d is not correct.\n", __func__, __LINE__, g_queryInfo.specifiedQueryInfo.sqlCount, g_queryInfo.specifiedQueryInfo.concurrent); @@ -4367,6 +4369,17 @@ static bool getMetaFromQueryJsonFile(cJSON* root) { tstrncpy(g_queryInfo.specifiedQueryInfo.sql[j], sqlStr->valuestring, MAX_QUERY_SQL_LENGTH); + cJSON* endAfterConsume = + cJSON_GetObjectItem(specifiedQuery, "endAfterConsume"); + if (endAfterConsume + && endAfterConsume->type == cJSON_Number) { + g_queryInfo.specifiedQueryInfo.endAfterConsume[j] + = endAfterConsume->valueint; + } else if (!endAfterConsume) { + // default value is -1, which mean infinite loop + g_queryInfo.specifiedQueryInfo.endAfterConsume[j] = -1; + } + cJSON* resubAfterConsume = cJSON_GetObjectItem(specifiedQuery, "resubAfterConsume"); if (resubAfterConsume @@ -4374,9 +4387,8 @@ static bool getMetaFromQueryJsonFile(cJSON* root) { g_queryInfo.specifiedQueryInfo.resubAfterConsume[j] = resubAfterConsume->valueint; } else if (!resubAfterConsume) { - //printf("failed to read json, subscribe interval no found\n"); - //goto PARSE_OVER; - g_queryInfo.specifiedQueryInfo.resubAfterConsume[j] = 1; + // default value is -1, which mean do not resub + g_queryInfo.specifiedQueryInfo.resubAfterConsume[j] = -1; } cJSON *result = cJSON_GetObjectItem(sql, "result"); @@ -4520,16 +4532,26 @@ static bool getMetaFromQueryJsonFile(cJSON* root) { g_queryInfo.superQueryInfo.subscribeKeepProgress = 0; } + cJSON* superEndAfterConsume = + cJSON_GetObjectItem(superQuery, "endAfterConsume"); + if (superEndAfterConsume + && superEndAfterConsume->type == cJSON_Number) { + g_queryInfo.superQueryInfo.endAfterConsume = + superEndAfterConsume->valueint; + } else if (!superEndAfterConsume) { + // default value is -1, which mean do not resub + g_queryInfo.superQueryInfo.endAfterConsume = -1; + } + cJSON* superResubAfterConsume = - cJSON_GetObjectItem(superQuery, "resubAfterConsume"); + cJSON_GetObjectItem(superQuery, "endAfterConsume"); if (superResubAfterConsume && superResubAfterConsume->type == cJSON_Number) { - g_queryInfo.superQueryInfo.resubAfterConsume = + g_queryInfo.superQueryInfo.endAfterConsume = superResubAfterConsume->valueint; } else if (!superResubAfterConsume) { - //printf("failed to read json, subscribe interval no found\n"); - ////goto PARSE_OVER; - g_queryInfo.superQueryInfo.resubAfterConsume = 1; + // default value is -1, which mean do not resub + g_queryInfo.superQueryInfo.endAfterConsume = -1; } // supert table sqls @@ -7250,7 +7272,10 @@ static void *superSubscribe(void *sarg) { uint64_t st = 0, et = 0; - while(1) { + while ((g_queryInfo.superQueryInfo.endAfterConsume == -1) + || (g_queryInfo.superQueryInfo.endAfterConsume < + consumed[pThreadInfo->end_table_to - pThreadInfo->start_table_from])) { + for (uint64_t i = pThreadInfo->start_table_from; i <= pThreadInfo->end_table_to; i++) { tsubSeq = i - pThreadInfo->start_table_from; @@ -7279,7 +7304,7 @@ static void *superSubscribe(void *sarg) { } consumed[tsubSeq] ++; - if ((g_queryInfo.superQueryInfo.subscribeKeepProgress) + if ((g_queryInfo.superQueryInfo.resubAfterConsume != -1) && (consumed[tsubSeq] >= g_queryInfo.superQueryInfo.resubAfterConsume)) { printf("keepProgress:%d, resub super table query: %"PRIu64"\n", @@ -7361,7 +7386,10 @@ static void *specifiedSubscribe(void *sarg) { // start loop to consume result g_queryInfo.specifiedQueryInfo.consumed[pThreadInfo->threadID] = 0; - while(1) { + while((g_queryInfo.specifiedQueryInfo.endAfterConsume[pThreadInfo->querySeq] == -1) + || (g_queryInfo.specifiedQueryInfo.consumed[pThreadInfo->threadID] < + g_queryInfo.specifiedQueryInfo.endAfterConsume[pThreadInfo->querySeq])) { + if (ASYNC_MODE == g_queryInfo.specifiedQueryInfo.asyncMode) { continue; } @@ -7377,7 +7405,7 @@ static void *specifiedSubscribe(void *sarg) { } g_queryInfo.specifiedQueryInfo.consumed[pThreadInfo->threadID] ++; - if ((g_queryInfo.specifiedQueryInfo.subscribeKeepProgress) + if ((g_queryInfo.specifiedQueryInfo.resubAfterConsume[pThreadInfo->querySeq] != -1) && (g_queryInfo.specifiedQueryInfo.consumed[pThreadInfo->threadID] >= g_queryInfo.specifiedQueryInfo.resubAfterConsume[pThreadInfo->querySeq])) { printf("keepProgress:%d, resub specified query: %"PRIu64"\n", @@ -7444,12 +7472,12 @@ static int subscribeTestProcess() { //==== create threads for query for specified table if (g_queryInfo.specifiedQueryInfo.sqlCount <= 0) { - debugPrint("%s() LN%d, sepcified query sqlCount %"PRIu64".\n", + debugPrint("%s() LN%d, sepcified query sqlCount %d.\n", __func__, __LINE__, g_queryInfo.specifiedQueryInfo.sqlCount); } else { if (g_queryInfo.specifiedQueryInfo.concurrent <= 0) { - errorPrint("%s() LN%d, sepcified query sqlCount %"PRIu64".\n", + errorPrint("%s() LN%d, sepcified query sqlCount %d.\n", __func__, __LINE__, g_queryInfo.specifiedQueryInfo.sqlCount); exit(-1); @@ -7482,7 +7510,7 @@ static int subscribeTestProcess() { //==== create threads for super table query if (g_queryInfo.superQueryInfo.sqlCount <= 0) { - debugPrint("%s() LN%d, super table query sqlCount %"PRIu64".\n", + debugPrint("%s() LN%d, super table query sqlCount %d.\n", __func__, __LINE__, g_queryInfo.superQueryInfo.sqlCount); } else { From 6f7a349f48d93e5d2a6eb73cbef7fd6bd1b1dd53 Mon Sep 17 00:00:00 2001 From: lichuang Date: Sat, 29 May 2021 09:14:11 +0800 Subject: [PATCH 60/70] [TD-1920]disable log --- src/mnode/src/mnodeTable.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mnode/src/mnodeTable.c b/src/mnode/src/mnodeTable.c index 4e879537e4..5132e9f67a 100644 --- a/src/mnode/src/mnodeTable.c +++ b/src/mnode/src/mnodeTable.c @@ -3261,7 +3261,7 @@ static int32_t mnodeCompactSuperTables() { .rowSize = sizeof(SSTableObj) + schemaSize, }; - mInfo("compact super %" PRIu64, pTable->uid); + //mInfo("compact super %" PRIu64, pTable->uid); sdbInsertCompactRow(&row); } @@ -3287,7 +3287,7 @@ static int32_t mnodeCompactChildTables() { .pTable = tsChildTableSdb, }; - mInfo("compact child %" PRIu64 ":%d", pTable->uid, pTable->tid); + //mInfo("compact child %" PRIu64 ":%d", pTable->uid, pTable->tid); sdbInsertCompactRow(&row); } From 889ed47b562aafcc4b08ac870b84cdfeadd20b49 Mon Sep 17 00:00:00 2001 From: Shuduo Sang Date: Sat, 29 May 2021 11:52:36 +0800 Subject: [PATCH 61/70] Hotfix/sangshuduo/td 4406 taosdemo auto create tables for develop (#6288) * cherry-pick from master branch. * cherry-pick from master branch. c23043c0ced30f7b1f85b0ae65db405e9fc70b5d Co-authored-by: Shuduo Sang --- src/kit/taosdemo/taosdemo.c | 227 +++++++++++++++++++----------------- 1 file changed, 121 insertions(+), 106 deletions(-) diff --git a/src/kit/taosdemo/taosdemo.c b/src/kit/taosdemo/taosdemo.c index 004ea280c4..ec15a99d14 100644 --- a/src/kit/taosdemo/taosdemo.c +++ b/src/kit/taosdemo/taosdemo.c @@ -255,12 +255,13 @@ typedef struct SColumn_S { typedef struct SSuperTable_S { char sTblName[MAX_TB_NAME_SIZE+1]; + char dataSource[MAX_TB_NAME_SIZE+1]; // rand_gen or sample + char childTblPrefix[MAX_TB_NAME_SIZE]; + char insertMode[MAX_TB_NAME_SIZE]; // taosc, rest + uint16_t childTblExists; int64_t childTblCount; - bool childTblExists; // 0: no, 1: yes uint64_t batchCreateTableNum; // 0: no batch, > 0: batch table number in one sql uint8_t autoCreateTable; // 0: create sub table, 1: auto create sub table - char childTblPrefix[MAX_TB_NAME_SIZE]; - char dataSource[MAX_TB_NAME_SIZE+1]; // rand_gen or sample uint16_t iface; // 0: taosc, 1: rest, 2: stmt int64_t childTblLimit; uint64_t childTblOffset; @@ -830,7 +831,7 @@ static void parse_args(int argc, char *argv[], SArguments *arguments) { if ((argc == i+1) || (!isStringNumber(argv[i+1]))) { printHelp(); - errorPrint("%s", "\n\t-q need a number following!\nQuery mode -- 0: SYNC, 1: ASYNC. Default is SYNC.\n"); + errorPrint("%s", "\n\t-q need a number following!\nQuery mode -- 0: SYNC, not-0: ASYNC. Default is SYNC.\n"); exit(EXIT_FAILURE); } arguments->async_mode = atoi(argv[++i]); @@ -1471,7 +1472,8 @@ static int printfInsertMeta() { if (PRE_CREATE_SUBTBL == g_Dbs.db[i].superTbls[j].autoCreateTable) { printf(" autoCreateTable: \033[33m%s\033[0m\n", "no"); - } else if (AUTO_CREATE_SUBTBL == g_Dbs.db[i].superTbls[j].autoCreateTable) { + } else if (AUTO_CREATE_SUBTBL == + g_Dbs.db[i].superTbls[j].autoCreateTable) { printf(" autoCreateTable: \033[33m%s\033[0m\n", "yes"); } else { printf(" autoCreateTable: \033[33m%s\033[0m\n", "error"); @@ -3063,64 +3065,61 @@ static void createChildTables() { char tblColsBuf[MAX_SQL_SIZE]; int len; - for (int i = 0; i < g_Dbs.dbCount; i++) { - if (g_Dbs.use_metric) { - if (g_Dbs.db[i].superTblCount > 0) { - // with super table - for (uint64_t j = 0; j < g_Dbs.db[i].superTblCount; j++) { - if ((AUTO_CREATE_SUBTBL == g_Dbs.db[i].superTbls[j].autoCreateTable) - || (TBL_ALREADY_EXISTS == g_Dbs.db[i].superTbls[j].childTblExists)) { - continue; - } + for (int i = 0; i < g_Dbs.dbCount; i++) { + if (g_Dbs.use_metric) { + if (g_Dbs.db[i].superTblCount > 0) { + // with super table + for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) { + if ((AUTO_CREATE_SUBTBL == g_Dbs.db[i].superTbls[j].autoCreateTable) + || (TBL_ALREADY_EXISTS == g_Dbs.db[i].superTbls[j].childTblExists)) { + continue; + } + verbosePrint("%s() LN%d: %s\n", __func__, __LINE__, + g_Dbs.db[i].superTbls[j].colsOfCreateChildTable); + uint64_t startFrom = 0; + g_totalChildTables += g_Dbs.db[i].superTbls[j].childTblCount; - verbosePrint("%s() LN%d: %s\n", __func__, __LINE__, - g_Dbs.db[i].superTbls[j].colsOfCreateChildTable); - uint64_t tableFrom = 0; - g_totalChildTables += g_Dbs.db[i].superTbls[j].childTblCount; + verbosePrint("%s() LN%d: create %"PRId64" child tables from %"PRIu64"\n", + __func__, __LINE__, g_totalChildTables, startFrom); - verbosePrint("%s() LN%d: create %"PRId64" child tables from %"PRIu64"\n", - __func__, __LINE__, g_totalChildTables, tableFrom); - startMultiThreadCreateChildTable( - g_Dbs.db[i].superTbls[j].colsOfCreateChildTable, - g_Dbs.threadCountByCreateTbl, - tableFrom, - g_Dbs.db[i].superTbls[j].childTblCount, - g_Dbs.db[i].dbName, &(g_Dbs.db[i].superTbls[j])); + startMultiThreadCreateChildTable( + g_Dbs.db[i].superTbls[j].colsOfCreateChildTable, + g_Dbs.threadCountByCreateTbl, + startFrom, + g_Dbs.db[i].superTbls[j].childTblCount, + g_Dbs.db[i].dbName, &(g_Dbs.db[i].superTbls[j])); + } + } + } else { + // normal table + len = snprintf(tblColsBuf, MAX_SQL_SIZE, "(TS TIMESTAMP"); + for (int j = 0; j < g_args.num_of_CPR; j++) { + if ((strncasecmp(g_args.datatype[j], "BINARY", strlen("BINARY")) == 0) + || (strncasecmp(g_args.datatype[j], + "NCHAR", strlen("NCHAR")) == 0)) { + snprintf(tblColsBuf + len, MAX_SQL_SIZE - len, + ", COL%d %s(%d)", j, g_args.datatype[j], g_args.len_of_binary); + } else { + snprintf(tblColsBuf + len, MAX_SQL_SIZE - len, + ", COL%d %s", j, g_args.datatype[j]); + } + len = strlen(tblColsBuf); + } + + snprintf(tblColsBuf + len, MAX_SQL_SIZE - len, ")"); + + verbosePrint("%s() LN%d: dbName: %s num of tb: %"PRId64" schema: %s\n", + __func__, __LINE__, + g_Dbs.db[i].dbName, g_args.num_of_tables, tblColsBuf); + startMultiThreadCreateChildTable( + tblColsBuf, + g_Dbs.threadCountByCreateTbl, + 0, + g_args.num_of_tables, + g_Dbs.db[i].dbName, + NULL); } - } - } else { - // normal table - len = snprintf(tblColsBuf, MAX_SQL_SIZE, "(TS TIMESTAMP"); - for (int j = 0; j < g_args.num_of_CPR; j++) { - if (g_args.datatype[j] - && ((strncasecmp(g_args.datatype[j], - "BINARY", strlen("BINARY")) == 0) - || (strncasecmp(g_args.datatype[j], - "NCHAR", strlen("NCHAR")) == 0))) { - snprintf(tblColsBuf + len, MAX_SQL_SIZE - len, - ", COL%d %s(%d)", j, g_args.datatype[j], - g_args.len_of_binary); - } else { - snprintf(tblColsBuf + len, MAX_SQL_SIZE - len, - ", COL%d %s", j, g_args.datatype[j]); - } - len = strlen(tblColsBuf); - } - - snprintf(tblColsBuf + len, MAX_SQL_SIZE - len, ")"); - - verbosePrint("%s() LN%d: dbName: %s num of tb: %"PRId64" schema: %s\n", - __func__, __LINE__, - g_Dbs.db[i].dbName, g_args.num_of_tables, tblColsBuf); - startMultiThreadCreateChildTable( - tblColsBuf, - g_Dbs.threadCountByCreateTbl, - 0, - g_args.num_of_tables, - g_Dbs.db[i].dbName, - NULL); } - } } /* @@ -3814,36 +3813,40 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { // dbinfo cJSON *stbName = cJSON_GetObjectItem(stbInfo, "name"); - if (!stbName || stbName->type != cJSON_String || stbName->valuestring == NULL) { + if (!stbName || stbName->type != cJSON_String + || stbName->valuestring == NULL) { errorPrint("%s() LN%d, failed to read json, stb name not found\n", __func__, __LINE__); goto PARSE_OVER; } - tstrncpy(g_Dbs.db[i].superTbls[j].sTblName, stbName->valuestring, MAX_TB_NAME_SIZE); + tstrncpy(g_Dbs.db[i].superTbls[j].sTblName, stbName->valuestring, + MAX_TB_NAME_SIZE); cJSON *prefix = cJSON_GetObjectItem(stbInfo, "childtable_prefix"); if (!prefix || prefix->type != cJSON_String || prefix->valuestring == NULL) { printf("ERROR: failed to read json, childtable_prefix not found\n"); goto PARSE_OVER; } - tstrncpy(g_Dbs.db[i].superTbls[j].childTblPrefix, prefix->valuestring, MAX_DB_NAME_SIZE); + tstrncpy(g_Dbs.db[i].superTbls[j].childTblPrefix, prefix->valuestring, + MAX_DB_NAME_SIZE); - cJSON *autoCreateTbl = cJSON_GetObjectItem(stbInfo, "auto_create_table"); // yes, no, null + cJSON *autoCreateTbl = cJSON_GetObjectItem(stbInfo, "auto_create_table"); if (autoCreateTbl && autoCreateTbl->type == cJSON_String && autoCreateTbl->valuestring != NULL) { - if (0 == strncasecmp(autoCreateTbl->valuestring, "yes", 3)) { - g_Dbs.db[i].superTbls[j].autoCreateTable = AUTO_CREATE_SUBTBL; - } else if (0 == strncasecmp(autoCreateTbl->valuestring, "no", 2)) { - g_Dbs.db[i].superTbls[j].autoCreateTable = PRE_CREATE_SUBTBL; - } else { - g_Dbs.db[i].superTbls[j].autoCreateTable = PRE_CREATE_SUBTBL; - } + if ((0 == strncasecmp(autoCreateTbl->valuestring, "yes", 3)) + && (TBL_ALREADY_EXISTS != g_Dbs.db[i].superTbls[j].childTblExists)) { + g_Dbs.db[i].superTbls[j].autoCreateTable = AUTO_CREATE_SUBTBL; + } else if (0 == strncasecmp(autoCreateTbl->valuestring, "no", 2)) { + g_Dbs.db[i].superTbls[j].autoCreateTable = PRE_CREATE_SUBTBL; + } else { + g_Dbs.db[i].superTbls[j].autoCreateTable = PRE_CREATE_SUBTBL; + } } else if (!autoCreateTbl) { - g_Dbs.db[i].superTbls[j].autoCreateTable = PRE_CREATE_SUBTBL; + g_Dbs.db[i].superTbls[j].autoCreateTable = PRE_CREATE_SUBTBL; } else { - printf("ERROR: failed to read json, auto_create_table not found\n"); - goto PARSE_OVER; + printf("ERROR: failed to read json, auto_create_table not found\n"); + goto PARSE_OVER; } cJSON* batchCreateTbl = cJSON_GetObjectItem(stbInfo, "batch_create_tbl_num"); @@ -3877,6 +3880,10 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { goto PARSE_OVER; } + if (TBL_ALREADY_EXISTS == g_Dbs.db[i].superTbls[j].childTblExists) { + g_Dbs.db[i].superTbls[j].autoCreateTable = PRE_CREATE_SUBTBL; + } + cJSON* count = cJSON_GetObjectItem(stbInfo, "childtable_count"); if (!count || count->type != cJSON_Number || 0 >= count->valueint) { errorPrint("%s() LN%d, failed to read json, childtable_count input mistake\n", @@ -3934,7 +3941,8 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { cJSON* childTbl_offset = cJSON_GetObjectItem(stbInfo, "childtable_offset"); if ((childTbl_offset) && (g_Dbs.db[i].drop != true) && (g_Dbs.db[i].superTbls[j].childTblExists == TBL_ALREADY_EXISTS)) { - if (childTbl_offset->type != cJSON_Number || 0 > childTbl_offset->valueint) { + if ((childTbl_offset->type != cJSON_Number) + || (0 > childTbl_offset->valueint)) { printf("ERROR: failed to read json, childtable_offset\n"); goto PARSE_OVER; } @@ -3990,7 +3998,8 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { } cJSON *tagsFile = cJSON_GetObjectItem(stbInfo, "tags_file"); - if (tagsFile && tagsFile->type == cJSON_String && tagsFile->valuestring != NULL) { + if ((tagsFile && tagsFile->type == cJSON_String) + && (tagsFile->valuestring != NULL)) { tstrncpy(g_Dbs.db[i].superTbls[j].tagsFile, tagsFile->valuestring, MAX_FILE_NAME_LEN); if (0 == g_Dbs.db[i].superTbls[j].tagsFile[0]) { @@ -4946,26 +4955,29 @@ static int32_t execInsert(threadInfo *pThreadInfo, uint32_t k) static void getTableName(char *pTblName, threadInfo* pThreadInfo, uint64_t tableSeq) { - SSuperTable* superTblInfo = pThreadInfo->superTblInfo; - if ((superTblInfo) - && (AUTO_CREATE_SUBTBL != superTblInfo->autoCreateTable)) { - if (superTblInfo->childTblLimit > 0) { - snprintf(pTblName, TSDB_TABLE_NAME_LEN, "%s", - superTblInfo->childTblName + - (tableSeq - superTblInfo->childTblOffset) * TSDB_TABLE_NAME_LEN); + SSuperTable* superTblInfo = pThreadInfo->superTblInfo; + if (superTblInfo) { + if (AUTO_CREATE_SUBTBL != superTblInfo->autoCreateTable) { + if (superTblInfo->childTblLimit > 0) { + snprintf(pTblName, TSDB_TABLE_NAME_LEN, "%s", + superTblInfo->childTblName + + (tableSeq - superTblInfo->childTblOffset) * TSDB_TABLE_NAME_LEN); + } else { + verbosePrint("[%d] %s() LN%d: from=%"PRIu64" count=%"PRId64" seq=%"PRIu64"\n", + pThreadInfo->threadID, __func__, __LINE__, + pThreadInfo->start_table_from, + pThreadInfo->ntables, tableSeq); + snprintf(pTblName, TSDB_TABLE_NAME_LEN, "%s", + superTblInfo->childTblName + tableSeq * TSDB_TABLE_NAME_LEN); + } + } else { + snprintf(pTblName, TSDB_TABLE_NAME_LEN, "%s%"PRIu64"", + superTblInfo->childTblPrefix, tableSeq); + } } else { - - verbosePrint("[%d] %s() LN%d: from=%"PRIu64" count=%"PRId64" seq=%"PRIu64"\n", - pThreadInfo->threadID, __func__, __LINE__, - pThreadInfo->start_table_from, - pThreadInfo->ntables, tableSeq); - snprintf(pTblName, TSDB_TABLE_NAME_LEN, "%s", - superTblInfo->childTblName + tableSeq * TSDB_TABLE_NAME_LEN); + snprintf(pTblName, TSDB_TABLE_NAME_LEN, "%s%"PRIu64"", + g_args.tb_prefix, tableSeq); } - } else { - snprintf(pTblName, TSDB_TABLE_NAME_LEN, "%s%"PRIu64"", - g_args.tb_prefix, tableSeq); - } } static int32_t generateDataTailWithoutStb( @@ -6753,7 +6765,6 @@ static int insertTestProcess() { } } - // taosMsleep(1000); // create sub threads for inserting data //start = taosGetTimestampMs(); for (int i = 0; i < g_Dbs.dbCount; i++) { @@ -7397,11 +7408,14 @@ static void *specifiedSubscribe(void *sarg) { g_queryInfo.specifiedQueryInfo.res[pThreadInfo->threadID] = taos_consume( g_queryInfo.specifiedQueryInfo.tsub[pThreadInfo->threadID]); if (g_queryInfo.specifiedQueryInfo.res[pThreadInfo->threadID]) { - if (g_queryInfo.specifiedQueryInfo.result[pThreadInfo->querySeq][0] != 0) { + if (g_queryInfo.specifiedQueryInfo.result[pThreadInfo->querySeq][0] + != 0) { sprintf(pThreadInfo->filePath, "%s-%d", g_queryInfo.specifiedQueryInfo.result[pThreadInfo->querySeq], pThreadInfo->threadID); - fetchResult(g_queryInfo.specifiedQueryInfo.res[pThreadInfo->threadID], pThreadInfo); + fetchResult( + g_queryInfo.specifiedQueryInfo.res[pThreadInfo->threadID], + pThreadInfo); } g_queryInfo.specifiedQueryInfo.consumed[pThreadInfo->threadID] ++; @@ -7414,16 +7428,17 @@ static void *specifiedSubscribe(void *sarg) { g_queryInfo.specifiedQueryInfo.consumed[pThreadInfo->threadID] = 0; taos_unsubscribe(g_queryInfo.specifiedQueryInfo.tsub[pThreadInfo->threadID], g_queryInfo.specifiedQueryInfo.subscribeKeepProgress); - g_queryInfo.specifiedQueryInfo.tsub[pThreadInfo->threadID] = subscribeImpl( - SPECIFIED_CLASS, - pThreadInfo, - g_queryInfo.specifiedQueryInfo.sql[pThreadInfo->querySeq], - g_queryInfo.specifiedQueryInfo.topic[pThreadInfo->threadID], - g_queryInfo.specifiedQueryInfo.subscribeRestart, - g_queryInfo.specifiedQueryInfo.subscribeInterval); + g_queryInfo.specifiedQueryInfo.tsub[pThreadInfo->threadID] = + subscribeImpl( + SPECIFIED_CLASS, + pThreadInfo, + g_queryInfo.specifiedQueryInfo.sql[pThreadInfo->querySeq], + g_queryInfo.specifiedQueryInfo.topic[pThreadInfo->threadID], + g_queryInfo.specifiedQueryInfo.subscribeRestart, + g_queryInfo.specifiedQueryInfo.subscribeInterval); if (NULL == g_queryInfo.specifiedQueryInfo.tsub[pThreadInfo->threadID]) { - taos_close(pThreadInfo->taos); - return NULL; + taos_close(pThreadInfo->taos); + return NULL; } } } @@ -7636,7 +7651,7 @@ static void setParaFromArg(){ g_Dbs.threadCountByCreateTbl = g_args.num_of_threads; g_Dbs.dbCount = 1; - g_Dbs.db[0].drop = 1; + g_Dbs.db[0].drop = true; tstrncpy(g_Dbs.db[0].dbName, g_args.database, MAX_DB_NAME_SIZE); g_Dbs.db[0].dbCfg.replica = g_args.replica; From 9bfe74aa8ce08d1619583a4a59c4c3274acdd68d Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Sat, 29 May 2021 14:24:44 +0800 Subject: [PATCH 62/70] [td-4385] add java api for dynamic create table during insert data. --- .../jni/com_taosdata_jdbc_TSDBJNIConnector.h | 10 +- src/client/src/TSDBJNIConnector.c | 101 ++++++-- .../com/taosdata/jdbc/TSDBJNIConnector.java | 10 + .../taosdata/jdbc/TSDBPreparedStatement.java | 222 +++++++++++++++++- 4 files changed, 317 insertions(+), 26 deletions(-) diff --git a/src/client/jni/com_taosdata_jdbc_TSDBJNIConnector.h b/src/client/jni/com_taosdata_jdbc_TSDBJNIConnector.h index 04bccc1a4a..d16b672f38 100644 --- a/src/client/jni/com_taosdata_jdbc_TSDBJNIConnector.h +++ b/src/client/jni/com_taosdata_jdbc_TSDBJNIConnector.h @@ -218,11 +218,19 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_executeBatchImp(J /* * Class: com_taosdata_jdbc_TSDBJNIConnector - * Method: executeBatchImp + * Method: closeStmt * Signature: (JJ)I */ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_closeStmt(JNIEnv *env, jobject jobj, jlong stmt, jlong con); +/** + * Class: com_taosdata_jdbc_TSDBJNIConnector + * Method: setTableNameTagsImp + * Signature: (JLjava/lang/String;I[B[B[B[BJ)I + */ +JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setTableNameTagsImp + (JNIEnv *, jobject, jlong, jstring, jint, jbyteArray, jbyteArray, jbyteArray, jbyteArray, jlong); + #ifdef __cplusplus } #endif diff --git a/src/client/src/TSDBJNIConnector.c b/src/client/src/TSDBJNIConnector.c index da7da17aa3..717f1689d3 100644 --- a/src/client/src/TSDBJNIConnector.c +++ b/src/client/src/TSDBJNIConnector.c @@ -749,7 +749,6 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setBindTableNameI } jniDebug("jobj:%p, conn:%p, set stmt bind table name:%s", jobj, tsconn, name); - (*env)->ReleaseStringUTFChars(env, jname, name); return JNI_SUCCESS; } @@ -762,7 +761,7 @@ JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_bindColDataImp(J return JNI_CONNECTION_NULL; } - TAOS_STMT* pStmt = (TAOS_STMT*) stmt; + TAOS_STMT *pStmt = (TAOS_STMT *)stmt; if (pStmt == NULL) { jniError("jobj:%p, conn:%p, invalid stmt", jobj, tscon); return JNI_SQL_NULL; @@ -777,14 +776,14 @@ JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_bindColDataImp(J } len = (*env)->GetArrayLength(env, lengthList); - char *lengthArray = (char*) calloc(1, len); - (*env)->GetByteArrayRegion(env, lengthList, 0, len, (jbyte*) lengthArray); + char *lengthArray = (char *)calloc(1, len); + (*env)->GetByteArrayRegion(env, lengthList, 0, len, (jbyte *)lengthArray); if ((*env)->ExceptionCheck(env)) { } len = (*env)->GetArrayLength(env, nullList); - char *nullArray = (char*) calloc(1, len); - (*env)->GetByteArrayRegion(env, nullList, 0, len, (jbyte*) nullArray); + char *nullArray = (char *)calloc(1, len); + (*env)->GetByteArrayRegion(env, nullList, 0, len, (jbyte *)nullArray); if ((*env)->ExceptionCheck(env)) { } @@ -799,22 +798,10 @@ JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_bindColDataImp(J b->length = (int32_t*)lengthArray; // set the length and is_null array - switch(dataType) { - case TSDB_DATA_TYPE_INT: - case TSDB_DATA_TYPE_TINYINT: - case TSDB_DATA_TYPE_SMALLINT: - case TSDB_DATA_TYPE_TIMESTAMP: - case TSDB_DATA_TYPE_BIGINT: { - int32_t bytes = tDataTypes[dataType].bytes; - for(int32_t i = 0; i < numOfRows; ++i) { - b->length[i] = bytes; - } - break; - } - - case TSDB_DATA_TYPE_NCHAR: - case TSDB_DATA_TYPE_BINARY: { - // do nothing + if (!IS_VAR_DATA_TYPE(dataType)) { + int32_t bytes = tDataTypes[dataType].bytes; + for (int32_t i = 0; i < numOfRows; ++i) { + b->length[i] = bytes; } } @@ -878,3 +865,73 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_closeStmt(JNIEnv jniDebug("jobj:%p, conn:%p, stmt closed", jobj, tscon); return JNI_SUCCESS; } + +JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setTableNameTagsImp(JNIEnv *env, jobject jobj, + jlong stmt, jstring tableName, jint numOfTags, jbyteArray tags, jbyteArray typeList, jbyteArray lengthList, jbyteArray nullList, jlong conn) { + TAOS *tsconn = (TAOS *)conn; + if (tsconn == NULL) { + jniError("jobj:%p, connection already closed", jobj); + return JNI_CONNECTION_NULL; + } + + TAOS_STMT* pStmt = (TAOS_STMT*) stmt; + if (pStmt == NULL) { + jniError("jobj:%p, conn:%p, invalid stmt handle", jobj, tsconn); + return JNI_SQL_NULL; + } + + jsize len = (*env)->GetArrayLength(env, tags); + char *tagsData = (char *)calloc(1, len); + (*env)->GetByteArrayRegion(env, tags, 0, len, (jbyte *)tagsData); + if ((*env)->ExceptionCheck(env)) { + // todo handle error + } + + len = (*env)->GetArrayLength(env, lengthList); + int64_t *lengthArray = (int64_t*) calloc(1, len); + (*env)->GetByteArrayRegion(env, lengthList, 0, len, (jbyte*) lengthArray); + if ((*env)->ExceptionCheck(env)) { + } + + len = (*env)->GetArrayLength(env, typeList); + char *typeArray = (char*) calloc(1, len); + (*env)->GetByteArrayRegion(env, typeList, 0, len, (jbyte*) typeArray); + if ((*env)->ExceptionCheck(env)) { + } + + len = (*env)->GetArrayLength(env, nullList); + int32_t *nullArray = (int32_t*) calloc(1, len); + (*env)->GetByteArrayRegion(env, nullList, 0, len, (jbyte*) nullArray); + if ((*env)->ExceptionCheck(env)) { + } + + const char *name = (*env)->GetStringUTFChars(env, tableName, NULL); + char* curTags = tagsData; + + TAOS_BIND *tagsBind = calloc(numOfTags, sizeof(TAOS_BIND)); + for(int32_t i = 0; i < numOfTags; ++i) { + tagsBind[i].buffer_type = typeArray[i]; + tagsBind[i].buffer = curTags; + tagsBind[i].is_null = &nullArray[i]; + tagsBind[i].length = (uintptr_t*) &lengthArray[i]; + + curTags += lengthArray[i]; + } + + int32_t code = taos_stmt_set_tbname_tags((void*)stmt, name, tagsBind); + jniDebug("jobj:%p, conn:%p, set table name:%s, numOfTags:%d", jobj, tsconn, name, + numOfTags); + + tfree(tagsData); + tfree(lengthArray); + tfree(typeArray); + tfree(nullArray); + (*env)->ReleaseStringUTFChars(env, tableName, name); + + if (code != TSDB_CODE_SUCCESS) { + jniError("jobj:%p, conn:%p, code:%s", jobj, tsconn, tstrerror(code)); + return JNI_TDENGINE_ERROR; + } + + return JNI_SUCCESS; +} diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBJNIConnector.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBJNIConnector.java index d6934b8e46..179bad2ced 100755 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBJNIConnector.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBJNIConnector.java @@ -310,6 +310,16 @@ public class TSDBJNIConnector { private native int setBindTableNameImp(long stmt, String name, long conn); + public void setBindTableNameAndTags(long stmt, String tableName, int numOfTags, ByteBuffer tags, ByteBuffer typeList, ByteBuffer lengthList, ByteBuffer nullList) throws SQLException { + int code = setTableNameTagsImp(stmt, tableName, numOfTags, tags.array(), typeList.array(), lengthList.array(), + nullList.array(), this.taos); + if (code != TSDBConstants.JNI_SUCCESS) { + throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNKNOWN, "failed to bind table name and corresponding tags"); + } + } + + private native int setTableNameTagsImp(long stmt, String name, int numOfTags, byte[] tags, byte[] typeList, byte[] lengthList, byte[] nullList, long conn); + public void bindColumnDataArray(long stmt, ByteBuffer colDataList, ByteBuffer lengthList, ByteBuffer isNullList, int type, int bytes, int numOfRows,int columnIndex) throws SQLException { int code = bindColDataImp(stmt, colDataList.array(), lengthList.array(), isNullList.array(), type, bytes, numOfRows, columnIndex, this.taos); if (code != TSDBConstants.JNI_SUCCESS) { diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBPreparedStatement.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBPreparedStatement.java index 71e07252a3..f6810237c0 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBPreparedStatement.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBPreparedStatement.java @@ -41,6 +41,9 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat private boolean isPrepared; private ArrayList colData; + private ArrayList tableTags; + private int tagValueLength; + private String tableName; private long nativeStmtHandle = 0; @@ -63,8 +66,8 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat if (parameterCnt > 1) { // the table name is also a parameter, so ignore it. - this.colData = new ArrayList(parameterCnt - 1); - this.colData.addAll(Collections.nCopies(parameterCnt - 1, null)); + this.colData = new ArrayList(); + this.tableTags = new ArrayList(); } } @@ -562,11 +565,109 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat } }; + private static class TableTagInfo { + private boolean isNull; + private Object value; + private int type; + public TableTagInfo(Object value, int type) { + this.value = value; + this.type = type; + } + + public static TableTagInfo createNullTag(int type) { + TableTagInfo info = new TableTagInfo(null, type); + info.isNull = true; + return info; + } + }; + public void setTableName(String name) { this.tableName = name; } + private void ensureTagCapacity(int index) { + if (this.tableTags.size() < index + 1) { + int delta = index + 1 - this.tableTags.size(); + this.tableTags.addAll(Collections.nCopies(delta, null)); + } + } + + public void setTagNull(int index, int type) { + ensureTagCapacity(index); + this.tableTags.set(index, TableTagInfo.createNullTag(type)); + } + + public void setTagBoolean(int index, boolean value) { + ensureTagCapacity(index); + this.tableTags.set(index, new TableTagInfo(value, TSDBConstants.TSDB_DATA_TYPE_BOOL)); + this.tagValueLength += Byte.BYTES; + } + + public void setTagInt(int index, int value) { + ensureTagCapacity(index); + this.tableTags.set(index, new TableTagInfo(value, TSDBConstants.TSDB_DATA_TYPE_INT)); + this.tagValueLength += Integer.BYTES; + } + + public void setTagByte(int index, byte value) { + ensureTagCapacity(index); + this.tableTags.set(index, new TableTagInfo(value, TSDBConstants.TSDB_DATA_TYPE_TINYINT)); + this.tagValueLength += Byte.BYTES; + } + + public void setTagShort(int index, short value) { + ensureTagCapacity(index); + this.tableTags.set(index, new TableTagInfo(value, TSDBConstants.TSDB_DATA_TYPE_SMALLINT)); + this.tagValueLength += Short.BYTES; + } + + public void setTagLong(int index, long value) { + ensureTagCapacity(index); + this.tableTags.set(index, new TableTagInfo(value, TSDBConstants.TSDB_DATA_TYPE_BIGINT)); + this.tagValueLength += Long.BYTES; + } + + public void setTagTimestamp(int index, long value) { + ensureTagCapacity(index); + this.tableTags.set(index, new TableTagInfo(value, TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP)); + this.tagValueLength += Long.BYTES; + } + + public void setTagFloat(int index, float value) { + ensureTagCapacity(index); + this.tableTags.set(index, new TableTagInfo(value, TSDBConstants.TSDB_DATA_TYPE_FLOAT)); + this.tagValueLength += Float.BYTES; + } + + public void setTagDouble(int index, double value) { + ensureTagCapacity(index); + this.tableTags.set(index, new TableTagInfo(value, TSDBConstants.TSDB_DATA_TYPE_DOUBLE)); + this.tagValueLength += Double.BYTES; + } + + public void setTagString(int index, String value) { + ensureTagCapacity(index); + this.tableTags.set(index, new TableTagInfo(value, TSDBConstants.TSDB_DATA_TYPE_BINARY)); + this.tagValueLength += value.getBytes().length; + } + + public void setTagNString(int index, String value) { + ensureTagCapacity(index); + this.tableTags.set(index, new TableTagInfo(value, TSDBConstants.TSDB_DATA_TYPE_NCHAR)); + + String charset = TaosGlobalConfig.getCharset(); + try { + this.tagValueLength += value.getBytes(charset).length; + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + } + public void setValueImpl(int columnIndex, ArrayList list, int type, int bytes) throws SQLException { + if (this.colData.size() == 0) { + this.colData.addAll(Collections.nCopies(this.parameters.length - 1 - this.tableTags.size(), null)); + + } ColumnInfo col = (ColumnInfo) this.colData.get(columnIndex); if (col == null) { ColumnInfo p = new ColumnInfo(); @@ -641,7 +742,122 @@ public class TSDBPreparedStatement extends TSDBStatement implements PreparedStat TSDBJNIConnector connector = ((TSDBConnection) this.getConnection()).getConnector(); this.nativeStmtHandle = connector.prepareStmt(rawSql); - connector.setBindTableName(this.nativeStmtHandle, this.tableName); + + if (this.tableTags == null) { + connector.setBindTableName(this.nativeStmtHandle, this.tableName); + } else { + int num = this.tableTags.size(); + ByteBuffer tagDataList = ByteBuffer.allocate(this.tagValueLength); + tagDataList.order(ByteOrder.LITTLE_ENDIAN); + + ByteBuffer typeList = ByteBuffer.allocate(num); + typeList.order(ByteOrder.LITTLE_ENDIAN); + + ByteBuffer lengthList = ByteBuffer.allocate(num * Long.BYTES); + lengthList.order(ByteOrder.LITTLE_ENDIAN); + + ByteBuffer isNullList = ByteBuffer.allocate(num * Integer.BYTES); + isNullList.order(ByteOrder.LITTLE_ENDIAN); + + for (int i = 0; i < num; ++i) { + TableTagInfo tag = this.tableTags.get(i); + if (tag.isNull) { + typeList.put((byte) tag.type); + isNullList.putInt(1); + lengthList.putLong(0); + continue; + } + + switch (tag.type) { + case TSDBConstants.TSDB_DATA_TYPE_INT: { + Integer val = (Integer) tag.value; + tagDataList.putInt(val); + lengthList.putLong(Integer.BYTES); + break; + } + case TSDBConstants.TSDB_DATA_TYPE_TINYINT: { + Byte val = (Byte) tag.value; + tagDataList.put(val); + lengthList.putLong(Byte.BYTES); + break; + } + + case TSDBConstants.TSDB_DATA_TYPE_BOOL: { + Boolean val = (Boolean) tag.value; + tagDataList.put((byte) (val ? 1 : 0)); + lengthList.putLong(Byte.BYTES); + break; + } + + case TSDBConstants.TSDB_DATA_TYPE_SMALLINT: { + Short val = (Short) tag.value; + tagDataList.putShort(val); + lengthList.putLong(Short.BYTES); + + break; + } + + case TSDBConstants.TSDB_DATA_TYPE_TIMESTAMP: + case TSDBConstants.TSDB_DATA_TYPE_BIGINT: { + Long val = (Long) tag.value; + tagDataList.putLong(val == null ? 0 : val); + lengthList.putLong(Long.BYTES); + + break; + } + + case TSDBConstants.TSDB_DATA_TYPE_FLOAT: { + Float val = (Float) tag.value; + tagDataList.putFloat(val == null ? 0 : val); + lengthList.putLong(Float.BYTES); + + break; + } + + case TSDBConstants.TSDB_DATA_TYPE_DOUBLE: { + Double val = (Double) tag.value; + tagDataList.putDouble(val == null ? 0 : val); + lengthList.putLong(Double.BYTES); + + break; + } + + case TSDBConstants.TSDB_DATA_TYPE_NCHAR: + case TSDBConstants.TSDB_DATA_TYPE_BINARY: { + String charset = TaosGlobalConfig.getCharset(); + String val = (String) tag.value; + + byte[] b = null; + try { + if (tag.type == TSDBConstants.TSDB_DATA_TYPE_BINARY) { + b = val.getBytes(); + } else { + b = val.getBytes(charset); + } + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + + tagDataList.put(b); + lengthList.putLong(b.length); + break; + } + + case TSDBConstants.TSDB_DATA_TYPE_UTINYINT: + case TSDBConstants.TSDB_DATA_TYPE_USMALLINT: + case TSDBConstants.TSDB_DATA_TYPE_UINT: + case TSDBConstants.TSDB_DATA_TYPE_UBIGINT: { + throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNKNOWN, "not support data types"); + } + } + + typeList.put((byte) tag.type); + isNullList.putInt(tag.isNull? 1 : 0); + } + + connector.setBindTableNameAndTags(this.nativeStmtHandle, this.tableName, this.tableTags.size(), tagDataList, + typeList, lengthList, isNullList); + } ColumnInfo colInfo = (ColumnInfo) this.colData.get(0); if (colInfo == null) { From ebd919bc43a879b95f104745a5a229f9be5e6de7 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Sat, 29 May 2021 15:48:24 +0800 Subject: [PATCH 63/70] [td-4385]fix compiler error on arm32 --- src/client/src/TSDBJNIConnector.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/client/src/TSDBJNIConnector.c b/src/client/src/TSDBJNIConnector.c index 717f1689d3..324c436dce 100644 --- a/src/client/src/TSDBJNIConnector.c +++ b/src/client/src/TSDBJNIConnector.c @@ -919,8 +919,9 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setTableNameTagsI } int32_t code = taos_stmt_set_tbname_tags((void*)stmt, name, tagsBind); - jniDebug("jobj:%p, conn:%p, set table name:%s, numOfTags:%d", jobj, tsconn, name, - numOfTags); + + int32_t nTags = (int32_t) numOfTags; + jniDebug("jobj:%p, conn:%p, set table name:%s, numOfTags:%d", jobj, tsconn, name, nTags); tfree(tagsData); tfree(lengthArray); From d43743e678ecbce5c1417034372b1a41bc167823 Mon Sep 17 00:00:00 2001 From: Ping Xiao Date: Sat, 29 May 2021 16:24:11 +0800 Subject: [PATCH 64/70] [TD-4420]: add test case --- tests/pytest/fulltest.sh | 2 ++ tests/pytest/stable/insert.py | 10 ++++++++++ 2 files changed, 12 insertions(+) diff --git a/tests/pytest/fulltest.sh b/tests/pytest/fulltest.sh index d8e2a31e70..be2cfee04b 100755 --- a/tests/pytest/fulltest.sh +++ b/tests/pytest/fulltest.sh @@ -38,6 +38,8 @@ python3 ./test.py -f table/boundary.py python3 ./test.py -f table/create.py python3 ./test.py -f table/del_stable.py +#stable +python3 ./test.py -f stable/insert.py # tag python3 ./test.py -f tag_lite/filter.py diff --git a/tests/pytest/stable/insert.py b/tests/pytest/stable/insert.py index 0ef816da8d..ef5635c77c 100644 --- a/tests/pytest/stable/insert.py +++ b/tests/pytest/stable/insert.py @@ -72,6 +72,9 @@ class TDTestCase: tdSql.query("describe db.stb") tdSql.checkRows(3) + tdSql.error("drop stable if exists db.dev_01") + tdSql.error("drop stable if exists db.dev_02") + tdSql.execute("alter stable db.stb add tag t1 int") tdSql.query("describe db.stb") tdSql.checkRows(4) @@ -80,6 +83,13 @@ class TDTestCase: tdSql.query("show stables") tdSql.checkRows(1) + tdSql.error("drop stable if exists db.dev_001") + tdSql.error("drop stable if exists db.dev_002") + + for i in range(10): + tdSql.execute("drop stable if exists db.stb") + tdSql.query("show stables") + tdSql.checkRows(1) def stop(self): tdSql.close() From 6eb29bf2b88b11ed0a030b9b9d3db6adc5b4ccdb Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Sat, 29 May 2021 19:35:42 +0800 Subject: [PATCH 65/70] [td-4385] fix bug found by regression test. --- src/mnode/src/mnodeTable.c | 49 ++++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 20 deletions(-) diff --git a/src/mnode/src/mnodeTable.c b/src/mnode/src/mnodeTable.c index 1584df16fe..db822c2b43 100644 --- a/src/mnode/src/mnodeTable.c +++ b/src/mnode/src/mnodeTable.c @@ -2860,7 +2860,7 @@ static int32_t mnodeProcessMultiTableMetaMsg(SMnodeMsg *pMsg) { if (num != pInfo->numOfTables + pInfo->numOfVgroups) { mError("msg:%p, app:%p, failed to get multi-tableMeta, msg inconsistent", pMsg, pMsg->rpcMsg.ahandle); code = TSDB_CODE_MND_INVALID_TABLE_NAME; - goto _error; + goto _end; } // first malloc 80KB, subsequent reallocation will expand the size as twice of the original size @@ -2868,7 +2868,7 @@ static int32_t mnodeProcessMultiTableMetaMsg(SMnodeMsg *pMsg) { pMultiMeta = rpcMallocCont(totalMallocLen); if (pMultiMeta == NULL) { code = TSDB_CODE_MND_OUT_OF_MEMORY; - goto _error; + goto _end; } pMultiMeta->contLen = sizeof(SMultiTableMeta); @@ -2878,12 +2878,11 @@ static int32_t mnodeProcessMultiTableMetaMsg(SMnodeMsg *pMsg) { for (; t < pInfo->numOfTables; ++t) { char *fullName = nameList[t]; - pMsg->pVgroup = NULL; pMsg->pTable = mnodeGetTable(fullName); if (pMsg->pTable == NULL) { mError("msg:%p, app:%p table:%s, failed to get table meta, table not exist", pMsg, pMsg->rpcMsg.ahandle, fullName); code = TSDB_CODE_MND_INVALID_TABLE_NAME; - goto _error; + goto _end; } if (pMsg->pDb == NULL) { @@ -2893,7 +2892,7 @@ static int32_t mnodeProcessMultiTableMetaMsg(SMnodeMsg *pMsg) { if (pMsg->pDb == NULL || pMsg->pDb->status != TSDB_DB_STATUS_READY) { mnodeDecTableRef(pMsg->pTable); code = TSDB_CODE_APP_NOT_READY; - goto _error; + goto _end; } int remain = totalMallocLen - pMultiMeta->contLen; @@ -2903,7 +2902,7 @@ static int32_t mnodeProcessMultiTableMetaMsg(SMnodeMsg *pMsg) { if (pMultiMeta == NULL) { mnodeDecTableRef(pMsg->pTable); code = TSDB_CODE_MND_OUT_OF_MEMORY; - goto _error; + goto _end; } } @@ -2911,19 +2910,26 @@ static int32_t mnodeProcessMultiTableMetaMsg(SMnodeMsg *pMsg) { if (pMsg->pTable->type == TSDB_SUPER_TABLE) { code = mnodeDoGetSuperTableMeta(pMsg, pMeta); - taosArrayPush(pList, &fullName);// keep the full name for each super table for retrieve vgroup list + taosArrayPush(pList, &fullName); // keep the full name for each super table for retrieve vgroup list } else { - code = mnodeDoGetChildTableMeta(pMsg, pMeta); - } - - if (code == TSDB_CODE_SUCCESS) { - pMultiMeta->numOfTables ++; - pMultiMeta->contLen += pMeta->contLen; + code = mnodeDoGetChildTableMeta(pMsg, pMeta); + if (pMsg->pVgroup != NULL) { + mnodeDecVgroupRef(pMsg->pVgroup); + pMsg->pVgroup = NULL; + } } mnodeDecTableRef(pMsg->pTable); - assert(((SCTableObj*)pMsg->pTable)->refCount >= 1); pMsg->pTable = NULL; + + if (code == TSDB_CODE_SUCCESS) { + pMultiMeta->numOfTables++; + pMultiMeta->contLen += pMeta->contLen; + } else { + // ignore error and continue. + // Otherwise the client may found that the responding message is inconsistent. +// goto _end; + } } char* msg = (char*) pMultiMeta + pMultiMeta->contLen; @@ -2944,7 +2950,7 @@ static int32_t mnodeProcessMultiTableMetaMsg(SMnodeMsg *pMsg) { if (pTable == NULL) { mError("msg:%p, app:%p stable:%s, not exist while get stable vgroup info", pMsg, pMsg->rpcMsg.ahandle, name); code = TSDB_CODE_MND_INVALID_TABLE_NAME; - goto _error; + goto _end; } msg = serializeVgroupInfo(pTable, name, msg, pMsg, pMsg->rpcMsg.ahandle); @@ -2955,15 +2961,18 @@ static int32_t mnodeProcessMultiTableMetaMsg(SMnodeMsg *pMsg) { pMultiMeta->numOfTables = htonl(pMultiMeta->numOfTables); pMsg->rpcRsp.rsp = pMultiMeta; pMsg->rpcRsp.len = pMultiMeta->contLen; + code = TSDB_CODE_SUCCESS; - return TSDB_CODE_SUCCESS; - - _error: + _end: tfree(str); tfree(nameList); - rpcFreeCont(pMultiMeta); taosArrayDestroy(pList); - pMsg->pTable = NULL; + pMsg->pTable = NULL; + pMsg->pVgroup = NULL; + + if (code != TSDB_CODE_SUCCESS) { + rpcFreeCont(pMultiMeta); + } return code; } From 32fba9d015f99f06935227739fd76cfc03fb7dd0 Mon Sep 17 00:00:00 2001 From: Shuduo Sang Date: Sun, 30 May 2021 07:02:51 +0800 Subject: [PATCH 66/70] Feature/sangshuduo/td 4068 taosdemo stmt (#6295) * merge with develop branch. change query/tests/CMakeLists.txt to allow unused function and variable. * refactor data generating. * refactor. * refactor. * refactor. * refactor. * refactor * add prepare stmt function. * refactor get rand timestamp. * fix windows compile error. * copy logic of generate data for stmt. * insert data basically works now. * fix windows compile issue. * [TD-4068]: taosdemo stmt interface. stb batch insert works. * [TD-4068]: taosdemo support stmt. normal table insert works. * [TD-4068]: taosdemo support stmt. interlace write works. * add compile macro to make taosdemo same with master branch. * fix clang compile error. * fix memory leak. * add more macro. Co-authored-by: Shuduo Sang --- src/kit/taosdemo/taosdemo.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/kit/taosdemo/taosdemo.c b/src/kit/taosdemo/taosdemo.c index ec15a99d14..4a54038ace 100644 --- a/src/kit/taosdemo/taosdemo.c +++ b/src/kit/taosdemo/taosdemo.c @@ -693,7 +693,11 @@ static void printHelp() { printf("%s%s%s%s\n", indent, "-p", indent, "The TCP/IP port number to use for the connection. Default is 0."); printf("%s%s%s%s\n", indent, "-I", indent, +#if STMT_IFACE_ENABLED == 1 "The interface (taosc, rest, and stmt) taosdemo uses. Default is 'taosc'."); +#else + "The interface (taosc, rest) taosdemo uses. Default is 'taosc'."); +#endif printf("%s%s%s%s\n", indent, "-d", indent, "Destination database. Default is 'test'."); printf("%s%s%s%s\n", indent, "-a", indent, @@ -793,8 +797,10 @@ static void parse_args(int argc, char *argv[], SArguments *arguments) { arguments->iface = TAOSC_IFACE; } else if (0 == strcasecmp(argv[i], "rest")) { arguments->iface = REST_IFACE; +#if STMT_IFACE_ENABLED == 1 } else if (0 == strcasecmp(argv[i], "stmt")) { arguments->iface = STMT_IFACE; +#endif } else { errorPrint("%s", "\n\t-I need a valid string following!\n"); exit(EXIT_FAILURE); @@ -3912,8 +3918,10 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { g_Dbs.db[i].superTbls[j].iface= TAOSC_IFACE; } else if (0 == strcasecmp(stbIface->valuestring, "rest")) { g_Dbs.db[i].superTbls[j].iface= REST_IFACE; +#if STMT_IFACE_ENABLED == 1 } else if (0 == strcasecmp(stbIface->valuestring, "stmt")) { g_Dbs.db[i].superTbls[j].iface= STMT_IFACE; +#endif } else { errorPrint("%s() LN%d, failed to read json, insert_mode %s not recognized\n", __func__, __LINE__, stbIface->valuestring); @@ -4933,6 +4941,7 @@ static int32_t execInsert(threadInfo *pThreadInfo, uint32_t k) } break; +#if STMT_IFACE_ENABLED == 1 case STMT_IFACE: debugPrint("%s() LN%d, stmt=%p", __func__, __LINE__, pThreadInfo->stmt); if (0 != taos_stmt_execute(pThreadInfo->stmt)) { @@ -4942,6 +4951,7 @@ static int32_t execInsert(threadInfo *pThreadInfo, uint32_t k) } affectedRows = k; break; +#endif default: errorPrint("%s() LN%d: unknown insert mode: %d\n", @@ -5506,6 +5516,7 @@ static int32_t prepareStmtWithoutStb( } } + free(bindArray); return k; } @@ -5586,6 +5597,7 @@ static int32_t prepareStbStmt(SSuperTable *stbInfo, } } + free(bindArray); return k; } #endif @@ -6407,6 +6419,7 @@ static void startMultiThreadInsertData(int threads, char* db_name, exit(-1); } +#if STMT_IFACE_ENABLED == 1 if ((g_args.iface == STMT_IFACE) || ((superTblInfo) && (superTblInfo->iface == STMT_IFACE))) { @@ -6446,6 +6459,7 @@ static void startMultiThreadInsertData(int threads, char* db_name, exit(-1); } } +#endif } else { pThreadInfo->taos = NULL; } @@ -6486,9 +6500,11 @@ static void startMultiThreadInsertData(int threads, char* db_name, tsem_destroy(&(pThreadInfo->lock_sem)); +#if STMT_IFACE_ENABLED == 1 if (pThreadInfo->stmt) { taos_stmt_close(pThreadInfo->stmt); } +#endif tsem_destroy(&(pThreadInfo->lock_sem)); taos_close(pThreadInfo->taos); From f58dbc2f4e216543d7df1ae8ff5812585174fa6a Mon Sep 17 00:00:00 2001 From: haojun Liao Date: Mon, 31 May 2021 00:09:20 +0800 Subject: [PATCH 67/70] Update tscSubquery.c --- src/client/src/tscSubquery.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/client/src/tscSubquery.c b/src/client/src/tscSubquery.c index 325281dce5..37c60edd38 100644 --- a/src/client/src/tscSubquery.c +++ b/src/client/src/tscSubquery.c @@ -604,7 +604,6 @@ static int32_t tscLaunchRealSubqueries(SSqlObj* pSql) { int16_t funcId = pExpr->base.functionId; // add the invisible timestamp column - printf("--------read:%p\n", pExpr); if ((pExpr->base.colInfo.colId != PRIMARYKEY_TIMESTAMP_COL_INDEX) || (funcId != TSDB_FUNC_TS && funcId != TSDB_FUNC_TS_DUMMY && funcId != TSDB_FUNC_PRJ)) { From 282eaa39748984c9319a57114b1ad0745c6fbe89 Mon Sep 17 00:00:00 2001 From: Kaili Xu Date: Mon, 31 May 2021 10:54:22 +0800 Subject: [PATCH 68/70] sync with master and restore log format --- src/tsdb/src/tsdbSync.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tsdb/src/tsdbSync.c b/src/tsdb/src/tsdbSync.c index e9f069c64f..edcb84d091 100644 --- a/src/tsdb/src/tsdbSync.c +++ b/src/tsdb/src/tsdbSync.c @@ -578,7 +578,7 @@ static int32_t tsdbSyncSendDFileSet(SSyncH *pSynch, SDFileSet *pSet) { return -1; } - // No file any more, no need to send file, just return + // No file any more, no need to send file, just return if (pSet == NULL) { return 0; } From 61fc1814878ffa14b1ce0bc1b09563ab2fb2eda9 Mon Sep 17 00:00:00 2001 From: Shuduo Sang Date: Mon, 31 May 2021 11:01:38 +0800 Subject: [PATCH 69/70] Feature/sangshuduo/td 4068 taosdemo stmt (#6299) * merge with develop branch. change query/tests/CMakeLists.txt to allow unused function and variable. * refactor data generating. * refactor. * refactor. * refactor. * refactor. * refactor * add prepare stmt function. * refactor get rand timestamp. * fix windows compile error. * copy logic of generate data for stmt. * insert data basically works now. * fix windows compile issue. * [TD-4068]: taosdemo stmt interface. stb batch insert works. * [TD-4068]: taosdemo support stmt. normal table insert works. * [TD-4068]: taosdemo support stmt. interlace write works. * add compile macro to make taosdemo same with master branch. * fix clang compile error. * fix memory leak. * add more macro. * fix rest segfault. Co-authored-by: Shuduo Sang --- src/kit/taosdemo/taosdemo.c | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/src/kit/taosdemo/taosdemo.c b/src/kit/taosdemo/taosdemo.c index 4a54038ace..d946f961c3 100644 --- a/src/kit/taosdemo/taosdemo.c +++ b/src/kit/taosdemo/taosdemo.c @@ -2910,8 +2910,8 @@ static void* createTable(void *sarg) int buff_len; buff_len = BUFFER_SIZE / 8; - char *buffer = calloc(buff_len, 1); - if (buffer == NULL) { + pThreadInfo->buffer = calloc(buff_len, 1); + if (pThreadInfo->buffer == NULL) { errorPrint("%s() LN%d, Memory allocated failed!\n", __func__, __LINE__); exit(-1); } @@ -2926,7 +2926,7 @@ static void* createTable(void *sarg) for (uint64_t i = pThreadInfo->start_table_from; i <= pThreadInfo->end_table_to; i++) { if (0 == g_Dbs.use_metric) { - snprintf(buffer, buff_len, + snprintf(pThreadInfo->buffer, buff_len, "create table if not exists %s.%s%"PRIu64" %s;", pThreadInfo->db_name, g_args.tb_prefix, i, @@ -2935,13 +2935,13 @@ static void* createTable(void *sarg) if (superTblInfo == NULL) { errorPrint("%s() LN%d, use metric, but super table info is NULL\n", __func__, __LINE__); - free(buffer); + free(pThreadInfo->buffer); exit(-1); } else { if (0 == len) { batchNum = 0; - memset(buffer, 0, buff_len); - len += snprintf(buffer + len, + memset(pThreadInfo->buffer, 0, buff_len); + len += snprintf(pThreadInfo->buffer + len, buff_len - len, "create table "); } char* tagsValBuf = NULL; @@ -2953,10 +2953,10 @@ static void* createTable(void *sarg) i % superTblInfo->tagSampleCount); } if (NULL == tagsValBuf) { - free(buffer); + free(pThreadInfo->buffer); return NULL; } - len += snprintf(buffer + len, + len += snprintf(pThreadInfo->buffer + len, buff_len - len, "if not exists %s.%s%"PRIu64" using %s.%s tags %s ", pThreadInfo->db_name, superTblInfo->childTblPrefix, @@ -2973,9 +2973,10 @@ static void* createTable(void *sarg) } len = 0; - if (0 != queryDbExec(pThreadInfo->taos, buffer, NO_INSERT_TYPE, false)){ - errorPrint( "queryDbExec() failed. buffer:\n%s\n", buffer); - free(buffer); + if (0 != queryDbExec(pThreadInfo->taos, pThreadInfo->buffer, + NO_INSERT_TYPE, false)){ + errorPrint( "queryDbExec() failed. buffer:\n%s\n", pThreadInfo->buffer); + free(pThreadInfo->buffer); return NULL; } @@ -2988,12 +2989,13 @@ static void* createTable(void *sarg) } if (0 != len) { - if (0 != queryDbExec(pThreadInfo->taos, buffer, NO_INSERT_TYPE, false)) { - errorPrint( "queryDbExec() failed. buffer:\n%s\n", buffer); + if (0 != queryDbExec(pThreadInfo->taos, pThreadInfo->buffer, + NO_INSERT_TYPE, false)) { + errorPrint( "queryDbExec() failed. buffer:\n%s\n", pThreadInfo->buffer); } } - free(buffer); + free(pThreadInfo->buffer); return NULL; } @@ -4932,7 +4934,7 @@ static int32_t execInsert(threadInfo *pThreadInfo, uint32_t k) case REST_IFACE: if (0 != postProceSql(g_Dbs.host, &g_Dbs.serv_addr, g_Dbs.port, - pThreadInfo->buffer, NULL /* not set result file */)) { + pThreadInfo->buffer, pThreadInfo)) { affectedRows = -1; printf("========restful return fail, threadID[%d]\n", pThreadInfo->threadID); From d7d38d88af1ae5cb99d33e2c34e3732b9396920a Mon Sep 17 00:00:00 2001 From: Shuduo Sang Date: Mon, 31 May 2021 13:39:09 +0800 Subject: [PATCH 70/70] Hotfix/sangshuduo/td 4353 taosdemo subscribe resub for develop (#6303) * [TD-4353]: taosdemo resub if resubAfterConsume != -1 * fix but resubafter use endafter section. Co-authored-by: Shuduo Sang --- src/kit/taosdemo/taosdemo.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/kit/taosdemo/taosdemo.c b/src/kit/taosdemo/taosdemo.c index d946f961c3..6f5d407a73 100644 --- a/src/kit/taosdemo/taosdemo.c +++ b/src/kit/taosdemo/taosdemo.c @@ -4401,8 +4401,9 @@ static bool getMetaFromQueryJsonFile(cJSON* root) { cJSON* resubAfterConsume = cJSON_GetObjectItem(specifiedQuery, "resubAfterConsume"); - if (resubAfterConsume - && resubAfterConsume->type == cJSON_Number) { + if ((resubAfterConsume) + && (resubAfterConsume->type == cJSON_Number) + && (resubAfterConsume->valueint >= 0)) { g_queryInfo.specifiedQueryInfo.resubAfterConsume[j] = resubAfterConsume->valueint; } else if (!resubAfterConsume) { @@ -4563,14 +4564,15 @@ static bool getMetaFromQueryJsonFile(cJSON* root) { } cJSON* superResubAfterConsume = - cJSON_GetObjectItem(superQuery, "endAfterConsume"); - if (superResubAfterConsume - && superResubAfterConsume->type == cJSON_Number) { - g_queryInfo.superQueryInfo.endAfterConsume = + cJSON_GetObjectItem(superQuery, "resubAfterConsume"); + if ((superResubAfterConsume) + && (superResubAfterConsume->type == cJSON_Number) + && (superResubAfterConsume->valueint >= 0)) { + g_queryInfo.superQueryInfo.resubAfterConsume = superResubAfterConsume->valueint; } else if (!superResubAfterConsume) { // default value is -1, which mean do not resub - g_queryInfo.superQueryInfo.endAfterConsume = -1; + g_queryInfo.superQueryInfo.resubAfterConsume = -1; } // supert table sqls