TDengine/source/dnode/vnode/src/meta/metaTable.c

2239 lines
65 KiB
C
Raw Normal View History

2021-11-02 05:57:16 +00:00
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
2021-11-02 07:24:55 +00:00
*/
2022-04-26 11:04:26 +00:00
#include "meta.h"
2021-11-02 07:24:55 +00:00
2022-10-19 11:44:07 +00:00
static int metaSaveJsonVarToIdx(SMeta *pMeta, const SMetaEntry *pCtbEntry, const SSchema *pSchema);
static int metaDelJsonVarFromIdx(SMeta *pMeta, const SMetaEntry *pCtbEntry, const SSchema *pSchema);
static int metaSaveToTbDb(SMeta *pMeta, const SMetaEntry *pME);
static int metaUpdateUidIdx(SMeta *pMeta, const SMetaEntry *pME);
static int metaUpdateNameIdx(SMeta *pMeta, const SMetaEntry *pME);
static int metaUpdateTtl(SMeta *pMeta, const SMetaEntry *pME);
2022-10-19 11:44:07 +00:00
static int metaSaveToSkmDb(SMeta *pMeta, const SMetaEntry *pME);
static int metaUpdateCtbIdx(SMeta *pMeta, const SMetaEntry *pME);
static int metaUpdateSuidIdx(SMeta *pMeta, const SMetaEntry *pME);
static int metaUpdateTagIdx(SMeta *pMeta, const SMetaEntry *pCtbEntry);
static int metaDropTableByUid(SMeta *pMeta, tb_uid_t uid, int *type);
static void metaDestroyTagIdxKey(STagIdxKey *pTagIdxKey);
2022-10-13 10:53:04 +00:00
// opt ins_tables query
static int metaUpdateBtimeIdx(SMeta *pMeta, const SMetaEntry *pME);
static int metaDeleteBtimeIdx(SMeta *pMeta, const SMetaEntry *pME);
2022-10-13 10:53:04 +00:00
static int metaUpdateNcolIdx(SMeta *pMeta, const SMetaEntry *pME);
static int metaDeleteNcolIdx(SMeta *pMeta, const SMetaEntry *pME);
2022-04-21 14:01:58 +00:00
2022-08-16 06:22:55 +00:00
static void metaGetEntryInfo(const SMetaEntry *pEntry, SMetaInfo *pInfo) {
pInfo->uid = pEntry->uid;
pInfo->version = pEntry->version;
if (pEntry->type == TSDB_SUPER_TABLE) {
pInfo->suid = pEntry->uid;
pInfo->skmVer = pEntry->stbEntry.schemaRow.version;
} else if (pEntry->type == TSDB_CHILD_TABLE) {
pInfo->suid = pEntry->ctbEntry.suid;
pInfo->skmVer = 0;
} else if (pEntry->type == TSDB_NORMAL_TABLE) {
pInfo->suid = 0;
pInfo->skmVer = pEntry->ntbEntry.schemaRow.version;
} else {
metaError("meta/table: invalide table type: %" PRId8 " get entry info failed.", pEntry->type);
2022-08-16 06:22:55 +00:00
}
}
2022-06-04 14:33:36 +00:00
static int metaUpdateMetaRsp(tb_uid_t uid, char *tbName, SSchemaWrapper *pSchema, STableMetaRsp *pMetaRsp) {
2022-06-01 12:28:29 +00:00
pMetaRsp->pSchemas = taosMemoryMalloc(pSchema->nCols * sizeof(SSchema));
if (NULL == pMetaRsp->pSchemas) {
2022-11-02 07:28:32 +00:00
terrno = TSDB_CODE_OUT_OF_MEMORY;
2022-06-01 12:28:29 +00:00
return -1;
}
2022-10-18 06:32:18 +00:00
tstrncpy(pMetaRsp->tbName, tbName, TSDB_TABLE_NAME_LEN);
2022-06-01 12:28:29 +00:00
pMetaRsp->numOfColumns = pSchema->nCols;
pMetaRsp->tableType = TSDB_NORMAL_TABLE;
pMetaRsp->sversion = pSchema->version;
pMetaRsp->tuid = uid;
memcpy(pMetaRsp->pSchemas, pSchema->pSchema, pSchema->nCols * sizeof(SSchema));
return 0;
}
2022-06-04 14:33:36 +00:00
static int metaSaveJsonVarToIdx(SMeta *pMeta, const SMetaEntry *pCtbEntry, const SSchema *pSchema) {
#ifdef USE_INVERTED_INDEX
if (pMeta->pTagIvtIdx == NULL || pCtbEntry == NULL) {
return -1;
}
2022-07-06 12:21:59 +00:00
void *data = pCtbEntry->ctbEntry.pTags;
2022-06-04 14:33:36 +00:00
const char *tagName = pSchema->name;
tb_uid_t suid = pCtbEntry->ctbEntry.suid;
tb_uid_t tuid = pCtbEntry->uid;
const void *pTagData = pCtbEntry->ctbEntry.pTags;
int32_t nTagData = 0;
SArray *pTagVals = NULL;
if (tTagToValArray((const STag *)data, &pTagVals) != 0) {
return -1;
}
2022-06-05 10:56:43 +00:00
2022-06-04 14:33:36 +00:00
SIndexMultiTerm *terms = indexMultiTermCreate();
int16_t nCols = taosArrayGetSize(pTagVals);
for (int i = 0; i < nCols; i++) {
STagVal *pTagVal = (STagVal *)taosArrayGet(pTagVals, i);
char type = pTagVal->type;
2022-06-07 08:02:41 +00:00
2022-07-06 12:21:59 +00:00
char *key = pTagVal->pKey;
2022-06-05 10:56:43 +00:00
int32_t nKey = strlen(key);
2022-06-04 14:33:36 +00:00
SIndexTerm *term = NULL;
if (type == TSDB_DATA_TYPE_NULL) {
2022-07-06 07:07:42 +00:00
term = indexTermCreate(suid, ADD_VALUE, TSDB_DATA_TYPE_VARCHAR, key, nKey, NULL, 0);
2022-06-04 14:33:36 +00:00
} else if (type == TSDB_DATA_TYPE_NCHAR) {
if (pTagVal->nData > 0) {
2022-07-06 12:21:59 +00:00
char *val = taosMemoryCalloc(1, pTagVal->nData + VARSTR_HEADER_SIZE);
2022-06-05 10:56:43 +00:00
int32_t len = taosUcs4ToMbs((TdUcs4 *)pTagVal->pData, pTagVal->nData, val + VARSTR_HEADER_SIZE);
memcpy(val, (uint16_t *)&len, VARSTR_HEADER_SIZE);
2022-06-04 14:33:36 +00:00
type = TSDB_DATA_TYPE_VARCHAR;
2022-06-05 10:56:43 +00:00
term = indexTermCreate(suid, ADD_VALUE, type, key, nKey, val, len);
2022-08-23 09:28:49 +00:00
taosMemoryFree(val);
2022-06-04 14:33:36 +00:00
} else if (pTagVal->nData == 0) {
2022-07-06 07:07:42 +00:00
term = indexTermCreate(suid, ADD_VALUE, TSDB_DATA_TYPE_VARCHAR, key, nKey, pTagVal->pData, 0);
2022-06-04 14:33:36 +00:00
}
} else if (type == TSDB_DATA_TYPE_DOUBLE) {
double val = *(double *)(&pTagVal->i64);
2022-07-06 12:05:45 +00:00
int len = sizeof(val);
2022-06-04 14:33:36 +00:00
term = indexTermCreate(suid, ADD_VALUE, type, key, nKey, (const char *)&val, len);
} else if (type == TSDB_DATA_TYPE_BOOL) {
int val = *(int *)(&pTagVal->i64);
2022-07-06 12:05:45 +00:00
int len = sizeof(val);
2022-07-07 02:05:48 +00:00
term = indexTermCreate(suid, ADD_VALUE, TSDB_DATA_TYPE_BOOL, key, nKey, (const char *)&val, len);
2022-06-04 14:33:36 +00:00
}
2022-06-05 10:56:43 +00:00
if (term != NULL) {
2022-06-04 14:33:36 +00:00
indexMultiTermAdd(terms, term);
}
}
2022-06-09 05:50:18 +00:00
indexJsonPut(pMeta->pTagIvtIdx, terms, tuid);
2022-06-04 14:33:36 +00:00
indexMultiTermDestroy(terms);
2022-10-17 08:29:50 +00:00
taosArrayDestroy(pTagVals);
2022-06-04 14:33:36 +00:00
#endif
2022-06-06 03:51:00 +00:00
return 0;
2022-06-04 14:33:36 +00:00
}
int metaDelJsonVarFromIdx(SMeta *pMeta, const SMetaEntry *pCtbEntry, const SSchema *pSchema) {
#ifdef USE_INVERTED_INDEX
if (pMeta->pTagIvtIdx == NULL || pCtbEntry == NULL) {
return -1;
}
void *data = pCtbEntry->ctbEntry.pTags;
const char *tagName = pSchema->name;
tb_uid_t suid = pCtbEntry->ctbEntry.suid;
tb_uid_t tuid = pCtbEntry->uid;
const void *pTagData = pCtbEntry->ctbEntry.pTags;
int32_t nTagData = 0;
SArray *pTagVals = NULL;
if (tTagToValArray((const STag *)data, &pTagVals) != 0) {
return -1;
}
SIndexMultiTerm *terms = indexMultiTermCreate();
int16_t nCols = taosArrayGetSize(pTagVals);
for (int i = 0; i < nCols; i++) {
STagVal *pTagVal = (STagVal *)taosArrayGet(pTagVals, i);
char type = pTagVal->type;
char *key = pTagVal->pKey;
int32_t nKey = strlen(key);
SIndexTerm *term = NULL;
if (type == TSDB_DATA_TYPE_NULL) {
term = indexTermCreate(suid, DEL_VALUE, TSDB_DATA_TYPE_VARCHAR, key, nKey, NULL, 0);
} else if (type == TSDB_DATA_TYPE_NCHAR) {
if (pTagVal->nData > 0) {
char *val = taosMemoryCalloc(1, pTagVal->nData + VARSTR_HEADER_SIZE);
int32_t len = taosUcs4ToMbs((TdUcs4 *)pTagVal->pData, pTagVal->nData, val + VARSTR_HEADER_SIZE);
memcpy(val, (uint16_t *)&len, VARSTR_HEADER_SIZE);
type = TSDB_DATA_TYPE_VARCHAR;
term = indexTermCreate(suid, DEL_VALUE, type, key, nKey, val, len);
2022-10-17 08:29:50 +00:00
taosMemoryFree(val);
} else if (pTagVal->nData == 0) {
term = indexTermCreate(suid, DEL_VALUE, TSDB_DATA_TYPE_VARCHAR, key, nKey, pTagVal->pData, 0);
}
} else if (type == TSDB_DATA_TYPE_DOUBLE) {
double val = *(double *)(&pTagVal->i64);
int len = sizeof(val);
term = indexTermCreate(suid, DEL_VALUE, type, key, nKey, (const char *)&val, len);
} else if (type == TSDB_DATA_TYPE_BOOL) {
int val = *(int *)(&pTagVal->i64);
int len = sizeof(val);
term = indexTermCreate(suid, DEL_VALUE, TSDB_DATA_TYPE_BOOL, key, nKey, (const char *)&val, len);
2022-06-04 14:33:36 +00:00
}
2022-06-05 10:56:43 +00:00
if (term != NULL) {
2022-06-04 14:33:36 +00:00
indexMultiTermAdd(terms, term);
}
}
2022-06-09 05:50:18 +00:00
indexJsonPut(pMeta->pTagIvtIdx, terms, tuid);
2022-06-04 14:33:36 +00:00
indexMultiTermDestroy(terms);
2022-10-17 08:29:50 +00:00
taosArrayDestroy(pTagVals);
2022-06-04 14:33:36 +00:00
#endif
2022-06-06 03:51:00 +00:00
return 0;
2022-06-04 14:33:36 +00:00
}
2022-04-21 14:01:58 +00:00
int metaCreateSTable(SMeta *pMeta, int64_t version, SVCreateStbReq *pReq) {
2022-04-21 03:47:58 +00:00
SMetaEntry me = {0};
2022-04-21 14:01:58 +00:00
int kLen = 0;
int vLen = 0;
const void *pKey = NULL;
const void *pVal = NULL;
2022-07-06 12:21:59 +00:00
void *pBuf = NULL;
2022-04-21 14:01:58 +00:00
int32_t szBuf = 0;
2022-07-06 12:21:59 +00:00
void *p = NULL;
2022-04-26 02:25:07 +00:00
// validate req
2022-08-17 09:35:06 +00:00
void *pData = NULL;
int nData = 0;
2022-08-17 09:51:49 +00:00
if (tdbTbGet(pMeta->pNameIdx, pReq->name, strlen(pReq->name) + 1, &pData, &nData) == 0) {
2022-08-17 09:35:06 +00:00
tb_uid_t uid = *(tb_uid_t *)pData;
tdbFree(pData);
SMetaInfo info;
if (metaGetInfo(pMeta, uid, &info, NULL) == TSDB_CODE_NOT_FOUND) {
terrno = TSDB_CODE_PAR_TABLE_NOT_EXIST;
return -1;
}
2022-08-17 09:35:06 +00:00
if (info.uid == info.suid) {
return 0;
} else {
terrno = TSDB_CODE_TDB_TABLE_ALREADY_EXIST;
return -1;
}
2022-04-21 14:01:58 +00:00
}
2022-04-21 03:47:58 +00:00
// set structs
2022-04-23 13:45:26 +00:00
me.version = version;
2022-04-21 03:47:58 +00:00
me.type = TSDB_SUPER_TABLE;
me.uid = pReq->suid;
me.name = pReq->name;
2022-05-26 08:29:52 +00:00
me.stbEntry.schemaRow = pReq->schemaRow;
2022-04-22 12:34:37 +00:00
me.stbEntry.schemaTag = pReq->schemaTag;
2022-06-27 06:47:14 +00:00
if (pReq->rollup) {
TABLE_SET_ROLLUP(me.flags);
me.stbEntry.rsmaParam = pReq->rsmaParam;
}
2022-04-21 03:47:58 +00:00
2022-04-23 13:45:26 +00:00
if (metaHandleEntry(pMeta, &me) < 0) goto _err;
2022-04-21 03:47:58 +00:00
++pMeta->pVnode->config.vndStats.numOfSTables;
2022-08-02 09:12:07 +00:00
metaDebug("vgId:%d, stb:%s is created, suid:%" PRId64, TD_VID(pMeta->pVnode), pReq->name, pReq->suid);
2022-04-21 14:01:58 +00:00
return 0;
_err:
2022-08-11 10:12:32 +00:00
metaError("vgId:%d, failed to create stb:%s uid:%" PRId64 " since %s", TD_VID(pMeta->pVnode), pReq->name, pReq->suid,
tstrerror(terrno));
2022-04-21 14:01:58 +00:00
return -1;
}
int metaDropSTable(SMeta *pMeta, int64_t verison, SVDropStbReq *pReq, SArray *tbUidList) {
2022-05-25 07:14:36 +00:00
void *pKey = NULL;
int nKey = 0;
void *pData = NULL;
int nData = 0;
int c = 0;
int rc = 0;
// check if super table exists
rc = tdbTbGet(pMeta->pNameIdx, pReq->name, strlen(pReq->name) + 1, &pData, &nData);
if (rc < 0 || *(tb_uid_t *)pData != pReq->suid) {
2022-09-13 05:35:14 +00:00
tdbFree(pData);
terrno = TSDB_CODE_TDB_STB_NOT_EXIST;
2022-05-25 07:14:36 +00:00
return -1;
2022-04-28 06:20:00 +00:00
}
2022-05-25 07:14:36 +00:00
// drop all child tables
TBC *pCtbIdxc = NULL;
2022-05-04 07:07:34 +00:00
tdbTbcOpen(pMeta->pCtbIdx, &pCtbIdxc, NULL);
2022-05-25 07:14:36 +00:00
rc = tdbTbcMoveTo(pCtbIdxc, &(SCtbIdxKey){.suid = pReq->suid, .uid = INT64_MIN}, sizeof(SCtbIdxKey), &c);
if (rc < 0) {
2022-05-18 07:57:29 +00:00
tdbTbcClose(pCtbIdxc);
2022-05-25 07:14:36 +00:00
metaWLock(pMeta);
goto _drop_super_table;
2022-05-04 07:07:34 +00:00
}
for (;;) {
2022-05-25 07:14:36 +00:00
rc = tdbTbcNext(pCtbIdxc, &pKey, &nKey, NULL, NULL);
if (rc < 0) break;
2022-05-04 07:07:34 +00:00
2022-05-25 07:14:36 +00:00
if (((SCtbIdxKey *)pKey)->suid < pReq->suid) {
continue;
} else if (((SCtbIdxKey *)pKey)->suid > pReq->suid) {
break;
}
2022-05-04 07:07:34 +00:00
taosArrayPush(tbUidList, &(((SCtbIdxKey *)pKey)->uid));
2022-05-25 07:14:36 +00:00
}
tdbTbcClose(pCtbIdxc);
metaWLock(pMeta);
2022-05-04 07:07:34 +00:00
for (int32_t iChild = 0; iChild < taosArrayGetSize(tbUidList); iChild++) {
tb_uid_t uid = *(tb_uid_t *)taosArrayGet(tbUidList, iChild);
2022-05-25 08:03:05 +00:00
metaDropTableByUid(pMeta, uid, NULL);
2022-05-04 07:07:34 +00:00
}
2022-05-25 07:14:36 +00:00
// drop super table
_drop_super_table:
tdbTbGet(pMeta->pUidIdx, &pReq->suid, sizeof(tb_uid_t), &pData, &nData);
2022-08-16 06:22:55 +00:00
tdbTbDelete(pMeta->pTbDb, &(STbDbKey){.version = ((SUidIdxVal *)pData)[0].version, .uid = pReq->suid},
sizeof(STbDbKey), pMeta->txn);
tdbTbDelete(pMeta->pNameIdx, pReq->name, strlen(pReq->name) + 1, pMeta->txn);
tdbTbDelete(pMeta->pUidIdx, &pReq->suid, sizeof(tb_uid_t), pMeta->txn);
tdbTbDelete(pMeta->pSuidIdx, &pReq->suid, sizeof(tb_uid_t), pMeta->txn);
2022-05-25 07:14:36 +00:00
metaULock(pMeta);
2022-05-04 07:07:34 +00:00
_exit:
2022-05-25 07:14:36 +00:00
tdbFree(pKey);
tdbFree(pData);
2022-07-18 11:34:53 +00:00
metaDebug("vgId:%d, super table %s uid:%" PRId64 " is dropped", TD_VID(pMeta->pVnode), pReq->name, pReq->suid);
2022-04-20 10:03:50 +00:00
return 0;
}
2022-05-14 14:29:04 +00:00
int metaAlterSTable(SMeta *pMeta, int64_t version, SVCreateStbReq *pReq) {
SMetaEntry oStbEntry = {0};
SMetaEntry nStbEntry = {0};
2022-07-06 12:21:59 +00:00
TBC *pUidIdxc = NULL;
TBC *pTbDbc = NULL;
2022-05-14 14:29:04 +00:00
const void *pData;
int nData;
int64_t oversion;
SDecoder dc = {0};
int32_t ret;
int32_t c = -2;
2022-05-14 14:29:04 +00:00
tdbTbcOpen(pMeta->pUidIdx, &pUidIdxc, NULL);
2022-05-18 07:57:29 +00:00
ret = tdbTbcMoveTo(pUidIdxc, &pReq->suid, sizeof(tb_uid_t), &c);
2022-05-14 14:29:04 +00:00
if (ret < 0 || c) {
tdbTbcClose(pUidIdxc);
terrno = TSDB_CODE_TDB_STB_NOT_EXIST;
2022-05-14 14:29:04 +00:00
return -1;
}
2022-05-18 07:57:29 +00:00
ret = tdbTbcGet(pUidIdxc, NULL, NULL, &pData, &nData);
2022-05-14 14:29:04 +00:00
if (ret < 0) {
2022-08-13 04:05:08 +00:00
tdbTbcClose(pUidIdxc);
2022-08-11 10:12:32 +00:00
terrno = TSDB_CODE_TDB_STB_NOT_EXIST;
2022-05-14 14:29:04 +00:00
return -1;
}
2022-08-16 06:22:55 +00:00
oversion = ((SUidIdxVal *)pData)[0].version;
2022-05-14 14:29:04 +00:00
tdbTbcOpen(pMeta->pTbDb, &pTbDbc, NULL);
2022-05-18 07:57:29 +00:00
ret = tdbTbcMoveTo(pTbDbc, &((STbDbKey){.uid = pReq->suid, .version = oversion}), sizeof(STbDbKey), &c);
if (!(ret == 0 && c == 0)) {
tdbTbcClose(pUidIdxc);
tdbTbcClose(pTbDbc);
terrno = TSDB_CODE_TDB_STB_NOT_EXIST;
metaError("meta/table: invalide ret: %" PRId32 " or c: %" PRId32 "alter stb failed.", ret, c);
return -1;
}
2022-05-14 14:29:04 +00:00
2022-05-18 07:57:29 +00:00
ret = tdbTbcGet(pTbDbc, NULL, NULL, &pData, &nData);
if (ret < 0) {
tdbTbcClose(pUidIdxc);
tdbTbcClose(pTbDbc);
terrno = TSDB_CODE_TDB_STB_NOT_EXIST;
return -1;
}
2022-05-14 14:29:04 +00:00
2022-05-23 07:47:49 +00:00
oStbEntry.pBuf = taosMemoryMalloc(nData);
memcpy(oStbEntry.pBuf, pData, nData);
tDecoderInit(&dc, oStbEntry.pBuf, nData);
2022-05-14 14:29:04 +00:00
metaDecodeEntry(&dc, &oStbEntry);
nStbEntry.version = version;
nStbEntry.type = TSDB_SUPER_TABLE;
nStbEntry.uid = pReq->suid;
nStbEntry.name = pReq->name;
2022-05-26 08:29:52 +00:00
nStbEntry.stbEntry.schemaRow = pReq->schemaRow;
2022-05-14 14:29:04 +00:00
nStbEntry.stbEntry.schemaTag = pReq->schemaTag;
metaWLock(pMeta);
// compare two entry
2022-05-26 08:29:52 +00:00
if (oStbEntry.stbEntry.schemaRow.version != pReq->schemaRow.version) {
metaSaveToSkmDb(pMeta, &nStbEntry);
2022-05-14 14:29:04 +00:00
}
// update table.db
metaSaveToTbDb(pMeta, &nStbEntry);
// update uid index
2022-08-21 07:05:56 +00:00
metaUpdateUidIdx(pMeta, &nStbEntry);
2022-05-14 14:29:04 +00:00
// metaStatsCacheDrop(pMeta, nStbEntry.uid);
2022-05-14 14:29:04 +00:00
metaULock(pMeta);
2022-09-20 08:33:35 +00:00
if (oStbEntry.pBuf) taosMemoryFree(oStbEntry.pBuf);
2022-05-14 14:29:04 +00:00
tDecoderClear(&dc);
2022-05-18 07:57:29 +00:00
tdbTbcClose(pTbDbc);
tdbTbcClose(pUidIdxc);
2022-05-14 14:29:04 +00:00
return 0;
}
2023-01-06 13:33:42 +00:00
int metaAddIndexToSTable(SMeta *pMeta, int64_t version, SVCreateStbReq *pReq) {
2023-01-11 05:36:07 +00:00
SMetaEntry oStbEntry = {0};
SMetaEntry nStbEntry = {0};
2023-01-11 08:28:59 +00:00
STbDbKey tbDbKey = {0};
2023-01-11 05:36:07 +00:00
TBC *pUidIdxc = NULL;
TBC *pTbDbc = NULL;
2023-01-11 08:28:59 +00:00
void *pData = NULL;
int nData = 0;
2023-01-11 05:36:07 +00:00
int64_t oversion;
SDecoder dc = {0};
int32_t ret;
int32_t c = -2;
tb_uid_t suid = pReq->suid;
// get super table
if (tdbTbGet(pMeta->pUidIdx, &suid, sizeof(tb_uid_t), &pData, &nData) != 0) {
ret = -1;
goto _err;
}
2023-01-11 08:28:59 +00:00
tbDbKey.uid = suid;
tbDbKey.version = ((SUidIdxVal *)pData)[0].version;
tdbTbGet(pMeta->pTbDb, &tbDbKey, sizeof(tbDbKey), &pData, &nData);
2023-01-11 05:36:07 +00:00
2023-01-11 08:28:59 +00:00
tDecoderInit(&dc, pData, nData);
ret = metaDecodeEntry(&dc, &oStbEntry);
if (ret < 0) {
goto _err;
}
2023-01-11 05:36:07 +00:00
2023-01-11 08:28:59 +00:00
if (oStbEntry.stbEntry.schemaTag.pSchema == NULL || oStbEntry.stbEntry.schemaTag.pSchema == NULL) {
goto _err;
}
2023-01-11 05:36:07 +00:00
2023-01-30 10:26:42 +00:00
if (oStbEntry.stbEntry.schemaTag.version == pReq->schemaTag.version) {
2023-01-11 08:28:59 +00:00
goto _err;
}
2023-01-11 05:36:07 +00:00
2023-01-11 08:28:59 +00:00
if (oStbEntry.stbEntry.schemaTag.nCols != pReq->schemaTag.nCols) {
goto _err;
}
2023-01-11 05:36:07 +00:00
2023-01-11 08:28:59 +00:00
int diffIdx = -1;
for (int i = 0; i < pReq->schemaTag.nCols; i++) {
SSchema *pNew = pReq->schemaTag.pSchema + i;
SSchema *pOld = oStbEntry.stbEntry.schemaTag.pSchema + i;
if (pNew->type != pOld->type || pNew->colId != pOld->colId || pNew->bytes != pOld->bytes ||
strncmp(pOld->name, pNew->name, sizeof(pNew->name))) {
goto _err;
}
if (IS_IDX_ON(pNew) && !IS_IDX_ON(pOld)) {
if (diffIdx != -1) goto _err;
diffIdx = i;
}
2023-01-11 05:36:07 +00:00
}
2023-02-09 08:09:46 +00:00
if (diffIdx == -1 && diffIdx == 0) {
2023-01-11 09:03:23 +00:00
goto _err;
}
2023-01-11 05:36:07 +00:00
// Get target schema info
2023-01-11 08:28:59 +00:00
SSchemaWrapper *pTagSchema = &pReq->schemaTag;
2023-01-11 05:36:07 +00:00
if (pTagSchema->nCols == 1 && pTagSchema->pSchema[0].type == TSDB_DATA_TYPE_JSON) {
terrno = TSDB_CODE_VND_COL_ALREADY_EXISTS;
goto _err;
}
2023-01-11 08:28:59 +00:00
SSchema *pCol = pTagSchema->pSchema + diffIdx;
2023-01-11 05:36:07 +00:00
/*
* iterator all pTdDbc by uid and version
*/
TBC *pCtbIdxc = NULL;
tdbTbcOpen(pMeta->pCtbIdx, &pCtbIdxc, NULL);
int rc = tdbTbcMoveTo(pCtbIdxc, &(SCtbIdxKey){.suid = suid, .uid = INT64_MIN}, sizeof(SCtbIdxKey), &c);
if (rc < 0) {
tdbTbcClose(pCtbIdxc);
goto _err;
}
for (;;) {
2023-01-30 10:26:42 +00:00
void *pKey = NULL, *pVal = NULL;
int nKey = 0, nVal = 0;
2023-01-11 05:36:07 +00:00
rc = tdbTbcNext(pCtbIdxc, &pKey, &nKey, &pVal, &nVal);
2023-02-10 10:29:03 +00:00
if (rc < 0) {
tdbFree(pKey);
tdbFree(pVal);
tdbTbcClose(pCtbIdxc);
pCtbIdxc = NULL;
break;
}
2023-01-11 05:36:07 +00:00
if (((SCtbIdxKey *)pKey)->suid != suid) {
tdbFree(pKey);
tdbFree(pVal);
continue;
}
STagIdxKey *pTagIdxKey = NULL;
int32_t nTagIdxKey;
const void *pTagData = NULL;
int32_t nTagData = 0;
SCtbIdxKey *table = (SCtbIdxKey *)pKey;
STagVal tagVal = {.cid = pCol->colId};
tTagGet((const STag *)pVal, &tagVal);
if (IS_VAR_DATA_TYPE(pCol->type)) {
pTagData = tagVal.pData;
nTagData = (int32_t)tagVal.nData;
} else {
pTagData = &(tagVal.i64);
nTagData = tDataTypes[pCol->type].bytes;
}
2023-02-10 10:29:03 +00:00
rc = metaCreateTagIdxKey(suid, pCol->colId, pTagData, nTagData, pCol->type, table->uid, &pTagIdxKey, &nTagIdxKey);
tdbFree(pKey);
tdbFree(pVal);
if (rc < 0) {
2023-01-11 05:36:07 +00:00
metaDestroyTagIdxKey(pTagIdxKey);
2023-02-10 10:29:03 +00:00
tdbTbcClose(pCtbIdxc);
2023-01-11 05:36:07 +00:00
goto _err;
}
2023-02-10 02:51:25 +00:00
metaWLock(pMeta);
2023-01-11 05:36:07 +00:00
tdbTbUpsert(pMeta->pTagIdx, pTagIdxKey, nTagIdxKey, NULL, 0, pMeta->txn);
2023-02-10 02:51:25 +00:00
metaULock(pMeta);
2023-01-11 05:36:07 +00:00
metaDestroyTagIdxKey(pTagIdxKey);
}
2023-01-30 10:26:42 +00:00
nStbEntry.version = version;
nStbEntry.type = TSDB_SUPER_TABLE;
nStbEntry.uid = pReq->suid;
nStbEntry.name = pReq->name;
nStbEntry.stbEntry.schemaRow = pReq->schemaRow;
nStbEntry.stbEntry.schemaTag = pReq->schemaTag;
2023-01-11 08:28:59 +00:00
metaWLock(pMeta);
2023-01-11 09:03:23 +00:00
// update table.db
metaSaveToTbDb(pMeta, &nStbEntry);
// update uid index
metaUpdateUidIdx(pMeta, &nStbEntry);
metaULock(pMeta);
2023-01-11 05:36:07 +00:00
if (oStbEntry.pBuf) taosMemoryFree(oStbEntry.pBuf);
tDecoderClear(&dc);
2023-02-10 10:29:03 +00:00
tdbFree(pData);
tdbTbcClose(pCtbIdxc);
2023-01-06 13:33:42 +00:00
return TSDB_CODE_SUCCESS;
2023-01-11 05:36:07 +00:00
_err:
2023-02-10 10:29:03 +00:00
if (oStbEntry.pBuf) taosMemoryFree(oStbEntry.pBuf);
tDecoderClear(&dc);
tdbFree(pData);
2023-01-11 05:36:07 +00:00
return TSDB_CODE_VND_COL_ALREADY_EXISTS;
2023-01-06 13:33:42 +00:00
}
2023-02-04 13:02:06 +00:00
int metaDropIndexFromSTable(SMeta *pMeta, int64_t version, SDropIndexReq *pReq) {
SMetaEntry oStbEntry = {0};
SMetaEntry nStbEntry = {0};
STbDbKey tbDbKey = {0};
TBC *pUidIdxc = NULL;
TBC *pTbDbc = NULL;
int ret = 0;
int c = -2;
void *pData = NULL;
int nData = 0;
int64_t oversion;
SDecoder dc = {0};
tb_uid_t suid = pReq->stbUid;
if (tdbTbGet(pMeta->pUidIdx, &suid, sizeof(tb_uid_t), &pData, &nData) != 0) {
ret = -1;
goto _err;
}
tbDbKey.uid = suid;
tbDbKey.version = ((SUidIdxVal *)pData)[0].version;
tdbTbGet(pMeta->pTbDb, &tbDbKey, sizeof(tbDbKey), &pData, &nData);
tDecoderInit(&dc, pData, nData);
ret = metaDecodeEntry(&dc, &oStbEntry);
if (ret < 0) {
goto _err;
}
SSchema *pCol = NULL;
int32_t colId = -1;
for (int i = 0; i < oStbEntry.stbEntry.schemaTag.nCols; i++) {
SSchema *schema = oStbEntry.stbEntry.schemaTag.pSchema + i;
2023-02-05 03:49:45 +00:00
if (0 == strncmp(schema->name, pReq->colName, sizeof(pReq->colName))) {
2023-02-09 08:09:46 +00:00
if (i != 0 || IS_IDX_ON(schema)) {
2023-02-04 13:02:06 +00:00
pCol = schema;
}
break;
}
}
if (pCol == NULL) {
goto _err;
}
/*
* iterator all pTdDbc by uid and version
*/
TBC *pCtbIdxc = NULL;
tdbTbcOpen(pMeta->pCtbIdx, &pCtbIdxc, NULL);
int rc = tdbTbcMoveTo(pCtbIdxc, &(SCtbIdxKey){.suid = suid, .uid = INT64_MIN}, sizeof(SCtbIdxKey), &c);
if (rc < 0) {
tdbTbcClose(pCtbIdxc);
goto _err;
}
for (;;) {
void *pKey = NULL, *pVal = NULL;
int nKey = 0, nVal = 0;
rc = tdbTbcNext(pCtbIdxc, &pKey, &nKey, &pVal, &nVal);
2023-02-10 10:29:03 +00:00
if (rc < 0) {
tdbFree(pKey);
tdbFree(pVal);
tdbTbcClose(pCtbIdxc);
pCtbIdxc = NULL;
break;
}
2023-02-04 13:02:06 +00:00
if (((SCtbIdxKey *)pKey)->suid != suid) {
tdbFree(pKey);
tdbFree(pVal);
continue;
}
STagIdxKey *pTagIdxKey = NULL;
int32_t nTagIdxKey;
const void *pTagData = NULL;
int32_t nTagData = 0;
SCtbIdxKey *table = (SCtbIdxKey *)pKey;
STagVal tagVal = {.cid = pCol->colId};
tTagGet((const STag *)pVal, &tagVal);
if (IS_VAR_DATA_TYPE(pCol->type)) {
pTagData = tagVal.pData;
nTagData = (int32_t)tagVal.nData;
} else {
pTagData = &(tagVal.i64);
nTagData = tDataTypes[pCol->type].bytes;
}
2023-02-10 10:29:03 +00:00
rc = metaCreateTagIdxKey(suid, pCol->colId, pTagData, nTagData, pCol->type, table->uid, &pTagIdxKey, &nTagIdxKey);
tdbFree(pKey);
tdbFree(pVal);
if (rc < 0) {
2023-02-04 13:02:06 +00:00
metaDestroyTagIdxKey(pTagIdxKey);
2023-02-10 10:29:03 +00:00
tdbTbcClose(pCtbIdxc);
2023-02-04 13:02:06 +00:00
goto _err;
}
2023-02-10 10:29:03 +00:00
metaWLock(pMeta);
2023-02-04 13:02:06 +00:00
tdbTbDelete(pMeta->pTagIdx, pTagIdxKey, nTagIdxKey, pMeta->txn);
2023-02-10 10:29:03 +00:00
metaULock(pMeta);
2023-02-04 13:02:06 +00:00
metaDestroyTagIdxKey(pTagIdxKey);
}
// clear idx flag
2023-02-14 09:31:10 +00:00
SSCHMEA_SET_IDX_OFF(pCol);
2023-02-04 13:02:06 +00:00
nStbEntry.version = version;
nStbEntry.type = TSDB_SUPER_TABLE;
nStbEntry.uid = oStbEntry.uid;
nStbEntry.name = oStbEntry.name;
SSchemaWrapper *row = tCloneSSchemaWrapper(&oStbEntry.stbEntry.schemaRow);
SSchemaWrapper *tag = tCloneSSchemaWrapper(&oStbEntry.stbEntry.schemaTag);
nStbEntry.stbEntry.schemaRow = *row;
nStbEntry.stbEntry.schemaTag = *tag;
nStbEntry.stbEntry.rsmaParam = oStbEntry.stbEntry.rsmaParam;
metaWLock(pMeta);
// update table.db
metaSaveToTbDb(pMeta, &nStbEntry);
// update uid index
metaUpdateUidIdx(pMeta, &nStbEntry);
metaULock(pMeta);
2023-05-04 08:15:14 +00:00
tDeleteSchemaWrapper(tag);
tDeleteSchemaWrapper(row);
2023-02-10 10:29:03 +00:00
2023-02-04 13:02:06 +00:00
if (oStbEntry.pBuf) taosMemoryFree(oStbEntry.pBuf);
tDecoderClear(&dc);
2023-02-10 10:29:03 +00:00
tdbFree(pData);
tdbTbcClose(pCtbIdxc);
2023-01-06 13:33:42 +00:00
return TSDB_CODE_SUCCESS;
2023-02-04 13:02:06 +00:00
_err:
2023-02-10 10:29:03 +00:00
if (oStbEntry.pBuf) taosMemoryFree(oStbEntry.pBuf);
tDecoderClear(&dc);
tdbFree(pData);
2023-02-04 13:02:06 +00:00
return -1;
2023-01-06 13:33:42 +00:00
}
2022-05-14 14:29:04 +00:00
int metaCreateTable(SMeta *pMeta, int64_t ver, SVCreateTbReq *pReq, STableMetaRsp **pMetaRsp) {
2022-04-26 02:25:07 +00:00
SMetaEntry me = {0};
SMetaReader mr = {0};
2022-04-22 09:42:31 +00:00
// validate message
if (pReq->type != TSDB_CHILD_TABLE && pReq->type != TSDB_NORMAL_TABLE) {
terrno = TSDB_CODE_INVALID_MSG;
goto _err;
2021-11-03 06:49:20 +00:00
}
if (pReq->type == TSDB_CHILD_TABLE) {
tb_uid_t suid = metaGetTableEntryUidByName(pMeta, pReq->ctb.stbName);
if (suid != pReq->ctb.suid) {
terrno = TSDB_CODE_PAR_TABLE_NOT_EXIST;
return -1;
}
}
2022-04-26 02:25:07 +00:00
// validate req
metaReaderDoInit(&mr, pMeta, 0);
2022-04-26 02:25:07 +00:00
if (metaGetTableEntryByName(&mr, pReq->name) == 0) {
if (pReq->type == TSDB_CHILD_TABLE && pReq->ctb.suid != mr.me.ctbEntry.suid) {
terrno = TSDB_CODE_TDB_TABLE_IN_OTHER_STABLE;
metaReaderClear(&mr);
return -1;
}
2022-05-08 03:19:57 +00:00
pReq->uid = mr.me.uid;
if (pReq->type == TSDB_CHILD_TABLE) {
pReq->ctb.suid = mr.me.ctbEntry.suid;
}
2022-04-26 02:25:07 +00:00
terrno = TSDB_CODE_TDB_TABLE_ALREADY_EXIST;
metaReaderClear(&mr);
return -1;
2022-08-06 10:06:02 +00:00
} else if (terrno == TSDB_CODE_PAR_TABLE_NOT_EXIST) {
terrno = TSDB_CODE_SUCCESS;
2022-04-22 09:42:31 +00:00
}
2022-04-26 02:25:07 +00:00
metaReaderClear(&mr);
2022-04-22 09:42:31 +00:00
// build SMetaEntry
me.version = ver;
2022-04-22 09:42:31 +00:00
me.type = pReq->type;
me.uid = pReq->uid;
me.name = pReq->name;
if (me.type == TSDB_CHILD_TABLE) {
me.ctbEntry.btime = pReq->btime;
2022-04-22 09:42:31 +00:00
me.ctbEntry.ttlDays = pReq->ttl;
2022-06-16 12:45:00 +00:00
me.ctbEntry.commentLen = pReq->commentLen;
2022-06-16 12:44:25 +00:00
me.ctbEntry.comment = pReq->comment;
2022-04-22 09:42:31 +00:00
me.ctbEntry.suid = pReq->ctb.suid;
me.ctbEntry.pTags = pReq->ctb.pTag;
2022-08-23 09:28:49 +00:00
#ifdef TAG_FILTER_DEBUG
2022-09-07 11:39:44 +00:00
SArray *pTagVals = NULL;
int32_t code = tTagToValArray((STag *)pReq->ctb.pTag, &pTagVals);
2022-08-19 07:12:04 +00:00
for (int i = 0; i < taosArrayGetSize(pTagVals); i++) {
2022-09-07 11:39:44 +00:00
STagVal *pTagVal = (STagVal *)taosArrayGet(pTagVals, i);
2022-08-19 07:12:04 +00:00
if (IS_VAR_DATA_TYPE(pTagVal->type)) {
2022-09-07 11:39:44 +00:00
char *buf = taosMemoryCalloc(pTagVal->nData + 1, 1);
2022-08-19 07:12:04 +00:00
memcpy(buf, pTagVal->pData, pTagVal->nData);
2022-09-07 11:39:44 +00:00
metaDebug("metaTag table:%s varchar index:%d cid:%d type:%d value:%s", pReq->name, i, pTagVal->cid,
pTagVal->type, buf);
2022-08-19 07:12:04 +00:00
taosMemoryFree(buf);
} else {
double val = 0;
GET_TYPED_DATA(val, double, pTagVal->type, &pTagVal->i64);
2022-09-07 11:39:44 +00:00
metaDebug("metaTag table:%s number index:%d cid:%d type:%d value:%f", pReq->name, i, pTagVal->cid,
pTagVal->type, val);
2022-08-19 07:12:04 +00:00
}
}
2022-08-23 09:28:49 +00:00
#endif
2022-08-19 07:12:04 +00:00
++pMeta->pVnode->config.vndStats.numOfCTables;
metaWLock(pMeta);
metaUpdateStbStats(pMeta, me.ctbEntry.suid, 1);
metaUidCacheClear(pMeta, me.ctbEntry.suid);
2023-05-06 11:24:47 +00:00
metaTbGroupCacheClear(pMeta, me.ctbEntry.suid);
metaULock(pMeta);
2022-04-22 09:42:31 +00:00
} else {
me.ntbEntry.btime = pReq->btime;
2022-04-22 09:42:31 +00:00
me.ntbEntry.ttlDays = pReq->ttl;
2022-06-16 12:45:00 +00:00
me.ntbEntry.commentLen = pReq->commentLen;
2022-06-16 12:44:25 +00:00
me.ntbEntry.comment = pReq->comment;
2022-05-26 08:29:52 +00:00
me.ntbEntry.schemaRow = pReq->ntb.schemaRow;
me.ntbEntry.ncid = me.ntbEntry.schemaRow.pSchema[me.ntbEntry.schemaRow.nCols - 1].colId + 1;
++pMeta->pVnode->config.vndStats.numOfNTables;
2022-08-25 08:22:55 +00:00
pMeta->pVnode->config.vndStats.numOfNTimeSeries += me.ntbEntry.schemaRow.nCols - 1;
2021-11-03 06:49:20 +00:00
}
2022-04-23 13:45:26 +00:00
if (metaHandleEntry(pMeta, &me) < 0) goto _err;
2022-04-22 09:42:31 +00:00
if (pMetaRsp) {
*pMetaRsp = taosMemoryCalloc(1, sizeof(STableMetaRsp));
if (*pMetaRsp) {
if (me.type == TSDB_CHILD_TABLE) {
(*pMetaRsp)->tableType = TSDB_CHILD_TABLE;
(*pMetaRsp)->tuid = pReq->uid;
(*pMetaRsp)->suid = pReq->ctb.suid;
strcpy((*pMetaRsp)->tbName, pReq->name);
} else {
metaUpdateMetaRsp(pReq->uid, pReq->name, &pReq->ntb.schemaRow, *pMetaRsp);
}
}
}
2022-08-02 09:12:07 +00:00
metaDebug("vgId:%d, table:%s uid %" PRId64 " is created, type:%" PRId8, TD_VID(pMeta->pVnode), pReq->name, pReq->uid,
2022-04-26 09:16:29 +00:00
pReq->type);
2021-11-02 07:24:55 +00:00
return 0;
2022-04-22 09:42:31 +00:00
_err:
2022-06-02 05:57:39 +00:00
metaError("vgId:%d, failed to create table:%s type:%s since %s", TD_VID(pMeta->pVnode), pReq->name,
2022-04-22 09:42:31 +00:00
pReq->type == TSDB_CHILD_TABLE ? "child table" : "normal table", tstrerror(terrno));
return -1;
2021-11-02 07:24:55 +00:00
}
int metaDropTable(SMeta *pMeta, int64_t version, SVDropTbReq *pReq, SArray *tbUids, tb_uid_t *tbUid) {
2022-07-06 12:21:59 +00:00
void *pData = NULL;
2022-05-25 08:03:05 +00:00
int nData = 0;
int rc = 0;
tb_uid_t uid;
int type;
2021-11-03 06:49:20 +00:00
2022-05-25 08:03:05 +00:00
rc = tdbTbGet(pMeta->pNameIdx, pReq->name, strlen(pReq->name) + 1, &pData, &nData);
if (rc < 0) {
2022-11-02 07:28:32 +00:00
terrno = TSDB_CODE_TDB_TABLE_NOT_EXIST;
2021-11-03 06:49:20 +00:00
return -1;
}
2022-05-04 03:57:16 +00:00
uid = *(tb_uid_t *)pData;
2022-05-25 08:03:05 +00:00
metaWLock(pMeta);
metaDropTableByUid(pMeta, uid, &type);
metaULock(pMeta);
2022-05-04 06:16:29 +00:00
if ((type == TSDB_CHILD_TABLE || type == TSDB_NORMAL_TABLE) && tbUids) {
2022-05-25 08:03:05 +00:00
taosArrayPush(tbUids, &uid);
2022-05-04 06:16:29 +00:00
}
2022-05-04 03:57:16 +00:00
if ((type == TSDB_CHILD_TABLE) && tbUid) {
*tbUid = uid;
}
2022-05-25 08:03:05 +00:00
tdbFree(pData);
return 0;
}
2022-05-04 06:16:29 +00:00
static void metaDropTables(SMeta *pMeta, SArray *tbUids) {
metaWLock(pMeta);
for (int i = 0; i < TARRAY_SIZE(tbUids); ++i) {
tb_uid_t uid = *(tb_uid_t *)taosArrayGet(tbUids, i);
metaDropTableByUid(pMeta, uid, NULL);
metaDebug("batch drop table:%" PRId64, uid);
}
metaULock(pMeta);
}
2023-06-01 00:13:32 +00:00
static int32_t metaFilterTableByHash(SMeta *pMeta, SArray *uidList) {
int32_t code = 0;
// 1, tranverse table's
// 2, validate table name using vnodeValidateTableHash
// 3, push invalidated table's uid into uidList
TBC *pCur;
code = tdbTbcOpen(pMeta->pTbDb, &pCur, NULL);
if (code < 0) {
return code;
}
code = tdbTbcMoveToFirst(pCur);
if (code) {
tdbTbcClose(pCur);
return code;
}
2023-06-01 02:41:01 +00:00
void *pData = NULL, *pKey = NULL;
int nData = 0, nKey = 0;
2023-06-01 00:13:32 +00:00
while (1) {
2023-06-01 02:41:01 +00:00
int32_t ret = tdbTbcNext(pCur, &pKey, &nKey, &pData, &nData);
2023-06-01 00:13:32 +00:00
if (ret < 0) {
break;
}
SMetaEntry me = {0};
SDecoder dc = {0};
tDecoderInit(&dc, pData, nData);
metaDecodeEntry(&dc, &me);
2023-06-01 02:41:01 +00:00
if (me.type != TSDB_SUPER_TABLE) {
char tbFName[TSDB_TABLE_FNAME_LEN + 1];
snprintf(tbFName, sizeof(tbFName), "%s.%s", pMeta->pVnode->config.dbname, me.name);
tbFName[TSDB_TABLE_FNAME_LEN] = '\0';
int32_t ret = vnodeValidateTableHash(pMeta->pVnode, tbFName);
if (ret < 0 && terrno == TSDB_CODE_VND_HASH_MISMATCH) {
2023-06-01 00:13:32 +00:00
taosArrayPush(uidList, &me.uid);
}
}
tDecoderClear(&dc);
}
tdbFree(pData);
2023-06-01 02:41:01 +00:00
tdbFree(pKey);
2023-06-01 00:13:32 +00:00
tdbTbcClose(pCur);
return 0;
}
int32_t metaTrimTables(SMeta *pMeta) {
int32_t code = 0;
SArray *tbUids = taosArrayInit(8, sizeof(int64_t));
if (tbUids == NULL) {
return TSDB_CODE_OUT_OF_MEMORY;
}
2023-06-01 00:13:32 +00:00
code = metaFilterTableByHash(pMeta, tbUids);
if (code != 0) {
goto end;
}
if (TARRAY_SIZE(tbUids) == 0) {
goto end;
}
metaInfo("vgId:%d, trim %ld tables", TD_VID(pMeta->pVnode), taosArrayGetSize(tbUids));
metaDropTables(pMeta, tbUids);
end:
taosArrayDestroy(tbUids);
return code;
}
int metaTtlDropTable(SMeta *pMeta, int64_t timePointMs, SArray *tbUids) {
int ret = ttlMgrFlush(pMeta->pTtlMgr, pMeta->txn);
2022-07-06 12:21:59 +00:00
if (ret != 0) {
metaError("ttl failed to flush, ret:%d", ret);
return ret;
}
ret = ttlMgrFindExpired(pMeta->pTtlMgr, timePointMs, tbUids);
if (ret != 0) {
metaError("ttl failed to find expired table, ret:%d", ret);
return ret;
}
if (TARRAY_SIZE(tbUids) == 0) {
return 0;
}
metaInfo("ttl find expired table count: %zu", TARRAY_SIZE(tbUids));
metaDropTables(pMeta, tbUids);
return 0;
}
static int metaBuildBtimeIdxKey(SBtimeIdxKey *btimeKey, const SMetaEntry *pME) {
int64_t btime;
if (pME->type == TSDB_CHILD_TABLE) {
btime = pME->ctbEntry.btime;
} else if (pME->type == TSDB_NORMAL_TABLE) {
btime = pME->ntbEntry.btime;
2022-10-13 10:53:04 +00:00
} else {
return -1;
}
btimeKey->btime = btime;
btimeKey->uid = pME->uid;
2022-10-13 10:53:04 +00:00
return 0;
}
static int metaBuildNColIdxKey(SNcolIdxKey *ncolKey, const SMetaEntry *pME) {
2022-10-24 11:22:09 +00:00
if (pME->type == TSDB_NORMAL_TABLE) {
ncolKey->ncol = pME->ntbEntry.schemaRow.nCols;
ncolKey->uid = pME->uid;
} else {
return -1;
}
2022-10-13 10:53:04 +00:00
return 0;
}
static int metaDeleteTtl(SMeta *pMeta, const SMetaEntry *pME) {
if (pME->type != TSDB_CHILD_TABLE && pME->type != TSDB_NORMAL_TABLE) return 0;
STtlDelTtlCtx ctx = {.uid = pME->uid, .pTxn = pMeta->txn};
if (pME->type == TSDB_CHILD_TABLE) {
ctx.ttlDays = pME->ctbEntry.ttlDays;
} else {
ctx.ttlDays = pME->ntbEntry.ttlDays;
}
return ttlMgrDeleteTtl(pMeta->pTtlMgr, &ctx);
}
2022-05-25 08:03:05 +00:00
static int metaDropTableByUid(SMeta *pMeta, tb_uid_t uid, int *type) {
2022-07-06 12:21:59 +00:00
void *pData = NULL;
2022-05-25 08:03:05 +00:00
int nData = 0;
int rc = 0;
SMetaEntry e = {0};
SDecoder dc = {0};
rc = tdbTbGet(pMeta->pUidIdx, &uid, sizeof(uid), &pData, &nData);
if (rc < 0) {
return -1;
}
2022-08-16 06:22:55 +00:00
int64_t version = ((SUidIdxVal *)pData)[0].version;
2022-05-25 08:03:05 +00:00
tdbTbGet(pMeta->pTbDb, &(STbDbKey){.version = version, .uid = uid}, sizeof(STbDbKey), &pData, &nData);
tDecoderInit(&dc, pData, nData);
2022-10-20 01:47:04 +00:00
rc = metaDecodeEntry(&dc, &e);
if (rc < 0) {
tDecoderClear(&dc);
return -1;
}
2022-05-25 08:03:05 +00:00
if (type) *type = e.type;
if (e.type == TSDB_CHILD_TABLE) {
void *tData = NULL;
int tLen = 0;
if (tdbTbGet(pMeta->pUidIdx, &e.ctbEntry.suid, sizeof(tb_uid_t), &tData, &tLen) == 0) {
2023-04-25 01:52:16 +00:00
STbDbKey tbDbKey = {.uid = e.ctbEntry.suid, .version = ((SUidIdxVal *)tData)[0].version};
if (tdbTbGet(pMeta->pTbDb, &tbDbKey, sizeof(tbDbKey), &tData, &tLen) == 0) {
SDecoder tdc = {0};
SMetaEntry stbEntry = {0};
tDecoderInit(&tdc, tData, tLen);
metaDecodeEntry(&tdc, &stbEntry);
2022-12-15 13:52:10 +00:00
SSchema *pTagColumn = NULL;
SSchemaWrapper *pTagSchema = &stbEntry.stbEntry.schemaTag;
if (pTagSchema->nCols == 1 && pTagSchema->pSchema[0].type == TSDB_DATA_TYPE_JSON) {
pTagColumn = &stbEntry.stbEntry.schemaTag.pSchema[0];
metaDelJsonVarFromIdx(pMeta, &e, pTagColumn);
2022-10-19 11:44:07 +00:00
} else {
2022-12-15 13:52:10 +00:00
for (int i = 0; i < pTagSchema->nCols; i++) {
pTagColumn = &stbEntry.stbEntry.schemaTag.pSchema[i];
2023-01-04 14:26:52 +00:00
if (!IS_IDX_ON(pTagColumn)) continue;
2022-12-15 13:52:10 +00:00
STagIdxKey *pTagIdxKey = NULL;
int32_t nTagIdxKey;
const void *pTagData = NULL;
int32_t nTagData = 0;
STagVal tagVal = {.cid = pTagColumn->colId};
tTagGet((const STag *)e.ctbEntry.pTags, &tagVal);
if (IS_VAR_DATA_TYPE(pTagColumn->type)) {
pTagData = tagVal.pData;
nTagData = (int32_t)tagVal.nData;
} else {
pTagData = &(tagVal.i64);
nTagData = tDataTypes[pTagColumn->type].bytes;
}
if (metaCreateTagIdxKey(e.ctbEntry.suid, pTagColumn->colId, pTagData, nTagData, pTagColumn->type, uid,
&pTagIdxKey, &nTagIdxKey) == 0) {
tdbTbDelete(pMeta->pTagIdx, pTagIdxKey, nTagIdxKey, pMeta->txn);
}
metaDestroyTagIdxKey(pTagIdxKey);
2022-10-19 11:44:07 +00:00
}
}
tDecoderClear(&tdc);
}
tdbFree(tData);
}
}
tdbTbDelete(pMeta->pTbDb, &(STbDbKey){.version = version, .uid = uid}, sizeof(STbDbKey), pMeta->txn);
tdbTbDelete(pMeta->pNameIdx, e.name, strlen(e.name) + 1, pMeta->txn);
tdbTbDelete(pMeta->pUidIdx, &uid, sizeof(uid), pMeta->txn);
if (e.type == TSDB_CHILD_TABLE || e.type == TSDB_NORMAL_TABLE) metaDeleteBtimeIdx(pMeta, &e);
2022-10-13 10:53:04 +00:00
if (e.type == TSDB_NORMAL_TABLE) metaDeleteNcolIdx(pMeta, &e);
if (e.type != TSDB_SUPER_TABLE) metaDeleteTtl(pMeta, &e);
2022-06-26 10:44:49 +00:00
2022-05-25 08:03:05 +00:00
if (e.type == TSDB_CHILD_TABLE) {
tdbTbDelete(pMeta->pCtbIdx, &(SCtbIdxKey){.suid = e.ctbEntry.suid, .uid = uid}, sizeof(SCtbIdxKey), pMeta->txn);
--pMeta->pVnode->config.vndStats.numOfCTables;
metaUpdateStbStats(pMeta, e.ctbEntry.suid, -1);
metaUidCacheClear(pMeta, e.ctbEntry.suid);
2023-06-01 00:13:32 +00:00
metaTbGroupCacheClear(pMeta, e.ctbEntry.suid);
2022-05-25 08:03:05 +00:00
} else if (e.type == TSDB_NORMAL_TABLE) {
// drop schema.db (todo)
--pMeta->pVnode->config.vndStats.numOfNTables;
2022-08-25 08:22:55 +00:00
pMeta->pVnode->config.vndStats.numOfNTimeSeries -= e.ntbEntry.schemaRow.nCols - 1;
2022-05-25 08:03:05 +00:00
} else if (e.type == TSDB_SUPER_TABLE) {
tdbTbDelete(pMeta->pSuidIdx, &e.uid, sizeof(tb_uid_t), pMeta->txn);
2022-05-25 08:03:05 +00:00
// drop schema.db (todo)
metaStatsCacheDrop(pMeta, uid);
metaUidCacheClear(pMeta, uid);
2023-06-01 00:13:32 +00:00
metaTbGroupCacheClear(pMeta, uid);
--pMeta->pVnode->config.vndStats.numOfSTables;
2022-05-04 06:16:29 +00:00
}
2022-08-16 06:22:55 +00:00
metaCacheDrop(pMeta, uid);
2022-05-25 08:03:05 +00:00
tDecoderClear(&dc);
tdbFree(pData);
2022-05-04 06:16:29 +00:00
2021-11-02 07:24:55 +00:00
return 0;
}
2022-10-13 10:53:04 +00:00
// opt ins_tables
int metaUpdateBtimeIdx(SMeta *pMeta, const SMetaEntry *pME) {
SBtimeIdxKey btimeKey = {0};
if (metaBuildBtimeIdxKey(&btimeKey, pME) < 0) {
2022-10-13 10:53:04 +00:00
return 0;
}
metaTrace("vgId:%d, start to save version:%" PRId64 " uid:%" PRId64 " btime:%" PRId64, TD_VID(pMeta->pVnode),
pME->version, pME->uid, btimeKey.btime);
return tdbTbUpsert(pMeta->pBtimeIdx, &btimeKey, sizeof(btimeKey), NULL, 0, pMeta->txn);
2022-10-13 10:53:04 +00:00
}
int metaDeleteBtimeIdx(SMeta *pMeta, const SMetaEntry *pME) {
SBtimeIdxKey btimeKey = {0};
if (metaBuildBtimeIdxKey(&btimeKey, pME) < 0) {
2022-10-13 10:53:04 +00:00
return 0;
}
return tdbTbDelete(pMeta->pBtimeIdx, &btimeKey, sizeof(btimeKey), pMeta->txn);
2022-10-13 10:53:04 +00:00
}
int metaUpdateNcolIdx(SMeta *pMeta, const SMetaEntry *pME) {
SNcolIdxKey ncolKey = {0};
if (metaBuildNColIdxKey(&ncolKey, pME) < 0) {
return 0;
}
return tdbTbUpsert(pMeta->pNcolIdx, &ncolKey, sizeof(ncolKey), NULL, 0, pMeta->txn);
2022-10-13 10:53:04 +00:00
}
int metaDeleteNcolIdx(SMeta *pMeta, const SMetaEntry *pME) {
SNcolIdxKey ncolKey = {0};
if (metaBuildNColIdxKey(&ncolKey, pME) < 0) {
return 0;
}
return tdbTbDelete(pMeta->pNcolIdx, &ncolKey, sizeof(ncolKey), pMeta->txn);
2022-10-13 10:53:04 +00:00
}
2022-04-21 14:01:58 +00:00
2022-06-01 12:28:29 +00:00
static int metaAlterTableColumn(SMeta *pMeta, int64_t version, SVAlterTbReq *pAlterTbReq, STableMetaRsp *pMetaRsp) {
2022-07-06 12:21:59 +00:00
void *pVal = NULL;
2022-05-16 07:18:44 +00:00
int nVal = 0;
2022-07-06 12:21:59 +00:00
const void *pData = NULL;
2022-05-16 07:18:44 +00:00
int nData = 0;
int ret = 0;
tb_uid_t uid;
int64_t oversion;
2022-07-06 12:21:59 +00:00
SSchema *pColumn = NULL;
2022-05-16 07:18:44 +00:00
SMetaEntry entry = {0};
SSchemaWrapper *pSchema;
int c;
2022-10-24 02:51:10 +00:00
if (pAlterTbReq->colName == NULL) {
2022-10-20 01:36:15 +00:00
terrno = TSDB_CODE_INVALID_MSG;
return -1;
}
2022-05-16 07:18:44 +00:00
// search name index
2022-05-18 07:57:29 +00:00
ret = tdbTbGet(pMeta->pNameIdx, pAlterTbReq->tbName, strlen(pAlterTbReq->tbName) + 1, &pVal, &nVal);
2022-05-16 07:18:44 +00:00
if (ret < 0) {
2022-11-02 07:28:32 +00:00
terrno = TSDB_CODE_TDB_TABLE_NOT_EXIST;
2022-05-16 07:18:44 +00:00
return -1;
}
uid = *(tb_uid_t *)pVal;
tdbFree(pVal);
pVal = NULL;
// search uid index
2022-05-18 07:57:29 +00:00
TBC *pUidIdxc = NULL;
2022-05-16 07:18:44 +00:00
tdbTbcOpen(pMeta->pUidIdx, &pUidIdxc, NULL);
2022-05-18 07:57:29 +00:00
tdbTbcMoveTo(pUidIdxc, &uid, sizeof(uid), &c);
if (c != 0) {
tdbTbcClose(pUidIdxc);
metaError("meta/table: invalide c: %" PRId32 " alt tb column failed.", c);
return -1;
}
2022-05-16 07:18:44 +00:00
2022-05-18 07:57:29 +00:00
tdbTbcGet(pUidIdxc, NULL, NULL, &pData, &nData);
2022-08-16 06:22:55 +00:00
oversion = ((SUidIdxVal *)pData)[0].version;
2022-05-16 07:18:44 +00:00
// search table.db
2022-05-18 07:57:29 +00:00
TBC *pTbDbc = NULL;
2022-05-16 07:18:44 +00:00
tdbTbcOpen(pMeta->pTbDb, &pTbDbc, NULL);
2022-05-18 07:57:29 +00:00
tdbTbcMoveTo(pTbDbc, &((STbDbKey){.uid = uid, .version = oversion}), sizeof(STbDbKey), &c);
if (c != 0) {
tdbTbcClose(pUidIdxc);
tdbTbcClose(pTbDbc);
metaError("meta/table: invalide c: %" PRId32 " alt tb column failed.", c);
return -1;
}
2022-05-18 07:57:29 +00:00
tdbTbcGet(pTbDbc, NULL, NULL, &pData, &nData);
2022-05-16 07:18:44 +00:00
// get table entry
SDecoder dc = {0};
2022-05-23 07:47:49 +00:00
entry.pBuf = taosMemoryMalloc(nData);
memcpy(entry.pBuf, pData, nData);
tDecoderInit(&dc, entry.pBuf, nData);
2022-05-17 02:52:46 +00:00
ret = metaDecodeEntry(&dc, &entry);
if (ret != 0) {
tdbTbcClose(pUidIdxc);
tdbTbcClose(pTbDbc);
tDecoderClear(&dc);
metaError("meta/table: invalide ret: %" PRId32 " alt tb column failed.", ret);
return -1;
}
2022-05-16 07:18:44 +00:00
if (entry.type != TSDB_NORMAL_TABLE) {
terrno = TSDB_CODE_VND_INVALID_TABLE_ACTION;
goto _err;
}
// search the column to add/drop/update
2022-05-26 08:29:52 +00:00
pSchema = &entry.ntbEntry.schemaRow;
2022-05-16 07:18:44 +00:00
2022-10-24 11:22:09 +00:00
// save old entry
SMetaEntry oldEntry = {.type = TSDB_NORMAL_TABLE, .uid = entry.uid};
oldEntry.ntbEntry.schemaRow.nCols = pSchema->nCols;
2022-05-16 07:18:44 +00:00
int32_t iCol = 0;
for (;;) {
pColumn = NULL;
if (iCol >= pSchema->nCols) break;
pColumn = &pSchema->pSchema[iCol];
if (NULL == pAlterTbReq->colName) {
metaError("meta/table: null pAlterTbReq->colName");
return -1;
}
2022-05-16 07:18:44 +00:00
if (strcmp(pColumn->name, pAlterTbReq->colName) == 0) break;
iCol++;
}
entry.version = version;
2022-05-18 11:54:52 +00:00
int tlen;
SSchema *pNewSchema = NULL;
2022-05-16 07:18:44 +00:00
switch (pAlterTbReq->action) {
case TSDB_ALTER_TABLE_ADD_COLUMN:
if (pColumn) {
terrno = TSDB_CODE_VND_COL_ALREADY_EXISTS;
goto _err;
}
2022-05-26 08:29:52 +00:00
pSchema->version++;
2022-05-16 07:18:44 +00:00
pSchema->nCols++;
2022-05-18 11:54:52 +00:00
pNewSchema = taosMemoryMalloc(sizeof(SSchema) * pSchema->nCols);
memcpy(pNewSchema, pSchema->pSchema, sizeof(SSchema) * (pSchema->nCols - 1));
pSchema->pSchema = pNewSchema;
2022-05-26 08:29:52 +00:00
pSchema->pSchema[entry.ntbEntry.schemaRow.nCols - 1].bytes = pAlterTbReq->bytes;
pSchema->pSchema[entry.ntbEntry.schemaRow.nCols - 1].type = pAlterTbReq->type;
pSchema->pSchema[entry.ntbEntry.schemaRow.nCols - 1].flags = pAlterTbReq->flags;
pSchema->pSchema[entry.ntbEntry.schemaRow.nCols - 1].colId = entry.ntbEntry.ncid++;
strcpy(pSchema->pSchema[entry.ntbEntry.schemaRow.nCols - 1].name, pAlterTbReq->colName);
2022-08-25 08:22:55 +00:00
++pMeta->pVnode->config.vndStats.numOfNTimeSeries;
2022-05-16 07:18:44 +00:00
break;
case TSDB_ALTER_TABLE_DROP_COLUMN:
if (pColumn == NULL) {
2022-11-02 07:28:32 +00:00
terrno = TSDB_CODE_VND_COL_NOT_EXISTS;
2022-05-16 07:18:44 +00:00
goto _err;
}
if (pColumn->colId == 0) {
terrno = TSDB_CODE_VND_INVALID_TABLE_ACTION;
goto _err;
}
2022-07-22 08:05:28 +00:00
if (tqCheckColModifiable(pMeta->pVnode->pTq, uid, pColumn->colId) != 0) {
terrno = TSDB_CODE_VND_COL_SUBSCRIBED;
goto _err;
}
2022-05-26 08:29:52 +00:00
pSchema->version++;
2022-05-16 07:18:44 +00:00
tlen = (pSchema->nCols - iCol - 1) * sizeof(SSchema);
if (tlen) {
memmove(pColumn, pColumn + 1, tlen);
}
2022-05-17 02:52:46 +00:00
pSchema->nCols--;
2022-08-25 08:22:55 +00:00
--pMeta->pVnode->config.vndStats.numOfNTimeSeries;
2022-05-16 07:18:44 +00:00
break;
case TSDB_ALTER_TABLE_UPDATE_COLUMN_BYTES:
if (pColumn == NULL) {
2022-11-02 07:28:32 +00:00
terrno = TSDB_CODE_VND_COL_NOT_EXISTS;
2022-05-16 07:18:44 +00:00
goto _err;
}
2022-05-21 03:28:29 +00:00
if (!IS_VAR_DATA_TYPE(pColumn->type) || pColumn->bytes > pAlterTbReq->colModBytes) {
2022-05-16 07:18:44 +00:00
terrno = TSDB_CODE_VND_INVALID_TABLE_ACTION;
goto _err;
}
2022-07-22 08:05:28 +00:00
if (tqCheckColModifiable(pMeta->pVnode->pTq, uid, pColumn->colId) != 0) {
terrno = TSDB_CODE_VND_COL_SUBSCRIBED;
goto _err;
}
2022-05-26 08:29:52 +00:00
pSchema->version++;
2022-05-21 03:28:29 +00:00
pColumn->bytes = pAlterTbReq->colModBytes;
2022-05-16 07:18:44 +00:00
break;
case TSDB_ALTER_TABLE_UPDATE_COLUMN_NAME:
2022-10-24 02:51:10 +00:00
if (pAlterTbReq->colNewName == NULL) {
terrno = TSDB_CODE_INVALID_MSG;
goto _err;
}
2022-05-16 07:18:44 +00:00
if (pColumn == NULL) {
2022-11-02 07:28:32 +00:00
terrno = TSDB_CODE_VND_COL_NOT_EXISTS;
2022-05-16 07:18:44 +00:00
goto _err;
}
2022-07-22 08:05:28 +00:00
if (tqCheckColModifiable(pMeta->pVnode->pTq, uid, pColumn->colId) != 0) {
terrno = TSDB_CODE_VND_COL_SUBSCRIBED;
goto _err;
}
2022-05-26 08:29:52 +00:00
pSchema->version++;
2022-05-16 07:18:44 +00:00
strcpy(pColumn->name, pAlterTbReq->colNewName);
break;
}
entry.version = version;
2022-05-16 11:29:34 +00:00
// do actual write
metaWLock(pMeta);
2023-02-14 08:54:20 +00:00
metaDeleteNcolIdx(pMeta, &oldEntry);
metaUpdateNcolIdx(pMeta, &entry);
2022-05-16 11:29:34 +00:00
// save to table db
metaSaveToTbDb(pMeta, &entry);
2022-08-16 06:22:55 +00:00
metaUpdateUidIdx(pMeta, &entry);
2022-05-16 11:29:34 +00:00
metaSaveToSkmDb(pMeta, &entry);
metaULock(pMeta);
metaUpdateChangeTime(pMeta, entry.uid, pAlterTbReq->ctimeMs);
2022-06-01 12:28:29 +00:00
metaUpdateMetaRsp(uid, pAlterTbReq->tbName, pSchema, pMetaRsp);
2022-06-16 12:44:25 +00:00
if (entry.pBuf) taosMemoryFree(entry.pBuf);
2022-05-18 11:54:52 +00:00
if (pNewSchema) taosMemoryFree(pNewSchema);
2022-05-18 07:57:29 +00:00
tdbTbcClose(pTbDbc);
tdbTbcClose(pUidIdxc);
tDecoderClear(&dc);
2022-05-16 06:17:56 +00:00
return 0;
2022-05-16 07:18:44 +00:00
_err:
2022-06-16 12:44:25 +00:00
if (entry.pBuf) taosMemoryFree(entry.pBuf);
2022-05-18 07:57:29 +00:00
tdbTbcClose(pTbDbc);
tdbTbcClose(pUidIdxc);
tDecoderClear(&dc);
2022-05-16 07:18:44 +00:00
return -1;
2022-05-16 06:17:56 +00:00
}
static int metaUpdateTableTagVal(SMeta *pMeta, int64_t version, SVAlterTbReq *pAlterTbReq) {
2022-05-16 12:13:59 +00:00
SMetaEntry ctbEntry = {0};
SMetaEntry stbEntry = {0};
2022-07-06 12:21:59 +00:00
void *pVal = NULL;
2022-05-16 11:29:34 +00:00
int nVal = 0;
int ret;
int c;
tb_uid_t uid;
int64_t oversion;
const void *pData = NULL;
int nData = 0;
2022-10-17 01:58:34 +00:00
if (pAlterTbReq->tagName == NULL) {
terrno = TSDB_CODE_INVALID_MSG;
return -1;
}
2022-05-16 11:29:34 +00:00
// search name index
2022-05-18 07:57:29 +00:00
ret = tdbTbGet(pMeta->pNameIdx, pAlterTbReq->tbName, strlen(pAlterTbReq->tbName) + 1, &pVal, &nVal);
2022-05-16 11:29:34 +00:00
if (ret < 0) {
2022-11-02 07:28:32 +00:00
terrno = TSDB_CODE_TDB_TABLE_NOT_EXIST;
2022-05-16 11:29:34 +00:00
return -1;
}
uid = *(tb_uid_t *)pVal;
tdbFree(pVal);
pVal = NULL;
// search uid index
2022-05-18 07:57:29 +00:00
TBC *pUidIdxc = NULL;
2022-05-16 11:29:34 +00:00
tdbTbcOpen(pMeta->pUidIdx, &pUidIdxc, NULL);
2022-05-18 07:57:29 +00:00
tdbTbcMoveTo(pUidIdxc, &uid, sizeof(uid), &c);
if (c != 0) {
tdbTbcClose(pUidIdxc);
terrno = TSDB_CODE_TDB_TABLE_NOT_EXIST;
metaError("meta/table: invalide c: %" PRId32 " update tb tag val failed.", c);
return -1;
}
2022-05-16 11:29:34 +00:00
2022-05-18 07:57:29 +00:00
tdbTbcGet(pUidIdxc, NULL, NULL, &pData, &nData);
2022-08-16 07:18:37 +00:00
oversion = ((SUidIdxVal *)pData)[0].version;
2022-05-16 11:29:34 +00:00
// search table.db
2022-07-06 12:21:59 +00:00
TBC *pTbDbc = NULL;
2022-05-21 12:37:04 +00:00
SDecoder dc1 = {0};
SDecoder dc2 = {0};
2022-05-16 11:29:34 +00:00
2022-05-16 12:13:59 +00:00
/* get ctbEntry */
tdbTbcOpen(pMeta->pTbDb, &pTbDbc, NULL);
2022-05-18 07:57:29 +00:00
tdbTbcMoveTo(pTbDbc, &((STbDbKey){.uid = uid, .version = oversion}), sizeof(STbDbKey), &c);
if (c != 0) {
tdbTbcClose(pUidIdxc);
tdbTbcClose(pTbDbc);
terrno = TSDB_CODE_TDB_TABLE_NOT_EXIST;
metaError("meta/table: invalide c: %" PRId32 " update tb tag val failed.", c);
return -1;
}
2022-05-18 07:57:29 +00:00
tdbTbcGet(pTbDbc, NULL, NULL, &pData, &nData);
2022-05-16 11:29:34 +00:00
2022-05-16 12:13:59 +00:00
ctbEntry.pBuf = taosMemoryMalloc(nData);
memcpy(ctbEntry.pBuf, pData, nData);
2022-05-21 12:37:04 +00:00
tDecoderInit(&dc1, ctbEntry.pBuf, nData);
metaDecodeEntry(&dc1, &ctbEntry);
2022-05-16 11:29:34 +00:00
2022-05-16 12:13:59 +00:00
/* get stbEntry*/
2022-05-18 07:57:29 +00:00
tdbTbGet(pMeta->pUidIdx, &ctbEntry.ctbEntry.suid, sizeof(tb_uid_t), &pVal, &nVal);
if (!pVal) {
terrno = TSDB_CODE_INVALID_MSG;
goto _err;
}
2022-08-16 06:22:55 +00:00
tdbTbGet(pMeta->pTbDb, &((STbDbKey){.uid = ctbEntry.ctbEntry.suid, .version = ((SUidIdxVal *)pVal)[0].version}),
sizeof(STbDbKey), (void **)&stbEntry.pBuf, &nVal);
2022-05-16 13:03:39 +00:00
tdbFree(pVal);
2022-05-21 12:37:04 +00:00
tDecoderInit(&dc2, stbEntry.pBuf, nVal);
metaDecodeEntry(&dc2, &stbEntry);
2022-05-16 13:03:39 +00:00
SSchemaWrapper *pTagSchema = &stbEntry.stbEntry.schemaTag;
2022-07-06 12:21:59 +00:00
SSchema *pColumn = NULL;
2022-05-16 13:03:39 +00:00
int32_t iCol = 0;
for (;;) {
pColumn = NULL;
if (iCol >= pTagSchema->nCols) break;
pColumn = &pTagSchema->pSchema[iCol];
if (strcmp(pColumn->name, pAlterTbReq->tagName) == 0) break;
iCol++;
}
if (pColumn == NULL) {
2022-11-02 07:28:32 +00:00
terrno = TSDB_CODE_VND_COL_NOT_EXISTS;
2022-05-16 13:03:39 +00:00
goto _err;
}
2022-05-16 11:29:34 +00:00
2022-05-17 05:30:08 +00:00
ctbEntry.version = version;
2022-05-25 07:14:36 +00:00
if (pTagSchema->nCols == 1 && pTagSchema->pSchema[0].type == TSDB_DATA_TYPE_JSON) {
2022-05-23 11:32:10 +00:00
ctbEntry.ctbEntry.pTags = taosMemoryMalloc(pAlterTbReq->nTagVal);
2022-05-25 07:14:36 +00:00
if (ctbEntry.ctbEntry.pTags == NULL) {
2022-05-23 11:32:10 +00:00
terrno = TSDB_CODE_OUT_OF_MEMORY;
goto _err;
}
2022-05-25 07:14:36 +00:00
memcpy((void *)ctbEntry.ctbEntry.pTags, pAlterTbReq->pTagVal, pAlterTbReq->nTagVal);
} else {
2022-05-28 09:16:04 +00:00
const STag *pOldTag = (const STag *)ctbEntry.ctbEntry.pTags;
2022-07-06 12:21:59 +00:00
STag *pNewTag = NULL;
SArray *pTagArray = taosArrayInit(pTagSchema->nCols, sizeof(STagVal));
2022-05-28 10:05:50 +00:00
if (!pTagArray) {
2022-05-28 09:16:04 +00:00
terrno = TSDB_CODE_OUT_OF_MEMORY;
goto _err;
}
2022-05-23 11:32:10 +00:00
for (int32_t i = 0; i < pTagSchema->nCols; i++) {
SSchema *pCol = &pTagSchema->pSchema[i];
if (iCol == i) {
if (pAlterTbReq->isNull) {
continue;
}
2022-05-31 09:49:33 +00:00
STagVal val = {0};
val.type = pCol->type;
val.cid = pCol->colId;
if (IS_VAR_DATA_TYPE(pCol->type)) {
val.pData = pAlterTbReq->pTagVal;
val.nData = pAlterTbReq->nTagVal;
} else {
2022-05-31 09:49:33 +00:00
memcpy(&val.i64, pAlterTbReq->pTagVal, pAlterTbReq->nTagVal);
}
taosArrayPush(pTagArray, &val);
2022-05-23 11:32:10 +00:00
} else {
2022-06-02 06:16:46 +00:00
STagVal val = {.cid = pCol->colId};
2022-05-31 09:49:33 +00:00
if (tTagGet(pOldTag, &val)) {
taosArrayPush(pTagArray, &val);
2022-05-17 05:30:08 +00:00
}
}
}
2022-05-28 10:05:50 +00:00
if ((terrno = tTagNew(pTagArray, pTagSchema->version, false, &pNewTag)) < 0) {
taosArrayDestroy(pTagArray);
2022-05-28 09:16:04 +00:00
goto _err;
}
ctbEntry.ctbEntry.pTags = (uint8_t *)pNewTag;
2022-05-28 10:05:50 +00:00
taosArrayDestroy(pTagArray);
2022-05-23 11:32:10 +00:00
}
2022-05-17 05:30:08 +00:00
2022-09-20 08:33:35 +00:00
metaWLock(pMeta);
2022-05-17 05:30:08 +00:00
// save to table.db
metaSaveToTbDb(pMeta, &ctbEntry);
// save to uid.idx
2022-08-16 06:22:55 +00:00
metaUpdateUidIdx(pMeta, &ctbEntry);
2022-05-17 05:30:08 +00:00
2023-02-09 13:04:11 +00:00
metaUpdateTagIdx(pMeta, &ctbEntry);
2022-07-30 07:09:53 +00:00
if (NULL == ctbEntry.ctbEntry.pTags) {
metaError("meta/table: null tags, update tag val failed.");
goto _err;
}
SCtbIdxKey ctbIdxKey = {.suid = ctbEntry.ctbEntry.suid, .uid = uid};
2022-08-21 07:05:56 +00:00
tdbTbUpsert(pMeta->pCtbIdx, &ctbIdxKey, sizeof(ctbIdxKey), ctbEntry.ctbEntry.pTags,
((STag *)(ctbEntry.ctbEntry.pTags))->len, pMeta->txn);
metaUidCacheClear(pMeta, ctbEntry.ctbEntry.suid);
2023-06-01 00:13:32 +00:00
metaTbGroupCacheClear(pMeta, ctbEntry.ctbEntry.suid);
2022-09-20 08:33:35 +00:00
metaULock(pMeta);
metaUpdateChangeTime(pMeta, ctbEntry.uid, pAlterTbReq->ctimeMs);
2022-05-21 12:37:04 +00:00
tDecoderClear(&dc1);
tDecoderClear(&dc2);
2022-10-17 07:28:10 +00:00
taosMemoryFree((void *)ctbEntry.ctbEntry.pTags);
2022-05-16 13:03:39 +00:00
if (ctbEntry.pBuf) taosMemoryFree(ctbEntry.pBuf);
if (stbEntry.pBuf) tdbFree(stbEntry.pBuf);
2022-05-18 07:57:29 +00:00
tdbTbcClose(pTbDbc);
tdbTbcClose(pUidIdxc);
2022-05-16 06:17:56 +00:00
return 0;
2022-05-16 11:29:34 +00:00
_err:
2022-05-21 12:37:04 +00:00
tDecoderClear(&dc1);
tDecoderClear(&dc2);
2022-05-16 13:03:39 +00:00
if (ctbEntry.pBuf) taosMemoryFree(ctbEntry.pBuf);
if (stbEntry.pBuf) tdbFree(stbEntry.pBuf);
2022-05-18 07:57:29 +00:00
tdbTbcClose(pTbDbc);
tdbTbcClose(pUidIdxc);
2022-05-16 11:29:34 +00:00
return -1;
2022-05-16 06:17:56 +00:00
}
static int metaUpdateTableOptions(SMeta *pMeta, int64_t version, SVAlterTbReq *pAlterTbReq) {
2022-07-06 12:21:59 +00:00
void *pVal = NULL;
int nVal = 0;
const void *pData = NULL;
int nData = 0;
int ret = 0;
tb_uid_t uid;
int64_t oversion;
SMetaEntry entry = {0};
int c = 0;
2022-06-16 12:44:25 +00:00
// search name index
ret = tdbTbGet(pMeta->pNameIdx, pAlterTbReq->tbName, strlen(pAlterTbReq->tbName) + 1, &pVal, &nVal);
if (ret < 0) {
2022-11-02 07:28:32 +00:00
terrno = TSDB_CODE_TDB_TABLE_NOT_EXIST;
2022-06-16 12:44:25 +00:00
return -1;
}
2022-06-16 12:44:25 +00:00
uid = *(tb_uid_t *)pVal;
tdbFree(pVal);
pVal = NULL;
// search uid index
TBC *pUidIdxc = NULL;
tdbTbcOpen(pMeta->pUidIdx, &pUidIdxc, NULL);
2022-06-16 12:44:25 +00:00
tdbTbcMoveTo(pUidIdxc, &uid, sizeof(uid), &c);
if (c != 0) {
tdbTbcClose(pUidIdxc);
metaError("meta/table: invalide c: %" PRId32 " update tb options failed.", c);
return -1;
}
2022-06-16 12:44:25 +00:00
tdbTbcGet(pUidIdxc, NULL, NULL, &pData, &nData);
2022-08-16 06:22:55 +00:00
oversion = ((SUidIdxVal *)pData)[0].version;
2022-06-16 12:44:25 +00:00
// search table.db
TBC *pTbDbc = NULL;
tdbTbcOpen(pMeta->pTbDb, &pTbDbc, NULL);
2022-06-16 12:44:25 +00:00
tdbTbcMoveTo(pTbDbc, &((STbDbKey){.uid = uid, .version = oversion}), sizeof(STbDbKey), &c);
if (c != 0) {
tdbTbcClose(pUidIdxc);
tdbTbcClose(pTbDbc);
metaError("meta/table: invalide c: %" PRId32 " update tb options failed.", c);
return -1;
}
2022-06-16 12:44:25 +00:00
tdbTbcGet(pTbDbc, NULL, NULL, &pData, &nData);
// get table entry
SDecoder dc = {0};
entry.pBuf = taosMemoryMalloc(nData);
memcpy(entry.pBuf, pData, nData);
tDecoderInit(&dc, entry.pBuf, nData);
ret = metaDecodeEntry(&dc, &entry);
if (ret != 0) {
tDecoderClear(&dc);
tdbTbcClose(pUidIdxc);
tdbTbcClose(pTbDbc);
metaError("meta/table: invalide ret: %" PRId32 " alt tb options failed.", ret);
return -1;
}
2022-06-16 12:44:25 +00:00
entry.version = version;
metaWLock(pMeta);
// build SMetaEntry
if (entry.type == TSDB_CHILD_TABLE) {
2022-07-06 12:21:59 +00:00
if (pAlterTbReq->updateTTL) {
metaDeleteTtl(pMeta, &entry);
2022-06-16 12:44:25 +00:00
entry.ctbEntry.ttlDays = pAlterTbReq->newTTL;
metaUpdateTtl(pMeta, &entry);
2022-06-16 12:44:25 +00:00
}
2022-07-06 12:21:59 +00:00
if (pAlterTbReq->newCommentLen >= 0) {
2022-06-16 12:45:00 +00:00
entry.ctbEntry.commentLen = pAlterTbReq->newCommentLen;
entry.ctbEntry.comment = pAlterTbReq->newComment;
}
2022-06-16 12:44:25 +00:00
} else {
2022-07-06 12:21:59 +00:00
if (pAlterTbReq->updateTTL) {
metaDeleteTtl(pMeta, &entry);
2022-06-16 12:44:25 +00:00
entry.ntbEntry.ttlDays = pAlterTbReq->newTTL;
metaUpdateTtl(pMeta, &entry);
2022-06-16 12:44:25 +00:00
}
2022-07-06 12:21:59 +00:00
if (pAlterTbReq->newCommentLen >= 0) {
2022-06-16 12:45:00 +00:00
entry.ntbEntry.commentLen = pAlterTbReq->newCommentLen;
entry.ntbEntry.comment = pAlterTbReq->newComment;
}
}
2022-06-16 12:44:25 +00:00
// save to table db
metaSaveToTbDb(pMeta, &entry);
2022-08-16 06:22:55 +00:00
metaUpdateUidIdx(pMeta, &entry);
2022-06-16 12:44:25 +00:00
metaULock(pMeta);
metaUpdateChangeTime(pMeta, entry.uid, pAlterTbReq->ctimeMs);
2022-06-16 12:44:25 +00:00
tdbTbcClose(pTbDbc);
tdbTbcClose(pUidIdxc);
tDecoderClear(&dc);
2022-06-16 12:44:25 +00:00
if (entry.pBuf) taosMemoryFree(entry.pBuf);
2022-05-16 06:17:56 +00:00
return 0;
}
2022-12-02 01:17:27 +00:00
static int metaAddTagIndex(SMeta *pMeta, int64_t version, SVAlterTbReq *pAlterTbReq) {
SMetaEntry stbEntry = {0};
void *pVal = NULL;
int nVal = 0;
int ret;
int c;
2022-12-15 12:28:19 +00:00
tb_uid_t uid, suid;
2022-12-02 01:17:27 +00:00
int64_t oversion;
const void *pData = NULL;
int nData = 0;
2022-12-05 10:21:36 +00:00
SDecoder dc = {0};
2022-12-02 15:12:57 +00:00
if (pAlterTbReq->tagName == NULL) {
terrno = TSDB_CODE_INVALID_MSG;
return -1;
}
// search name index
ret = tdbTbGet(pMeta->pNameIdx, pAlterTbReq->tbName, strlen(pAlterTbReq->tbName) + 1, &pVal, &nVal);
if (ret < 0) {
terrno = TSDB_CODE_TDB_TABLE_NOT_EXIST;
return -1;
}
uid = *(tb_uid_t *)pVal;
tdbFree(pVal);
pVal = NULL;
2022-12-05 10:21:36 +00:00
if (tdbTbGet(pMeta->pUidIdx, &uid, sizeof(tb_uid_t), &pVal, &nVal) == -1) {
ret = -1;
goto _err;
}
2022-12-15 12:28:19 +00:00
suid = ((SUidIdxVal *)pVal)[0].suid;
2022-12-02 15:12:57 +00:00
2022-12-05 10:21:36 +00:00
STbDbKey tbDbKey = {0};
2022-12-15 12:28:19 +00:00
tbDbKey.uid = suid;
2022-12-05 10:21:36 +00:00
tbDbKey.version = ((SUidIdxVal *)pVal)[0].version;
tdbTbGet(pMeta->pTbDb, &tbDbKey, sizeof(tbDbKey), &pVal, &nVal);
tDecoderInit(&dc, pVal, nVal);
ret = metaDecodeEntry(&dc, &stbEntry);
if (ret < 0) {
goto _err;
}
2022-12-02 15:12:57 +00:00
2023-01-11 05:36:07 +00:00
// Get target schema info
2022-12-05 10:21:36 +00:00
SSchemaWrapper *pTagSchema = &stbEntry.stbEntry.schemaTag;
if (pTagSchema->nCols == 1 && pTagSchema->pSchema[0].type == TSDB_DATA_TYPE_JSON) {
terrno = TSDB_CODE_VND_COL_ALREADY_EXISTS;
2022-12-02 15:12:57 +00:00
goto _err;
}
2022-12-05 10:21:36 +00:00
SSchema *pCol = NULL;
int32_t iCol = 0;
2022-12-02 15:12:57 +00:00
for (;;) {
2022-12-05 10:21:36 +00:00
pCol = NULL;
2022-12-02 15:12:57 +00:00
if (iCol >= pTagSchema->nCols) break;
2022-12-05 10:21:36 +00:00
pCol = &pTagSchema->pSchema[iCol];
if (strcmp(pCol->name, pAlterTbReq->tagName) == 0) break;
2022-12-02 15:12:57 +00:00
iCol++;
}
2022-12-05 10:21:36 +00:00
if (iCol == 0) {
terrno = TSDB_CODE_VND_COL_ALREADY_EXISTS;
2022-12-02 15:12:57 +00:00
goto _err;
}
2022-12-05 10:21:36 +00:00
if (pCol == NULL) {
terrno = TSDB_CODE_VND_COL_NOT_EXISTS;
2022-12-02 15:12:57 +00:00
goto _err;
}
2022-12-15 12:28:19 +00:00
2022-12-05 10:21:36 +00:00
/*
* iterator all pTdDbc by uid and version
*/
TBC *pCtbIdxc = NULL;
tdbTbcOpen(pMeta->pCtbIdx, &pCtbIdxc, NULL);
2022-12-15 12:28:19 +00:00
int rc = tdbTbcMoveTo(pCtbIdxc, &(SCtbIdxKey){.suid = suid, .uid = INT64_MIN}, sizeof(SCtbIdxKey), &c);
2022-12-05 10:21:36 +00:00
if (rc < 0) {
tdbTbcClose(pCtbIdxc);
2022-12-02 15:12:57 +00:00
goto _err;
}
2022-12-05 10:21:36 +00:00
for (;;) {
void *pKey, *pVal;
int nKey, nVal;
rc = tdbTbcNext(pCtbIdxc, &pKey, &nKey, &pVal, &nVal);
if (rc < 0) break;
if (((SCtbIdxKey *)pKey)->suid != uid) {
2022-12-06 13:43:03 +00:00
tdbFree(pKey);
2022-12-05 10:21:36 +00:00
tdbFree(pVal);
continue;
}
2022-12-06 13:43:03 +00:00
STagIdxKey *pTagIdxKey = NULL;
int32_t nTagIdxKey;
2022-12-05 10:21:36 +00:00
2022-12-06 13:43:03 +00:00
const void *pTagData = NULL;
int32_t nTagData = 0;
2022-12-05 10:21:36 +00:00
2022-12-06 13:43:03 +00:00
STagVal tagVal = {.cid = pCol->colId};
tTagGet((const STag *)pVal, &tagVal);
if (IS_VAR_DATA_TYPE(pCol->type)) {
pTagData = tagVal.pData;
nTagData = (int32_t)tagVal.nData;
} else {
pTagData = &(tagVal.i64);
nTagData = tDataTypes[pCol->type].bytes;
}
2023-01-11 05:36:07 +00:00
if (metaCreateTagIdxKey(suid, pCol->colId, pTagData, nTagData, pCol->type, uid, &pTagIdxKey, &nTagIdxKey) < 0) {
2022-12-06 13:43:03 +00:00
metaDestroyTagIdxKey(pTagIdxKey);
goto _err;
}
tdbTbUpsert(pMeta->pTagIdx, pTagIdxKey, nTagIdxKey, NULL, 0, pMeta->txn);
metaDestroyTagIdxKey(pTagIdxKey);
}
2022-12-02 01:17:27 +00:00
return 0;
2022-12-02 15:12:57 +00:00
_err:
2022-12-05 10:21:36 +00:00
// tDecoderClear(&dc1);
// tDecoderClear(&dc2);
// if (ctbEntry.pBuf) taosMemoryFree(ctbEntry.pBuf);
// if (stbEntry.pBuf) tdbFree(stbEntry.pBuf);
// tdbTbcClose(pTbDbc);
// tdbTbcClose(pUidIdxc);
2022-12-02 15:12:57 +00:00
return -1;
2022-12-02 01:17:27 +00:00
}
2022-12-02 15:12:57 +00:00
2022-12-15 12:28:19 +00:00
typedef struct SMetaPair {
void *key;
int nkey;
} SMetaPair;
2022-12-02 01:17:27 +00:00
static int metaDropTagIndex(SMeta *pMeta, int64_t version, SVAlterTbReq *pAlterTbReq) {
SMetaEntry stbEntry = {0};
void *pVal = NULL;
int nVal = 0;
int ret;
int c;
2022-12-06 13:43:03 +00:00
tb_uid_t suid;
2022-12-02 01:17:27 +00:00
int64_t oversion;
const void *pData = NULL;
int nData = 0;
2022-12-06 13:43:03 +00:00
SDecoder dc = {0};
if (pAlterTbReq->tagName == NULL) {
terrno = TSDB_CODE_INVALID_MSG;
return -1;
}
// search name index
ret = tdbTbGet(pMeta->pNameIdx, pAlterTbReq->tbName, strlen(pAlterTbReq->tbName) + 1, &pVal, &nVal);
if (ret < 0) {
terrno = TSDB_CODE_TDB_TABLE_NOT_EXIST;
return -1;
}
suid = *(tb_uid_t *)pVal;
tdbFree(pVal);
pVal = NULL;
if (tdbTbGet(pMeta->pUidIdx, &suid, sizeof(tb_uid_t), &pVal, &nVal) == -1) {
ret = -1;
goto _err;
}
STbDbKey tbDbKey = {0};
tbDbKey.uid = suid;
tbDbKey.version = ((SUidIdxVal *)pVal)[0].version;
tdbTbGet(pMeta->pTbDb, &tbDbKey, sizeof(tbDbKey), &pVal, &nVal);
tDecoderInit(&dc, pVal, nVal);
ret = metaDecodeEntry(&dc, &stbEntry);
if (ret < 0) {
goto _err;
}
// Get targe schema info
SSchemaWrapper *pTagSchema = &stbEntry.stbEntry.schemaTag;
if (pTagSchema->nCols == 1 && pTagSchema->pSchema[0].type == TSDB_DATA_TYPE_JSON) {
terrno = TSDB_CODE_VND_COL_ALREADY_EXISTS;
goto _err;
}
SSchema *pCol = NULL;
int32_t iCol = 0;
for (;;) {
pCol = NULL;
if (iCol >= pTagSchema->nCols) break;
pCol = &pTagSchema->pSchema[iCol];
if (strcmp(pCol->name, pAlterTbReq->tagName) == 0) break;
iCol++;
}
if (iCol == 0) {
// cannot drop 1th tag index
terrno = -1;
goto _err;
}
if (pCol == NULL) {
terrno = TSDB_CODE_VND_COL_NOT_EXISTS;
goto _err;
}
2022-12-15 13:52:10 +00:00
2023-01-04 14:26:52 +00:00
if (IS_IDX_ON(pCol)) {
2022-12-15 13:52:10 +00:00
terrno = TSDB_CODE_VND_COL_ALREADY_EXISTS;
goto _err;
}
2022-12-15 12:28:19 +00:00
SArray *tagIdxList = taosArrayInit(512, sizeof(SMetaPair));
2022-12-06 13:43:03 +00:00
TBC *pTagIdxc = NULL;
tdbTbcOpen(pMeta->pTagIdx, &pTagIdxc, NULL);
int rc =
tdbTbcMoveTo(pTagIdxc, &(STagIdxKey){.suid = suid, .cid = INT32_MIN, .type = pCol->type}, sizeof(STagIdxKey), &c);
for (;;) {
void *pKey, *pVal;
int nKey, nVal;
rc = tdbTbcNext(pTagIdxc, &pKey, &nKey, &pVal, &nVal);
STagIdxKey *pIdxKey = (STagIdxKey *)pKey;
2022-12-15 12:28:19 +00:00
if (pIdxKey->suid != suid || pIdxKey->cid != pCol->colId) {
2022-12-06 13:43:03 +00:00
tdbFree(pKey);
tdbFree(pVal);
continue;
}
2022-12-15 12:28:19 +00:00
SMetaPair pair = {.key = pKey, nKey = nKey};
taosArrayPush(tagIdxList, &pair);
2022-12-06 13:43:03 +00:00
}
tdbTbcClose(pTagIdxc);
2022-12-02 15:12:57 +00:00
2023-02-10 10:29:03 +00:00
metaWLock(pMeta);
2022-12-15 12:28:19 +00:00
for (int i = 0; i < taosArrayGetSize(tagIdxList); i++) {
SMetaPair *pair = taosArrayGet(tagIdxList, i);
tdbTbDelete(pMeta->pTagIdx, pair->key, pair->nkey, pMeta->txn);
}
2023-02-10 10:29:03 +00:00
metaULock(pMeta);
2022-12-15 12:28:19 +00:00
taosArrayDestroy(tagIdxList);
2022-12-15 13:52:10 +00:00
// set pCol->flags; INDEX_ON
2022-12-02 01:17:27 +00:00
return 0;
2022-12-06 13:43:03 +00:00
_err:
return -1;
2022-12-02 01:17:27 +00:00
}
2022-06-01 12:28:29 +00:00
int metaAlterTable(SMeta *pMeta, int64_t version, SVAlterTbReq *pReq, STableMetaRsp *pMetaRsp) {
2022-05-16 06:17:56 +00:00
switch (pReq->action) {
case TSDB_ALTER_TABLE_ADD_COLUMN:
case TSDB_ALTER_TABLE_DROP_COLUMN:
case TSDB_ALTER_TABLE_UPDATE_COLUMN_BYTES:
case TSDB_ALTER_TABLE_UPDATE_COLUMN_NAME:
2022-06-01 12:28:29 +00:00
return metaAlterTableColumn(pMeta, version, pReq, pMetaRsp);
2022-05-16 06:17:56 +00:00
case TSDB_ALTER_TABLE_UPDATE_TAG_VAL:
return metaUpdateTableTagVal(pMeta, version, pReq);
case TSDB_ALTER_TABLE_UPDATE_OPTIONS:
return metaUpdateTableOptions(pMeta, version, pReq);
2022-12-02 01:17:27 +00:00
case TSDB_ALTER_TABLE_ADD_TAG_INDEX:
return metaAddTagIndex(pMeta, version, pReq);
case TSDB_ALTER_TABLE_DROP_TAG_INDEX:
return metaDropTagIndex(pMeta, version, pReq);
2022-05-16 06:17:56 +00:00
default:
terrno = TSDB_CODE_VND_INVALID_TABLE_ACTION;
return -1;
break;
}
}
2022-04-23 13:45:26 +00:00
static int metaSaveToTbDb(SMeta *pMeta, const SMetaEntry *pME) {
2022-04-22 11:55:21 +00:00
STbDbKey tbDbKey;
2022-07-06 12:21:59 +00:00
void *pKey = NULL;
void *pVal = NULL;
2022-04-22 11:55:21 +00:00
int kLen = 0;
int vLen = 0;
2022-05-07 10:03:06 +00:00
SEncoder coder = {0};
2022-04-21 14:01:58 +00:00
// set key and value
2022-04-23 13:45:26 +00:00
tbDbKey.version = pME->version;
2022-04-22 11:55:21 +00:00
tbDbKey.uid = pME->uid;
2022-08-02 07:57:37 +00:00
metaDebug("vgId:%d, start to save table version:%" PRId64 " uid:%" PRId64, TD_VID(pMeta->pVnode), pME->version,
pME->uid);
2022-04-22 11:55:21 +00:00
pKey = &tbDbKey;
kLen = sizeof(tbDbKey);
2022-04-21 14:01:58 +00:00
2022-04-27 09:39:54 +00:00
int32_t ret = 0;
tEncodeSize(metaEncodeEntry, pME, vLen, ret);
if (ret < 0) {
2022-04-21 14:01:58 +00:00
goto _err;
}
pVal = taosMemoryMalloc(vLen);
if (pVal == NULL) {
terrno = TSDB_CODE_OUT_OF_MEMORY;
goto _err;
}
2022-05-07 10:03:06 +00:00
tEncoderInit(&coder, pVal, vLen);
2022-04-21 14:01:58 +00:00
if (metaEncodeEntry(&coder, pME) < 0) {
goto _err;
}
2022-05-07 10:03:06 +00:00
tEncoderClear(&coder);
2022-04-21 14:01:58 +00:00
// write to table.db
if (tdbTbInsert(pMeta->pTbDb, pKey, kLen, pVal, vLen, pMeta->txn) < 0) {
2022-04-21 14:01:58 +00:00
goto _err;
}
taosMemoryFree(pVal);
return 0;
_err:
2022-08-02 07:57:37 +00:00
metaError("vgId:%d, failed to save table version:%" PRId64 "uid:%" PRId64 " %s", TD_VID(pMeta->pVnode), pME->version,
pME->uid, tstrerror(terrno));
2022-04-21 14:01:58 +00:00
taosMemoryFree(pVal);
return -1;
}
2022-04-23 13:45:26 +00:00
static int metaUpdateUidIdx(SMeta *pMeta, const SMetaEntry *pME) {
2022-08-16 06:22:55 +00:00
// upsert cache
SMetaInfo info;
metaGetEntryInfo(pME, &info);
metaCacheUpsert(pMeta, &info);
SUidIdxVal uidIdxVal = {.suid = info.suid, .version = info.version, .skmVer = info.skmVer};
return tdbTbUpsert(pMeta->pUidIdx, &pME->uid, sizeof(tb_uid_t), &uidIdxVal, sizeof(uidIdxVal), pMeta->txn);
2022-04-21 14:01:58 +00:00
}
2022-06-26 10:44:49 +00:00
static int metaUpdateSuidIdx(SMeta *pMeta, const SMetaEntry *pME) {
return tdbTbUpsert(pMeta->pSuidIdx, &pME->uid, sizeof(tb_uid_t), NULL, 0, pMeta->txn);
2022-06-26 10:44:49 +00:00
}
2022-04-23 13:45:26 +00:00
static int metaUpdateNameIdx(SMeta *pMeta, const SMetaEntry *pME) {
return tdbTbUpsert(pMeta->pNameIdx, pME->name, strlen(pME->name) + 1, &pME->uid, sizeof(tb_uid_t), pMeta->txn);
2022-04-22 09:42:31 +00:00
}
static int metaUpdateTtl(SMeta *pMeta, const SMetaEntry *pME) {
if (pME->type != TSDB_CHILD_TABLE && pME->type != TSDB_NORMAL_TABLE) return 0;
STtlUpdTtlCtx ctx = {.uid = pME->uid};
if (pME->type == TSDB_CHILD_TABLE) {
ctx.ttlDays = pME->ctbEntry.ttlDays;
ctx.changeTimeMs = pME->ctbEntry.btime;
} else {
ctx.ttlDays = pME->ntbEntry.ttlDays;
ctx.changeTimeMs = pME->ntbEntry.btime;
}
return ttlMgrInsertTtl(pMeta->pTtlMgr, &ctx);
}
int metaUpdateChangeTime(SMeta *pMeta, tb_uid_t uid, int64_t changeTimeMs) {
if (!tsTtlChangeOnWrite) return 0;
2023-06-29 03:42:06 +00:00
if (changeTimeMs <= 0) {
metaWarn("Skip to change ttl deletetion time on write, uid: %" PRId64, uid);
return TSDB_CODE_VERSION_NOT_COMPATIBLE;
}
STtlUpdCtimeCtx ctx = {.uid = uid, .changeTimeMs = changeTimeMs};
return ttlMgrUpdateChangeTime(pMeta->pTtlMgr, &ctx);
2022-04-22 09:42:31 +00:00
}
2022-04-23 13:45:26 +00:00
static int metaUpdateCtbIdx(SMeta *pMeta, const SMetaEntry *pME) {
SCtbIdxKey ctbIdxKey = {.suid = pME->ctbEntry.suid, .uid = pME->uid};
2022-08-12 13:57:29 +00:00
return tdbTbUpsert(pMeta->pCtbIdx, &ctbIdxKey, sizeof(ctbIdxKey), pME->ctbEntry.pTags,
((STag *)(pME->ctbEntry.pTags))->len, pMeta->txn);
2022-04-23 13:45:26 +00:00
}
2022-06-01 01:58:58 +00:00
int metaCreateTagIdxKey(tb_uid_t suid, int32_t cid, const void *pTagData, int32_t nTagData, int8_t type, tb_uid_t uid,
STagIdxKey **ppTagIdxKey, int32_t *nTagIdxKey) {
2022-06-02 08:36:48 +00:00
if (IS_VAR_DATA_TYPE(type)) {
*nTagIdxKey = sizeof(STagIdxKey) + nTagData + VARSTR_HEADER_SIZE + sizeof(tb_uid_t);
} else {
*nTagIdxKey = sizeof(STagIdxKey) + nTagData + sizeof(tb_uid_t);
}
2022-05-13 09:32:15 +00:00
*ppTagIdxKey = (STagIdxKey *)taosMemoryMalloc(*nTagIdxKey);
if (*ppTagIdxKey == NULL) {
terrno = TSDB_CODE_OUT_OF_MEMORY;
return -1;
}
(*ppTagIdxKey)->suid = suid;
(*ppTagIdxKey)->cid = cid;
(*ppTagIdxKey)->isNull = (pTagData == NULL) ? 1 : 0;
(*ppTagIdxKey)->type = type;
2022-06-02 08:36:48 +00:00
// refactor
if (IS_VAR_DATA_TYPE(type)) {
memcpy((*ppTagIdxKey)->data, (uint16_t *)&nTagData, VARSTR_HEADER_SIZE);
2023-02-23 09:54:51 +00:00
if (pTagData != NULL) memcpy((*ppTagIdxKey)->data + VARSTR_HEADER_SIZE, pTagData, nTagData);
2022-06-02 08:36:48 +00:00
*(tb_uid_t *)((*ppTagIdxKey)->data + VARSTR_HEADER_SIZE + nTagData) = uid;
} else {
2023-02-23 09:54:51 +00:00
if (pTagData != NULL) memcpy((*ppTagIdxKey)->data, pTagData, nTagData);
2022-06-02 08:36:48 +00:00
*(tb_uid_t *)((*ppTagIdxKey)->data + nTagData) = uid;
}
2022-05-13 09:32:15 +00:00
return 0;
}
static void metaDestroyTagIdxKey(STagIdxKey *pTagIdxKey) {
if (pTagIdxKey) taosMemoryFree(pTagIdxKey);
}
static int metaUpdateTagIdx(SMeta *pMeta, const SMetaEntry *pCtbEntry) {
2022-07-06 12:21:59 +00:00
void *pData = NULL;
2022-05-13 09:32:15 +00:00
int nData = 0;
STbDbKey tbDbKey = {0};
SMetaEntry stbEntry = {0};
2022-07-06 12:21:59 +00:00
STagIdxKey *pTagIdxKey = NULL;
2022-05-13 09:32:15 +00:00
int32_t nTagIdxKey;
2022-10-17 07:28:10 +00:00
const SSchema *pTagColumn;
const void *pTagData = NULL;
2022-05-29 12:28:54 +00:00
int32_t nTagData = 0;
2022-05-13 09:32:15 +00:00
SDecoder dc = {0};
int32_t ret = 0;
2022-05-13 09:32:15 +00:00
// get super table
2022-07-06 12:21:59 +00:00
if (tdbTbGet(pMeta->pUidIdx, &pCtbEntry->ctbEntry.suid, sizeof(tb_uid_t), &pData, &nData) != 0) {
metaError("vgId:%d, failed to get stable suid for update. version:%" PRId64, TD_VID(pMeta->pVnode),
pCtbEntry->version);
terrno = TSDB_CODE_TDB_INVALID_TABLE_ID;
ret = -1;
goto end;
2022-06-21 02:52:09 +00:00
}
2022-05-13 09:32:15 +00:00
tbDbKey.uid = pCtbEntry->ctbEntry.suid;
2022-08-16 06:22:55 +00:00
tbDbKey.version = ((SUidIdxVal *)pData)[0].version;
2022-05-18 07:57:29 +00:00
tdbTbGet(pMeta->pTbDb, &tbDbKey, sizeof(tbDbKey), &pData, &nData);
2022-05-13 09:32:15 +00:00
tDecoderInit(&dc, pData, nData);
2022-10-20 01:47:04 +00:00
ret = metaDecodeEntry(&dc, &stbEntry);
if (ret < 0) {
goto end;
}
2022-05-13 09:32:15 +00:00
2022-12-08 02:55:08 +00:00
if (stbEntry.stbEntry.schemaTag.pSchema == NULL) {
goto end;
}
2022-12-15 13:52:10 +00:00
SSchemaWrapper *pTagSchema = &stbEntry.stbEntry.schemaTag;
if (pTagSchema->nCols == 1 && pTagSchema->pSchema[0].type == TSDB_DATA_TYPE_JSON) {
pTagColumn = &stbEntry.stbEntry.schemaTag.pSchema[0];
2023-02-13 07:47:19 +00:00
STagVal tagVal = {.cid = pTagColumn->colId};
2022-05-28 09:16:04 +00:00
2022-06-04 14:33:36 +00:00
pTagData = pCtbEntry->ctbEntry.pTags;
nTagData = ((const STag *)pCtbEntry->ctbEntry.pTags)->len;
ret = metaSaveJsonVarToIdx(pMeta, pCtbEntry, pTagColumn);
goto end;
2022-12-15 13:52:10 +00:00
} else {
for (int i = 0; i < pTagSchema->nCols; i++) {
pTagColumn = &pTagSchema->pSchema[i];
2023-01-31 15:04:05 +00:00
if (i != 0 && !IS_IDX_ON(pTagColumn)) continue;
2022-12-15 13:52:10 +00:00
STagVal tagVal = {.cid = pTagColumn->colId};
tTagGet((const STag *)pCtbEntry->ctbEntry.pTags, &tagVal);
if (IS_VAR_DATA_TYPE(pTagColumn->type)) {
pTagData = tagVal.pData;
nTagData = (int32_t)tagVal.nData;
} else {
pTagData = &(tagVal.i64);
nTagData = tDataTypes[pTagColumn->type].bytes;
}
if (pTagData != NULL) {
if (metaCreateTagIdxKey(pCtbEntry->ctbEntry.suid, pTagColumn->colId, pTagData, nTagData, pTagColumn->type,
pCtbEntry->uid, &pTagIdxKey, &nTagIdxKey) < 0) {
ret = -1;
goto end;
}
tdbTbUpsert(pMeta->pTagIdx, pTagIdxKey, nTagIdxKey, NULL, 0, pMeta->txn);
}
metaDestroyTagIdxKey(pTagIdxKey);
2022-10-23 04:25:52 +00:00
}
2022-05-13 09:32:15 +00:00
}
end:
2022-12-15 13:52:10 +00:00
// metaDestroyTagIdxKey(pTagIdxKey);
2022-05-13 09:32:15 +00:00
tDecoderClear(&dc);
tdbFree(pData);
return ret;
2022-04-22 09:42:31 +00:00
}
2022-04-23 13:45:26 +00:00
static int metaSaveToSkmDb(SMeta *pMeta, const SMetaEntry *pME) {
2022-05-07 10:03:06 +00:00
SEncoder coder = {0};
2022-07-06 12:21:59 +00:00
void *pVal = NULL;
2022-04-23 13:45:26 +00:00
int vLen = 0;
int rcode = 0;
SSkmDbKey skmDbKey = {0};
const SSchemaWrapper *pSW;
if (pME->type == TSDB_SUPER_TABLE) {
2022-05-26 08:29:52 +00:00
pSW = &pME->stbEntry.schemaRow;
2022-04-23 13:45:26 +00:00
} else if (pME->type == TSDB_NORMAL_TABLE) {
2022-05-26 08:29:52 +00:00
pSW = &pME->ntbEntry.schemaRow;
2022-04-23 13:45:26 +00:00
} else {
metaError("meta/table: invalide table type: %" PRId8 " save skm db failed.", pME->type);
return TSDB_CODE_FAILED;
2022-04-22 09:42:31 +00:00
}
2022-04-23 13:45:26 +00:00
skmDbKey.uid = pME->uid;
2022-05-26 08:29:52 +00:00
skmDbKey.sver = pSW->version;
2022-04-22 12:51:50 +00:00
// if receive tmq meta message is: create stable1 then delete stable1 then create stable1 with multi vgroups
if (tdbTbGet(pMeta->pSkmDb, &skmDbKey, sizeof(skmDbKey), NULL, NULL) == 0) {
return rcode;
}
2022-04-22 12:51:50 +00:00
// encode schema
2022-04-27 09:39:54 +00:00
int32_t ret = 0;
tEncodeSize(tEncodeSSchemaWrapper, pSW, vLen, ret);
if (ret < 0) return -1;
2022-04-23 13:45:26 +00:00
pVal = taosMemoryMalloc(vLen);
2022-04-22 12:51:50 +00:00
if (pVal == NULL) {
rcode = -1;
terrno = TSDB_CODE_OUT_OF_MEMORY;
goto _exit;
}
2022-05-07 10:03:06 +00:00
tEncoderInit(&coder, pVal, vLen);
2022-04-23 13:45:26 +00:00
tEncodeSSchemaWrapper(&coder, pSW);
if (tdbTbInsert(pMeta->pSkmDb, &skmDbKey, sizeof(skmDbKey), pVal, vLen, pMeta->txn) < 0) {
2022-04-22 12:51:50 +00:00
rcode = -1;
goto _exit;
}
2022-08-11 10:12:32 +00:00
metaDebug("vgId:%d, set schema:(%" PRId64 ") sver:%d since %s", TD_VID(pMeta->pVnode), pME->uid, pSW->version,
tstrerror(terrno));
2022-04-22 12:51:50 +00:00
_exit:
2022-04-23 13:45:26 +00:00
taosMemoryFree(pVal);
2022-05-07 10:03:06 +00:00
tEncoderClear(&coder);
2022-04-23 13:45:26 +00:00
return rcode;
}
2022-07-06 12:21:59 +00:00
int metaHandleEntry(SMeta *pMeta, const SMetaEntry *pME) {
int32_t code = 0;
int32_t line = 0;
2022-05-11 14:20:14 +00:00
metaWLock(pMeta);
2022-04-23 13:45:26 +00:00
// save to table.db
code = metaSaveToTbDb(pMeta, pME);
VND_CHECK_CODE(code, line, _err);
2022-04-23 13:45:26 +00:00
// update uid.idx
code = metaUpdateUidIdx(pMeta, pME);
VND_CHECK_CODE(code, line, _err);
2022-04-23 13:45:26 +00:00
// update name.idx
code = metaUpdateNameIdx(pMeta, pME);
VND_CHECK_CODE(code, line, _err);
2022-04-23 13:45:26 +00:00
if (pME->type == TSDB_CHILD_TABLE) {
// update ctb.idx
code = metaUpdateCtbIdx(pMeta, pME);
VND_CHECK_CODE(code, line, _err);
2022-04-23 13:45:26 +00:00
// update tag.idx
code = metaUpdateTagIdx(pMeta, pME);
VND_CHECK_CODE(code, line, _err);
2022-04-23 13:45:26 +00:00
} else {
// update schema.db
code = metaSaveToSkmDb(pMeta, pME);
VND_CHECK_CODE(code, line, _err);
2022-06-26 10:44:49 +00:00
if (pME->type == TSDB_SUPER_TABLE) {
code = metaUpdateSuidIdx(pMeta, pME);
VND_CHECK_CODE(code, line, _err);
2022-07-06 12:21:59 +00:00
}
2022-04-23 13:45:26 +00:00
}
code = metaUpdateBtimeIdx(pMeta, pME);
VND_CHECK_CODE(code, line, _err);
2022-10-13 10:53:04 +00:00
if (pME->type == TSDB_NORMAL_TABLE) {
code = metaUpdateNcolIdx(pMeta, pME);
VND_CHECK_CODE(code, line, _err);
2022-10-13 10:53:04 +00:00
}
2022-04-23 13:45:26 +00:00
if (pME->type != TSDB_SUPER_TABLE) {
code = metaUpdateTtl(pMeta, pME);
VND_CHECK_CODE(code, line, _err);
2022-04-23 13:45:26 +00:00
}
2022-05-11 14:20:14 +00:00
metaULock(pMeta);
metaDebug("vgId:%d, handle meta entry, ver:%" PRId64 ", uid:%" PRId64 ", name:%s", TD_VID(pMeta->pVnode),
pME->version, pME->uid, pME->name);
2022-04-22 12:51:50 +00:00
return 0;
2022-05-11 14:20:14 +00:00
_err:
metaULock(pMeta);
metaError("vgId:%d, failed to handle meta entry since %s at line:%d, ver:%" PRId64 ", uid:%" PRId64 ", name:%s",
TD_VID(pMeta->pVnode), terrstr(), line, pME->version, pME->uid, pME->name);
2022-05-11 14:20:14 +00:00
return -1;
}
2022-05-28 08:15:24 +00:00
// refactor later
2022-06-05 13:46:07 +00:00
void *metaGetIdx(SMeta *pMeta) { return pMeta->pTagIdx; }
void *metaGetIvtIdx(SMeta *pMeta) { return pMeta->pTagIvtIdx; }