1501 lines
54 KiB
C
1501 lines
54 KiB
C
/*
|
|
* 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 "parUtil.h"
|
|
#include "cJSON.h"
|
|
#include "querynodes.h"
|
|
#include "tarray.h"
|
|
#include "tlog.h"
|
|
|
|
#define USER_AUTH_KEY_MAX_LEN TSDB_USER_LEN + TSDB_TABLE_FNAME_LEN + 2
|
|
|
|
const void* nullPointer = NULL;
|
|
|
|
static char* getSyntaxErrFormat(int32_t errCode) {
|
|
switch (errCode) {
|
|
case TSDB_CODE_PAR_SYNTAX_ERROR:
|
|
return "syntax error near \"%s\"";
|
|
case TSDB_CODE_PAR_INCOMPLETE_SQL:
|
|
return "Incomplete SQL statement";
|
|
case TSDB_CODE_PAR_INVALID_COLUMN:
|
|
return "Invalid column name: %s";
|
|
case TSDB_CODE_PAR_TABLE_NOT_EXIST:
|
|
return "Table does not exist: %s";
|
|
case TSDB_CODE_PAR_GET_META_ERROR:
|
|
return "Fail to get table info, error: %s";
|
|
case TSDB_CODE_PAR_AMBIGUOUS_COLUMN:
|
|
return "Column ambiguously defined: %s";
|
|
case TSDB_CODE_PAR_WRONG_VALUE_TYPE:
|
|
return "Invalid value type: %s";
|
|
case TSDB_CODE_PAR_INVALID_VARBINARY:
|
|
return "Invalid varbinary value: %s";
|
|
case TSDB_CODE_PAR_ILLEGAL_USE_AGG_FUNCTION:
|
|
return "There mustn't be aggregation";
|
|
case TSDB_CODE_PAR_WRONG_NUMBER_OF_SELECT:
|
|
return "ORDER BY / GROUP BY item must be the number of a SELECT-list expression";
|
|
case TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION:
|
|
return "Not a GROUP BY expression";
|
|
case TSDB_CODE_PAR_NOT_SELECTED_EXPRESSION:
|
|
return "Not SELECTed expression";
|
|
case TSDB_CODE_PAR_NOT_SINGLE_GROUP:
|
|
return "Not a single-group group function";
|
|
case TSDB_CODE_PAR_TAGS_NOT_MATCHED:
|
|
return "Tags number not matched";
|
|
case TSDB_CODE_PAR_INVALID_TAG_NAME:
|
|
return "Invalid tag name: %s";
|
|
case TSDB_CODE_PAR_NAME_OR_PASSWD_TOO_LONG:
|
|
return "Name or password too long";
|
|
case TSDB_CODE_PAR_PASSWD_EMPTY:
|
|
return "Password can not be empty";
|
|
case TSDB_CODE_PAR_INVALID_PORT:
|
|
return "Port should be an integer that is less than 65535 and greater than 0";
|
|
case TSDB_CODE_PAR_INVALID_ENDPOINT:
|
|
return "Endpoint should be in the format of 'fqdn:port'";
|
|
case TSDB_CODE_PAR_EXPRIE_STATEMENT:
|
|
return "This statement is no longer supported";
|
|
case TSDB_CODE_PAR_INTER_VALUE_TOO_SMALL:
|
|
return "Interval cannot be less than %d %s";
|
|
case TSDB_CODE_PAR_INTER_VALUE_TOO_BIG:
|
|
return "Interval cannot be more than %d %s";
|
|
case TSDB_CODE_PAR_DB_NOT_SPECIFIED:
|
|
return "Database not specified";
|
|
case TSDB_CODE_PAR_INVALID_IDENTIFIER_NAME:
|
|
return "Invalid identifier name: %s";
|
|
case TSDB_CODE_PAR_CORRESPONDING_STABLE_ERR:
|
|
return "Corresponding super table not in this db";
|
|
case TSDB_CODE_PAR_GROUPBY_WINDOW_COEXIST:
|
|
return "GROUP BY and WINDOW-clause can't be used together";
|
|
case TSDB_CODE_PAR_AGG_FUNC_NESTING:
|
|
return "Aggregate functions do not support nesting";
|
|
case TSDB_CODE_PAR_INVALID_STATE_WIN_TYPE:
|
|
return "Only support STATE_WINDOW on integer/bool/varchar column";
|
|
case TSDB_CODE_PAR_INVALID_STATE_WIN_COL:
|
|
return "Not support STATE_WINDOW on tag column";
|
|
case TSDB_CODE_PAR_INVALID_STATE_WIN_TABLE:
|
|
return "STATE_WINDOW not support for super table query";
|
|
case TSDB_CODE_PAR_INTER_SESSION_GAP:
|
|
return "SESSION gap should be fixed time window, and greater than 0";
|
|
case TSDB_CODE_PAR_INTER_SESSION_COL:
|
|
return "Only support SESSION on primary timestamp column";
|
|
case TSDB_CODE_PAR_INTER_OFFSET_NEGATIVE:
|
|
return "Interval offset cannot be negative";
|
|
case TSDB_CODE_PAR_INTER_OFFSET_UNIT:
|
|
return "Cannot use 'year' as offset when interval is 'month'";
|
|
case TSDB_CODE_PAR_INTER_OFFSET_TOO_BIG:
|
|
return "Interval offset should be shorter than interval";
|
|
case TSDB_CODE_PAR_INTER_SLIDING_UNIT:
|
|
return "Does not support sliding when interval is natural month/year";
|
|
case TSDB_CODE_PAR_INTER_SLIDING_TOO_BIG:
|
|
return "sliding value no larger than the interval value";
|
|
case TSDB_CODE_PAR_INTER_SLIDING_TOO_SMALL:
|
|
return "sliding value can not less than 1%% of interval value";
|
|
case TSDB_CODE_PAR_ONLY_ONE_JSON_TAG:
|
|
return "Only one tag if there is a json tag";
|
|
case TSDB_CODE_PAR_INCORRECT_NUM_OF_COL:
|
|
return "Query block has incorrect number of result columns";
|
|
case TSDB_CODE_PAR_INCORRECT_TIMESTAMP_VAL:
|
|
return "Incorrect TIMESTAMP value: %s";
|
|
case TSDB_CODE_PAR_OFFSET_LESS_ZERO:
|
|
return "soffset/offset can not be less than 0";
|
|
case TSDB_CODE_PAR_SLIMIT_LEAK_PARTITION_GROUP_BY:
|
|
return "slimit/soffset only available for PARTITION/GROUP BY query";
|
|
case TSDB_CODE_PAR_INVALID_TOPIC_QUERY:
|
|
return "Invalid topic query";
|
|
case TSDB_CODE_PAR_INVALID_DROP_STABLE:
|
|
return "Cannot drop super table in batch";
|
|
case TSDB_CODE_PAR_INVALID_FILL_TIME_RANGE:
|
|
return "Start(end) time of query range required or time range too large";
|
|
case TSDB_CODE_PAR_DUPLICATED_COLUMN:
|
|
return "Duplicated column names";
|
|
case TSDB_CODE_PAR_INVALID_TAGS_LENGTH:
|
|
return "Tags length exceeds max length %d";
|
|
case TSDB_CODE_PAR_INVALID_ROW_LENGTH:
|
|
return "Row length exceeds max length %d";
|
|
case TSDB_CODE_PAR_INVALID_COLUMNS_NUM:
|
|
return "Illegal number of columns";
|
|
case TSDB_CODE_PAR_TOO_MANY_COLUMNS:
|
|
return "Too many columns";
|
|
case TSDB_CODE_PAR_INVALID_FIRST_COLUMN:
|
|
return "First column must be timestamp";
|
|
case TSDB_CODE_PAR_INVALID_VAR_COLUMN_LEN:
|
|
return "Invalid column length for var length type";
|
|
case TSDB_CODE_PAR_INVALID_TAGS_NUM:
|
|
return "Invalid number of tag columns";
|
|
case TSDB_CODE_PAR_INVALID_INTERNAL_PK:
|
|
return "Invalid _c0 or _rowts expression";
|
|
case TSDB_CODE_PAR_INVALID_TIMELINE_FUNC:
|
|
return "Invalid timeline function";
|
|
case TSDB_CODE_PAR_INVALID_PASSWD:
|
|
return "Invalid password";
|
|
case TSDB_CODE_PAR_INVALID_ALTER_TABLE:
|
|
return "Invalid alter table statement";
|
|
case TSDB_CODE_PAR_CANNOT_DROP_PRIMARY_KEY:
|
|
return "Primary timestamp column cannot be dropped";
|
|
case TSDB_CODE_PAR_INVALID_MODIFY_COL:
|
|
return "Only varbinary/binary/nchar/geometry column length could be modified, and the length can only be "
|
|
"increased, not decreased";
|
|
case TSDB_CODE_PAR_INVALID_TBNAME:
|
|
return "Invalid tbname pseudo column";
|
|
case TSDB_CODE_PAR_INVALID_FUNCTION_NAME:
|
|
return "Invalid function name";
|
|
case TSDB_CODE_PAR_COMMENT_TOO_LONG:
|
|
return "Comment too long";
|
|
case TSDB_CODE_PAR_NOT_ALLOWED_FUNC:
|
|
return "Some functions are allowed only in the SELECT list of a query. "
|
|
"And, cannot be mixed with other non scalar functions or columns.";
|
|
case TSDB_CODE_PAR_NOT_ALLOWED_WIN_QUERY:
|
|
return "Window query not supported, since not valid primary timestamp column as input";
|
|
case TSDB_CODE_PAR_INVALID_DROP_COL:
|
|
return "No columns can be dropped";
|
|
case TSDB_CODE_PAR_INVALID_COL_JSON:
|
|
return "Only tag can be json type";
|
|
case TSDB_CODE_PAR_VALUE_TOO_LONG:
|
|
return "Value too long for column/tag: %s";
|
|
case TSDB_CODE_PAR_INVALID_DELETE_WHERE:
|
|
return "The DELETE statement must only have a definite time window range";
|
|
case TSDB_CODE_PAR_INVALID_REDISTRIBUTE_VG:
|
|
return "The REDISTRIBUTE VGROUP statement only support 1 to 3 dnodes";
|
|
case TSDB_CODE_PAR_FILL_NOT_ALLOWED_FUNC:
|
|
return "%s function is not supported in fill query";
|
|
case TSDB_CODE_PAR_INVALID_WINDOW_PC:
|
|
return "_WSTART, _WEND and _WDURATION can only be used in window query";
|
|
case TSDB_CODE_PAR_INVALID_TAGS_PC:
|
|
return "Tags can only applied to super table and child table";
|
|
case TSDB_CODE_PAR_WINDOW_NOT_ALLOWED_FUNC:
|
|
return "%s function is not supported in time window query";
|
|
case TSDB_CODE_PAR_STREAM_NOT_ALLOWED_FUNC:
|
|
return "%s function is not supported in stream query";
|
|
case TSDB_CODE_PAR_GROUP_BY_NOT_ALLOWED_FUNC:
|
|
return "%s function is not supported in group query";
|
|
case TSDB_CODE_PAR_SYSTABLE_NOT_ALLOWED_FUNC:
|
|
return "%s function is not supported in system table query";
|
|
case TSDB_CODE_PAR_SYSTABLE_NOT_ALLOWED:
|
|
return "%s is not supported in system table query";
|
|
case TSDB_CODE_PAR_INVALID_INTERP_CLAUSE:
|
|
return "Invalid usage of RANGE clause, EVERY clause or FILL clause";
|
|
case TSDB_CODE_PAR_INVALID_FORECAST_CLAUSE:
|
|
return "Invalid usage of forecast clause";
|
|
case TSDB_CODE_PAR_NO_VALID_FUNC_IN_WIN:
|
|
return "No valid function in window query";
|
|
case TSDB_CODE_PAR_INVALID_OPTR_USAGE:
|
|
return "Invalid usage of expr: %s";
|
|
case TSDB_CODE_PAR_INVALID_IP_RANGE:
|
|
return "invalid ip range";
|
|
case TSDB_CODE_OUT_OF_MEMORY:
|
|
return "Out of memory";
|
|
case TSDB_CODE_PAR_ORDERBY_AMBIGUOUS:
|
|
return "ORDER BY \"%s\" is ambiguous";
|
|
case TSDB_CODE_PAR_NOT_SUPPORT_MULTI_RESULT:
|
|
return "Operator not supported multi result: %s";
|
|
case TSDB_CODE_PAR_INVALID_WJOIN_HAVING_EXPR:
|
|
return "Not supported window join having expr";
|
|
case TSDB_CODE_PAR_INVALID_WIN_OFFSET_UNIT:
|
|
return "Invalid WINDOW_OFFSET unit \"%c\"";
|
|
case TSDB_CODE_PAR_VALID_PRIM_TS_REQUIRED:
|
|
return "Valid primary timestamp required";
|
|
case TSDB_CODE_PAR_NOT_WIN_FUNC:
|
|
return "Column exists for window join with aggregation functions";
|
|
case TSDB_CODE_PAR_TAG_IS_PRIMARY_KEY:
|
|
return "tag %s can not be primary key";
|
|
case TSDB_CODE_PAR_SECOND_COL_PK:
|
|
return "primary key column must be second column";
|
|
case TSDB_CODE_PAR_COL_PK_TYPE:
|
|
return "primary key column must be of type int, uint, bigint, ubigint, and varchar";
|
|
case TSDB_CODE_PAR_INVALID_PK_OP:
|
|
return "primary key column can not be added, modified, and dropped";
|
|
case TSDB_CODE_TSMA_NAME_TOO_LONG:
|
|
return "Tsma name too long";
|
|
case TSDB_CODE_PAR_TBNAME_ERROR:
|
|
return "Pseudo tag tbname not set";
|
|
case TSDB_CODE_PAR_TBNAME_DUPLICATED:
|
|
return "Table name:%s duplicated";
|
|
case TSDB_CODE_PAR_TAG_NAME_DUPLICATED:
|
|
return "Tag name:%s duplicated";
|
|
case TSDB_CODE_PAR_NOT_ALLOWED_DIFFERENT_BY_ROW_FUNC:
|
|
return "Some functions cannot appear in the select list at the same time";
|
|
case TSDB_CODE_PAR_REGULAR_EXPRESSION_ERROR:
|
|
return "Syntax error in regular expression";
|
|
default:
|
|
return "Unknown error";
|
|
}
|
|
}
|
|
|
|
int32_t generateSyntaxErrMsg(SMsgBuf* pBuf, int32_t errCode, ...) {
|
|
va_list vArgList;
|
|
va_start(vArgList, errCode);
|
|
(void)vsnprintf(pBuf->buf, pBuf->len, getSyntaxErrFormat(errCode), vArgList);
|
|
va_end(vArgList);
|
|
return errCode;
|
|
}
|
|
|
|
int32_t generateSyntaxErrMsgExt(SMsgBuf* pBuf, int32_t errCode, const char* pFormat, ...) {
|
|
va_list vArgList;
|
|
va_start(vArgList, pFormat);
|
|
(void)vsnprintf(pBuf->buf, pBuf->len, pFormat, vArgList);
|
|
va_end(vArgList);
|
|
return errCode;
|
|
}
|
|
|
|
int32_t buildInvalidOperationMsg(SMsgBuf* pBuf, const char* msg) {
|
|
if (pBuf->buf) {
|
|
strncpy(pBuf->buf, msg, pBuf->len);
|
|
}
|
|
|
|
return TSDB_CODE_TSC_INVALID_OPERATION;
|
|
}
|
|
|
|
int32_t buildInvalidOperationMsgExt(SMsgBuf* pBuf, const char* pFormat, ...) {
|
|
va_list vArgList;
|
|
va_start(vArgList, pFormat);
|
|
(void)vsnprintf(pBuf->buf, pBuf->len, pFormat, vArgList);
|
|
va_end(vArgList);
|
|
return TSDB_CODE_TSC_INVALID_OPERATION;
|
|
}
|
|
|
|
int32_t buildSyntaxErrMsg(SMsgBuf* pBuf, const char* additionalInfo, const char* sourceStr) {
|
|
if (pBuf == NULL) return TSDB_CODE_TSC_SQL_SYNTAX_ERROR;
|
|
const char* msgFormat1 = "syntax error near \'%s\'";
|
|
const char* msgFormat2 = "syntax error near \'%s\' (%s)";
|
|
const char* msgFormat3 = "%s";
|
|
|
|
const char* prefix = "syntax error";
|
|
if (sourceStr == NULL) {
|
|
snprintf(pBuf->buf, pBuf->len, msgFormat1, additionalInfo);
|
|
return TSDB_CODE_TSC_SQL_SYNTAX_ERROR;
|
|
}
|
|
|
|
char buf[64] = {0}; // only extract part of sql string
|
|
strncpy(buf, sourceStr, tListLen(buf) - 1);
|
|
|
|
if (additionalInfo != NULL) {
|
|
snprintf(pBuf->buf, pBuf->len, msgFormat2, buf, additionalInfo);
|
|
} else {
|
|
const char* msgFormat = (0 == strncmp(sourceStr, prefix, strlen(prefix))) ? msgFormat3 : msgFormat1;
|
|
snprintf(pBuf->buf, pBuf->len, msgFormat, buf);
|
|
}
|
|
|
|
return TSDB_CODE_TSC_SQL_SYNTAX_ERROR;
|
|
}
|
|
|
|
SSchema* getTableColumnSchema(const STableMeta* pTableMeta) { return (SSchema*)pTableMeta->schema; }
|
|
|
|
static SSchema* getOneColumnSchema(const STableMeta* pTableMeta, int32_t colIndex) {
|
|
SSchema* pSchema = (SSchema*)pTableMeta->schema;
|
|
return &pSchema[colIndex];
|
|
}
|
|
|
|
SSchema* getTableTagSchema(const STableMeta* pTableMeta) {
|
|
return getOneColumnSchema(pTableMeta, getTableInfo(pTableMeta).numOfColumns);
|
|
}
|
|
|
|
int32_t getNumOfColumns(const STableMeta* pTableMeta) {
|
|
// table created according to super table, use data from super table
|
|
return getTableInfo(pTableMeta).numOfColumns;
|
|
}
|
|
|
|
int32_t getNumOfTags(const STableMeta* pTableMeta) { return getTableInfo(pTableMeta).numOfTags; }
|
|
|
|
STableComInfo getTableInfo(const STableMeta* pTableMeta) { return pTableMeta->tableInfo; }
|
|
|
|
int32_t getTableTypeFromTableNode(SNode* pTable) {
|
|
if (NULL == pTable) {
|
|
return -1;
|
|
}
|
|
if (QUERY_NODE_REAL_TABLE != nodeType(pTable)) {
|
|
return -1;
|
|
}
|
|
return ((SRealTableNode*)pTable)->pMeta->tableType;
|
|
}
|
|
|
|
STableMeta* tableMetaDup(const STableMeta* pTableMeta) {
|
|
int32_t numOfFields = TABLE_TOTAL_COL_NUM(pTableMeta);
|
|
if (numOfFields > TSDB_MAX_COLUMNS || numOfFields < TSDB_MIN_COLUMNS) {
|
|
return NULL;
|
|
}
|
|
|
|
bool hasSchemaExt = pTableMeta->schemaExt == NULL ? false : true;
|
|
size_t schemaExtSize = hasSchemaExt ? pTableMeta->tableInfo.numOfColumns * sizeof(SSchemaExt) : 0;
|
|
|
|
size_t size = sizeof(STableMeta) + numOfFields * sizeof(SSchema);
|
|
STableMeta* p = taosMemoryMalloc(size + schemaExtSize);
|
|
if (NULL == p) return NULL;
|
|
|
|
memcpy(p, pTableMeta, schemaExtSize + size);
|
|
if (hasSchemaExt) {
|
|
p->schemaExt = (SSchemaExt*)(((char*)p) + size);
|
|
} else {
|
|
p->schemaExt = NULL;
|
|
}
|
|
return p;
|
|
}
|
|
|
|
int32_t trimString(const char* src, int32_t len, char* dst, int32_t dlen) {
|
|
if (len <= 0 || dlen <= 0) return 0;
|
|
|
|
char delim = src[0];
|
|
int32_t j = 0;
|
|
for (uint32_t k = 1; k < len - 1; ++k) {
|
|
if (j >= dlen) {
|
|
dst[j - 1] = '\0';
|
|
return j;
|
|
}
|
|
if (src[k] == delim && src[k + 1] == delim) { // deal with "", ''
|
|
dst[j] = src[k + 1];
|
|
j++;
|
|
k++;
|
|
continue;
|
|
}
|
|
|
|
if (src[k] == '\\') { // deal with escape character
|
|
if (src[k + 1] == 'n') {
|
|
dst[j] = '\n';
|
|
} else if (src[k + 1] == 'r') {
|
|
dst[j] = '\r';
|
|
} else if (src[k + 1] == 't') {
|
|
dst[j] = '\t';
|
|
} else if (src[k + 1] == '\\') {
|
|
dst[j] = '\\';
|
|
} else if (src[k + 1] == '\'') {
|
|
dst[j] = '\'';
|
|
} else if (src[k + 1] == '"') {
|
|
dst[j] = '"';
|
|
} else if (src[k + 1] == '%' || src[k + 1] == '_' || src[k + 1] == 'x') {
|
|
dst[j++] = src[k];
|
|
dst[j] = src[k + 1];
|
|
} else {
|
|
dst[j] = src[k + 1];
|
|
}
|
|
j++;
|
|
k++;
|
|
continue;
|
|
}
|
|
|
|
dst[j] = src[k];
|
|
j++;
|
|
}
|
|
if (j >= dlen) j = dlen - 1;
|
|
dst[j] = '\0';
|
|
return j;
|
|
}
|
|
|
|
static bool isValidateTag(char* input) {
|
|
if (!input) return false;
|
|
for (size_t i = 0; i < strlen(input); ++i) {
|
|
#ifdef WINDOWS
|
|
if (input[i] < 0x20 || input[i] > 0x7E) return false;
|
|
#else
|
|
if (isprint(input[i]) == 0) return false;
|
|
#endif
|
|
}
|
|
return true;
|
|
}
|
|
|
|
int32_t parseJsontoTagData(const char* json, SArray* pTagVals, STag** ppTag, void* pMsgBuf) {
|
|
int32_t retCode = TSDB_CODE_SUCCESS;
|
|
cJSON* root = NULL;
|
|
SHashObj* keyHash = NULL;
|
|
int32_t size = 0;
|
|
// set json NULL data
|
|
if (!json || strcasecmp(json, TSDB_DATA_NULL_STR_L) == 0 || strtrim((char*)json) == 0) {
|
|
retCode = TSDB_CODE_SUCCESS;
|
|
goto end;
|
|
}
|
|
|
|
// set json real data
|
|
root = cJSON_Parse(json);
|
|
if (root == NULL) {
|
|
retCode = buildSyntaxErrMsg(pMsgBuf, "json parse error", json);
|
|
goto end;
|
|
}
|
|
|
|
size = cJSON_GetArraySize(root);
|
|
if (!cJSON_IsObject(root)) {
|
|
retCode = buildSyntaxErrMsg(pMsgBuf, "json error invalide value", json);
|
|
goto end;
|
|
}
|
|
|
|
keyHash = taosHashInit(8, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, false);
|
|
if (!keyHash) {
|
|
retCode = terrno;
|
|
goto end;
|
|
}
|
|
for (int32_t i = 0; i < size; i++) {
|
|
cJSON* item = cJSON_GetArrayItem(root, i);
|
|
if (!item) {
|
|
uError("json inner error:%d", i);
|
|
retCode = buildSyntaxErrMsg(pMsgBuf, "json inner error", json);
|
|
goto end;
|
|
}
|
|
|
|
char* jsonKey = item->string;
|
|
if (!isValidateTag(jsonKey)) {
|
|
retCode = buildSyntaxErrMsg(pMsgBuf, "json key not validate", jsonKey);
|
|
goto end;
|
|
}
|
|
size_t keyLen = strlen(jsonKey);
|
|
if (keyLen > TSDB_MAX_JSON_KEY_LEN) {
|
|
uError("json key too long error");
|
|
retCode = buildSyntaxErrMsg(pMsgBuf, "json key too long, more than 256", jsonKey);
|
|
goto end;
|
|
}
|
|
if (keyLen == 0 || taosHashGet(keyHash, jsonKey, keyLen) != NULL) {
|
|
continue;
|
|
}
|
|
STagVal val = {0};
|
|
// strcpy(val.colName, colName);
|
|
val.pKey = jsonKey;
|
|
retCode = taosHashPut(keyHash, jsonKey, keyLen, &keyLen,
|
|
CHAR_BYTES); // add key to hash to remove dumplicate, value is useless
|
|
if (TSDB_CODE_SUCCESS != retCode) {
|
|
goto end;
|
|
}
|
|
|
|
if (item->type == cJSON_String) { // add json value format: type|data
|
|
char* jsonValue = item->valuestring;
|
|
int32_t valLen = (int32_t)strlen(jsonValue);
|
|
char* tmp = taosMemoryCalloc(1, valLen * TSDB_NCHAR_SIZE);
|
|
if (!tmp) {
|
|
retCode = terrno;
|
|
goto end;
|
|
}
|
|
val.type = TSDB_DATA_TYPE_NCHAR;
|
|
if (valLen > 0 && !taosMbsToUcs4(jsonValue, valLen, (TdUcs4*)tmp, (int32_t)(valLen * TSDB_NCHAR_SIZE), &valLen)) {
|
|
uError("charset:%s to %s. val:%s, errno:%s, convert failed.", DEFAULT_UNICODE_ENCODEC, tsCharset, jsonValue,
|
|
strerror(terrno));
|
|
retCode = buildSyntaxErrMsg(pMsgBuf, "charset convert json error", jsonValue);
|
|
taosMemoryFree(tmp);
|
|
goto end;
|
|
}
|
|
val.nData = valLen;
|
|
val.pData = tmp;
|
|
} else if (item->type == cJSON_Number) {
|
|
if (!isfinite(item->valuedouble)) {
|
|
uError("json value is invalidate");
|
|
retCode = buildSyntaxErrMsg(pMsgBuf, "json value number is illegal", json);
|
|
goto end;
|
|
}
|
|
val.type = TSDB_DATA_TYPE_DOUBLE;
|
|
*((double*)&(val.i64)) = item->valuedouble;
|
|
} else if (item->type == cJSON_True || item->type == cJSON_False) {
|
|
val.type = TSDB_DATA_TYPE_BOOL;
|
|
*((char*)&(val.i64)) = (char)(item->valueint);
|
|
} else if (item->type == cJSON_NULL) {
|
|
val.type = TSDB_DATA_TYPE_NULL;
|
|
} else {
|
|
retCode = buildSyntaxErrMsg(pMsgBuf, "invalidate json value", json);
|
|
goto end;
|
|
}
|
|
if (NULL == taosArrayPush(pTagVals, &val)) {
|
|
retCode = terrno;
|
|
goto end;
|
|
}
|
|
}
|
|
|
|
end:
|
|
taosHashCleanup(keyHash);
|
|
if (retCode == TSDB_CODE_SUCCESS) {
|
|
retCode = tTagNew(pTagVals, 1, true, ppTag);
|
|
}
|
|
for (int i = 0; i < taosArrayGetSize(pTagVals); ++i) {
|
|
STagVal* p = (STagVal*)taosArrayGet(pTagVals, i);
|
|
if (IS_VAR_DATA_TYPE(p->type)) {
|
|
taosMemoryFreeClear(p->pData);
|
|
}
|
|
}
|
|
cJSON_Delete(root);
|
|
return retCode;
|
|
}
|
|
|
|
static int32_t getInsTagsTableTargetNameFromOp(int32_t acctId, SOperatorNode* pOper, SName* pName) {
|
|
if (OP_TYPE_EQUAL != pOper->opType) {
|
|
return TSDB_CODE_SUCCESS;
|
|
}
|
|
|
|
SColumnNode* pCol = NULL;
|
|
SValueNode* pVal = NULL;
|
|
if (QUERY_NODE_COLUMN == nodeType(pOper->pLeft)) {
|
|
pCol = (SColumnNode*)pOper->pLeft;
|
|
} else if (QUERY_NODE_VALUE == nodeType(pOper->pLeft)) {
|
|
pVal = (SValueNode*)pOper->pLeft;
|
|
}
|
|
if (QUERY_NODE_COLUMN == nodeType(pOper->pRight)) {
|
|
pCol = (SColumnNode*)pOper->pRight;
|
|
} else if (QUERY_NODE_VALUE == nodeType(pOper->pRight)) {
|
|
pVal = (SValueNode*)pOper->pRight;
|
|
}
|
|
if (NULL == pCol || NULL == pVal || NULL == pVal->literal || 0 == strcmp(pVal->literal, "")) {
|
|
return TSDB_CODE_SUCCESS;
|
|
}
|
|
|
|
if (0 == strcmp(pCol->colName, "db_name")) {
|
|
return tNameSetDbName(pName, acctId, pVal->literal, strlen(pVal->literal));
|
|
} else if (0 == strcmp(pCol->colName, "table_name")) {
|
|
return tNameAddTbName(pName, pVal->literal, strlen(pVal->literal));
|
|
}
|
|
|
|
return TSDB_CODE_SUCCESS;
|
|
}
|
|
|
|
static int32_t getInsTagsTableTargetObjName(int32_t acctId, SNode* pNode, SName* pName) {
|
|
if (QUERY_NODE_OPERATOR == nodeType(pNode)) {
|
|
return getInsTagsTableTargetNameFromOp(acctId, (SOperatorNode*)pNode, pName);
|
|
}
|
|
return TSDB_CODE_SUCCESS;
|
|
}
|
|
|
|
static int32_t getInsTagsTableTargetNameFromCond(int32_t acctId, SLogicConditionNode* pCond, SName* pName) {
|
|
if (LOGIC_COND_TYPE_AND != pCond->condType) {
|
|
return TSDB_CODE_SUCCESS;
|
|
}
|
|
|
|
SNode* pNode = NULL;
|
|
FOREACH(pNode, pCond->pParameterList) {
|
|
int32_t code = getInsTagsTableTargetObjName(acctId, pNode, pName);
|
|
if (TSDB_CODE_SUCCESS != code) {
|
|
return code;
|
|
}
|
|
}
|
|
if ('\0' == pName->dbname[0]) {
|
|
pName->type = 0;
|
|
}
|
|
return TSDB_CODE_SUCCESS;
|
|
}
|
|
|
|
int32_t getVnodeSysTableTargetName(int32_t acctId, SNode* pWhere, SName* pName) {
|
|
if (NULL == pWhere) {
|
|
return TSDB_CODE_SUCCESS;
|
|
}
|
|
|
|
if (QUERY_NODE_OPERATOR == nodeType(pWhere)) {
|
|
int32_t code = getInsTagsTableTargetNameFromOp(acctId, (SOperatorNode*)pWhere, pName);
|
|
if (TSDB_CODE_SUCCESS == code && '\0' == pName->dbname[0]) {
|
|
pName->type = 0;
|
|
}
|
|
return code;
|
|
}
|
|
|
|
if (QUERY_NODE_LOGIC_CONDITION == nodeType(pWhere)) {
|
|
return getInsTagsTableTargetNameFromCond(acctId, (SLogicConditionNode*)pWhere, pName);
|
|
}
|
|
|
|
return TSDB_CODE_SUCCESS;
|
|
}
|
|
|
|
static int32_t userAuthToString(int32_t acctId, const char* pUser, const char* pDb, const char* pTable, AUTH_TYPE type,
|
|
char* pStr, bool isView) {
|
|
return sprintf(pStr, "%s*%d*%s*%s*%d*%d", pUser, acctId, pDb, (NULL == pTable || '\0' == pTable[0]) ? "``" : pTable,
|
|
type, isView);
|
|
}
|
|
|
|
static int32_t getIntegerFromAuthStr(const char* pStart, char** pNext) {
|
|
char* p = strchr(pStart, '*');
|
|
char buf[10] = {0};
|
|
if (NULL == p) {
|
|
strcpy(buf, pStart);
|
|
*pNext = NULL;
|
|
} else {
|
|
strncpy(buf, pStart, p - pStart);
|
|
*pNext = ++p;
|
|
}
|
|
return taosStr2Int32(buf, NULL, 10);
|
|
}
|
|
|
|
static void getStringFromAuthStr(const char* pStart, char* pStr, char** pNext) {
|
|
char* p = strchr(pStart, '*');
|
|
if (NULL == p) {
|
|
strcpy(pStr, pStart);
|
|
*pNext = NULL;
|
|
} else {
|
|
strncpy(pStr, pStart, p - pStart);
|
|
*pNext = ++p;
|
|
}
|
|
if (*pStart == '`' && *(pStart + 1) == '`') {
|
|
*pStr = 0;
|
|
}
|
|
}
|
|
|
|
static void stringToUserAuth(const char* pStr, int32_t len, SUserAuthInfo* pUserAuth) {
|
|
char* p = NULL;
|
|
getStringFromAuthStr(pStr, pUserAuth->user, &p);
|
|
pUserAuth->tbName.acctId = getIntegerFromAuthStr(p, &p);
|
|
getStringFromAuthStr(p, pUserAuth->tbName.dbname, &p);
|
|
getStringFromAuthStr(p, pUserAuth->tbName.tname, &p);
|
|
if (pUserAuth->tbName.tname[0]) {
|
|
pUserAuth->tbName.type = TSDB_TABLE_NAME_T;
|
|
} else {
|
|
pUserAuth->tbName.type = TSDB_DB_NAME_T;
|
|
}
|
|
pUserAuth->type = getIntegerFromAuthStr(p, &p);
|
|
pUserAuth->isView = getIntegerFromAuthStr(p, &p);
|
|
}
|
|
|
|
static int32_t buildTableReq(SHashObj* pTablesHash, SArray** pTables) {
|
|
if (NULL != pTablesHash) {
|
|
*pTables = taosArrayInit(taosHashGetSize(pTablesHash), sizeof(SName));
|
|
if (NULL == *pTables) {
|
|
return terrno;
|
|
}
|
|
void* p = taosHashIterate(pTablesHash, NULL);
|
|
while (NULL != p) {
|
|
size_t len = 0;
|
|
char* pKey = taosHashGetKey(p, &len);
|
|
char fullName[TSDB_TABLE_FNAME_LEN] = {0};
|
|
strncpy(fullName, pKey, len);
|
|
SName name = {0};
|
|
int32_t code = tNameFromString(&name, fullName, T_NAME_ACCT | T_NAME_DB | T_NAME_TABLE);
|
|
if (TSDB_CODE_SUCCESS == code) {
|
|
if (NULL == taosArrayPush(*pTables, &name)) {
|
|
code = terrno;
|
|
}
|
|
}
|
|
if (TSDB_CODE_SUCCESS != code) {
|
|
taosHashCancelIterate(pTablesHash, p);
|
|
taosArrayDestroy(*pTables);
|
|
*pTables = NULL;
|
|
return code;
|
|
}
|
|
p = taosHashIterate(pTablesHash, p);
|
|
}
|
|
}
|
|
return TSDB_CODE_SUCCESS;
|
|
}
|
|
|
|
static int32_t buildDbReq(SHashObj* pDbsHash, SArray** pDbs) {
|
|
if (NULL != pDbsHash) {
|
|
*pDbs = taosArrayInit(taosHashGetSize(pDbsHash), TSDB_DB_FNAME_LEN);
|
|
if (NULL == *pDbs) {
|
|
return terrno;
|
|
}
|
|
void* p = taosHashIterate(pDbsHash, NULL);
|
|
while (NULL != p) {
|
|
size_t len = 0;
|
|
char* pKey = taosHashGetKey(p, &len);
|
|
char fullName[TSDB_DB_FNAME_LEN] = {0};
|
|
strncpy(fullName, pKey, len);
|
|
if (NULL == taosArrayPush(*pDbs, fullName)) {
|
|
taosHashCancelIterate(pDbsHash, p);
|
|
taosArrayDestroy(*pDbs);
|
|
*pDbs = NULL;
|
|
return terrno;
|
|
}
|
|
p = taosHashIterate(pDbsHash, p);
|
|
}
|
|
}
|
|
return TSDB_CODE_SUCCESS;
|
|
}
|
|
|
|
static int32_t buildTableReqFromDb(SHashObj* pDbsHash, SArray** pDbs) {
|
|
if (NULL != pDbsHash) {
|
|
if (NULL == *pDbs) {
|
|
*pDbs = taosArrayInit(taosHashGetSize(pDbsHash), sizeof(STablesReq));
|
|
if (NULL == *pDbs) {
|
|
return terrno;
|
|
}
|
|
}
|
|
SParseTablesMetaReq* p = taosHashIterate(pDbsHash, NULL);
|
|
while (NULL != p) {
|
|
STablesReq req = {0};
|
|
strcpy(req.dbFName, p->dbFName);
|
|
int32_t code = buildTableReq(p->pTables, &req.pTables);
|
|
if (TSDB_CODE_SUCCESS == code) {
|
|
if (NULL == taosArrayPush(*pDbs, &req)) {
|
|
code = terrno;
|
|
}
|
|
}
|
|
if (TSDB_CODE_SUCCESS != code) {
|
|
taosHashCancelIterate(pDbsHash, p);
|
|
taosArrayDestroy(*pDbs);
|
|
*pDbs = NULL;
|
|
return code;
|
|
}
|
|
p = taosHashIterate(pDbsHash, p);
|
|
}
|
|
}
|
|
return TSDB_CODE_SUCCESS;
|
|
}
|
|
|
|
static int32_t buildUserAuthReq(SHashObj* pUserAuthHash, SArray** pUserAuth) {
|
|
if (NULL != pUserAuthHash) {
|
|
*pUserAuth = taosArrayInit(taosHashGetSize(pUserAuthHash), sizeof(SUserAuthInfo));
|
|
if (NULL == *pUserAuth) {
|
|
return terrno;
|
|
}
|
|
void* p = taosHashIterate(pUserAuthHash, NULL);
|
|
while (NULL != p) {
|
|
size_t len = 0;
|
|
char* pKey = taosHashGetKey(p, &len);
|
|
char key[USER_AUTH_KEY_MAX_LEN] = {0};
|
|
strncpy(key, pKey, len);
|
|
SUserAuthInfo userAuth = {0};
|
|
stringToUserAuth(key, len, &userAuth);
|
|
if (NULL == taosArrayPush(*pUserAuth, &userAuth)) {
|
|
taosHashCancelIterate(pUserAuthHash, p);
|
|
taosArrayDestroy(*pUserAuth);
|
|
*pUserAuth = NULL;
|
|
return terrno;
|
|
}
|
|
p = taosHashIterate(pUserAuthHash, p);
|
|
}
|
|
}
|
|
return TSDB_CODE_SUCCESS;
|
|
}
|
|
|
|
static int32_t buildUdfReq(SHashObj* pUdfHash, SArray** pUdf) {
|
|
if (NULL != pUdfHash) {
|
|
*pUdf = taosArrayInit(taosHashGetSize(pUdfHash), TSDB_FUNC_NAME_LEN);
|
|
if (NULL == *pUdf) {
|
|
return terrno;
|
|
}
|
|
void* p = taosHashIterate(pUdfHash, NULL);
|
|
while (NULL != p) {
|
|
size_t len = 0;
|
|
char* pFunc = taosHashGetKey(p, &len);
|
|
char func[TSDB_FUNC_NAME_LEN] = {0};
|
|
strncpy(func, pFunc, len);
|
|
if (NULL == taosArrayPush(*pUdf, func)) {
|
|
taosHashCancelIterate(pUdfHash, p);
|
|
taosArrayDestroy(*pUdf);
|
|
*pUdf = NULL;
|
|
return terrno;
|
|
}
|
|
p = taosHashIterate(pUdfHash, p);
|
|
}
|
|
}
|
|
return TSDB_CODE_SUCCESS;
|
|
}
|
|
|
|
int32_t buildCatalogReq(const SParseMetaCache* pMetaCache, SCatalogReq* pCatalogReq) {
|
|
int32_t code = buildTableReqFromDb(pMetaCache->pTableMeta, &pCatalogReq->pTableMeta);
|
|
if (TSDB_CODE_SUCCESS == code) {
|
|
code = buildDbReq(pMetaCache->pDbVgroup, &pCatalogReq->pDbVgroup);
|
|
}
|
|
if (TSDB_CODE_SUCCESS == code) {
|
|
code = buildTableReqFromDb(pMetaCache->pTableVgroup, &pCatalogReq->pTableHash);
|
|
}
|
|
if (TSDB_CODE_SUCCESS == code) {
|
|
code = buildDbReq(pMetaCache->pDbCfg, &pCatalogReq->pDbCfg);
|
|
}
|
|
if (TSDB_CODE_SUCCESS == code) {
|
|
code = buildDbReq(pMetaCache->pDbInfo, &pCatalogReq->pDbInfo);
|
|
}
|
|
if (TSDB_CODE_SUCCESS == code) {
|
|
code = buildUserAuthReq(pMetaCache->pUserAuth, &pCatalogReq->pUser);
|
|
}
|
|
if (TSDB_CODE_SUCCESS == code) {
|
|
code = buildUdfReq(pMetaCache->pUdf, &pCatalogReq->pUdf);
|
|
}
|
|
if (TSDB_CODE_SUCCESS == code) {
|
|
code = buildTableReq(pMetaCache->pTableIndex, &pCatalogReq->pTableIndex);
|
|
}
|
|
if (TSDB_CODE_SUCCESS == code) {
|
|
code = buildTableReq(pMetaCache->pTableCfg, &pCatalogReq->pTableCfg);
|
|
}
|
|
if (TSDB_CODE_SUCCESS == code) {
|
|
code = buildTableReqFromDb(pMetaCache->pTableMeta, &pCatalogReq->pTableTSMAs);
|
|
}
|
|
if (TSDB_CODE_SUCCESS == code) {
|
|
code = buildTableReqFromDb(pMetaCache->pTSMAs, &pCatalogReq->pTSMAs);
|
|
}
|
|
if (TSDB_CODE_SUCCESS == code) {
|
|
code = buildTableReqFromDb(pMetaCache->pTableName, &pCatalogReq->pTableName);
|
|
}
|
|
#ifdef TD_ENTERPRISE
|
|
if (TSDB_CODE_SUCCESS == code) {
|
|
code = buildTableReqFromDb(pMetaCache->pTableMeta, &pCatalogReq->pView);
|
|
}
|
|
#endif
|
|
pCatalogReq->dNodeRequired = pMetaCache->dnodeRequired;
|
|
pCatalogReq->forceFetchViewMeta = pMetaCache->forceFetchViewMeta;
|
|
return code;
|
|
}
|
|
|
|
int32_t createSelectStmtImpl(bool isDistinct, SNodeList* pProjectionList, SNode* pTable, SNodeList* pHint,
|
|
SNode** ppSelect) {
|
|
SSelectStmt* select = NULL;
|
|
int32_t code = nodesMakeNode(QUERY_NODE_SELECT_STMT, (SNode**)&select);
|
|
if (NULL == select) {
|
|
return code;
|
|
}
|
|
select->isDistinct = isDistinct;
|
|
select->pProjectionList = pProjectionList;
|
|
select->pFromTable = pTable;
|
|
sprintf(select->stmtName, "%p", select);
|
|
select->timeLineResMode = select->isDistinct ? TIME_LINE_NONE : TIME_LINE_GLOBAL;
|
|
select->timeLineCurMode = TIME_LINE_GLOBAL;
|
|
select->onlyHasKeepOrderFunc = true;
|
|
select->timeRange = TSWINDOW_INITIALIZER;
|
|
select->pHint = pHint;
|
|
select->lastProcessByRowFuncId = -1;
|
|
*ppSelect = (SNode*)select;
|
|
return code;
|
|
}
|
|
|
|
static int32_t putMetaDataToHash(const char* pKey, int32_t len, const SArray* pData, int32_t index, SHashObj** pHash) {
|
|
if (NULL == *pHash) {
|
|
*pHash = taosHashInit(4, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
|
|
if (NULL == *pHash) {
|
|
return terrno;
|
|
}
|
|
}
|
|
SMetaRes* pRes = taosArrayGet(pData, index);
|
|
return taosHashPut(*pHash, pKey, len, &pRes, POINTER_BYTES);
|
|
}
|
|
|
|
int32_t getMetaDataFromHash(const char* pKey, int32_t len, SHashObj* pHash, void** pOutput) {
|
|
SMetaRes** pRes = taosHashGet(pHash, pKey, len);
|
|
if (NULL == pRes || NULL == *pRes) {
|
|
return TSDB_CODE_PAR_INTERNAL_ERROR;
|
|
}
|
|
if (TSDB_CODE_SUCCESS == (*pRes)->code) {
|
|
*pOutput = (*pRes)->pRes;
|
|
}
|
|
return (*pRes)->code;
|
|
}
|
|
|
|
static int32_t putTableDataToCache(const SArray* pTableReq, const SArray* pTableData, SHashObj** pTable) {
|
|
int32_t ntables = taosArrayGetSize(pTableReq);
|
|
for (int32_t i = 0; i < ntables; ++i) {
|
|
char fullName[TSDB_TABLE_FNAME_LEN];
|
|
int32_t code = tNameExtractFullName(taosArrayGet(pTableReq, i), fullName);
|
|
if (TSDB_CODE_SUCCESS != code) {
|
|
return code;
|
|
}
|
|
if (TSDB_CODE_SUCCESS != putMetaDataToHash(fullName, strlen(fullName), pTableData, i, pTable)) {
|
|
return TSDB_CODE_OUT_OF_MEMORY;
|
|
}
|
|
}
|
|
return TSDB_CODE_SUCCESS;
|
|
}
|
|
|
|
static int32_t putDbDataToCache(const SArray* pDbReq, const SArray* pDbData, SHashObj** pDb) {
|
|
int32_t nvgs = taosArrayGetSize(pDbReq);
|
|
for (int32_t i = 0; i < nvgs; ++i) {
|
|
char* pDbFName = taosArrayGet(pDbReq, i);
|
|
if (TSDB_CODE_SUCCESS != putMetaDataToHash(pDbFName, strlen(pDbFName), pDbData, i, pDb)) {
|
|
return TSDB_CODE_OUT_OF_MEMORY;
|
|
}
|
|
}
|
|
return TSDB_CODE_SUCCESS;
|
|
}
|
|
|
|
static int32_t putDbTableDataToCache(const SArray* pDbReq, const SArray* pTableData, SHashObj** pTable) {
|
|
if (!pTableData || pTableData->size == 0) return TSDB_CODE_SUCCESS;
|
|
int32_t ndbs = taosArrayGetSize(pDbReq);
|
|
int32_t tableNo = 0;
|
|
for (int32_t i = 0; i < ndbs; ++i) {
|
|
STablesReq* pReq = taosArrayGet(pDbReq, i);
|
|
int32_t ntables = taosArrayGetSize(pReq->pTables);
|
|
for (int32_t j = 0; j < ntables; ++j) {
|
|
char fullName[TSDB_TABLE_FNAME_LEN];
|
|
int32_t code = tNameExtractFullName(taosArrayGet(pReq->pTables, j), fullName);
|
|
if (TSDB_CODE_SUCCESS != code) {
|
|
return code;
|
|
}
|
|
if (TSDB_CODE_SUCCESS != putMetaDataToHash(fullName, strlen(fullName), pTableData, tableNo, pTable)) {
|
|
return TSDB_CODE_OUT_OF_MEMORY;
|
|
}
|
|
++tableNo;
|
|
}
|
|
}
|
|
return TSDB_CODE_SUCCESS;
|
|
}
|
|
|
|
static int32_t putUserAuthToCache(const SArray* pUserAuthReq, const SArray* pUserAuthData, SHashObj** pUserAuth) {
|
|
int32_t nvgs = taosArrayGetSize(pUserAuthReq);
|
|
for (int32_t i = 0; i < nvgs; ++i) {
|
|
SUserAuthInfo* pUser = taosArrayGet(pUserAuthReq, i);
|
|
char key[USER_AUTH_KEY_MAX_LEN] = {0};
|
|
int32_t len = userAuthToString(pUser->tbName.acctId, pUser->user, pUser->tbName.dbname, pUser->tbName.tname,
|
|
pUser->type, key, pUser->isView);
|
|
if (TSDB_CODE_SUCCESS != putMetaDataToHash(key, len, pUserAuthData, i, pUserAuth)) {
|
|
return TSDB_CODE_OUT_OF_MEMORY;
|
|
}
|
|
}
|
|
return TSDB_CODE_SUCCESS;
|
|
}
|
|
|
|
static int32_t putUdfToCache(const SArray* pUdfReq, const SArray* pUdfData, SHashObj** pUdf) {
|
|
int32_t num = taosArrayGetSize(pUdfReq);
|
|
for (int32_t i = 0; i < num; ++i) {
|
|
char* pFunc = taosArrayGet(pUdfReq, i);
|
|
if (TSDB_CODE_SUCCESS != putMetaDataToHash(pFunc, strlen(pFunc), pUdfData, i, pUdf)) {
|
|
return TSDB_CODE_OUT_OF_MEMORY;
|
|
}
|
|
}
|
|
return TSDB_CODE_SUCCESS;
|
|
}
|
|
|
|
int32_t putMetaDataToCache(const SCatalogReq* pCatalogReq, const SMetaData* pMetaData, SParseMetaCache* pMetaCache) {
|
|
int32_t code = putDbTableDataToCache(pCatalogReq->pTableMeta, pMetaData->pTableMeta, &pMetaCache->pTableMeta);
|
|
if (TSDB_CODE_SUCCESS == code) {
|
|
code = putDbDataToCache(pCatalogReq->pDbVgroup, pMetaData->pDbVgroup, &pMetaCache->pDbVgroup);
|
|
}
|
|
if (TSDB_CODE_SUCCESS == code) {
|
|
code = putDbTableDataToCache(pCatalogReq->pTableHash, pMetaData->pTableHash, &pMetaCache->pTableVgroup);
|
|
}
|
|
if (TSDB_CODE_SUCCESS == code) {
|
|
code = putDbDataToCache(pCatalogReq->pDbCfg, pMetaData->pDbCfg, &pMetaCache->pDbCfg);
|
|
}
|
|
if (TSDB_CODE_SUCCESS == code) {
|
|
code = putDbDataToCache(pCatalogReq->pDbInfo, pMetaData->pDbInfo, &pMetaCache->pDbInfo);
|
|
}
|
|
if (TSDB_CODE_SUCCESS == code) {
|
|
code = putUserAuthToCache(pCatalogReq->pUser, pMetaData->pUser, &pMetaCache->pUserAuth);
|
|
}
|
|
if (TSDB_CODE_SUCCESS == code) {
|
|
code = putUdfToCache(pCatalogReq->pUdf, pMetaData->pUdfList, &pMetaCache->pUdf);
|
|
}
|
|
if (TSDB_CODE_SUCCESS == code) {
|
|
code = putTableDataToCache(pCatalogReq->pTableIndex, pMetaData->pTableIndex, &pMetaCache->pTableIndex);
|
|
}
|
|
if (TSDB_CODE_SUCCESS == code) {
|
|
code = putTableDataToCache(pCatalogReq->pTableCfg, pMetaData->pTableCfg, &pMetaCache->pTableCfg);
|
|
}
|
|
if (TSDB_CODE_SUCCESS == code) {
|
|
code = putDbTableDataToCache(pCatalogReq->pTableTSMAs, pMetaData->pTableTsmas, &pMetaCache->pTableTSMAs);
|
|
}
|
|
if (TSDB_CODE_SUCCESS == code) {
|
|
code = putDbTableDataToCache(pCatalogReq->pTSMAs, pMetaData->pTsmas, &pMetaCache->pTSMAs);
|
|
}
|
|
if (TSDB_CODE_SUCCESS == code) {
|
|
code = putDbTableDataToCache(pCatalogReq->pTableName, pMetaData->pTableMeta, &pMetaCache->pTableName);
|
|
}
|
|
#ifdef TD_ENTERPRISE
|
|
if (TSDB_CODE_SUCCESS == code) {
|
|
code = putDbTableDataToCache(pCatalogReq->pView, pMetaData->pView, &pMetaCache->pViews);
|
|
}
|
|
#endif
|
|
pMetaCache->pDnodes = pMetaData->pDnodeList;
|
|
return code;
|
|
}
|
|
|
|
static int32_t reserveTableReqInCacheImpl(const char* pTbFName, int32_t len, SHashObj** pTables) {
|
|
if (NULL == *pTables) {
|
|
*pTables = taosHashInit(4, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
|
|
if (NULL == *pTables) {
|
|
return terrno;
|
|
}
|
|
}
|
|
return taosHashPut(*pTables, pTbFName, len, &nullPointer, POINTER_BYTES);
|
|
}
|
|
|
|
static int32_t reserveTableReqInCache(int32_t acctId, const char* pDb, const char* pTable, SHashObj** pTables) {
|
|
char fullName[TSDB_TABLE_FNAME_LEN];
|
|
int32_t len = tsnprintf(fullName, sizeof(fullName), "%d.%s.%s", acctId, pDb, pTable);
|
|
return reserveTableReqInCacheImpl(fullName, len, pTables);
|
|
}
|
|
|
|
static int32_t reserveTableReqInDbCacheImpl(int32_t acctId, const char* pDb, const char* pTable, SHashObj* pDbs) {
|
|
SParseTablesMetaReq req = {0};
|
|
int32_t len = tsnprintf(req.dbFName, sizeof(req.dbFName), "%d.%s", acctId, pDb);
|
|
int32_t code = reserveTableReqInCache(acctId, pDb, pTable, &req.pTables);
|
|
if (TSDB_CODE_SUCCESS == code) {
|
|
code = taosHashPut(pDbs, req.dbFName, len, &req, sizeof(SParseTablesMetaReq));
|
|
}
|
|
return code;
|
|
}
|
|
|
|
static int32_t reserveTableReqInDbCache(int32_t acctId, const char* pDb, const char* pTable, SHashObj** pDbs) {
|
|
if (NULL == *pDbs) {
|
|
*pDbs = taosHashInit(4, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
|
|
if (NULL == *pDbs) {
|
|
return terrno;
|
|
}
|
|
}
|
|
char fullName[TSDB_DB_FNAME_LEN];
|
|
int32_t len = tsnprintf(fullName, sizeof(fullName), "%d.%s", acctId, pDb);
|
|
SParseTablesMetaReq* pReq = taosHashGet(*pDbs, fullName, len);
|
|
if (NULL == pReq) {
|
|
return reserveTableReqInDbCacheImpl(acctId, pDb, pTable, *pDbs);
|
|
}
|
|
return reserveTableReqInCache(acctId, pDb, pTable, &pReq->pTables);
|
|
}
|
|
|
|
int32_t reserveTableMetaInCache(int32_t acctId, const char* pDb, const char* pTable, SParseMetaCache* pMetaCache) {
|
|
return reserveTableReqInDbCache(acctId, pDb, pTable, &pMetaCache->pTableMeta);
|
|
}
|
|
|
|
int32_t reserveTableMetaInCacheExt(const SName* pName, SParseMetaCache* pMetaCache) {
|
|
return reserveTableReqInDbCache(pName->acctId, pName->dbname, pName->tname, &pMetaCache->pTableMeta);
|
|
}
|
|
|
|
int32_t reserveTableUidInCache(int32_t acctId, const char* pDb, const char* pTable, SParseMetaCache* pMetaCache) {
|
|
return reserveTableReqInDbCache(acctId, pDb, pTable, &pMetaCache->pTableName);
|
|
}
|
|
|
|
int32_t getTableMetaFromCache(SParseMetaCache* pMetaCache, const SName* pName, STableMeta** pMeta) {
|
|
char fullName[TSDB_TABLE_FNAME_LEN];
|
|
int32_t code = tNameExtractFullName(pName, fullName);
|
|
if (TSDB_CODE_SUCCESS != code) {
|
|
return code;
|
|
}
|
|
STableMeta* pTableMeta = NULL;
|
|
code = getMetaDataFromHash(fullName, strlen(fullName), pMetaCache->pTableMeta, (void**)&pTableMeta);
|
|
if (TSDB_CODE_SUCCESS == code) {
|
|
*pMeta = tableMetaDup(pTableMeta);
|
|
if (NULL == *pMeta) {
|
|
code = TSDB_CODE_OUT_OF_MEMORY;
|
|
}
|
|
}
|
|
return code;
|
|
}
|
|
|
|
int32_t getTableNameFromCache(SParseMetaCache* pMetaCache, const SName* pName, char* pTbName) {
|
|
char fullName[TSDB_TABLE_FNAME_LEN];
|
|
int32_t code = tNameExtractFullName(pName, fullName);
|
|
if (TSDB_CODE_SUCCESS != code) {
|
|
return code;
|
|
}
|
|
const STableMeta* pMeta = NULL;
|
|
code = getMetaDataFromHash(fullName, strlen(fullName), pMetaCache->pTableName, (void**)&pMeta);
|
|
if (TSDB_CODE_SUCCESS == code) {
|
|
if (!pMeta) code = TSDB_CODE_PAR_INTERNAL_ERROR;
|
|
int32_t metaSize =
|
|
sizeof(STableMeta) + sizeof(SSchema) * (pMeta->tableInfo.numOfColumns + pMeta->tableInfo.numOfTags);
|
|
int32_t schemaExtSize =
|
|
(useCompress(pMeta->tableType) && pMeta->schemaExt) ? sizeof(SSchemaExt) * pMeta->tableInfo.numOfColumns : 0;
|
|
const char* pTableName = (const char*)pMeta + metaSize + schemaExtSize;
|
|
tstrncpy(pTbName, pTableName, TSDB_TABLE_NAME_LEN);
|
|
}
|
|
|
|
return code;
|
|
}
|
|
|
|
int32_t buildTableMetaFromViewMeta(STableMeta** pMeta, SViewMeta* pViewMeta) {
|
|
*pMeta = taosMemoryCalloc(1, sizeof(STableMeta) + pViewMeta->numOfCols * sizeof(SSchema));
|
|
if (NULL == *pMeta) {
|
|
return terrno;
|
|
}
|
|
(*pMeta)->uid = pViewMeta->viewId;
|
|
(*pMeta)->vgId = MNODE_HANDLE;
|
|
(*pMeta)->tableType = TSDB_VIEW_TABLE;
|
|
(*pMeta)->sversion = pViewMeta->version;
|
|
(*pMeta)->tversion = pViewMeta->version;
|
|
(*pMeta)->tableInfo.precision = pViewMeta->precision;
|
|
(*pMeta)->tableInfo.numOfColumns = pViewMeta->numOfCols;
|
|
memcpy((*pMeta)->schema, pViewMeta->pSchema, sizeof(SSchema) * pViewMeta->numOfCols);
|
|
|
|
for (int32_t i = 0; i < pViewMeta->numOfCols; ++i) {
|
|
(*pMeta)->tableInfo.rowSize += (*pMeta)->schema[i].bytes;
|
|
}
|
|
return TSDB_CODE_SUCCESS;
|
|
}
|
|
|
|
int32_t getViewMetaFromCache(SParseMetaCache* pMetaCache, const SName* pName, STableMeta** pMeta) {
|
|
char fullName[TSDB_TABLE_FNAME_LEN];
|
|
int32_t code = tNameExtractFullName(pName, fullName);
|
|
if (TSDB_CODE_SUCCESS != code) {
|
|
return code;
|
|
}
|
|
SViewMeta* pViewMeta = NULL;
|
|
code = getMetaDataFromHash(fullName, strlen(fullName), pMetaCache->pViews, (void**)&pViewMeta);
|
|
if (TSDB_CODE_SUCCESS == code) {
|
|
code = buildTableMetaFromViewMeta(pMeta, pViewMeta);
|
|
}
|
|
return code;
|
|
}
|
|
|
|
static int32_t reserveDbReqInCache(int32_t acctId, const char* pDb, SHashObj** pDbs) {
|
|
if (NULL == *pDbs) {
|
|
*pDbs = taosHashInit(4, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
|
|
if (NULL == *pDbs) {
|
|
return terrno;
|
|
}
|
|
}
|
|
char fullName[TSDB_TABLE_FNAME_LEN];
|
|
int32_t len = tsnprintf(fullName, sizeof(fullName), "%d.%s", acctId, pDb);
|
|
return taosHashPut(*pDbs, fullName, len, &nullPointer, POINTER_BYTES);
|
|
}
|
|
|
|
int32_t reserveDbVgInfoInCache(int32_t acctId, const char* pDb, SParseMetaCache* pMetaCache) {
|
|
return reserveDbReqInCache(acctId, pDb, &pMetaCache->pDbVgroup);
|
|
}
|
|
|
|
int32_t getDbVgInfoFromCache(SParseMetaCache* pMetaCache, const char* pDbFName, SArray** pVgInfo) {
|
|
SArray* pVgList = NULL;
|
|
int32_t code = getMetaDataFromHash(pDbFName, strlen(pDbFName), pMetaCache->pDbVgroup, (void**)&pVgList);
|
|
// pVgList is null, which is a legal value, indicating that the user DB has not been created
|
|
if (TSDB_CODE_SUCCESS == code && NULL != pVgList) {
|
|
*pVgInfo = taosArrayDup(pVgList, NULL);
|
|
if (NULL == *pVgInfo) {
|
|
code = terrno;
|
|
}
|
|
}
|
|
return code;
|
|
}
|
|
|
|
int32_t reserveTableVgroupInCache(int32_t acctId, const char* pDb, const char* pTable, SParseMetaCache* pMetaCache) {
|
|
return reserveTableReqInDbCache(acctId, pDb, pTable, &pMetaCache->pTableVgroup);
|
|
}
|
|
|
|
int32_t reserveTableVgroupInCacheExt(const SName* pName, SParseMetaCache* pMetaCache) {
|
|
return reserveTableReqInDbCache(pName->acctId, pName->dbname, pName->tname, &pMetaCache->pTableVgroup);
|
|
}
|
|
|
|
int32_t getTableVgroupFromCache(SParseMetaCache* pMetaCache, const SName* pName, SVgroupInfo* pVgroup) {
|
|
char fullName[TSDB_TABLE_FNAME_LEN];
|
|
int32_t code = tNameExtractFullName(pName, fullName);
|
|
if (TSDB_CODE_SUCCESS != code) {
|
|
return code;
|
|
}
|
|
SVgroupInfo* pVg = NULL;
|
|
code = getMetaDataFromHash(fullName, strlen(fullName), pMetaCache->pTableVgroup, (void**)&pVg);
|
|
if (TSDB_CODE_SUCCESS == code) {
|
|
memcpy(pVgroup, pVg, sizeof(SVgroupInfo));
|
|
}
|
|
return code;
|
|
}
|
|
|
|
int32_t getDbTableVgroupFromCache(SParseMetaCache* pMetaCache, const SName* pName, SVgroupInfo* pVgroup) {
|
|
char fullName[TSDB_TABLE_FNAME_LEN];
|
|
int32_t code = tNameExtractFullName(pName, fullName);
|
|
if (TSDB_CODE_SUCCESS != code) {
|
|
return code;
|
|
}
|
|
const char* pDb = strstr(fullName, ".");
|
|
if (pDb == NULL) return TSDB_CODE_PAR_INTERNAL_ERROR;
|
|
pDb = strstr(pDb + 1, ".");
|
|
if (pDb == NULL) return TSDB_CODE_PAR_INTERNAL_ERROR;
|
|
int32_t fullDbLen = pDb - fullName;
|
|
int32_t fullTbLen = strlen(fullName);
|
|
|
|
SArray* pVgArray = NULL;
|
|
SDbCfgInfo* pDbCfg = NULL;
|
|
code = getMetaDataFromHash(fullName, fullDbLen, pMetaCache->pDbVgroup, (void**)&pVgArray);
|
|
if (TSDB_CODE_SUCCESS == code) {
|
|
code = getMetaDataFromHash(fullName, fullDbLen, pMetaCache->pDbCfg, (void**)&pDbCfg);
|
|
}
|
|
if (TSDB_CODE_SUCCESS == code) {
|
|
uint32_t hashValue =
|
|
taosGetTbHashVal(fullName, fullTbLen, pDbCfg->hashMethod, pDbCfg->hashPrefix, pDbCfg->hashSuffix);
|
|
SVgroupInfo* pVg = taosArraySearch(pVgArray, &hashValue, ctgHashValueComp, TD_EQ);
|
|
if (pVg) {
|
|
memcpy(pVgroup, pVg, sizeof(SVgroupInfo));
|
|
} else {
|
|
code = TSDB_CODE_PAR_INTERNAL_ERROR;
|
|
}
|
|
}
|
|
return code;
|
|
}
|
|
|
|
int32_t reserveDbVgVersionInCache(int32_t acctId, const char* pDb, SParseMetaCache* pMetaCache) {
|
|
return reserveDbReqInCache(acctId, pDb, &pMetaCache->pDbInfo);
|
|
}
|
|
|
|
int32_t getDbVgVersionFromCache(SParseMetaCache* pMetaCache, const char* pDbFName, int32_t* pVersion, int64_t* pDbId,
|
|
int32_t* pTableNum, int64_t* pStateTs) {
|
|
SDbInfo* pDbInfo = NULL;
|
|
int32_t code = getMetaDataFromHash(pDbFName, strlen(pDbFName), pMetaCache->pDbInfo, (void**)&pDbInfo);
|
|
if (TSDB_CODE_SUCCESS == code) {
|
|
*pVersion = pDbInfo->vgVer;
|
|
*pDbId = pDbInfo->dbId;
|
|
*pTableNum = pDbInfo->tbNum;
|
|
*pStateTs = pDbInfo->stateTs;
|
|
}
|
|
return code;
|
|
}
|
|
|
|
int32_t reserveDbCfgInCache(int32_t acctId, const char* pDb, SParseMetaCache* pMetaCache) {
|
|
return reserveDbReqInCache(acctId, pDb, &pMetaCache->pDbCfg);
|
|
}
|
|
|
|
int32_t getDbCfgFromCache(SParseMetaCache* pMetaCache, const char* pDbFName, SDbCfgInfo* pInfo) {
|
|
SDbCfgInfo* pDbCfg = NULL;
|
|
int32_t code = getMetaDataFromHash(pDbFName, strlen(pDbFName), pMetaCache->pDbCfg, (void**)&pDbCfg);
|
|
if (TSDB_CODE_SUCCESS == code) {
|
|
memcpy(pInfo, pDbCfg, sizeof(SDbCfgInfo));
|
|
}
|
|
return code;
|
|
}
|
|
|
|
static int32_t reserveUserAuthInCacheImpl(const char* pKey, int32_t len, SParseMetaCache* pMetaCache) {
|
|
if (NULL == pMetaCache->pUserAuth) {
|
|
pMetaCache->pUserAuth = taosHashInit(4, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
|
|
if (NULL == pMetaCache->pUserAuth) {
|
|
return terrno;
|
|
}
|
|
}
|
|
return taosHashPut(pMetaCache->pUserAuth, pKey, len, &nullPointer, POINTER_BYTES);
|
|
}
|
|
|
|
int32_t reserveUserAuthInCache(int32_t acctId, const char* pUser, const char* pDb, const char* pTable, AUTH_TYPE type,
|
|
SParseMetaCache* pMetaCache) {
|
|
char key[USER_AUTH_KEY_MAX_LEN] = {0};
|
|
int32_t len = userAuthToString(acctId, pUser, pDb, pTable, type, key, false);
|
|
return reserveUserAuthInCacheImpl(key, len, pMetaCache);
|
|
}
|
|
|
|
int32_t reserveViewUserAuthInCache(int32_t acctId, const char* pUser, const char* pDb, const char* pTable,
|
|
AUTH_TYPE type, SParseMetaCache* pMetaCache) {
|
|
char key[USER_AUTH_KEY_MAX_LEN] = {0};
|
|
int32_t len = userAuthToString(acctId, pUser, pDb, pTable, type, key, true);
|
|
return reserveUserAuthInCacheImpl(key, len, pMetaCache);
|
|
}
|
|
|
|
int32_t getUserAuthFromCache(SParseMetaCache* pMetaCache, SUserAuthInfo* pAuthReq, SUserAuthRes* pAuthRes) {
|
|
char key[USER_AUTH_KEY_MAX_LEN] = {0};
|
|
int32_t len = userAuthToString(pAuthReq->tbName.acctId, pAuthReq->user, pAuthReq->tbName.dbname,
|
|
pAuthReq->tbName.tname, pAuthReq->type, key, pAuthReq->isView);
|
|
SUserAuthRes* pAuth = NULL;
|
|
int32_t code = getMetaDataFromHash(key, len, pMetaCache->pUserAuth, (void**)&pAuth);
|
|
if (TSDB_CODE_SUCCESS == code) {
|
|
memcpy(pAuthRes, pAuth, sizeof(SUserAuthRes));
|
|
}
|
|
return code;
|
|
}
|
|
|
|
int32_t reserveUdfInCache(const char* pFunc, SParseMetaCache* pMetaCache) {
|
|
if (NULL == pMetaCache->pUdf) {
|
|
pMetaCache->pUdf = taosHashInit(4, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
|
|
if (NULL == pMetaCache->pUdf) {
|
|
return terrno;
|
|
}
|
|
}
|
|
return taosHashPut(pMetaCache->pUdf, pFunc, strlen(pFunc), &nullPointer, POINTER_BYTES);
|
|
}
|
|
|
|
int32_t getUdfInfoFromCache(SParseMetaCache* pMetaCache, const char* pFunc, SFuncInfo* pInfo) {
|
|
SFuncInfo* pFuncInfo = NULL;
|
|
int32_t code = getMetaDataFromHash(pFunc, strlen(pFunc), pMetaCache->pUdf, (void**)&pFuncInfo);
|
|
if (TSDB_CODE_SUCCESS == code) {
|
|
memcpy(pInfo, pFuncInfo, sizeof(SFuncInfo));
|
|
}
|
|
return code;
|
|
}
|
|
|
|
static void destroySmaIndex(void* p) { taosMemoryFree(((STableIndexInfo*)p)->expr); }
|
|
|
|
static SArray* smaIndexesDup(SArray* pSrc) {
|
|
SArray* pDst = taosArrayDup(pSrc, NULL);
|
|
if (NULL == pDst) {
|
|
return NULL;
|
|
}
|
|
int32_t size = taosArrayGetSize(pDst);
|
|
for (int32_t i = 0; i < size; ++i) {
|
|
((STableIndexInfo*)taosArrayGet(pDst, i))->expr = NULL;
|
|
}
|
|
for (int32_t i = 0; i < size; ++i) {
|
|
STableIndexInfo* pIndex = taosArrayGet(pDst, i);
|
|
pIndex->expr = taosStrdup(((STableIndexInfo*)taosArrayGet(pSrc, i))->expr);
|
|
if (NULL == pIndex->expr) {
|
|
taosArrayDestroyEx(pDst, destroySmaIndex);
|
|
return NULL;
|
|
}
|
|
}
|
|
return pDst;
|
|
}
|
|
|
|
int32_t reserveTableIndexInCache(int32_t acctId, const char* pDb, const char* pTable, SParseMetaCache* pMetaCache) {
|
|
return reserveTableReqInCache(acctId, pDb, pTable, &pMetaCache->pTableIndex);
|
|
}
|
|
|
|
int32_t reserveTableCfgInCache(int32_t acctId, const char* pDb, const char* pTable, SParseMetaCache* pMetaCache) {
|
|
return reserveTableReqInCache(acctId, pDb, pTable, &pMetaCache->pTableCfg);
|
|
}
|
|
|
|
int32_t reserveTableTSMAInfoInCache(int32_t acctId, const char* pDb, const char* pTable, SParseMetaCache* pMetaCache) {
|
|
return reserveTableReqInCache(acctId, pDb, pTable, &pMetaCache->pTableTSMAs);
|
|
}
|
|
|
|
int32_t reserveTSMAInfoInCache(int32_t acctId, const char* pDb, const char* pTsmaName, SParseMetaCache* pMetaCache) {
|
|
return reserveTableReqInDbCache(acctId, pDb, pTsmaName, &pMetaCache->pTSMAs);
|
|
}
|
|
|
|
int32_t getTableIndexFromCache(SParseMetaCache* pMetaCache, const SName* pName, SArray** pIndexes) {
|
|
char fullName[TSDB_TABLE_FNAME_LEN];
|
|
int32_t code = tNameExtractFullName(pName, fullName);
|
|
if (TSDB_CODE_SUCCESS != code) return code;
|
|
;
|
|
SArray* pSmaIndexes = NULL;
|
|
code = getMetaDataFromHash(fullName, strlen(fullName), pMetaCache->pTableIndex, (void**)&pSmaIndexes);
|
|
if (TSDB_CODE_SUCCESS == code && NULL != pSmaIndexes) {
|
|
*pIndexes = smaIndexesDup(pSmaIndexes);
|
|
if (NULL == *pIndexes) {
|
|
code = TSDB_CODE_OUT_OF_MEMORY;
|
|
}
|
|
}
|
|
return code;
|
|
}
|
|
|
|
int32_t getTableTsmasFromCache(SParseMetaCache* pMetaCache, const SName* pTbName, SArray** pTsmas) {
|
|
char tbFName[TSDB_TABLE_FNAME_LEN];
|
|
int32_t code = tNameExtractFullName(pTbName, tbFName);
|
|
if (TSDB_CODE_SUCCESS != code) {
|
|
return code;
|
|
}
|
|
STableTSMAInfoRsp* pTsmasRsp = NULL;
|
|
code = getMetaDataFromHash(tbFName, strlen(tbFName), pMetaCache->pTableTSMAs, (void**)&pTsmasRsp);
|
|
if (TSDB_CODE_SUCCESS == code && pTsmasRsp) {
|
|
*pTsmas = pTsmasRsp->pTsmas;
|
|
}
|
|
return TSDB_CODE_SUCCESS;
|
|
}
|
|
|
|
int32_t getTsmaFromCache(SParseMetaCache* pMetaCache, const SName* pTsmaName, STableTSMAInfo** pTsma) {
|
|
char tsmaFName[TSDB_TABLE_FNAME_LEN];
|
|
int32_t code = tNameExtractFullName(pTsmaName, tsmaFName);
|
|
if (TSDB_CODE_SUCCESS != code) {
|
|
return code;
|
|
}
|
|
STableTSMAInfoRsp* pTsmaRsp = NULL;
|
|
code = getMetaDataFromHash(tsmaFName, strlen(tsmaFName), pMetaCache->pTSMAs, (void**)&pTsmaRsp);
|
|
if (TSDB_CODE_SUCCESS == code) {
|
|
if (!pTsmaRsp || pTsmaRsp->pTsmas->size != 1) {
|
|
return TSDB_CODE_PAR_INTERNAL_ERROR;
|
|
}
|
|
*pTsma = taosArrayGetP(pTsmaRsp->pTsmas, 0);
|
|
} else if (code == TSDB_CODE_PAR_INTERNAL_ERROR) {
|
|
code = TSDB_CODE_MND_SMA_NOT_EXIST;
|
|
}
|
|
return code;
|
|
}
|
|
|
|
STableCfg* tableCfgDup(STableCfg* pCfg) {
|
|
STableCfg* pNew = taosMemoryMalloc(sizeof(*pNew));
|
|
if (!pNew) {
|
|
return NULL;
|
|
}
|
|
memcpy(pNew, pCfg, sizeof(*pNew));
|
|
pNew->pComment = NULL;
|
|
pNew->pFuncs = NULL;
|
|
pNew->pTags = NULL;
|
|
pNew->pSchemas = NULL;
|
|
pNew->pSchemaExt = NULL;
|
|
if (NULL != pCfg->pComment) {
|
|
pNew->pComment = taosMemoryCalloc(pNew->commentLen + 1, 1);
|
|
if (!pNew->pComment) goto err;
|
|
memcpy(pNew->pComment, pCfg->pComment, pNew->commentLen);
|
|
}
|
|
if (NULL != pCfg->pFuncs) {
|
|
pNew->pFuncs = taosArrayDup(pCfg->pFuncs, NULL);
|
|
if (!pNew->pFuncs) goto err;
|
|
}
|
|
if (NULL != pCfg->pTags) {
|
|
pNew->pTags = taosMemoryCalloc(pCfg->tagsLen + 1, 1);
|
|
if (!pNew->pTags) goto err;
|
|
memcpy(pNew->pTags, pCfg->pTags, pNew->tagsLen);
|
|
}
|
|
|
|
int32_t schemaSize = (pCfg->numOfColumns + pCfg->numOfTags) * sizeof(SSchema);
|
|
|
|
SSchema* pSchema = taosMemoryMalloc(schemaSize);
|
|
if (!pSchema) goto err;
|
|
memcpy(pSchema, pCfg->pSchemas, schemaSize);
|
|
pNew->pSchemas = pSchema;
|
|
|
|
SSchemaExt* pSchemaExt = NULL;
|
|
if (useCompress(pCfg->tableType) && pCfg->pSchemaExt) {
|
|
int32_t schemaExtSize = pCfg->numOfColumns * sizeof(SSchemaExt);
|
|
pSchemaExt = taosMemoryMalloc(schemaExtSize);
|
|
if (!pSchemaExt) goto err;
|
|
memcpy(pSchemaExt, pCfg->pSchemaExt, schemaExtSize);
|
|
}
|
|
|
|
pNew->pSchemaExt = pSchemaExt;
|
|
|
|
return pNew;
|
|
err:
|
|
if (pNew->pComment) taosMemoryFreeClear(pNew->pComment);
|
|
if (pNew->pFuncs) taosArrayDestroy(pNew->pFuncs);
|
|
if (pNew->pTags) taosMemoryFreeClear(pNew->pTags);
|
|
if (pNew->pSchemas) taosMemoryFreeClear(pNew->pSchemas);
|
|
if (pNew->pSchemaExt) taosMemoryFreeClear(pNew->pSchemaExt);
|
|
taosMemoryFreeClear(pNew);
|
|
return NULL;
|
|
}
|
|
|
|
int32_t getTableCfgFromCache(SParseMetaCache* pMetaCache, const SName* pName, STableCfg** pOutput) {
|
|
char fullName[TSDB_TABLE_FNAME_LEN];
|
|
int32_t code = tNameExtractFullName(pName, fullName);
|
|
if (TSDB_CODE_SUCCESS != code) {
|
|
return code;
|
|
}
|
|
STableCfg* pCfg = NULL;
|
|
code = getMetaDataFromHash(fullName, strlen(fullName), pMetaCache->pTableCfg, (void**)&pCfg);
|
|
if (TSDB_CODE_SUCCESS == code && NULL != pCfg) {
|
|
*pOutput = tableCfgDup(pCfg);
|
|
if (NULL == *pOutput) {
|
|
code = TSDB_CODE_OUT_OF_MEMORY;
|
|
}
|
|
}
|
|
return code;
|
|
}
|
|
|
|
int32_t reserveDnodeRequiredInCache(SParseMetaCache* pMetaCache) {
|
|
pMetaCache->dnodeRequired = true;
|
|
return TSDB_CODE_SUCCESS;
|
|
}
|
|
|
|
int32_t getDnodeListFromCache(SParseMetaCache* pMetaCache, SArray** pDnodes) {
|
|
SMetaRes* pRes = taosArrayGet(pMetaCache->pDnodes, 0);
|
|
if (TSDB_CODE_SUCCESS != pRes->code) {
|
|
return pRes->code;
|
|
}
|
|
|
|
*pDnodes = taosArrayDup((SArray*)pRes->pRes, NULL);
|
|
if (NULL == *pDnodes) {
|
|
return terrno;
|
|
}
|
|
return TSDB_CODE_SUCCESS;
|
|
}
|
|
|
|
void destoryParseTablesMetaReqHash(SHashObj* pHash) {
|
|
SParseTablesMetaReq* p = taosHashIterate(pHash, NULL);
|
|
while (NULL != p) {
|
|
taosHashCleanup(p->pTables);
|
|
p = taosHashIterate(pHash, p);
|
|
}
|
|
taosHashCleanup(pHash);
|
|
}
|
|
|
|
void destoryParseMetaCache(SParseMetaCache* pMetaCache, bool request) {
|
|
if (request) {
|
|
destoryParseTablesMetaReqHash(pMetaCache->pTableMeta);
|
|
destoryParseTablesMetaReqHash(pMetaCache->pTableVgroup);
|
|
destoryParseTablesMetaReqHash(pMetaCache->pViews);
|
|
destoryParseTablesMetaReqHash(pMetaCache->pTSMAs);
|
|
destoryParseTablesMetaReqHash(pMetaCache->pTableName);
|
|
} else {
|
|
taosHashCleanup(pMetaCache->pTableMeta);
|
|
taosHashCleanup(pMetaCache->pTableVgroup);
|
|
taosHashCleanup(pMetaCache->pViews);
|
|
taosHashCleanup(pMetaCache->pTSMAs);
|
|
taosHashCleanup(pMetaCache->pTableName);
|
|
}
|
|
taosHashCleanup(pMetaCache->pDbVgroup);
|
|
taosHashCleanup(pMetaCache->pDbCfg);
|
|
taosHashCleanup(pMetaCache->pDbInfo);
|
|
taosHashCleanup(pMetaCache->pUserAuth);
|
|
taosHashCleanup(pMetaCache->pUdf);
|
|
taosHashCleanup(pMetaCache->pTableIndex);
|
|
taosHashCleanup(pMetaCache->pTableCfg);
|
|
taosHashCleanup(pMetaCache->pTableTSMAs);
|
|
}
|
|
|
|
int64_t int64SafeSub(int64_t a, int64_t b) {
|
|
int64_t res = (uint64_t)a - (uint64_t)b;
|
|
|
|
if (a >= 0 && b < 0) {
|
|
if ((uint64_t)res > (uint64_t)INT64_MAX) {
|
|
// overflow
|
|
res = INT64_MAX;
|
|
}
|
|
} else if (a < 0 && b > 0 && res >= 0) {
|
|
// underflow
|
|
res = INT64_MIN;
|
|
}
|
|
return res;
|
|
}
|