TDengine/source/libs/qcom/src/queryUtil.c

576 lines
15 KiB
C
Raw Normal View History

2022-03-04 09:08:46 +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/>.
*/
#include "os.h"
2021-12-21 09:18:39 +00:00
#include "query.h"
#include "tglobal.h"
2022-03-04 09:08:46 +00:00
#include "tmsg.h"
#include "trpc.h"
2022-03-04 09:08:46 +00:00
#include "tsched.h"
2022-06-22 10:50:39 +00:00
// clang-format off
2022-06-21 01:18:53 +00:00
#include "cJSON.h"
2022-03-04 09:08:46 +00:00
#define VALIDNUMOFCOLS(x) ((x) >= TSDB_MIN_COLUMNS && (x) <= TSDB_MAX_COLUMNS)
#define VALIDNUMOFTAGS(x) ((x) >= 0 && (x) <= TSDB_MAX_TAGS)
static struct SSchema _s = {
.colId = TSDB_TBNAME_COLUMN_INDEX,
2022-03-04 09:08:46 +00:00
.type = TSDB_DATA_TYPE_BINARY,
.bytes = TSDB_TABLE_NAME_LEN + VARSTR_HEADER_SIZE,
.name = "tbname",
};
2022-03-04 09:08:46 +00:00
const SSchema* tGetTbnameColumnSchema() { return &_s; }
static bool doValidateSchema(SSchema* pSchema, int32_t numOfCols, int32_t maxLen) {
int32_t rowLen = 0;
for (int32_t i = 0; i < numOfCols; ++i) {
// 1. valid types
if (!isValidDataType(pSchema[i].type)) {
return false;
}
// 2. valid length for each type
if (pSchema[i].type == TSDB_DATA_TYPE_BINARY) {
if (pSchema[i].bytes > TSDB_MAX_BINARY_LEN) {
return false;
}
} else if (pSchema[i].type == TSDB_DATA_TYPE_NCHAR) {
if (pSchema[i].bytes > TSDB_MAX_NCHAR_LEN) {
return false;
}
Feature/3.0 geometry (#21037) * Add GEOMETRY data type and make sql.c able to parse it. The GEMETRY works like BINARY so far. * add GEOMETRY type into gConvertTypes to fix some issues like DELETE calling * change some test cases to make sure no same timestamp is inserted, and add my smoketest.sh * Add a function MakePoint() and introduce a lib geometry * implement sql functions GeomFromText() and AsText() * Use GEOS *_r funcions instead for thread safety * Handle with TSDB_DATA_TYPE_GEOMETRY when INSERT geometry data by converting WKT. Add geosWrapper to wrap the basic GEOS functions for TDEngine. * refactor AsText and MakePoint functions to be like GeomFromText * Show WKT when print geometry data in screen Dump hex data when dump geometry data in a file * define TYPE_BYTES item for TSDB_DATA_TYPE_GEOMETRY, which casued some strange issues. * set number of decimals of WKT to 6 * Implement SQL function Intersects() * refactor geometry sql functions * Add geosErrMsgeHandler() to get the GEOS error detail * use threadlocal to instantiate SGeosContext call destroyGeosContext() only if the thread exists * remove SGeosContext *context param for all geometry functions since we use thread local one, so that all caller do not need to know the context. * Modify Intersects() to call PreparedIntersects() when one of param is a constant, which has higher performance. * rename prepareFn() to initCtxFn() to avoid confusion with PreparedFn * Add prefix "ST_" for all geometry functions * move getThreadLocalGeosCtx() and destroyThreadLocalGeosCtx() into util, so that all unit test tools can compile * Add unit test for geometry lib, only test MakePoint so far * refactor and enhance existing cases in geomFuncTest * implement NULL type and NULL value test for geomFuncTest * add test on geomFromText() * add unit test on AsText() in geomFuncTest * combine some makePointFunction test items * add intersectsFunctionTwoColumns test refactor on callGeomFromTextWrapper functions * enhance intersectsFunction test to add cases like input constant , NULL type, NULL value, or wrong content * add more cases into intersectsFunction test * Add basic test on geometry in system test * Add ST_GeomFromText and ST_AsText function test in system test on geometry * add ST_Intersects function test in system test on geometry * support to check expectedErrno in system test on geometry * adjust geomTest unit test and geometry system test * add geometry data type and functions in doc english version * implement touchesFunction() in geometry lib refactor geometry relation functions model * separate gemFuncTest into several src files * add unit test on touchesFunction * support sql function ST_Touches() add system test on ST_Touches * add docs for ST_Touches() * Add ST_Contains() * Add ST_Covers() * Add ST_Equals() * add swapAllowed param for geomRelationFunction() read geom2 earlier intead of at doGeosRelation() * Add ST_ContainsProperly() * build on windows * Merge from 3.0 to 3.0_geometry * change macro definition TSDB_DATA_TYPE_GEOMETRY as the last one for compatibility * change '\\NULL' to 'NULL' back in shellDumpFieldToFile() * add /usr/local/include into include directory * add /usr/local/inlcude and /usr/local/lib in cmake.platform for DARWIN
2023-05-24 07:36:46 +00:00
} else if (pSchema[i].type == TSDB_DATA_TYPE_GEOMETRY) {
if (pSchema[i].bytes > TSDB_MAX_GEOMETRY_LEN) {
return false;
}
} else {
if (pSchema[i].bytes != tDataTypes[pSchema[i].type].bytes) {
return false;
}
}
// 3. valid column names
for (int32_t j = i + 1; j < numOfCols; ++j) {
2022-05-20 10:00:05 +00:00
if (strncmp(pSchema[i].name, pSchema[j].name, sizeof(pSchema[i].name) - 1) == 0) {
return false;
}
}
rowLen += pSchema[i].bytes;
}
return rowLen <= maxLen;
}
bool tIsValidSchema(struct SSchema* pSchema, int32_t numOfCols, int32_t numOfTags) {
if (!VALIDNUMOFCOLS(numOfCols)) {
return false;
}
if (!VALIDNUMOFTAGS(numOfTags)) {
return false;
}
/* first column must be the timestamp, which is a primary key */
if (pSchema[0].type != TSDB_DATA_TYPE_TIMESTAMP) {
return false;
}
if (!doValidateSchema(pSchema, numOfCols, TSDB_MAX_BYTES_PER_ROW)) {
return false;
}
if (!doValidateSchema(&pSchema[numOfCols], numOfTags, TSDB_MAX_TAGS_LEN)) {
return false;
}
return true;
2021-12-21 09:18:39 +00:00
}
2022-08-12 02:41:02 +00:00
static SSchedQueue pTaskQueue = {0};
2021-12-21 09:18:39 +00:00
int32_t initTaskQueue() {
2022-05-13 05:32:09 +00:00
int32_t queueSize = tsMaxShellConns * 2;
2022-08-12 02:41:02 +00:00
void *p = taosInitScheduler(queueSize, tsNumOfTaskQueueThreads, "tsc", &pTaskQueue);
if (NULL == p) {
2021-12-21 09:18:39 +00:00
qError("failed to init task queue");
return -1;
}
2022-04-07 06:48:13 +00:00
qDebug("task queue is initialized, numOfThreads: %d", tsNumOfTaskQueueThreads);
2022-03-04 09:08:46 +00:00
return 0;
2021-12-21 09:18:39 +00:00
}
int32_t cleanupTaskQueue() {
2022-08-12 02:41:02 +00:00
taosCleanUpScheduler(&pTaskQueue);
2022-03-04 09:08:46 +00:00
return 0;
2021-12-21 09:18:39 +00:00
}
static void execHelper(struct SSchedMsg* pSchedMsg) {
2022-03-04 09:08:46 +00:00
__async_exec_fn_t execFn = (__async_exec_fn_t)pSchedMsg->ahandle;
int32_t code = execFn(pSchedMsg->thandle);
2021-12-21 09:18:39 +00:00
if (code != 0 && pSchedMsg->msg != NULL) {
2022-03-04 09:08:46 +00:00
*(int32_t*)pSchedMsg->msg = code;
2021-12-21 09:18:39 +00:00
}
}
int32_t taosAsyncExec(__async_exec_fn_t execFn, void* execParam, int32_t* code) {
SSchedMsg schedMsg = {0};
2022-03-04 09:08:46 +00:00
schedMsg.fp = execHelper;
2021-12-21 09:18:39 +00:00
schedMsg.ahandle = execFn;
schedMsg.thandle = execParam;
2022-03-04 09:08:46 +00:00
schedMsg.msg = code;
2021-12-21 09:18:39 +00:00
2022-09-13 09:48:57 +00:00
return taosScheduleTask(&pTaskQueue, &schedMsg);
2021-12-21 09:18:39 +00:00
}
2022-07-18 05:32:17 +00:00
void destroySendMsgInfo(SMsgSendInfo* pMsgBody) {
2022-12-30 07:35:03 +00:00
if (NULL == pMsgBody) {
return;
}
2022-07-18 05:32:17 +00:00
taosMemoryFreeClear(pMsgBody->target.dbFName);
taosMemoryFreeClear(pMsgBody->msgInfo.pData);
if (pMsgBody->paramFreeFp) {
(*pMsgBody->paramFreeFp)(pMsgBody->param);
}
taosMemoryFreeClear(pMsgBody);
}
2022-11-08 12:45:11 +00:00
void destroyAhandle(void *ahandle) {
SMsgSendInfo *pSendInfo = ahandle;
if (pSendInfo == NULL) return;
destroySendMsgInfo(pSendInfo);
}
2022-07-18 05:32:17 +00:00
2022-07-20 10:48:27 +00:00
int32_t asyncSendMsgToServerExt(void* pTransporter, SEpSet* epSet, int64_t* pTransporterId, SMsgSendInfo* pInfo,
bool persistHandle, void* rpcCtx) {
2022-03-04 09:08:46 +00:00
char* pMsg = rpcMallocCont(pInfo->msgInfo.len);
if (NULL == pMsg) {
2022-03-04 09:08:46 +00:00
qError("0x%" PRIx64 " msg:%s malloc failed", pInfo->requestId, TMSG_INFO(pInfo->msgType));
2022-07-20 10:48:27 +00:00
destroySendMsgInfo(pInfo);
2022-12-03 02:03:18 +00:00
terrno = TSDB_CODE_OUT_OF_MEMORY;
return terrno;
}
memcpy(pMsg, pInfo->msgInfo.pData, pInfo->msgInfo.len);
2022-06-22 10:50:39 +00:00
SRpcMsg rpcMsg = {
.msgType = pInfo->msgType,
.pCont = pMsg,
.contLen = pInfo->msgInfo.len,
.info.ahandle = (void*)pInfo,
.info.handle = pInfo->msgInfo.handle,
.info.persistHandle = persistHandle,
2022-06-22 10:50:39 +00:00
.code = 0
};
2022-06-18 06:07:54 +00:00
TRACE_SET_ROOTID(&rpcMsg.info.traceId, pInfo->requestId);
2022-07-20 10:48:27 +00:00
int code = rpcSendRequestWithCtx(pTransporter, epSet, &rpcMsg, pTransporterId, rpcCtx);
if (code) {
destroySendMsgInfo(pInfo);
}
return code;
2022-03-04 09:08:46 +00:00
}
2022-03-10 11:05:58 +00:00
2022-07-20 10:48:27 +00:00
int32_t asyncSendMsgToServer(void* pTransporter, SEpSet* epSet, int64_t* pTransporterId, SMsgSendInfo* pInfo) {
return asyncSendMsgToServerExt(pTransporter, epSet, pTransporterId, pInfo, false, NULL);
2022-03-18 10:04:57 +00:00
}
2022-05-12 09:38:16 +00:00
char* jobTaskStatusStr(int32_t status) {
2022-03-15 11:47:08 +00:00
switch (status) {
case JOB_TASK_STATUS_NULL:
return "NULL";
2022-07-02 08:59:49 +00:00
case JOB_TASK_STATUS_INIT:
return "INIT";
case JOB_TASK_STATUS_EXEC:
2022-03-15 11:47:08 +00:00
return "EXECUTING";
2022-07-02 08:59:49 +00:00
case JOB_TASK_STATUS_PART_SUCC:
2022-03-15 11:47:08 +00:00
return "PARTIAL_SUCCEED";
2023-03-28 01:20:53 +00:00
case JOB_TASK_STATUS_FETCH:
return "FETCHING";
2022-07-02 08:59:49 +00:00
case JOB_TASK_STATUS_SUCC:
2022-03-15 11:47:08 +00:00
return "SUCCEED";
2022-07-02 08:59:49 +00:00
case JOB_TASK_STATUS_FAIL:
2022-03-15 11:47:08 +00:00
return "FAILED";
2022-07-02 08:59:49 +00:00
case JOB_TASK_STATUS_DROP:
2022-03-15 11:47:08 +00:00
return "DROPPING";
default:
break;
}
return "UNKNOWN";
}
2022-03-10 11:05:58 +00:00
2022-10-26 11:25:12 +00:00
#if 0
SSchema createSchema(int8_t type, int32_t bytes, col_id_t colId, const char* name) {
2022-03-10 11:05:58 +00:00
SSchema s = {0};
2022-05-12 09:38:16 +00:00
s.type = type;
2022-03-10 11:05:58 +00:00
s.bytes = bytes;
s.colId = colId;
tstrncpy(s.name, name, tListLen(s.name));
return s;
}
2022-10-26 11:25:12 +00:00
#endif
2022-06-02 04:34:35 +00:00
void freeSTableMetaRspPointer(void *p) {
tFreeSTableMetaRsp(*(void**)p);
taosMemoryFreeClear(*(void**)p);
}
2022-07-04 01:08:57 +00:00
void destroyQueryExecRes(SExecResult* pRes) {
2022-06-02 04:34:35 +00:00
if (NULL == pRes || NULL == pRes->res) {
return;
}
switch (pRes->msgType) {
case TDMT_VND_CREATE_TABLE: {
taosArrayDestroyEx((SArray*)pRes->res, freeSTableMetaRspPointer);
break;
}
case TDMT_MND_CREATE_STB:
2022-06-02 04:34:35 +00:00
case TDMT_VND_ALTER_TABLE:
case TDMT_MND_ALTER_STB: {
tFreeSTableMetaRsp(pRes->res);
2022-06-02 04:34:35 +00:00
taosMemoryFreeClear(pRes->res);
break;
}
case TDMT_VND_SUBMIT: {
tDestroySSubmitRsp2((SSubmitRsp2*)pRes->res, TSDB_MSG_FLG_DECODE);
2022-12-03 10:46:59 +00:00
taosMemoryFreeClear(pRes->res);
2022-06-02 04:34:35 +00:00
break;
2022-06-18 06:07:54 +00:00
}
case TDMT_SCH_QUERY:
2022-06-29 02:51:22 +00:00
case TDMT_SCH_MERGE_QUERY: {
2022-06-02 04:34:35 +00:00
taosArrayDestroy((SArray*)pRes->res);
break;
}
default:
qError("invalid exec result for request type %d", pRes->msgType);
}
}
2022-06-22 10:50:39 +00:00
// clang-format on
2022-06-20 12:58:36 +00:00
2022-06-23 12:29:14 +00:00
int32_t dataConverToStr(char* str, int type, void* buf, int32_t bufSize, int32_t* len) {
2022-06-20 12:58:36 +00:00
int32_t n = 0;
switch (type) {
case TSDB_DATA_TYPE_NULL:
n = sprintf(str, "null");
break;
case TSDB_DATA_TYPE_BOOL:
n = sprintf(str, (*(int8_t*)buf) ? "true" : "false");
break;
case TSDB_DATA_TYPE_TINYINT:
n = sprintf(str, "%d", *(int8_t*)buf);
break;
case TSDB_DATA_TYPE_SMALLINT:
n = sprintf(str, "%d", *(int16_t*)buf);
break;
case TSDB_DATA_TYPE_INT:
n = sprintf(str, "%d", *(int32_t*)buf);
break;
case TSDB_DATA_TYPE_BIGINT:
case TSDB_DATA_TYPE_TIMESTAMP:
n = sprintf(str, "%" PRId64, *(int64_t*)buf);
break;
case TSDB_DATA_TYPE_FLOAT:
n = sprintf(str, "%e", GET_FLOAT_VAL(buf));
break;
case TSDB_DATA_TYPE_DOUBLE:
n = sprintf(str, "%e", GET_DOUBLE_VAL(buf));
break;
case TSDB_DATA_TYPE_BINARY:
Feature/3.0 geometry (#21037) * Add GEOMETRY data type and make sql.c able to parse it. The GEMETRY works like BINARY so far. * add GEOMETRY type into gConvertTypes to fix some issues like DELETE calling * change some test cases to make sure no same timestamp is inserted, and add my smoketest.sh * Add a function MakePoint() and introduce a lib geometry * implement sql functions GeomFromText() and AsText() * Use GEOS *_r funcions instead for thread safety * Handle with TSDB_DATA_TYPE_GEOMETRY when INSERT geometry data by converting WKT. Add geosWrapper to wrap the basic GEOS functions for TDEngine. * refactor AsText and MakePoint functions to be like GeomFromText * Show WKT when print geometry data in screen Dump hex data when dump geometry data in a file * define TYPE_BYTES item for TSDB_DATA_TYPE_GEOMETRY, which casued some strange issues. * set number of decimals of WKT to 6 * Implement SQL function Intersects() * refactor geometry sql functions * Add geosErrMsgeHandler() to get the GEOS error detail * use threadlocal to instantiate SGeosContext call destroyGeosContext() only if the thread exists * remove SGeosContext *context param for all geometry functions since we use thread local one, so that all caller do not need to know the context. * Modify Intersects() to call PreparedIntersects() when one of param is a constant, which has higher performance. * rename prepareFn() to initCtxFn() to avoid confusion with PreparedFn * Add prefix "ST_" for all geometry functions * move getThreadLocalGeosCtx() and destroyThreadLocalGeosCtx() into util, so that all unit test tools can compile * Add unit test for geometry lib, only test MakePoint so far * refactor and enhance existing cases in geomFuncTest * implement NULL type and NULL value test for geomFuncTest * add test on geomFromText() * add unit test on AsText() in geomFuncTest * combine some makePointFunction test items * add intersectsFunctionTwoColumns test refactor on callGeomFromTextWrapper functions * enhance intersectsFunction test to add cases like input constant , NULL type, NULL value, or wrong content * add more cases into intersectsFunction test * Add basic test on geometry in system test * Add ST_GeomFromText and ST_AsText function test in system test on geometry * add ST_Intersects function test in system test on geometry * support to check expectedErrno in system test on geometry * adjust geomTest unit test and geometry system test * add geometry data type and functions in doc english version * implement touchesFunction() in geometry lib refactor geometry relation functions model * separate gemFuncTest into several src files * add unit test on touchesFunction * support sql function ST_Touches() add system test on ST_Touches * add docs for ST_Touches() * Add ST_Contains() * Add ST_Covers() * Add ST_Equals() * add swapAllowed param for geomRelationFunction() read geom2 earlier intead of at doGeosRelation() * Add ST_ContainsProperly() * build on windows * Merge from 3.0 to 3.0_geometry * change macro definition TSDB_DATA_TYPE_GEOMETRY as the last one for compatibility * change '\\NULL' to 'NULL' back in shellDumpFieldToFile() * add /usr/local/include into include directory * add /usr/local/inlcude and /usr/local/lib in cmake.platform for DARWIN
2023-05-24 07:36:46 +00:00
case TSDB_DATA_TYPE_GEOMETRY:
2022-06-20 12:58:36 +00:00
if (bufSize < 0) {
2022-06-23 12:29:14 +00:00
// tscError("invalid buf size");
2022-06-20 12:58:36 +00:00
return TSDB_CODE_TSC_INVALID_VALUE;
}
*str = '"';
memcpy(str + 1, buf, bufSize);
*(str + bufSize + 1) = '"';
n = bufSize + 2;
break;
2022-07-06 08:02:55 +00:00
case TSDB_DATA_TYPE_NCHAR:
if (bufSize < 0) {
// tscError("invalid buf size");
return TSDB_CODE_TSC_INVALID_VALUE;
}
2022-06-20 12:58:36 +00:00
2022-07-06 08:02:55 +00:00
*str = '"';
2022-07-12 12:00:26 +00:00
int32_t length = taosUcs4ToMbs((TdUcs4*)buf, bufSize, str + 1);
2022-07-06 08:02:55 +00:00
if (length <= 0) {
return TSDB_CODE_TSC_INVALID_VALUE;
}
*(str + length + 1) = '"';
n = length + 2;
break;
2022-06-20 12:58:36 +00:00
case TSDB_DATA_TYPE_UTINYINT:
n = sprintf(str, "%d", *(uint8_t*)buf);
break;
case TSDB_DATA_TYPE_USMALLINT:
n = sprintf(str, "%d", *(uint16_t*)buf);
break;
case TSDB_DATA_TYPE_UINT:
n = sprintf(str, "%u", *(uint32_t*)buf);
break;
case TSDB_DATA_TYPE_UBIGINT:
n = sprintf(str, "%" PRIu64, *(uint64_t*)buf);
break;
default:
2022-06-23 12:29:14 +00:00
// tscError("unsupported type:%d", type);
2022-06-20 12:58:36 +00:00
return TSDB_CODE_TSC_INVALID_VALUE;
}
2022-07-12 12:00:26 +00:00
if (len) *len = n;
2022-06-20 12:58:36 +00:00
return TSDB_CODE_SUCCESS;
}
2022-06-21 01:18:53 +00:00
char* parseTagDatatoJson(void* p) {
2022-07-12 12:00:26 +00:00
char* string = NULL;
2022-06-21 01:18:53 +00:00
SArray* pTagVals = NULL;
2022-07-12 12:00:26 +00:00
cJSON* json = NULL;
2022-06-21 01:18:53 +00:00
if (tTagToValArray((const STag*)p, &pTagVals) != 0) {
goto end;
}
int16_t nCols = taosArrayGetSize(pTagVals);
2022-07-01 08:47:54 +00:00
if (nCols == 0) {
goto end;
}
2022-07-12 12:00:26 +00:00
char tagJsonKey[256] = {0};
2022-07-01 08:47:54 +00:00
json = cJSON_CreateObject();
if (json == NULL) {
goto end;
}
2022-06-21 01:18:53 +00:00
for (int j = 0; j < nCols; ++j) {
STagVal* pTagVal = (STagVal*)taosArrayGet(pTagVals, j);
// json key encode by binary
2022-10-18 08:33:27 +00:00
tstrncpy(tagJsonKey, pTagVal->pKey, sizeof(tagJsonKey));
2022-06-21 01:18:53 +00:00
// json value
char type = pTagVal->type;
if (type == TSDB_DATA_TYPE_NULL) {
cJSON* value = cJSON_CreateNull();
if (value == NULL) {
goto end;
}
cJSON_AddItemToObject(json, tagJsonKey, value);
} else if (type == TSDB_DATA_TYPE_NCHAR) {
cJSON* value = NULL;
if (pTagVal->nData > 0) {
char* tagJsonValue = taosMemoryCalloc(pTagVal->nData, 1);
int32_t length = taosUcs4ToMbs((TdUcs4*)pTagVal->pData, pTagVal->nData, tagJsonValue);
if (length < 0) {
qError("charset:%s to %s. val:%s convert json value failed.", DEFAULT_UNICODE_ENCODEC, tsCharset,
2022-06-23 12:29:14 +00:00
pTagVal->pData);
2022-06-21 01:18:53 +00:00
taosMemoryFree(tagJsonValue);
goto end;
}
value = cJSON_CreateString(tagJsonValue);
taosMemoryFree(tagJsonValue);
if (value == NULL) {
goto end;
}
} else if (pTagVal->nData == 0) {
value = cJSON_CreateString("");
} else {
2022-12-30 07:35:03 +00:00
goto end;
2022-06-21 01:18:53 +00:00
}
cJSON_AddItemToObject(json, tagJsonKey, value);
} else if (type == TSDB_DATA_TYPE_DOUBLE) {
double jsonVd = *(double*)(&pTagVal->i64);
cJSON* value = cJSON_CreateNumber(jsonVd);
if (value == NULL) {
goto end;
}
cJSON_AddItemToObject(json, tagJsonKey, value);
} else if (type == TSDB_DATA_TYPE_BOOL) {
char jsonVd = *(char*)(&pTagVal->i64);
cJSON* value = cJSON_CreateBool(jsonVd);
if (value == NULL) {
goto end;
}
cJSON_AddItemToObject(json, tagJsonKey, value);
} else {
2022-12-30 07:35:03 +00:00
goto end;
2022-06-21 01:18:53 +00:00
}
}
string = cJSON_PrintUnformatted(json);
end:
cJSON_Delete(json);
2022-07-01 08:47:54 +00:00
taosArrayDestroy(pTagVals);
2022-07-12 12:00:26 +00:00
if (string == NULL) {
string = taosStrdup(TSDB_DATA_NULL_STR_L);
2022-07-01 08:47:54 +00:00
}
2022-06-21 01:18:53 +00:00
return string;
}
2022-06-21 08:45:59 +00:00
int32_t cloneTableMeta(STableMeta* pSrc, STableMeta** pDst) {
if (NULL == pSrc) {
*pDst = NULL;
return TSDB_CODE_SUCCESS;
}
2022-10-19 05:56:39 +00:00
int32_t numOfField = pSrc->tableInfo.numOfColumns + pSrc->tableInfo.numOfTags;
if (numOfField > TSDB_MAX_COL_TAG_NUM || numOfField < TSDB_MIN_COLUMNS) {
2022-10-17 11:48:36 +00:00
*pDst = NULL;
qError("too many column and tag num:%d,%d", pSrc->tableInfo.numOfColumns, pSrc->tableInfo.numOfTags);
return TSDB_CODE_INVALID_PARA;
}
2022-10-19 05:56:39 +00:00
int32_t metaSize = sizeof(STableMeta) + numOfField * sizeof(SSchema);
2022-06-21 08:45:59 +00:00
*pDst = taosMemoryMalloc(metaSize);
if (NULL == *pDst) {
2022-12-03 02:03:18 +00:00
return TSDB_CODE_OUT_OF_MEMORY;
2022-06-21 08:45:59 +00:00
}
memcpy(*pDst, pSrc, metaSize);
return TSDB_CODE_SUCCESS;
}
void getColumnTypeFromMeta(STableMeta* pMeta, char* pName, ETableColumnType* pType) {
int32_t nums = pMeta->tableInfo.numOfTags + pMeta->tableInfo.numOfColumns;
for (int32_t i = 0; i < nums; ++i) {
if (0 == strcmp(pName, pMeta->schema[i].name)) {
*pType = (i < pMeta->tableInfo.numOfColumns) ? TCOL_TYPE_COLUMN : TCOL_TYPE_TAG;
return;
}
}
*pType = TCOL_TYPE_NONE;
}
void freeVgInfo(SDBVgInfo* vgInfo) {
if (NULL == vgInfo) {
return;
}
taosHashCleanup(vgInfo->vgHash);
taosArrayDestroy(vgInfo->vgArray);
taosMemoryFreeClear(vgInfo);
}
2022-06-21 08:45:59 +00:00
int32_t cloneDbVgInfo(SDBVgInfo* pSrc, SDBVgInfo** pDst) {
if (NULL == pSrc) {
*pDst = NULL;
return TSDB_CODE_SUCCESS;
}
2022-06-23 12:29:14 +00:00
2022-06-21 08:45:59 +00:00
*pDst = taosMemoryMalloc(sizeof(*pSrc));
if (NULL == *pDst) {
2022-12-03 02:03:18 +00:00
return TSDB_CODE_OUT_OF_MEMORY;
2022-06-21 08:45:59 +00:00
}
memcpy(*pDst, pSrc, sizeof(*pSrc));
if (pSrc->vgHash) {
2022-06-23 12:29:14 +00:00
(*pDst)->vgHash = taosHashInit(taosHashGetSize(pSrc->vgHash), taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true,
HASH_ENTRY_LOCK);
2022-06-21 08:45:59 +00:00
if (NULL == (*pDst)->vgHash) {
2022-11-01 03:43:40 +00:00
taosMemoryFreeClear(*pDst);
2022-12-03 02:03:18 +00:00
return TSDB_CODE_OUT_OF_MEMORY;
2022-06-21 08:45:59 +00:00
}
SVgroupInfo* vgInfo = NULL;
2022-06-23 12:29:14 +00:00
void* pIter = taosHashIterate(pSrc->vgHash, NULL);
2022-06-21 08:45:59 +00:00
while (pIter) {
vgInfo = pIter;
int32_t* vgId = taosHashGetKey(pIter, NULL);
2022-06-23 12:29:14 +00:00
2022-06-21 08:45:59 +00:00
if (0 != taosHashPut((*pDst)->vgHash, vgId, sizeof(*vgId), vgInfo, sizeof(*vgInfo))) {
qError("taosHashPut failed, vgId:%d", vgInfo->vgId);
2022-06-23 12:29:14 +00:00
taosHashCancelIterate(pSrc->vgHash, pIter);
freeVgInfo(*pDst);
2022-06-24 12:53:52 +00:00
return TSDB_CODE_OUT_OF_MEMORY;
2022-06-21 08:45:59 +00:00
}
2022-06-23 12:29:14 +00:00
2022-06-21 08:45:59 +00:00
pIter = taosHashIterate(pSrc->vgHash, pIter);
}
}
2022-06-23 12:29:14 +00:00
2022-06-21 08:45:59 +00:00
return TSDB_CODE_SUCCESS;
}
2022-12-03 06:56:51 +00:00
int32_t cloneSVreateTbReq(SVCreateTbReq* pSrc, SVCreateTbReq** pDst) {
if (NULL == pSrc) {
*pDst = NULL;
return TSDB_CODE_SUCCESS;
}
*pDst = taosMemoryCalloc(1, sizeof(SVCreateTbReq));
if (NULL == *pDst) {
2022-12-06 06:53:02 +00:00
return TSDB_CODE_OUT_OF_MEMORY;
2022-12-03 06:56:51 +00:00
}
(*pDst)->flags = pSrc->flags;
2022-12-03 10:46:59 +00:00
if (pSrc->name) {
(*pDst)->name = taosStrdup(pSrc->name);
2022-12-03 10:46:59 +00:00
}
2022-12-03 06:56:51 +00:00
(*pDst)->uid = pSrc->uid;
(*pDst)->btime = pSrc->btime;
2022-12-03 06:56:51 +00:00
(*pDst)->ttl = pSrc->ttl;
(*pDst)->commentLen = pSrc->commentLen;
2022-12-03 10:46:59 +00:00
if (pSrc->comment) {
(*pDst)->comment = taosStrdup(pSrc->comment);
2022-12-03 10:46:59 +00:00
}
2022-12-03 06:56:51 +00:00
(*pDst)->type = pSrc->type;
if (pSrc->type == TSDB_CHILD_TABLE) {
2022-12-03 10:46:59 +00:00
if (pSrc->ctb.stbName) {
(*pDst)->ctb.stbName = taosStrdup(pSrc->ctb.stbName);
2022-12-03 10:46:59 +00:00
}
2022-12-03 06:56:51 +00:00
(*pDst)->ctb.tagNum = pSrc->ctb.tagNum;
(*pDst)->ctb.suid = pSrc->ctb.suid;
2022-12-03 10:46:59 +00:00
if (pSrc->ctb.tagName) {
(*pDst)->ctb.tagName = taosArrayDup(pSrc->ctb.tagName, NULL);
}
2022-12-06 06:53:02 +00:00
STag* pTag = (STag*)pSrc->ctb.pTag;
2022-12-03 10:46:59 +00:00
if (pTag) {
(*pDst)->ctb.pTag = taosMemoryMalloc(pTag->len);
memcpy((*pDst)->ctb.pTag, pTag, pTag->len);
}
2022-12-03 06:56:51 +00:00
} else {
(*pDst)->ntb.schemaRow.nCols = pSrc->ntb.schemaRow.nCols;
(*pDst)->ntb.schemaRow.version = pSrc->ntb.schemaRow.nCols;
2022-12-03 10:46:59 +00:00
if (pSrc->ntb.schemaRow.nCols > 0 && pSrc->ntb.schemaRow.pSchema) {
(*pDst)->ntb.schemaRow.pSchema = taosMemoryMalloc(pSrc->ntb.schemaRow.nCols * sizeof(SSchema));
memcpy((*pDst)->ntb.schemaRow.pSchema, pSrc->ntb.schemaRow.pSchema, pSrc->ntb.schemaRow.nCols * sizeof(SSchema));
}
2022-12-03 06:56:51 +00:00
}
return TSDB_CODE_SUCCESS;
}
2023-04-13 02:54:57 +00:00
void freeDbCfgInfo(SDbCfgInfo *pInfo) {
if (pInfo) {
taosArrayDestroy(pInfo->pRetensions);
}
taosMemoryFree(pInfo);
}