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

909 lines
24 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-04-23 13:45:26 +00:00
static int metaHandleEntry(SMeta *pMeta, const SMetaEntry *pME);
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 metaUpdateTtlIdx(SMeta *pMeta, const SMetaEntry *pME);
static int metaSaveToSkmDb(SMeta *pMeta, const SMetaEntry *pME);
static int metaUpdateCtbIdx(SMeta *pMeta, const SMetaEntry *pME);
2022-05-13 09:32:15 +00:00
static int metaUpdateTagIdx(SMeta *pMeta, const SMetaEntry *pCtbEntry);
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;
void *pBuf = NULL;
int32_t szBuf = 0;
void *p = NULL;
2022-04-26 02:25:07 +00:00
SMetaReader mr = {0};
// validate req
2022-04-26 11:04:26 +00:00
metaReaderInit(&mr, pMeta, 0);
2022-04-26 02:25:07 +00:00
if (metaGetTableEntryByName(&mr, pReq->name) == 0) {
2022-04-26 02:43:00 +00:00
// TODO: just for pass case
#if 0
2022-04-26 02:25:07 +00:00
terrno = TSDB_CODE_TDB_TABLE_ALREADY_EXIST;
metaReaderClear(&mr);
return -1;
2022-04-26 02:43:00 +00:00
#else
metaReaderClear(&mr);
return 0;
#endif
2022-04-21 14:01:58 +00:00
}
2022-04-26 02:25:07 +00:00
metaReaderClear(&mr);
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-04-22 12:34:37 +00:00
me.stbEntry.schema = pReq->schema;
me.stbEntry.schemaTag = pReq->schemaTag;
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
2022-04-28 06:20:00 +00:00
metaDebug("vgId:%d super table is created, name:%s uid: %" PRId64, TD_VID(pMeta->pVnode), pReq->name, pReq->suid);
2022-04-21 14:01:58 +00:00
return 0;
_err:
2022-04-28 06:20:00 +00:00
metaError("vgId:%d failed to create super table: %s uid: %" PRId64 " since %s", TD_VID(pMeta->pVnode), pReq->name,
2022-04-21 14:01:58 +00:00
pReq->suid, tstrerror(terrno));
return -1;
}
int metaDropSTable(SMeta *pMeta, int64_t verison, SVDropStbReq *pReq) {
2022-05-18 07:57:29 +00:00
TBC *pNameIdxc = NULL;
TBC *pUidIdxc = NULL;
TBC *pCtbIdxc = NULL;
2022-05-04 07:07:34 +00:00
SCtbIdxKey *pCtbIdxKey;
const void *pKey = NULL;
int nKey;
const void *pData = NULL;
int nData;
int c, ret;
2022-04-28 06:20:00 +00:00
2022-05-04 07:07:34 +00:00
// prepare uid idx cursor
2022-05-18 07:57:29 +00:00
tdbTbcOpen(pMeta->pUidIdx, &pUidIdxc, &pMeta->txn);
ret = tdbTbcMoveTo(pUidIdxc, &pReq->suid, sizeof(tb_uid_t), &c);
2022-05-04 07:07:34 +00:00
if (ret < 0 || c != 0) {
terrno = TSDB_CODE_VND_TB_NOT_EXIST;
2022-05-18 07:57:29 +00:00
tdbTbcClose(pUidIdxc);
2022-04-28 06:20:00 +00:00
goto _err;
}
2022-05-04 07:07:34 +00:00
// prepare name idx cursor
2022-05-18 07:57:29 +00:00
tdbTbcOpen(pMeta->pNameIdx, &pNameIdxc, &pMeta->txn);
ret = tdbTbcMoveTo(pNameIdxc, pReq->name, strlen(pReq->name) + 1, &c);
2022-05-04 07:07:34 +00:00
if (ret < 0 || c != 0) {
ASSERT(0);
}
2022-05-18 07:57:29 +00:00
tdbTbcDelete(pUidIdxc);
tdbTbcDelete(pNameIdxc);
tdbTbcClose(pUidIdxc);
tdbTbcClose(pNameIdxc);
2022-05-04 07:07:34 +00:00
// loop to drop each child table
2022-05-18 07:57:29 +00:00
tdbTbcOpen(pMeta->pCtbIdx, &pCtbIdxc, &pMeta->txn);
ret = tdbTbcMoveTo(pCtbIdxc, &(SCtbIdxKey){.suid = pReq->suid, .uid = INT64_MIN}, sizeof(SCtbIdxKey), &c);
if (ret < 0 || (c < 0 && tdbTbcMoveToNext(pCtbIdxc) < 0)) {
tdbTbcClose(pCtbIdxc);
2022-05-04 07:07:34 +00:00
goto _exit;
}
for (;;) {
2022-05-18 07:57:29 +00:00
tdbTbcGet(pCtbIdxc, &pKey, &nKey, NULL, NULL);
2022-05-04 07:07:34 +00:00
pCtbIdxKey = (SCtbIdxKey *)pKey;
if (pCtbIdxKey->suid > pReq->suid) break;
// drop the child table (TODO)
2022-05-18 07:57:29 +00:00
if (tdbTbcMoveToNext(pCtbIdxc) < 0) break;
2022-05-04 07:07:34 +00:00
}
_exit:
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-04-28 06:20:00 +00:00
_err:
metaError("vgId:%d failed to drop super table %s uid:%" PRId64 " since %s", TD_VID(pMeta->pVnode), pReq->name,
pReq->suid, tstrerror(terrno));
return -1;
2022-04-20 10:03:50 +00:00
}
2022-05-14 14:29:04 +00:00
int metaAlterSTable(SMeta *pMeta, int64_t version, SVCreateStbReq *pReq) {
SMetaEntry oStbEntry = {0};
SMetaEntry nStbEntry = {0};
2022-05-18 07:57:29 +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;
2022-05-18 07:57:29 +00:00
tdbTbcOpen(pMeta->pUidIdx, &pUidIdxc, &pMeta->txn);
ret = tdbTbcMoveTo(pUidIdxc, &pReq->suid, sizeof(tb_uid_t), &c);
2022-05-14 14:29:04 +00:00
if (ret < 0 || c) {
ASSERT(0);
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) {
ASSERT(0);
return -1;
}
oversion = *(int64_t *)pData;
2022-05-18 07:57:29 +00:00
tdbTbcOpen(pMeta->pTbDb, &pTbDbc, &pMeta->txn);
ret = tdbTbcMoveTo(pTbDbc, &((STbDbKey){.uid = pReq->suid, .version = oversion}), sizeof(STbDbKey), &c);
2022-05-14 14:29:04 +00:00
ASSERT(ret == 0 && c == 0);
2022-05-18 07:57:29 +00:00
ret = tdbTbcGet(pTbDbc, NULL, NULL, &pData, &nData);
2022-05-14 14:29:04 +00:00
ASSERT(ret == 0);
tDecoderInit(&dc, pData, nData);
metaDecodeEntry(&dc, &oStbEntry);
nStbEntry.version = version;
nStbEntry.type = TSDB_SUPER_TABLE;
nStbEntry.uid = pReq->suid;
nStbEntry.name = pReq->name;
nStbEntry.stbEntry.schema = pReq->schema;
nStbEntry.stbEntry.schemaTag = pReq->schemaTag;
metaWLock(pMeta);
// compare two entry
if (oStbEntry.stbEntry.schema.sver != pReq->schema.sver) {
if (oStbEntry.stbEntry.schema.nCols != pReq->schema.nCols) {
metaSaveToSkmDb(pMeta, &nStbEntry);
}
}
// if (oStbEntry.stbEntry.schemaTag.sver != pReq->schemaTag.sver) {
// // change tag schema
// }
// update table.db
metaSaveToTbDb(pMeta, &nStbEntry);
// update uid index
2022-05-18 07:57:29 +00:00
tdbTbcUpsert(pUidIdxc, &pReq->suid, sizeof(tb_uid_t), &version, sizeof(version), 0);
2022-05-14 14:29:04 +00:00
metaULock(pMeta);
tDecoderClear(&dc);
2022-05-18 07:57:29 +00:00
tdbTbcClose(pTbDbc);
tdbTbcClose(pUidIdxc);
2022-05-14 14:29:04 +00:00
return 0;
}
2022-04-22 09:42:31 +00:00
int metaCreateTable(SMeta *pMeta, int64_t version, SVCreateTbReq *pReq) {
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
}
2022-04-26 02:25:07 +00:00
// validate req
2022-04-26 11:04:26 +00:00
metaReaderInit(&mr, pMeta, 0);
2022-04-26 02:25:07 +00:00
if (metaGetTableEntryByName(&mr, pReq->name) == 0) {
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-05-08 03:19:57 +00:00
} else {
pReq->uid = tGenIdPI64();
pReq->ctime = taosGetTimestampMs();
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
2022-04-24 02:50:08 +00:00
me.version = version;
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.ctime = pReq->ctime;
me.ctbEntry.ttlDays = pReq->ttl;
me.ctbEntry.suid = pReq->ctb.suid;
me.ctbEntry.pTags = pReq->ctb.pTag;
} else {
me.ntbEntry.ctime = pReq->ctime;
me.ntbEntry.ttlDays = pReq->ttl;
2022-04-22 12:34:37 +00:00
me.ntbEntry.schema = pReq->ntb.schema;
2022-05-16 07:23:16 +00:00
me.ntbEntry.ncid = me.ntbEntry.schema.pSchema[me.ntbEntry.schema.nCols - 1].colId + 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
2022-04-26 09:16:29 +00:00
metaDebug("vgId:%d table %s uid %" PRId64 " is created, type:%" PRId8, TD_VID(pMeta->pVnode), pReq->name, pReq->uid,
pReq->type);
2021-11-02 07:24:55 +00:00
return 0;
2022-04-22 09:42:31 +00:00
_err:
metaError("vgId:%d failed to create table:%s type:%s since %s", TD_VID(pMeta->pVnode), pReq->name,
pReq->type == TSDB_CHILD_TABLE ? "child table" : "normal table", tstrerror(terrno));
return -1;
2021-11-02 07:24:55 +00:00
}
2022-05-04 03:57:16 +00:00
int metaDropTable(SMeta *pMeta, int64_t version, SVDropTbReq *pReq) {
2022-05-18 07:57:29 +00:00
TBC *pTbDbc = NULL;
TBC *pUidIdxc = NULL;
TBC *pNameIdxc = NULL;
2022-05-04 03:57:16 +00:00
const void *pData;
int nData;
tb_uid_t uid;
int64_t tver;
SMetaEntry me = {0};
2022-05-07 10:03:06 +00:00
SDecoder coder = {0};
2022-05-04 06:16:29 +00:00
int8_t type;
int64_t ctime;
tb_uid_t suid;
2022-05-07 01:58:01 +00:00
int c = 0, ret;
2022-05-04 03:57:16 +00:00
// search & delete the name idx
2022-05-18 07:57:29 +00:00
tdbTbcOpen(pMeta->pNameIdx, &pNameIdxc, &pMeta->txn);
ret = tdbTbcMoveTo(pNameIdxc, pReq->name, strlen(pReq->name) + 1, &c);
if (ret < 0 || !tdbTbcIsValid(pNameIdxc) || c) {
tdbTbcClose(pNameIdxc);
2022-05-04 03:57:16 +00:00
terrno = TSDB_CODE_VND_TABLE_NOT_EXIST;
2021-11-03 06:49:20 +00:00
return -1;
}
2022-05-18 07:57:29 +00:00
ret = tdbTbcGet(pNameIdxc, NULL, NULL, &pData, &nData);
2022-05-04 03:57:16 +00:00
if (ret < 0) {
ASSERT(0);
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-18 07:57:29 +00:00
tdbTbcDelete(pNameIdxc);
tdbTbcClose(pNameIdxc);
2022-05-04 03:57:16 +00:00
// search & delete uid idx
2022-05-18 07:57:29 +00:00
tdbTbcOpen(pMeta->pUidIdx, &pUidIdxc, &pMeta->txn);
ret = tdbTbcMoveTo(pUidIdxc, &uid, sizeof(uid), &c);
2022-05-04 03:57:16 +00:00
if (ret < 0 || c != 0) {
ASSERT(0);
return -1;
}
2022-05-18 07:57:29 +00:00
ret = tdbTbcGet(pUidIdxc, NULL, NULL, &pData, &nData);
2022-05-04 03:57:16 +00:00
if (ret < 0) {
ASSERT(0);
return -1;
}
tver = *(int64_t *)pData;
2022-05-18 07:57:29 +00:00
tdbTbcDelete(pUidIdxc);
tdbTbcClose(pUidIdxc);
2022-05-04 03:57:16 +00:00
// search and get meta entry
2022-05-18 07:57:29 +00:00
tdbTbcOpen(pMeta->pTbDb, &pTbDbc, &pMeta->txn);
ret = tdbTbcMoveTo(pTbDbc, &(STbDbKey){.uid = uid, .version = tver}, sizeof(STbDbKey), &c);
2022-05-04 03:57:16 +00:00
if (ret < 0 || c != 0) {
ASSERT(0);
return -1;
}
2022-05-18 07:57:29 +00:00
ret = tdbTbcGet(pTbDbc, NULL, NULL, &pData, &nData);
2022-05-04 03:57:16 +00:00
if (ret < 0) {
ASSERT(0);
return -1;
}
2022-05-04 06:16:29 +00:00
// decode entry
void *pDataCopy = taosMemoryMalloc(nData); // remove the copy (todo)
memcpy(pDataCopy, pData, nData);
2022-05-07 10:03:06 +00:00
tDecoderInit(&coder, pDataCopy, nData);
2022-05-04 06:16:29 +00:00
ret = metaDecodeEntry(&coder, &me);
if (ret < 0) {
ASSERT(0);
return -1;
}
type = me.type;
if (type == TSDB_CHILD_TABLE) {
ctime = me.ctbEntry.ctime;
suid = me.ctbEntry.suid;
} else if (type == TSDB_NORMAL_TABLE) {
ctime = me.ntbEntry.ctime;
suid = 0;
} else {
ASSERT(0);
}
2022-05-04 03:57:16 +00:00
2022-05-04 06:16:29 +00:00
taosMemoryFree(pDataCopy);
2022-05-07 10:03:06 +00:00
tDecoderClear(&coder);
2022-05-18 07:57:29 +00:00
tdbTbcClose(pTbDbc);
2021-11-03 06:49:20 +00:00
2022-05-04 06:16:29 +00:00
if (type == TSDB_CHILD_TABLE) {
// remove the pCtbIdx
2022-05-18 07:57:29 +00:00
TBC *pCtbIdxc = NULL;
tdbTbcOpen(pMeta->pCtbIdx, &pCtbIdxc, &pMeta->txn);
2022-05-04 06:16:29 +00:00
2022-05-18 07:57:29 +00:00
ret = tdbTbcMoveTo(pCtbIdxc, &(SCtbIdxKey){.suid = suid, .uid = uid}, sizeof(SCtbIdxKey), &c);
2022-05-04 06:16:29 +00:00
if (ret < 0 || c != 0) {
ASSERT(0);
return -1;
}
2022-05-18 07:57:29 +00:00
tdbTbcDelete(pCtbIdxc);
tdbTbcClose(pCtbIdxc);
2022-05-04 06:16:29 +00:00
// remove tags from pTagIdx (todo)
} else if (type == TSDB_NORMAL_TABLE) {
// remove from pSkmDb
} else {
ASSERT(0);
}
// remove from ttl (todo)
if (ctime > 0) {
}
2021-11-02 07:24:55 +00:00
return 0;
}
2022-04-21 14:01:58 +00:00
2022-05-16 06:17:56 +00:00
static int metaAlterTableColumn(SMeta *pMeta, int64_t version, SVAlterTbReq *pAlterTbReq) {
2022-05-16 07:18:44 +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;
SSchema *pColumn = NULL;
SMetaEntry entry = {0};
SSchemaWrapper *pSchema;
int c;
// 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) {
terrno = TSDB_CODE_VND_TABLE_NOT_EXIST;
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
2022-05-18 07:57:29 +00:00
tdbTbcOpen(pMeta->pUidIdx, &pUidIdxc, &pMeta->txn);
tdbTbcMoveTo(pUidIdxc, &uid, sizeof(uid), &c);
2022-05-16 07:18:44 +00:00
ASSERT(c == 0);
2022-05-18 07:57:29 +00:00
tdbTbcGet(pUidIdxc, NULL, NULL, &pData, &nData);
2022-05-16 07:18:44 +00:00
oversion = *(int64_t *)pData;
// search table.db
2022-05-18 07:57:29 +00:00
TBC *pTbDbc = NULL;
2022-05-16 07:18:44 +00:00
2022-05-18 07:57:29 +00:00
tdbTbcOpen(pMeta->pTbDb, &pTbDbc, &pMeta->txn);
tdbTbcMoveTo(pTbDbc, &((STbDbKey){.uid = uid, .version = oversion}), sizeof(STbDbKey), &c);
2022-05-16 07:18:44 +00:00
ASSERT(c == 0);
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};
tDecoderInit(&dc, pData, nData);
2022-05-17 02:52:46 +00:00
ret = metaDecodeEntry(&dc, &entry);
ASSERT(ret == 0);
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
pSchema = &entry.ntbEntry.schema;
int32_t iCol = 0;
for (;;) {
pColumn = NULL;
if (iCol >= pSchema->nCols) break;
pColumn = &pSchema->pSchema[iCol];
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;
}
pSchema->sver++;
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-16 07:18:44 +00:00
pSchema->pSchema[entry.ntbEntry.schema.nCols - 1].bytes = pAlterTbReq->bytes;
pSchema->pSchema[entry.ntbEntry.schema.nCols - 1].type = pAlterTbReq->type;
pSchema->pSchema[entry.ntbEntry.schema.nCols - 1].flags = pAlterTbReq->flags;
pSchema->pSchema[entry.ntbEntry.schema.nCols - 1].colId = entry.ntbEntry.ncid++;
strcpy(pSchema->pSchema[entry.ntbEntry.schema.nCols - 1].name, pAlterTbReq->colName);
break;
case TSDB_ALTER_TABLE_DROP_COLUMN:
if (pColumn == NULL) {
terrno = TSDB_CODE_VND_TABLE_COL_NOT_EXISTS;
goto _err;
}
if (pColumn->colId == 0) {
terrno = TSDB_CODE_VND_INVALID_TABLE_ACTION;
goto _err;
}
pSchema->sver++;
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-05-16 07:18:44 +00:00
break;
case TSDB_ALTER_TABLE_UPDATE_COLUMN_BYTES:
if (pColumn == NULL) {
terrno = TSDB_CODE_VND_TABLE_COL_NOT_EXISTS;
goto _err;
}
if (!IS_VAR_DATA_TYPE(pColumn->type) || pColumn->bytes <= pAlterTbReq->bytes) {
terrno = TSDB_CODE_VND_INVALID_TABLE_ACTION;
goto _err;
}
pSchema->sver++;
pColumn->bytes = pAlterTbReq->bytes;
break;
case TSDB_ALTER_TABLE_UPDATE_COLUMN_NAME:
if (pColumn == NULL) {
terrno = TSDB_CODE_VND_TABLE_COL_NOT_EXISTS;
goto _err;
}
pSchema->sver++;
strcpy(pColumn->name, pAlterTbReq->colNewName);
break;
}
entry.version = version;
2022-05-16 11:29:34 +00:00
// do actual write
metaWLock(pMeta);
// save to table db
metaSaveToTbDb(pMeta, &entry);
2022-05-18 07:57:29 +00:00
tdbTbcUpsert(pUidIdxc, &entry.uid, sizeof(tb_uid_t), &version, sizeof(version), 0);
2022-05-16 11:29:34 +00:00
metaSaveToSkmDb(pMeta, &entry);
metaULock(pMeta);
2022-05-18 11:54:52 +00:00
if (pNewSchema) taosMemoryFree(pNewSchema);
2022-05-16 07:18:44 +00:00
tDecoderClear(&dc);
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 07:18:44 +00:00
_err:
tDecoderClear(&dc);
2022-05-18 07:57:29 +00:00
tdbTbcClose(pTbDbc);
tdbTbcClose(pUidIdxc);
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-05-16 11:29:34 +00:00
void *pVal = NULL;
int nVal = 0;
int ret;
int c;
tb_uid_t uid;
int64_t oversion;
const void *pData = NULL;
int nData = 0;
// 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) {
terrno = TSDB_CODE_VND_TABLE_NOT_EXIST;
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
2022-05-18 07:57:29 +00:00
tdbTbcOpen(pMeta->pUidIdx, &pUidIdxc, &pMeta->txn);
tdbTbcMoveTo(pUidIdxc, &uid, sizeof(uid), &c);
2022-05-16 11:29:34 +00:00
ASSERT(c == 0);
2022-05-18 07:57:29 +00:00
tdbTbcGet(pUidIdxc, NULL, NULL, &pData, &nData);
2022-05-16 11:29:34 +00:00
oversion = *(int64_t *)pData;
// search table.db
2022-05-18 07:57:29 +00:00
TBC *pTbDbc = NULL;
2022-05-16 12:13:59 +00:00
SDecoder dc = {0};
2022-05-16 11:29:34 +00:00
2022-05-16 12:13:59 +00:00
/* get ctbEntry */
2022-05-18 07:57:29 +00:00
tdbTbcOpen(pMeta->pTbDb, &pTbDbc, &pMeta->txn);
tdbTbcMoveTo(pTbDbc, &((STbDbKey){.uid = uid, .version = oversion}), sizeof(STbDbKey), &c);
2022-05-16 11:29:34 +00:00
ASSERT(c == 0);
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);
tDecoderInit(&dc, ctbEntry.pBuf, nData);
metaDecodeEntry(&dc, &ctbEntry);
tDecoderClear(&dc);
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);
tdbTbGet(pMeta->pTbDb, &((STbDbKey){.uid = ctbEntry.ctbEntry.suid, .version = *(int64_t *)pVal}), sizeof(STbDbKey),
(void **)&stbEntry.pBuf, &nVal);
2022-05-16 13:03:39 +00:00
tdbFree(pVal);
tDecoderInit(&dc, stbEntry.pBuf, nVal);
metaDecodeEntry(&dc, &stbEntry);
tDecoderClear(&dc);
SSchemaWrapper *pTagSchema = &stbEntry.stbEntry.schemaTag;
2022-05-16 13:08:34 +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) {
terrno = TSDB_CODE_VND_TABLE_COL_NOT_EXISTS;
goto _err;
}
2022-05-16 11:29:34 +00:00
2022-05-17 05:30:08 +00:00
if (iCol == 0) {
// TODO : need to update tag index
2022-05-16 11:29:34 +00:00
}
2022-05-17 05:30:08 +00:00
ctbEntry.version = version;
SKVRowBuilder kvrb = {0};
const SKVRow pOldTag = (const SKVRow)ctbEntry.ctbEntry.pTags;
SKVRow pNewTag = NULL;
tdInitKVRowBuilder(&kvrb);
for (int32_t i = 0; i < pTagSchema->nCols; i++) {
SSchema *pCol = &pTagSchema->pSchema[i];
if (iCol == i) {
tdAddColToKVRow(&kvrb, pCol->colId, pAlterTbReq->pTagVal, pAlterTbReq->nTagVal);
} else {
void *p = tdGetKVRowValOfCol(pOldTag, pCol->colId);
if (p) {
if (IS_VAR_DATA_TYPE(pCol->type)) {
tdAddColToKVRow(&kvrb, pCol->colId, p, varDataTLen(p));
} else {
tdAddColToKVRow(&kvrb, pCol->colId, p, pCol->bytes);
}
}
}
}
ctbEntry.ctbEntry.pTags = tdGetKVRowFromBuilder(&kvrb);
tdDestroyKVRowBuilder(&kvrb);
// save to table.db
metaSaveToTbDb(pMeta, &ctbEntry);
// save to uid.idx
2022-05-18 07:57:29 +00:00
tdbTbUpsert(pMeta->pUidIdx, &ctbEntry.uid, sizeof(tb_uid_t), &version, sizeof(version), &pMeta->txn);
2022-05-17 05:30:08 +00:00
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-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) {
// TODO
ASSERT(0);
return 0;
}
int metaAlterTable(SMeta *pMeta, int64_t version, SVAlterTbReq *pReq) {
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:
return metaAlterTableColumn(pMeta, version, pReq);
case TSDB_ALTER_TABLE_UPDATE_TAG_VAL:
return metaUpdateTableTagVal(pMeta, version, pReq);
case TSDB_ALTER_TABLE_UPDATE_OPTIONS:
return metaUpdateTableOptions(pMeta, version, pReq);
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;
void *pKey = NULL;
void *pVal = NULL;
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;
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
2022-05-18 07:57:29 +00:00
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:
taosMemoryFree(pVal);
return -1;
}
2022-04-23 13:45:26 +00:00
static int metaUpdateUidIdx(SMeta *pMeta, const SMetaEntry *pME) {
2022-05-18 07:57:29 +00:00
return tdbTbInsert(pMeta->pUidIdx, &pME->uid, sizeof(tb_uid_t), &pME->version, sizeof(int64_t), &pMeta->txn);
2022-04-21 14:01:58 +00:00
}
2022-04-23 13:45:26 +00:00
static int metaUpdateNameIdx(SMeta *pMeta, const SMetaEntry *pME) {
2022-05-18 07:57:29 +00:00
return tdbTbInsert(pMeta->pNameIdx, pME->name, strlen(pME->name) + 1, &pME->uid, sizeof(tb_uid_t), &pMeta->txn);
2022-04-22 09:42:31 +00:00
}
2022-04-23 13:45:26 +00:00
static int metaUpdateTtlIdx(SMeta *pMeta, const SMetaEntry *pME) {
int32_t ttlDays;
int64_t ctime;
STtlIdxKey ttlKey;
if (pME->type == TSDB_CHILD_TABLE) {
ctime = pME->ctbEntry.ctime;
ttlDays = pME->ctbEntry.ttlDays;
} else if (pME->type == TSDB_NORMAL_TABLE) {
ctime = pME->ntbEntry.ctime;
ttlDays = pME->ntbEntry.ttlDays;
} else {
ASSERT(0);
}
if (ttlDays <= 0) return 0;
ttlKey.dtime = ctime + ttlDays * 24 * 60 * 60;
ttlKey.uid = pME->uid;
2022-05-18 07:57:29 +00:00
return tdbTbInsert(pMeta->pTtlIdx, &ttlKey, sizeof(ttlKey), NULL, 0, &pMeta->txn);
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-05-18 07:57:29 +00:00
return tdbTbInsert(pMeta->pCtbIdx, &ctbIdxKey, sizeof(ctbIdxKey), NULL, 0, &pMeta->txn);
2022-04-23 13:45:26 +00:00
}
2022-05-13 09:32:15 +00:00
static int metaCreateTagIdxKey(tb_uid_t suid, int32_t cid, const void *pTagData, int8_t type, tb_uid_t uid,
STagIdxKey **ppTagIdxKey, int32_t *nTagIdxKey) {
int32_t nTagData = 0;
if (pTagData) {
if (IS_VAR_DATA_TYPE(type)) {
nTagData = varDataTLen(pTagData);
} else {
nTagData = tDataTypes[type].bytes;
}
}
*nTagIdxKey = sizeof(STagIdxKey) + nTagData + sizeof(tb_uid_t);
*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;
if (nTagData) memcpy((*ppTagIdxKey)->data, pTagData, nTagData);
*(tb_uid_t *)((*ppTagIdxKey)->data + nTagData) = uid;
return 0;
}
static void metaDestroyTagIdxKey(STagIdxKey *pTagIdxKey) {
if (pTagIdxKey) taosMemoryFree(pTagIdxKey);
}
static int metaUpdateTagIdx(SMeta *pMeta, const SMetaEntry *pCtbEntry) {
void *pData = NULL;
int nData = 0;
STbDbKey tbDbKey = {0};
SMetaEntry stbEntry = {0};
STagIdxKey *pTagIdxKey = NULL;
int32_t nTagIdxKey;
const SSchema *pTagColumn; // = &stbEntry.stbEntry.schema.pSchema[0];
const void *pTagData = NULL; //
SDecoder dc = {0};
// get super table
2022-05-18 07:57:29 +00:00
tdbTbGet(pMeta->pUidIdx, &pCtbEntry->ctbEntry.suid, sizeof(tb_uid_t), &pData, &nData);
2022-05-13 09:32:15 +00:00
tbDbKey.uid = pCtbEntry->ctbEntry.suid;
tbDbKey.version = *(int64_t *)pData;
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);
metaDecodeEntry(&dc, &stbEntry);
pTagColumn = &stbEntry.stbEntry.schemaTag.pSchema[0];
pTagData = tdGetKVRowValOfCol((const SKVRow)pCtbEntry->ctbEntry.pTags, pTagColumn->colId);
// update tag index
if (metaCreateTagIdxKey(pCtbEntry->ctbEntry.suid, pTagColumn->colId, pTagData, pTagColumn->type, pCtbEntry->uid,
&pTagIdxKey, &nTagIdxKey) < 0) {
return -1;
}
2022-05-18 07:57:29 +00:00
tdbTbInsert(pMeta->pTagIdx, pTagIdxKey, nTagIdxKey, NULL, 0, &pMeta->txn);
2022-05-13 09:32:15 +00:00
metaDestroyTagIdxKey(pTagIdxKey);
tDecoderClear(&dc);
tdbFree(pData);
2022-04-22 09:42:31 +00:00
return 0;
}
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-04-23 13:45:26 +00:00
void *pVal = NULL;
int vLen = 0;
int rcode = 0;
SSkmDbKey skmDbKey = {0};
const SSchemaWrapper *pSW;
if (pME->type == TSDB_SUPER_TABLE) {
pSW = &pME->stbEntry.schema;
} else if (pME->type == TSDB_NORMAL_TABLE) {
pSW = &pME->ntbEntry.schema;
} else {
ASSERT(0);
2022-04-22 09:42:31 +00:00
}
2022-04-23 13:45:26 +00:00
skmDbKey.uid = pME->uid;
skmDbKey.sver = pSW->sver;
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);
2022-05-18 07:57:29 +00:00
if (tdbTbInsert(pMeta->pSkmDb, &skmDbKey, sizeof(skmDbKey), pVal, vLen, &pMeta->txn) < 0) {
2022-04-22 12:51:50 +00:00
rcode = -1;
goto _exit;
}
_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;
}
static int metaHandleEntry(SMeta *pMeta, const SMetaEntry *pME) {
2022-05-11 14:20:14 +00:00
metaWLock(pMeta);
2022-04-23 13:45:26 +00:00
// save to table.db
2022-05-11 14:20:14 +00:00
if (metaSaveToTbDb(pMeta, pME) < 0) goto _err;
2022-04-23 13:45:26 +00:00
// update uid.idx
2022-05-11 14:20:14 +00:00
if (metaUpdateUidIdx(pMeta, pME) < 0) goto _err;
2022-04-23 13:45:26 +00:00
// update name.idx
2022-05-11 14:20:14 +00:00
if (metaUpdateNameIdx(pMeta, pME) < 0) goto _err;
2022-04-23 13:45:26 +00:00
if (pME->type == TSDB_CHILD_TABLE) {
// update ctb.idx
2022-05-11 14:20:14 +00:00
if (metaUpdateCtbIdx(pMeta, pME) < 0) goto _err;
2022-04-23 13:45:26 +00:00
// update tag.idx
2022-05-11 14:20:14 +00:00
if (metaUpdateTagIdx(pMeta, pME) < 0) goto _err;
2022-04-23 13:45:26 +00:00
} else {
// update schema.db
2022-05-11 14:20:14 +00:00
if (metaSaveToSkmDb(pMeta, pME) < 0) goto _err;
2022-04-23 13:45:26 +00:00
}
if (pME->type != TSDB_SUPER_TABLE) {
2022-05-11 14:20:14 +00:00
if (metaUpdateTtlIdx(pMeta, pME) < 0) goto _err;
2022-04-23 13:45:26 +00:00
}
2022-05-11 14:20:14 +00:00
metaULock(pMeta);
2022-04-22 12:51:50 +00:00
return 0;
2022-05-11 14:20:14 +00:00
_err:
metaULock(pMeta);
return -1;
2022-04-22 12:51:50 +00:00
}