diff --git a/cmake/cmake.define b/cmake/cmake.define index d1d9266bca..aeab39cab4 100644 --- a/cmake/cmake.define +++ b/cmake/cmake.define @@ -62,7 +62,7 @@ ELSE () MESSAGE(STATUS "Will compile with Address Sanitizer!") ELSE () SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror -Werror=return-type -fPIC -gdwarf-2 -g3") - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -Werror=return-type -fPIC -gdwarf-2 -g3") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-literal-suffix -Werror=return-type -fpermissive -fPIC -gdwarf-2 -g3") ENDIF () MESSAGE("System processor ID: ${CMAKE_SYSTEM_PROCESSOR}") diff --git a/example/src/tstream.c b/example/src/tstream.c index 5bd833213d..65fd005954 100644 --- a/example/src/tstream.c +++ b/example/src/tstream.c @@ -81,10 +81,10 @@ int32_t create_stream() { /*const char* sql = "select min(k), max(k), sum(k) as sum_of_k from st1";*/ /*const char* sql = "select sum(k) from tu1 interval(10m)";*/ /*pRes = tmq_create_stream(pConn, "stream1", "out1", sql);*/ - pRes = - taos_query(pConn, - "create stream stream1 trigger window_close as select _wstartts, min(k), max(k), sum(k) as sum_of_k " - "from tu1 interval(10m)"); + pRes = taos_query( + pConn, + "create stream stream1 trigger window_close into outstb as select _wstartts, min(k), max(k), sum(k) as sum_of_k " + "from tu1 interval(10m)"); if (taos_errno(pRes) != 0) { printf("failed to create stream stream1, reason:%s\n", taos_errstr(pRes)); return -1; diff --git a/include/common/tcommon.h b/include/common/tcommon.h index 16653ebfee..1d979c274f 100644 --- a/include/common/tcommon.h +++ b/include/common/tcommon.h @@ -194,6 +194,21 @@ typedef struct SExprInfo { struct tExprNode* pExpr; } SExprInfo; +typedef struct { + const char* key; + int32_t keyLen; + uint8_t type; + int16_t length; + union{ + const char* value; + int64_t i; + uint64_t u; + double d; + float f; + }; + int32_t valueLen; +} SSmlKv; + #define QUERY_ASC_FORWARD_STEP 1 #define QUERY_DESC_FORWARD_STEP -1 diff --git a/include/common/tmsg.h b/include/common/tmsg.h index 3889784f2f..26c8072df6 100644 --- a/include/common/tmsg.h +++ b/include/common/tmsg.h @@ -326,11 +326,11 @@ typedef struct { int8_t alterType; int32_t numOfFields; SArray* pFields; -} SMAltertbReq; +} SMAlterStbReq; -int32_t tSerializeSMAlterStbReq(void* buf, int32_t bufLen, SMAltertbReq* pReq); -int32_t tDeserializeSMAlterStbReq(void* buf, int32_t bufLen, SMAltertbReq* pReq); -void tFreeSMAltertbReq(SMAltertbReq* pReq); +int32_t tSerializeSMAlterStbReq(void* buf, int32_t bufLen, SMAlterStbReq* pReq); +int32_t tDeserializeSMAlterStbReq(void* buf, int32_t bufLen, SMAlterStbReq* pReq); +void tFreeSMAltertbReq(SMAlterStbReq* pReq); typedef struct SEpSet { int8_t inUse; @@ -672,7 +672,6 @@ typedef struct { SArray* pArray; // Array of SUseDbRsp } SUseDbBatchRsp; - int32_t tSerializeSUseDbBatchRsp(void* buf, int32_t bufLen, SUseDbBatchRsp* pRsp); int32_t tDeserializeSUseDbBatchRsp(void* buf, int32_t bufLen, SUseDbBatchRsp* pRsp); void tFreeSUseDbBatchRsp(SUseDbBatchRsp* pRsp); @@ -685,7 +684,6 @@ int32_t tSerializeSUserAuthBatchRsp(void* buf, int32_t bufLen, SUserAuthBatchRsp int32_t tDeserializeSUserAuthBatchRsp(void* buf, int32_t bufLen, SUserAuthBatchRsp* pRsp); void tFreeSUserAuthBatchRsp(SUserAuthBatchRsp* pRsp); - typedef struct { char db[TSDB_DB_FNAME_LEN]; } SCompactDbReq; @@ -1554,7 +1552,9 @@ typedef struct SVDropStbReq { int32_t tEncodeSVDropStbReq(SCoder* pCoder, const SVDropStbReq* pReq); int32_t tDecodeSVDropStbReq(SCoder* pCoder, SVDropStbReq* pReq); +#define TD_CREATE_IF_NOT_EXISTS 0x1 typedef struct SVCreateTbReq { + int32_t flags; tb_uid_t uid; int64_t ctime; const char* name; diff --git a/include/common/ttypes.h b/include/common/ttypes.h index 405b20c521..377b443843 100644 --- a/include/common/ttypes.h +++ b/include/common/ttypes.h @@ -186,14 +186,14 @@ typedef struct { #define IS_NUMERIC_TYPE(_t) ((IS_SIGNED_NUMERIC_TYPE(_t)) || (IS_UNSIGNED_NUMERIC_TYPE(_t)) || (IS_FLOAT_TYPE(_t))) #define IS_MATHABLE_TYPE(_t) (IS_NUMERIC_TYPE(_t) || (_t) == (TSDB_DATA_TYPE_BOOL) || (_t) == (TSDB_DATA_TYPE_TIMESTAMP)) -#define IS_VALID_TINYINT(_t) ((_t) > INT8_MIN && (_t) <= INT8_MAX) -#define IS_VALID_SMALLINT(_t) ((_t) > INT16_MIN && (_t) <= INT16_MAX) -#define IS_VALID_INT(_t) ((_t) > INT32_MIN && (_t) <= INT32_MAX) -#define IS_VALID_BIGINT(_t) ((_t) > INT64_MIN && (_t) <= INT64_MAX) -#define IS_VALID_UTINYINT(_t) ((_t) >= 0 && (_t) < UINT8_MAX) -#define IS_VALID_USMALLINT(_t) ((_t) >= 0 && (_t) < UINT16_MAX) -#define IS_VALID_UINT(_t) ((_t) >= 0 && (_t) < UINT32_MAX) -#define IS_VALID_UBIGINT(_t) ((_t) >= 0 && (_t) < UINT64_MAX) +#define IS_VALID_TINYINT(_t) ((_t) >= INT8_MIN && (_t) <= INT8_MAX) +#define IS_VALID_SMALLINT(_t) ((_t) >= INT16_MIN && (_t) <= INT16_MAX) +#define IS_VALID_INT(_t) ((_t) >= INT32_MIN && (_t) <= INT32_MAX) +#define IS_VALID_BIGINT(_t) ((_t) >= INT64_MIN && (_t) <= INT64_MAX) +#define IS_VALID_UTINYINT(_t) ((_t) >= 0 && (_t) <= UINT8_MAX) +#define IS_VALID_USMALLINT(_t) ((_t) >= 0 && (_t) <= UINT16_MAX) +#define IS_VALID_UINT(_t) ((_t) >= 0 && (_t) <= UINT32_MAX) +#define IS_VALID_UBIGINT(_t) ((_t) >= 0 && (_t) <= UINT64_MAX) #define IS_VALID_FLOAT(_t) ((_t) >= -FLT_MAX && (_t) <= FLT_MAX) #define IS_VALID_DOUBLE(_t) ((_t) >= -DBL_MAX && (_t) <= DBL_MAX) diff --git a/include/libs/parser/parser.h b/include/libs/parser/parser.h index 84fa166881..7c9602734b 100644 --- a/include/libs/parser/parser.h +++ b/include/libs/parser/parser.h @@ -91,17 +91,23 @@ int32_t qCloneStmtDataBlock(void** pDst, void* pSrc); void qFreeStmtDataBlock(void* pDataBlock); int32_t qRebuildStmtDataBlock(void** pDst, void* pSrc); void qDestroyStmtDataBlock(void* pBlock); + int32_t qBindStmtColsValue(void* pBlock, TAOS_MULTI_BIND* bind, char* msgBuf, int32_t msgBufLen); int32_t qBindStmtSingleColValue(void* pBlock, TAOS_MULTI_BIND* bind, char* msgBuf, int32_t msgBufLen, int32_t colIdx, int32_t rowNum); int32_t qBuildStmtColFields(void* pDataBlock, int32_t* fieldNum, TAOS_FIELD** fields); int32_t qBuildStmtTagFields(void* pBlock, void* boundTags, int32_t* fieldNum, TAOS_FIELD** fields); -int32_t qBindStmtTagsValue(void* pBlock, void* boundTags, int64_t suid, SName* pName, TAOS_MULTI_BIND* bind, +int32_t qBindStmtTagsValue(void* pBlock, void* boundTags, int64_t suid, char* tName, TAOS_MULTI_BIND* bind, char* msgBuf, int32_t msgBufLen); void destroyBoundColumnInfo(void* pBoundInfo); int32_t qCreateSName(SName* pName, const char* pTableName, int32_t acctId, char* dbName, char* msgBuf, int32_t msgBufLen); +void* smlInitHandle(SQuery *pQuery); +void smlDestroyHandle(void *pHandle); +int32_t smlBindData(void *handle, SArray *tags, SArray *colsFormat, SHashObj *colsHash, SArray *cols, bool format, STableMeta *pTableMeta, char *tableName, char *msgBuf, int16_t msgBufLen); +int32_t smlBuildOutput(void* handle, SHashObj* pVgHash); + #ifdef __cplusplus } #endif diff --git a/include/util/taoserror.h b/include/util/taoserror.h index 441e87eff7..8ff62f825c 100644 --- a/include/util/taoserror.h +++ b/include/util/taoserror.h @@ -327,29 +327,32 @@ int32_t* taosGetErrno(); #define TSDB_CODE_TDB_INVALID_TABLE_TYPE TAOS_DEF_ERROR_CODE(0, 0x0601) #define TSDB_CODE_TDB_IVD_TB_SCHEMA_VERSION TAOS_DEF_ERROR_CODE(0, 0x0602) #define TSDB_CODE_TDB_TABLE_ALREADY_EXIST TAOS_DEF_ERROR_CODE(0, 0x0603) -#define TSDB_CODE_TDB_INVALID_CONFIG TAOS_DEF_ERROR_CODE(0, 0x0604) -#define TSDB_CODE_TDB_INIT_FAILED TAOS_DEF_ERROR_CODE(0, 0x0605) -#define TSDB_CODE_TDB_NO_DISKSPACE TAOS_DEF_ERROR_CODE(0, 0x0606) -#define TSDB_CODE_TDB_NO_DISK_PERMISSIONS TAOS_DEF_ERROR_CODE(0, 0x0607) -#define TSDB_CODE_TDB_FILE_CORRUPTED TAOS_DEF_ERROR_CODE(0, 0x0608) -#define TSDB_CODE_TDB_OUT_OF_MEMORY TAOS_DEF_ERROR_CODE(0, 0x0609) -#define TSDB_CODE_TDB_TAG_VER_OUT_OF_DATE TAOS_DEF_ERROR_CODE(0, 0x060A) -#define TSDB_CODE_TDB_TIMESTAMP_OUT_OF_RANGE TAOS_DEF_ERROR_CODE(0, 0x060B) -#define TSDB_CODE_TDB_SUBMIT_MSG_MSSED_UP TAOS_DEF_ERROR_CODE(0, 0x060C) -#define TSDB_CODE_TDB_INVALID_ACTION TAOS_DEF_ERROR_CODE(0, 0x060D) -#define TSDB_CODE_TDB_INVALID_CREATE_TB_MSG TAOS_DEF_ERROR_CODE(0, 0x060E) -#define TSDB_CODE_TDB_NO_TABLE_DATA_IN_MEM TAOS_DEF_ERROR_CODE(0, 0x060F) -#define TSDB_CODE_TDB_FILE_ALREADY_EXISTS TAOS_DEF_ERROR_CODE(0, 0x0610) -#define TSDB_CODE_TDB_TABLE_RECONFIGURE TAOS_DEF_ERROR_CODE(0, 0x0611) -#define TSDB_CODE_TDB_IVD_CREATE_TABLE_INFO TAOS_DEF_ERROR_CODE(0, 0x0612) -#define TSDB_CODE_TDB_NO_AVAIL_DISK TAOS_DEF_ERROR_CODE(0, 0x0613) -#define TSDB_CODE_TDB_MESSED_MSG TAOS_DEF_ERROR_CODE(0, 0x0614) -#define TSDB_CODE_TDB_IVLD_TAG_VAL TAOS_DEF_ERROR_CODE(0, 0x0615) -#define TSDB_CODE_TDB_NO_CACHE_LAST_ROW TAOS_DEF_ERROR_CODE(0, 0x0616) -#define TSDB_CODE_TDB_TABLE_RECREATED TAOS_DEF_ERROR_CODE(0, 0x0617) -#define TSDB_CODE_TDB_TDB_ENV_OPEN_ERROR TAOS_DEF_ERROR_CODE(0, 0x0618) -#define TSDB_CODE_TDB_NO_SMA_INDEX_IN_META TAOS_DEF_ERROR_CODE(0, 0x0619) -#define TSDB_CODE_TDB_INVALID_SMA_STAT TAOS_DEF_ERROR_CODE(0, 0x0620) +#define TSDB_CODE_TDB_TABLE_NOT_EXIST TAOS_DEF_ERROR_CODE(0, 0x0604) +#define TSDB_CODE_TDB_STB_ALREADY_EXIST TAOS_DEF_ERROR_CODE(0, 0x0605) +#define TSDB_CODE_TDB_STB_NOT_EXIST TAOS_DEF_ERROR_CODE(0, 0x0606) +#define TSDB_CODE_TDB_INVALID_CONFIG TAOS_DEF_ERROR_CODE(0, 0x0607) +#define TSDB_CODE_TDB_INIT_FAILED TAOS_DEF_ERROR_CODE(0, 0x0608) +#define TSDB_CODE_TDB_NO_DISKSPACE TAOS_DEF_ERROR_CODE(0, 0x0609) +#define TSDB_CODE_TDB_NO_DISK_PERMISSIONS TAOS_DEF_ERROR_CODE(0, 0x060A) +#define TSDB_CODE_TDB_FILE_CORRUPTED TAOS_DEF_ERROR_CODE(0, 0x060B) +#define TSDB_CODE_TDB_OUT_OF_MEMORY TAOS_DEF_ERROR_CODE(0, 0x060C) +#define TSDB_CODE_TDB_TAG_VER_OUT_OF_DATE TAOS_DEF_ERROR_CODE(0, 0x060D) +#define TSDB_CODE_TDB_TIMESTAMP_OUT_OF_RANGE TAOS_DEF_ERROR_CODE(0, 0x060E) +#define TSDB_CODE_TDB_SUBMIT_MSG_MSSED_UP TAOS_DEF_ERROR_CODE(0, 0x060F) +#define TSDB_CODE_TDB_INVALID_ACTION TAOS_DEF_ERROR_CODE(0, 0x0600) +#define TSDB_CODE_TDB_INVALID_CREATE_TB_MSG TAOS_DEF_ERROR_CODE(0, 0x0601) +#define TSDB_CODE_TDB_NO_TABLE_DATA_IN_MEM TAOS_DEF_ERROR_CODE(0, 0x0602) +#define TSDB_CODE_TDB_FILE_ALREADY_EXISTS TAOS_DEF_ERROR_CODE(0, 0x0613) +#define TSDB_CODE_TDB_TABLE_RECONFIGURE TAOS_DEF_ERROR_CODE(0, 0x0614) +#define TSDB_CODE_TDB_IVD_CREATE_TABLE_INFO TAOS_DEF_ERROR_CODE(0, 0x0615) +#define TSDB_CODE_TDB_NO_AVAIL_DISK TAOS_DEF_ERROR_CODE(0, 0x0616) +#define TSDB_CODE_TDB_MESSED_MSG TAOS_DEF_ERROR_CODE(0, 0x0617) +#define TSDB_CODE_TDB_IVLD_TAG_VAL TAOS_DEF_ERROR_CODE(0, 0x0618) +#define TSDB_CODE_TDB_NO_CACHE_LAST_ROW TAOS_DEF_ERROR_CODE(0, 0x0619) +#define TSDB_CODE_TDB_TABLE_RECREATED TAOS_DEF_ERROR_CODE(0, 0x061A) +#define TSDB_CODE_TDB_TDB_ENV_OPEN_ERROR TAOS_DEF_ERROR_CODE(0, 0x061B) +#define TSDB_CODE_TDB_NO_SMA_INDEX_IN_META TAOS_DEF_ERROR_CODE(0, 0x061C) +#define TSDB_CODE_TDB_INVALID_SMA_STAT TAOS_DEF_ERROR_CODE(0, 0x062D) // query #define TSDB_CODE_QRY_INVALID_QHANDLE TAOS_DEF_ERROR_CODE(0, 0x0700) @@ -642,6 +645,10 @@ int32_t* taosGetErrno(); #define TSDB_CODE_FUNC_FUNTION_PARA_VALUE TAOS_DEF_ERROR_CODE(0, 0x2803) #define TSDB_CODE_FUNC_INVALID_FUNTION TAOS_DEF_ERROR_CODE(0, 0x2604) +#define TSDB_CODE_SML_INVALID_PROTOCOL_TYPE TAOS_DEF_ERROR_CODE(0, 0x3000) +#define TSDB_CODE_SML_INVALID_PRECISION_TYPE TAOS_DEF_ERROR_CODE(0, 0x3001) +#define TSDB_CODE_SML_INVALID_DATA TAOS_DEF_ERROR_CODE(0, 0x3002) + #ifdef __cplusplus } #endif diff --git a/include/util/tdef.h b/include/util/tdef.h index 0ab277e0c3..4669a29883 100644 --- a/include/util/tdef.h +++ b/include/util/tdef.h @@ -86,9 +86,13 @@ extern const int32_t TYPE_BYTES[15]; #define TS_PATH_DELIMITER "." #define TS_ESCAPE_CHAR '`' + #define TSDB_TIME_PRECISION_MILLI 0 #define TSDB_TIME_PRECISION_MICRO 1 #define TSDB_TIME_PRECISION_NANO 2 +#define TSDB_TIME_PRECISION_HOURS 3 +#define TSDB_TIME_PRECISION_MINUTES 4 +#define TSDB_TIME_PRECISION_SECONDS 5 #define TSDB_TIME_PRECISION_MILLI_STR "ms" #define TSDB_TIME_PRECISION_MICRO_STR "us" diff --git a/source/client/src/clientMain.c b/source/client/src/clientMain.c index 818436b411..9d75586917 100644 --- a/source/client/src/clientMain.c +++ b/source/client/src/clientMain.c @@ -787,8 +787,3 @@ int taos_stmt_close(TAOS_STMT *stmt) { return stmtClose(stmt); } -TAOS_RES *taos_schemaless_insert(TAOS *taos, char *lines[], int numLines, int protocol, int precision) { - // TODO - return NULL; -} - diff --git a/source/client/src/clientSml.c b/source/client/src/clientSml.c new file mode 100644 index 0000000000..5f9138bb43 --- /dev/null +++ b/source/client/src/clientSml.c @@ -0,0 +1,1757 @@ +#include +#include +#include +#include + +#include "query.h" +#include "taos.h" +#include "taoserror.h" +#include "tdef.h" +#include "tlog.h" +#include "tmsg.h" +#include "tstrbuild.h" +#include "ttime.h" +#include "ttypes.h" +#include "tcommon.h" +#include "catalog.h" +#include "clientInt.h" +//================================================================================================= + +#define SPACE ' ' +#define COMMA ',' +#define EQUAL '=' +#define QUOTE '"' +#define SLASH '\\' +#define tsMaxSQLStringLen (1024*1024) + +//================================================================================================= +typedef TSDB_SML_PROTOCOL_TYPE SMLProtocolType; + +typedef enum { + SCHEMA_ACTION_CREATE_STABLE, + SCHEMA_ACTION_ADD_COLUMN, + SCHEMA_ACTION_ADD_TAG, + SCHEMA_ACTION_CHANGE_COLUMN_SIZE, + SCHEMA_ACTION_CHANGE_TAG_SIZE, +} ESchemaAction; + +typedef struct { + char sTableName[TSDB_TABLE_NAME_LEN]; + SHashObj *tags; + SHashObj *fields; +} SCreateSTableActionInfo; + +typedef struct { + char sTableName[TSDB_TABLE_NAME_LEN]; + SSmlKv * field; +} SAlterSTableActionInfo; + +typedef struct { + ESchemaAction action; + union { + SCreateSTableActionInfo createSTable; + SAlterSTableActionInfo alterSTable; + }; +} SSchemaAction; + +typedef struct { + const char* measure; + const char* tags; + const char* cols; + const char* timestamp; + + int32_t measureLen; + int32_t measureTagsLen; + int32_t tagsLen; + int32_t colsLen; + int32_t timestampLen; +} SSmlLineInfo; + +typedef struct { + const char *sTableName; // super table name + uint8_t sTableNameLen; + char childTableName[TSDB_TABLE_NAME_LEN]; + uint64_t uid; + + SArray *tags; + + // colsFormat store cols formated, for quick parse, if info->formatData is true + SArray *colsFormat; // elements are SArray + + // cols & colsColumn store cols un formated + SArray *cols; // elements are SHashObj for find by key quickly + SHashObj *columnsHash; // elements are , just for judge if key exists quickly. +} SSmlTableInfo; + +typedef struct { + SHashObj *tagHash; + SHashObj *fieldHash; + STableMeta *tableMeta; +} SSmlSTableMeta; + +typedef struct { + int32_t len; + char *buf; +} SSmlMsgBuf; + +typedef struct { + uint64_t id; + + SMLProtocolType protocol; + int8_t precision; + bool dataFormat; // true means that the name, number and order of keys in each line are the same + + SHashObj *childTables; + SHashObj *superTables; + SHashObj *pVgHash; + void *exec; + + STscObj *taos; + SCatalog *pCatalog; + SRequestObj *pRequest; + SQuery *pQuery; + + int32_t affectedRows; + SSmlMsgBuf msgBuf; +} SSmlHandle; +//================================================================================================= + +static uint64_t linesSmlHandleId = 0; +static const char* TS = "_ts"; +static const char* TAG = "_tagNone"; + +//================================================================================================= + +static uint64_t smlGenId() { + uint64_t id; + + do { + id = atomic_add_fetch_64(&linesSmlHandleId, 1); + } while (id == 0); + + return id; +} + +static int32_t smlBuildInvalidDataMsg(SSmlMsgBuf* pBuf, const char *msg1, const char *msg2) { + if(msg1) strncat(pBuf->buf, msg1, pBuf->len); + int32_t left = pBuf->len - strlen(pBuf->buf); + if(left > 2 && msg2) { + strncat(pBuf->buf, ":", left - 1); + strncat(pBuf->buf, msg2, left - 2); + } + return TSDB_CODE_SML_INVALID_DATA; +} + +static int smlCompareKv(const void* p1, const void* p2) { + SSmlKv* kv1 = (SSmlKv*)p1; + SSmlKv* kv2 = (SSmlKv*)p2; + int32_t kvLen1 = kv1->keyLen; + int32_t kvLen2 = kv2->keyLen; + int32_t res = strncasecmp(kv1->key, kv2->key, TMIN(kvLen1, kvLen2)); + if (res != 0) { + return res; + } else { + return kvLen1-kvLen2; + } +} + +static void smlBuildChildTableName(SSmlTableInfo *tags) { + int32_t size = taosArrayGetSize(tags->tags); + ASSERT(size > 0); + taosArraySort(tags->tags, smlCompareKv); + + SStringBuilder sb = {0}; + taosStringBuilderAppendStringLen(&sb, tags->sTableName, tags->sTableNameLen); + for (int j = 0; j < size; ++j) { + SSmlKv *tagKv = taosArrayGetP(tags->tags, j); + taosStringBuilderAppendStringLen(&sb, tagKv->key, tagKv->keyLen); + taosStringBuilderAppendStringLen(&sb, tagKv->value, tagKv->valueLen); + } + size_t len = 0; + char* keyJoined = taosStringBuilderGetResult(&sb, &len); + T_MD5_CTX context; + tMD5Init(&context); + tMD5Update(&context, (uint8_t *)keyJoined, (uint32_t)len); + tMD5Final(&context); + uint64_t digest1 = *(uint64_t*)(context.digest); + uint64_t digest2 = *(uint64_t*)(context.digest + 8); + snprintf(tags->childTableName, TSDB_TABLE_NAME_LEN, "t_%016"PRIx64"%016"PRIx64, digest1, digest2); + taosStringBuilderDestroy(&sb); + tags->uid = digest1; +} + +static int32_t smlGenerateSchemaAction(SSchema* pointColField, SHashObj* dbAttrHash, SArray* dbAttrArray, bool isTag, char sTableName[], + SSchemaAction* action, bool* actionNeeded, SSmlHandle* info) { +// char fieldName[TSDB_COL_NAME_LEN] = {0}; +// strcpy(fieldName, pointColField->name); +// +// size_t* pDbIndex = taosHashGet(dbAttrHash, fieldName, strlen(fieldName)); +// if (pDbIndex) { +// SSchema* dbAttr = taosArrayGet(dbAttrArray, *pDbIndex); +// assert(strcasecmp(dbAttr->name, pointColField->name) == 0); +// if (pointColField->type != dbAttr->type) { +// uError("SML:0x%"PRIx64" point type and db type mismatch. key: %s. point type: %d, db type: %d", info->id, pointColField->name, +// pointColField->type, dbAttr->type); +// return TSDB_CODE_TSC_INVALID_VALUE; +// } +// +// if (IS_VAR_DATA_TYPE(pointColField->type) && (pointColField->bytes > dbAttr->bytes)) { +// if (isTag) { +// action->action = SCHEMA_ACTION_CHANGE_TAG_SIZE; +// } else { +// action->action = SCHEMA_ACTION_CHANGE_COLUMN_SIZE; +// } +// memset(&action->alterSTable, 0, sizeof(SAlterSTableActionInfo)); +// memcpy(action->alterSTable.sTableName, sTableName, TSDB_TABLE_NAME_LEN); +// action->alterSTable.field = pointColField; +// *actionNeeded = true; +// } +// } else { +// if (isTag) { +// action->action = SCHEMA_ACTION_ADD_TAG; +// } else { +// action->action = SCHEMA_ACTION_ADD_COLUMN; +// } +// memset(&action->alterSTable, 0, sizeof(SAlterSTableActionInfo)); +// memcpy(action->alterSTable.sTableName, sTableName, TSDB_TABLE_NAME_LEN); +// action->alterSTable.field = pointColField; +// *actionNeeded = true; +// } +// if (*actionNeeded) { +// uDebug("SML:0x%" PRIx64 " generate schema action. column name: %s, action: %d", info->id, fieldName, +// action->action); +// } + return 0; +} + +static int32_t smlBuildColumnDescription(SSmlKv* field, char* buf, int32_t bufSize, int32_t* outBytes) { + uint8_t type = field->type; + char tname[TSDB_TABLE_NAME_LEN] = {0}; + memcpy(tname, field->key, field->keyLen); + if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) { + int32_t bytes = field->valueLen; // todo + int out = snprintf(buf, bufSize,"%s %s(%d)", + tname,tDataTypes[field->type].name, bytes); + *outBytes = out; + } else { + int out = snprintf(buf, bufSize, "%s %s", tname, tDataTypes[type].name); + *outBytes = out; + } + + return 0; +} + +static int32_t smlApplySchemaAction(SSmlHandle* info, SSchemaAction* action) { + int32_t code = 0; + int32_t outBytes = 0; + char *result = (char *)taosMemoryCalloc(1, tsMaxSQLStringLen+1); + int32_t capacity = tsMaxSQLStringLen + 1; + + uDebug("SML:0x%"PRIx64" apply schema action. action: %d", info->id, action->action); + switch (action->action) { + case SCHEMA_ACTION_ADD_COLUMN: { + int n = sprintf(result, "alter stable %s add column ", action->alterSTable.sTableName); + smlBuildColumnDescription(action->alterSTable.field, result+n, capacity-n, &outBytes); + TAOS_RES* res = taos_query(info->taos, result); //TODO async doAsyncQuery + code = taos_errno(res); + const char* errStr = taos_errstr(res); + char* begin = strstr(errStr, "duplicated column names"); + bool tscDupColNames = (begin != NULL); + if (code != TSDB_CODE_SUCCESS) { + uError("SML:0x%"PRIx64" apply schema action. error: %s", info->id, errStr); + } + taos_free_result(res); + +// if (code == TSDB_CODE_MND_FIELD_ALREADY_EXIST || code == TSDB_CODE_MND_TAG_ALREADY_EXIST || tscDupColNames) { + if (code == TSDB_CODE_MND_TAG_ALREADY_EXIST || tscDupColNames) { + TAOS_RES* res2 = taos_query(info->taos, "RESET QUERY CACHE"); + code = taos_errno(res2); + if (code != TSDB_CODE_SUCCESS) { + uError("SML:0x%" PRIx64 " apply schema action. reset query cache. error: %s", info->id, taos_errstr(res2)); + } + taos_free_result(res2); + taosMsleep(500); + } + break; + } + case SCHEMA_ACTION_ADD_TAG: { + int n = sprintf(result, "alter stable %s add tag ", action->alterSTable.sTableName); + smlBuildColumnDescription(action->alterSTable.field, + result+n, capacity-n, &outBytes); + TAOS_RES* res = taos_query(info->taos, result); //TODO async doAsyncQuery + code = taos_errno(res); + const char* errStr = taos_errstr(res); + char* begin = strstr(errStr, "duplicated column names"); + bool tscDupColNames = (begin != NULL); + if (code != TSDB_CODE_SUCCESS) { + uError("SML:0x%"PRIx64" apply schema action. error : %s", info->id, taos_errstr(res)); + } + taos_free_result(res); + +// if (code ==TSDB_CODE_MND_TAG_ALREADY_EXIST || code == TSDB_CODE_MND_FIELD_ALREAY_EXIST || tscDupColNames) { + if (code ==TSDB_CODE_MND_TAG_ALREADY_EXIST || tscDupColNames) { + TAOS_RES* res2 = taos_query(info->taos, "RESET QUERY CACHE"); + code = taos_errno(res2); + if (code != TSDB_CODE_SUCCESS) { + uError("SML:0x%" PRIx64 " apply schema action. reset query cache. error: %s", info->id, taos_errstr(res2)); + } + taos_free_result(res2); + taosMsleep(500); + } + break; + } + case SCHEMA_ACTION_CHANGE_COLUMN_SIZE: { + int n = sprintf(result, "alter stable %s modify column ", action->alterSTable.sTableName); + smlBuildColumnDescription(action->alterSTable.field, result+n, + capacity-n, &outBytes); + TAOS_RES* res = taos_query(info->taos, result); //TODO async doAsyncQuery + code = taos_errno(res); + if (code != TSDB_CODE_SUCCESS) { + uError("SML:0x%"PRIx64" apply schema action. error : %s", info->id, taos_errstr(res)); + } + taos_free_result(res); + +// if (code == TSDB_CODE_MND_INVALID_COLUMN_LENGTH || code == TSDB_CODE_TSC_INVALID_COLUMN_LENGTH) { + if (code == TSDB_CODE_TSC_INVALID_COLUMN_LENGTH) { + TAOS_RES* res2 = taos_query(info->taos, "RESET QUERY CACHE"); + code = taos_errno(res2); + if (code != TSDB_CODE_SUCCESS) { + uError("SML:0x%" PRIx64 " apply schema action. reset query cache. error: %s", info->id, taos_errstr(res2)); + } + taos_free_result(res2); + taosMsleep(500); + } + break; + } + case SCHEMA_ACTION_CHANGE_TAG_SIZE: { + int n = sprintf(result, "alter stable %s modify tag ", action->alterSTable.sTableName); + smlBuildColumnDescription(action->alterSTable.field, result+n, + capacity-n, &outBytes); + TAOS_RES* res = taos_query(info->taos, result); //TODO async doAsyncQuery + code = taos_errno(res); + if (code != TSDB_CODE_SUCCESS) { + uError("SML:0x%"PRIx64" apply schema action. error : %s", info->id, taos_errstr(res)); + } + taos_free_result(res); + +// if (code == TSDB_CODE_MND_INVALID_TAG_LENGTH || code == TSDB_CODE_TSC_INVALID_TAG_LENGTH) { + if (code == TSDB_CODE_TSC_INVALID_TAG_LENGTH) { + TAOS_RES* res2 = taos_query(info->taos, "RESET QUERY CACHE"); + code = taos_errno(res2); + if (code != TSDB_CODE_SUCCESS) { + uError("SML:0x%" PRIx64 " apply schema action. reset query cache. error: %s", info->id, taos_errstr(res2)); + } + taos_free_result(res2); + taosMsleep(500); + } + break; + } + case SCHEMA_ACTION_CREATE_STABLE: { + int n = sprintf(result, "create stable %s (", action->createSTable.sTableName); + char* pos = result + n; int freeBytes = capacity - n; + + size_t size = taosHashGetSize(action->createSTable.fields); + SArray *cols = taosArrayInit(size, POINTER_BYTES); + SSmlKv **kv = taosHashIterate(action->createSTable.fields, NULL); + while(kv){ + if(strncmp((*kv)->key, TS, strlen(TS)) == 0 && (*kv)->type == TSDB_DATA_TYPE_TIMESTAMP){ + taosArrayInsert(cols, 0, kv); + }else{ + taosArrayPush(cols, kv); + } + kv = taosHashIterate(action->createSTable.fields, kv); + } + + for(int i = 0; i < taosArrayGetSize(cols); i++){ + SSmlKv *kvNew = taosArrayGetP(cols, i); + smlBuildColumnDescription(kvNew, pos, freeBytes, &outBytes); + pos += outBytes; freeBytes -= outBytes; + *pos = ','; ++pos; --freeBytes; + } + taosArrayDestroy(cols); + + --pos; ++freeBytes; + + outBytes = snprintf(pos, freeBytes, ") tags ("); + pos += outBytes; freeBytes -= outBytes; + + kv = taosHashIterate(action->createSTable.tags, NULL); + while(kv){ + smlBuildColumnDescription(*kv, pos, freeBytes, &outBytes); + pos += outBytes; freeBytes -= outBytes; + *pos = ','; ++pos; --freeBytes; + kv = taosHashIterate(action->createSTable.tags, kv); + } + pos--; ++freeBytes; + outBytes = snprintf(pos, freeBytes, ")"); + TAOS_RES* res = taos_query(info->taos, result); + code = taos_errno(res); + if (code != TSDB_CODE_SUCCESS) { + uError("SML:0x%"PRIx64" apply schema action. error : %s", info->id, taos_errstr(res)); + } + taos_free_result(res); + + if (code == TSDB_CODE_MND_STB_ALREADY_EXIST) { + TAOS_RES* res2 = taos_query(info->taos, "RESET QUERY CACHE"); + code = taos_errno(res2); + if (code != TSDB_CODE_SUCCESS) { + uError("SML:0x%" PRIx64 " apply schema action. reset query cache. error: %s", info->id, taos_errstr(res2)); + } + taos_free_result(res2); + taosMsleep(500); + } + break; + } + + default: + break; + } + + taosMemoryFreeClear(result); + if (code != 0) { + uError("SML:0x%"PRIx64 " apply schema action failure. %s", info->id, tstrerror(code)); + } + return code; +} + +static int32_t smlModifyDBSchemas(SSmlHandle* info) { + int32_t code = 0; + + SSmlSTableMeta** tableMetaSml = taosHashIterate(info->superTables, NULL); + while (tableMetaSml) { + SSmlSTableMeta* cTablePoints = *tableMetaSml; + + STableMeta *pTableMeta = NULL; + SEpSet ep = getEpSet_s(&info->taos->pAppInfo->mgmtEp); + + size_t superTableLen = 0; + void *superTable = taosHashGetKey(tableMetaSml, &superTableLen); // todo escape + SName pName = {TSDB_TABLE_NAME_T, info->taos->acctId, {0}, {0}}; + strcpy(pName.dbname, info->pRequest->pDb); + memcpy(pName.tname, superTable, superTableLen); + + code = catalogGetSTableMeta(info->pCatalog, info->taos->pAppInfo->pTransporter, &ep, &pName, &pTableMeta); + + if (code == TSDB_CODE_TDB_INVALID_TABLE_ID || code == TSDB_CODE_MND_INVALID_STB) { + SSchemaAction schemaAction = {0}; + schemaAction.action = SCHEMA_ACTION_CREATE_STABLE; + memcpy(schemaAction.createSTable.sTableName, superTable, superTableLen); + schemaAction.createSTable.tags = cTablePoints->tagHash; + schemaAction.createSTable.fields = cTablePoints->fieldHash; + code = smlApplySchemaAction(info, &schemaAction); + if (code != 0) { + uError("SML:0x%"PRIx64" smlApplySchemaAction failed. can not create %s", info->id, schemaAction.createSTable.sTableName); + return code; + } + + code = catalogGetSTableMeta(info->pCatalog, info->taos->pAppInfo->pTransporter, &ep, &pName, &pTableMeta); + if (code != 0) { + uError("SML:0x%"PRIx64" catalogGetSTableMeta failed. super table name %s", info->id, schemaAction.createSTable.sTableName); + return code; + } + }else if (code == TSDB_CODE_SUCCESS) { + } else { + uError("SML:0x%"PRIx64" load table meta error: %s", info->id, tstrerror(code)); + return code; + } + cTablePoints->tableMeta = pTableMeta; + + tableMetaSml = taosHashIterate(info->superTables, tableMetaSml); + } + return 0; +} + +//========================================================================= + +/* Field Escape charaters + 1: measurement Comma,Space + 2: tag_key, tag_value, field_key Comma,Equal Sign,Space + 3: field_value Double quote,Backslash +*/ +//static void escapeSpecialCharacter(uint8_t field, const char **pos) { +// const char *cur = *pos; +// if (*cur != '\\') { +// return; +// } +// switch (field) { +// case 1: +// switch (*(cur + 1)) { +// case ',': +// case ' ': +// cur++; +// break; +// default: +// break; +// } +// break; +// case 2: +// switch (*(cur + 1)) { +// case ',': +// case ' ': +// case '=': +// cur++; +// break; +// default: +// break; +// } +// break; +// case 3: +// switch (*(cur + 1)) { +// case '"': +// case '\\': +// cur++; +// break; +// default: +// break; +// } +// break; +// default: +// break; +// } +// *pos = cur; +//} + +static bool smlParseTinyInt(SSmlKv *kvVal, bool *isValid, SSmlMsgBuf *msg) { + const char *pVal = kvVal->value; + int32_t len = kvVal->valueLen; + if (len <= 2) { + return false; + } + const char *signalPos = pVal + len - 2; + if (!strncasecmp(signalPos, "i8", 2)) { + char *endptr = NULL; + int64_t result = strtoll(pVal, &endptr, 10); + if(endptr != signalPos){ // 78ri8 + *isValid = false; + smlBuildInvalidDataMsg(msg, "invalid tiny int", endptr); + }else if(!IS_VALID_TINYINT(result)){ + *isValid = false; + smlBuildInvalidDataMsg(msg, "tiny int out of range[-128,127]", endptr); + }else{ + kvVal->i = result; + *isValid = true; + } + return true; + } + return false; +} + +static bool smlParseTinyUint(SSmlKv *kvVal, bool *isValid, SSmlMsgBuf *msg) { + const char *pVal = kvVal->value; + int32_t len = kvVal->valueLen; + if (len <= 2) { + return false; + } + if (pVal[0] == '-') { + return false; + } + const char *signalPos = pVal + len - 2; + if (!strncasecmp(signalPos, "u8", 2)) { + char *endptr = NULL; + int64_t result = strtoll(pVal, &endptr, 10); + if(endptr != signalPos){ // 78ri8 + *isValid = false; + smlBuildInvalidDataMsg(msg, "invalid unsigned tiny int", endptr); + }else if(!IS_VALID_UTINYINT(result)){ + *isValid = false; + smlBuildInvalidDataMsg(msg, "unsigned tiny int out of range[0,255]", endptr); + }else{ + kvVal->i = result; + *isValid = true; + } + return true; + } + return false; +} + +static bool smlParseSmallInt(SSmlKv *kvVal, bool *isValid, SSmlMsgBuf *msg) { + const char *pVal = kvVal->value; + int32_t len = kvVal->valueLen; + if (len <= 3) { + return false; + } + const char *signalPos = pVal + len - 3; + if (!strncasecmp(signalPos, "i16", 3)) { + char *endptr = NULL; + int64_t result = strtoll(pVal, &endptr, 10); + if(endptr != signalPos){ // 78ri8 + *isValid = false; + smlBuildInvalidDataMsg(msg, "invalid small int", endptr); + }else if(!IS_VALID_SMALLINT(result)){ + *isValid = false; + smlBuildInvalidDataMsg(msg, "small int our of range[-32768,32767]", endptr); + }else{ + kvVal->i = result; + *isValid = true; + } + return true; + } + return false; +} + +static bool smlParseSmallUint(SSmlKv *kvVal, bool *isValid, SSmlMsgBuf *msg) { + const char *pVal = kvVal->value; + int32_t len = kvVal->valueLen; + if (len <= 3) { + return false; + } + if (pVal[0] == '-') { + return false; + } + const char *signalPos = pVal + len - 3; + if (strncasecmp(signalPos, "u16", 3) == 0) { + char *endptr = NULL; + int64_t result = strtoll(pVal, &endptr, 10); + if(endptr != signalPos){ // 78ri8 + *isValid = false; + smlBuildInvalidDataMsg(msg, "invalid unsigned small int", endptr); + }else if(!IS_VALID_USMALLINT(result)){ + *isValid = false; + smlBuildInvalidDataMsg(msg, "unsigned small int out of rang[0,65535]", endptr); + }else{ + kvVal->i = result; + *isValid = true; + } + return true; + } + return false; +} + +static bool smlParseInt(SSmlKv *kvVal, bool *isValid, SSmlMsgBuf *msg) { + const char *pVal = kvVal->value; + int32_t len = kvVal->valueLen; + if (len <= 3) { + return false; + } + const char *signalPos = pVal + len - 3; + if (strncasecmp(signalPos, "i32", 3) == 0) { + char *endptr = NULL; + int64_t result = strtoll(pVal, &endptr, 10); + if(endptr != signalPos){ // 78ri8 + *isValid = false; + smlBuildInvalidDataMsg(msg, "invalid int", endptr); + }else if(!IS_VALID_INT(result)){ + *isValid = false; + smlBuildInvalidDataMsg(msg, "int out of range[-2147483648,2147483647]", endptr); + }else{ + kvVal->i = result; + *isValid = true; + } + return true; + } + return false; +} + +static bool smlParseUint(SSmlKv *kvVal, bool *isValid, SSmlMsgBuf *msg) { + const char *pVal = kvVal->value; + int32_t len = kvVal->valueLen; + if (len <= 3) { + return false; + } + if (pVal[0] == '-') { + return false; + } + const char *signalPos = pVal + len - 3; + if (strncasecmp(signalPos, "u32", 3) == 0) { + char *endptr = NULL; + int64_t result = strtoll(pVal, &endptr, 10); + if(endptr != signalPos){ // 78ri8 + *isValid = false; + smlBuildInvalidDataMsg(msg, "invalid unsigned int", endptr); + }else if(!IS_VALID_UINT(result)){ + *isValid = false; + smlBuildInvalidDataMsg(msg, "unsigned int out of range[0,4294967295]", endptr); + }else{ + kvVal->i = result; + *isValid = true; + } + return true; + } + return false; +} + +static bool smlParseBigInt(SSmlKv *kvVal, bool *isValid, SSmlMsgBuf *msg) { + const char *pVal = kvVal->value; + int32_t len = kvVal->valueLen; + if (len > 3 && strncasecmp(pVal + len - 3, "i64", 3) == 0) { + char *endptr = NULL; + errno = 0; + int64_t result = strtoll(pVal, &endptr, 10); + if(endptr != pVal + len - 3){ // 78ri8 + *isValid = false; + smlBuildInvalidDataMsg(msg, "invalid big int", endptr); + }else if(errno == ERANGE || !IS_VALID_BIGINT(result)){ + *isValid = false; + smlBuildInvalidDataMsg(msg, "big int out of range[-9223372036854775808,9223372036854775807]", endptr); + }else{ + kvVal->i = result; + *isValid = true; + } + return true; + }else if (len > 1 && pVal[len - 1] == 'i') { + char *endptr = NULL; + errno = 0; + int64_t result = strtoll(pVal, &endptr, 10); + if(endptr != pVal + len - 1){ // 78ri8 + *isValid = false; + smlBuildInvalidDataMsg(msg, "invalid big int", endptr); + }else if(errno == ERANGE || !IS_VALID_BIGINT(result)){ + *isValid = false; + smlBuildInvalidDataMsg(msg, "big int out of range[-9223372036854775808,9223372036854775807]", endptr); + }else{ + kvVal->i = result; + *isValid = true; + } + return true; + } + return false; +} + +static bool smlParseBigUint(SSmlKv *kvVal, bool *isValid, SSmlMsgBuf *msg) { + const char *pVal = kvVal->value; + int32_t len = kvVal->valueLen; + if (len <= 3) { + return false; + } + if (pVal[0] == '-') { + return false; + } + const char *signalPos = pVal + len - 3; + if (strncasecmp(signalPos, "u64", 3) == 0) { + char *endptr = NULL; + errno = 0; + uint64_t result = strtoull(pVal, &endptr, 10); + if(endptr != signalPos){ // 78ri8 + *isValid = false; + smlBuildInvalidDataMsg(msg, "invalid unsigned big int", endptr); + }else if(errno == ERANGE || !IS_VALID_UBIGINT(result)){ + *isValid = false; + smlBuildInvalidDataMsg(msg, "unsigned big int out of range[0,18446744073709551615]", endptr); + }else{ + kvVal->u = result; + *isValid = true; + } + return true; + } + return false; +} + +static bool smlParseFloat(SSmlKv *kvVal, bool *isValid, SSmlMsgBuf *msg) { + const char *pVal = kvVal->value; + int32_t len = kvVal->valueLen; + char *endptr = NULL; + errno = 0; + float result = strtof(pVal, &endptr); + if(endptr == pVal + len && errno != ERANGE && IS_VALID_FLOAT(result)){ // 78 + kvVal->f = result; + *isValid = true; + return true; + } + + if (len > 3 && strncasecmp(pVal + len - 3, "f32", 3) == 0) { + if(endptr != pVal + len - 3){ // 78ri8 + *isValid = false; + smlBuildInvalidDataMsg(msg, "invalid float", endptr); + }else if(errno == ERANGE || !IS_VALID_FLOAT(result)){ + *isValid = false; + smlBuildInvalidDataMsg(msg, "float out of range[-3.402823466e+38,3.402823466e+38]", endptr); + }else{ + kvVal->f = result; + *isValid = true; + } + return true; + } + return false; +} + +static bool smlParseDouble(SSmlKv *kvVal, bool *isValid, SSmlMsgBuf *msg) { + const char *pVal = kvVal->value; + int32_t len = kvVal->valueLen; + if (len <= 3) { + return false; + } + const char *signalPos = pVal + len - 3; + if (strncasecmp(signalPos, "f64", 3) == 0) { + char *endptr = NULL; + errno = 0; + double result = strtod(pVal, &endptr); + if(endptr != signalPos){ // 78ri8 + *isValid = false; + smlBuildInvalidDataMsg(msg, "invalid double", endptr); + }else if(errno == ERANGE || !IS_VALID_DOUBLE(result)){ + *isValid = false; + smlBuildInvalidDataMsg(msg, "double out of range[-1.7976931348623158e+308,1.7976931348623158e+308]", endptr); + }else{ + kvVal->d = result; + *isValid = true; + } + return true; + } + return false; +} + +static bool smlParseBool(SSmlKv *kvVal) { + const char *pVal = kvVal->value; + int32_t len = kvVal->valueLen; + if ((len == 1) && pVal[len - 1] == 't') { + kvVal->i = true; + return true; + } + + if ((len == 1) && pVal[len - 1] == 'f') { + kvVal->i = false; + return true; + } + + if((len == 4) && !strncasecmp(pVal, "true", len)) { + kvVal->i = true; + return true; + } + if((len == 5) && !strncasecmp(pVal, "false", len)) { + kvVal->i = false; + return true; + } + return false; +} + +static bool smlIsBinary(const char *pVal, uint16_t len) { + //binary: "abc" + if (len < 2) { + return false; + } + if (pVal[0] == '"' && pVal[len - 1] == '"') { + return true; + } + return false; +} + +static bool smlIsNchar(const char *pVal, uint16_t len) { + //nchar: L"abc" + if (len < 3) { + return false; + } + if ((pVal[0] == 'l' || pVal[0] == 'L')&& pVal[1] == '"' && pVal[len - 1] == '"') { + return true; + } + return false; +} + +static bool smlParseValue(SSmlKv *pVal, SSmlMsgBuf *msg) { + // put high probability matching type first + bool isValid = false; + + //binary + if (smlIsBinary(pVal->value, pVal->valueLen)) { + pVal->type = TSDB_DATA_TYPE_BINARY; + pVal->valueLen -= 2; + pVal->length = pVal->valueLen; + pVal->value++; + return true; + } + //nchar + if (smlIsNchar(pVal->value, pVal->valueLen)) { + pVal->type = TSDB_DATA_TYPE_NCHAR; + pVal->valueLen -= 3; + pVal->length = pVal->valueLen; + pVal->value += 2; + return true; + } + //float + if (smlParseFloat(pVal, &isValid, msg)) { + if(!isValid) return false; + pVal->type = TSDB_DATA_TYPE_FLOAT; + pVal->length = (int16_t)tDataTypes[pVal->type].bytes; + return true; + } + //double + if (smlParseDouble(pVal, &isValid, msg)) { + if(!isValid) return false; + pVal->type = TSDB_DATA_TYPE_DOUBLE; + pVal->length = (int16_t)tDataTypes[pVal->type].bytes; + + return true; + } + //bool + if (smlParseBool(pVal)) { + pVal->type = TSDB_DATA_TYPE_BOOL; + pVal->length = (int16_t)tDataTypes[pVal->type].bytes; + return true; + } + + if (smlParseTinyInt(pVal, &isValid, msg)) { + if(!isValid) return false; + pVal->type = TSDB_DATA_TYPE_TINYINT; + pVal->length = (int16_t)tDataTypes[pVal->type].bytes; + return true; + } + if (smlParseTinyUint(pVal, &isValid, msg)) { + if(!isValid) return false; + pVal->type = TSDB_DATA_TYPE_UTINYINT; + pVal->length = (int16_t)tDataTypes[pVal->type].bytes; + return true; + } + if (smlParseSmallInt(pVal, &isValid, msg)) { + if(!isValid) return false; + pVal->type = TSDB_DATA_TYPE_SMALLINT; + pVal->length = (int16_t)tDataTypes[pVal->type].bytes; + return true; + } + if (smlParseSmallUint(pVal, &isValid, msg)) { + if(!isValid) return false; + pVal->type = TSDB_DATA_TYPE_USMALLINT; + pVal->length = (int16_t)tDataTypes[pVal->type].bytes; + return true; + } + if (smlParseInt(pVal, &isValid, msg)) { + if(!isValid) return false; + pVal->type = TSDB_DATA_TYPE_INT; + pVal->length = (int16_t)tDataTypes[pVal->type].bytes; + return true; + } + if (smlParseUint(pVal, &isValid, msg)) { + if(!isValid) return false; + pVal->type = TSDB_DATA_TYPE_UINT; + pVal->length = (int16_t)tDataTypes[pVal->type].bytes; + return true; + } + if (smlParseBigInt(pVal, &isValid, msg)) { + if(!isValid) return false; + pVal->type = TSDB_DATA_TYPE_BIGINT; + pVal->length = (int16_t)tDataTypes[pVal->type].bytes; + return true; + } + if (smlParseBigUint(pVal, &isValid, msg)) { + if(!isValid) return false; + pVal->type = TSDB_DATA_TYPE_UBIGINT; + pVal->length = (int16_t)tDataTypes[pVal->type].bytes; + return true; + } + + smlBuildInvalidDataMsg(msg, "invalid data", pVal->value); + return false; +} + +static bool checkDuplicateKey(char *key, SHashObj *pHash, SSmlHandle* info) { + char *val = NULL; + val = taosHashGet(pHash, key, strlen(key)); + if (val) { + uError("SML:0x%"PRIx64" Duplicate key detected:%s", info->id, key); + return true; + } + + uint8_t dummy_val = 0; + taosHashPut(pHash, key, strlen(key), &dummy_val, sizeof(uint8_t)); + + return false; +} + +static int32_t smlParseString(const char* sql, SSmlLineInfo *elements, SSmlMsgBuf *msg){ + if(!sql) return TSDB_CODE_SML_INVALID_DATA; + while (*sql != '\0') { // jump the space at the begining + if(*sql != SPACE) { + elements->measure = sql; + break; + } + sql++; + } + if (!elements->measure || *sql == COMMA) { + smlBuildInvalidDataMsg(msg, "invalid data", sql); + return TSDB_CODE_SML_INVALID_DATA; + } + + // parse measure and tag + while (*sql != '\0') { + if (elements->measureLen == 0 && *sql == COMMA && *(sql - 1) != SLASH) { // find the first comma + elements->measureLen = sql - elements->measure; + sql++; + elements->tags = sql; + continue; + } + + if (*sql == SPACE && *(sql - 1) != SLASH) { // find the first space + if (elements->measureLen == 0) { + elements->measureLen = sql - elements->measure; + elements->tags = sql; + } + elements->tagsLen = sql - elements->tags; + elements->measureTagsLen = sql - elements->measure; + break; + } + + sql++; + } + if(elements->tagsLen == 0){ // measure, cols1=a measure cols1=a + elements->measureTagsLen = elements->measureLen; + } + if(elements->measureLen == 0) { + smlBuildInvalidDataMsg(msg, "invalid measure", elements->measure); + return TSDB_CODE_SML_INVALID_DATA; + } + + // parse cols + while (*sql != '\0') { + if(*sql != SPACE) { + elements->cols = sql; + break; + } + sql++; + } + if(!elements->cols) { + smlBuildInvalidDataMsg(msg, "invalid columns", elements->cols); + return TSDB_CODE_SML_INVALID_DATA; + } + + bool isInQuote = false; + while (*sql != '\0') { + if(*sql == QUOTE && *(sql - 1) != SLASH){ + isInQuote = !isInQuote; + } + if(!isInQuote && *sql == SPACE && *(sql - 1) != SLASH) { + break; + } + sql++; + } + if(isInQuote){ + smlBuildInvalidDataMsg(msg, "only one quote", elements->cols); + return TSDB_CODE_SML_INVALID_DATA; + } + elements->colsLen = sql - elements->cols; + + // parse ts,ts can be empty + while (*sql != '\0') { + if(*sql != SPACE && elements->timestamp == NULL) { + elements->timestamp = sql; + } + if(*sql == SPACE && elements->timestamp != NULL){ + break; + } + sql++; + } + if(elements->timestamp){ + elements->timestampLen = sql - elements->timestamp; + } + + return TSDB_CODE_SUCCESS; +} + +static int32_t smlParseCols(const char* data, int32_t len, SArray *cols, bool isTag, SSmlMsgBuf *msg){ + if(isTag && len == 0){ + SSmlKv *kv = taosMemoryCalloc(sizeof(SSmlKv), 1); + kv->key = TAG; + kv->keyLen = strlen(TAG); + kv->value = TAG; + kv->valueLen = strlen(TAG); + kv->type = TSDB_DATA_TYPE_NCHAR; + if(cols) taosArrayPush(cols, &kv); + return TSDB_CODE_SUCCESS; + } + + for(int i = 0; i < len; i++){ + // parse key + const char *key = data + i; + int32_t keyLen = 0; + while(i < len){ + if(data[i] == EQUAL && i > 0 && data[i-1] != SLASH){ + keyLen = data + i - key; + break; + } + i++; + } + if(keyLen == 0 || keyLen >= TSDB_COL_NAME_LEN){ + smlBuildInvalidDataMsg(msg, "invalid key or key is too long than 64", key); + return TSDB_CODE_SML_INVALID_DATA; + } + + // parse value + i++; + const char *value = data + i; + bool isInQuote = false; + while(i < len){ + if(data[i] == QUOTE && data[i-1] != SLASH){ + isInQuote = !isInQuote; + } + if(!isInQuote && data[i] == COMMA && i > 0 && data[i-1] != SLASH){ + break; + } + i++; + } + if(isInQuote){ + smlBuildInvalidDataMsg(msg, "only one quote", value); + return TSDB_CODE_SML_INVALID_DATA; + } + int32_t valueLen = data + i - value; + if(valueLen == 0){ + smlBuildInvalidDataMsg(msg, "invalid value", value); + return TSDB_CODE_SML_INVALID_DATA; + } + + // add kv to SSmlKv + SSmlKv *kv = taosMemoryCalloc(sizeof(SSmlKv), 1); + kv->key = key; + kv->keyLen = keyLen; + kv->value = value; + kv->valueLen = valueLen; + if(isTag){ + kv->type = TSDB_DATA_TYPE_NCHAR; + }else{ + if(!smlParseValue(kv, msg)){ + return TSDB_CODE_SML_INVALID_DATA; + } + } + + if(cols) taosArrayPush(cols, &kv); + } + + return TSDB_CODE_SUCCESS; +} + +static int64_t smlGetTimeValue(const char *value, int32_t len, int8_t type) { + char *endPtr = NULL; + double ts = (double)strtoll(value, &endPtr, 10); + if(value + len != endPtr){ + return -1; + } + switch (type) { + case TSDB_TIME_PRECISION_HOURS: + ts *= (3600 * 1e9); + break; + case TSDB_TIME_PRECISION_MINUTES: + ts *= (60 * 1e9); + break; + case TSDB_TIME_PRECISION_SECONDS: + ts *= (1e9); + break; + case TSDB_TIME_PRECISION_MILLI: + ts *= (1e6); + break; + case TSDB_TIME_PRECISION_MICRO: + ts *= (1e3); + break; + case TSDB_TIME_PRECISION_NANO: + break; + default: + ASSERT(0); + } + if(ts > (double)INT64_MAX || ts < 0){ + return -1; + } + + return (int64_t)ts; +} + +static int64_t smlGetTimeNow(int8_t precision) { + switch (precision) { + case TSDB_TIME_PRECISION_HOURS: + return taosGetTimestampMs()/1000/3600; + case TSDB_TIME_PRECISION_MINUTES: + return taosGetTimestampMs()/1000/60; + case TSDB_TIME_PRECISION_SECONDS: + return taosGetTimestampMs()/1000; + case TSDB_TIME_PRECISION_MILLI: + case TSDB_TIME_PRECISION_MICRO: + case TSDB_TIME_PRECISION_NANO: + return taosGetTimestamp(precision); + default: + ASSERT(0); + } +} + +static int8_t smlGetTsTypeByLen(int32_t len) { + if (len == TSDB_TIME_PRECISION_SEC_DIGITS) { + return TSDB_TIME_PRECISION_SECONDS; + } else if (len == TSDB_TIME_PRECISION_MILLI_DIGITS) { + return TSDB_TIME_PRECISION_MILLI_DIGITS; + } else { + return -1; + } +} + +static int8_t smlGetTsTypeByPrecision(int8_t precision) { + switch (precision) { + case TSDB_SML_TIMESTAMP_HOURS: + return TSDB_TIME_PRECISION_HOURS; + case TSDB_SML_TIMESTAMP_MILLI_SECONDS: + return TSDB_TIME_PRECISION_MILLI; + case TSDB_SML_TIMESTAMP_NANO_SECONDS: + case TSDB_SML_TIMESTAMP_NOT_CONFIGURED: + return TSDB_TIME_PRECISION_NANO; + case TSDB_SML_TIMESTAMP_MICRO_SECONDS: + return TSDB_TIME_PRECISION_MICRO; + case TSDB_SML_TIMESTAMP_SECONDS: + return TSDB_TIME_PRECISION_SECONDS; + case TSDB_SML_TIMESTAMP_MINUTES: + return TSDB_TIME_PRECISION_MINUTES; + default: + return -1; + } +} + +static int64_t smlParseInfluxTime(SSmlHandle* info, const char* data, int32_t len){ + int8_t tsType = smlGetTsTypeByPrecision(info->precision); + if (tsType == -1) { + smlBuildInvalidDataMsg(&info->msgBuf, "invalid timestamp precision", NULL); + return -1; + } + if(!data){ + return smlGetTimeNow(tsType); + } + + int64_t ts = smlGetTimeValue(data, len, tsType); + if(ts == -1){ + smlBuildInvalidDataMsg(&info->msgBuf, "invalid timestamp", data); + return -1; + } + return ts; +} + +static int64_t smlParseOpenTsdbTime(SSmlHandle* info, const char* data, int32_t len){ + if(!data){ + smlBuildInvalidDataMsg(&info->msgBuf, "timestamp can not be null", NULL); + return -1; + } + int8_t tsType = smlGetTsTypeByLen(len); + if (tsType == -1) { + smlBuildInvalidDataMsg(&info->msgBuf, "timestamp precision can only be seconds(10 digits) or milli seconds(13 digits)", data); + return -1; + } + int64_t ts = smlGetTimeValue(data, len, tsType); + if(ts == -1){ + smlBuildInvalidDataMsg(&info->msgBuf, "invalid timestamp", data); + return -1; + } + return ts; +} + +static int32_t smlParseTS(SSmlHandle* info, const char* data, int32_t len, SArray *cols){ + int64_t ts = 0; + if(info->protocol == TSDB_SML_LINE_PROTOCOL){ + ts = smlParseInfluxTime(info, data, len); + }else{ + ts = smlParseOpenTsdbTime(info, data, len); + } + if(ts == -1) return TSDB_CODE_TSC_INVALID_TIME_STAMP; + + // add ts to + SSmlKv *kv = taosMemoryCalloc(sizeof(SSmlKv), 1); + if(!kv){ + return TSDB_CODE_OUT_OF_MEMORY; + } + + kv->key = TS; + kv->keyLen = strlen(kv->key); + kv->i = ts; + kv->type = TSDB_DATA_TYPE_TIMESTAMP; + kv->length = (int16_t)tDataTypes[kv->type].bytes; + if(cols) taosArrayPush(cols, &kv); + return TSDB_CODE_SUCCESS; +} + +//static int32_t parseSmlCols(const char* data, SArray *cols){ +// while(*data != '\0'){ +// if(*data == EQUAL) return TSDB_CODE_SML_INVALID_DATA; +// const char *key = data; +// int32_t keyLen = 0; +// while(*data != '\0'){ +// if(*data == EQUAL && *(data-1) != SLASH){ +// keyLen = data - key; +// data ++; +// break; +// } +// data++; +// } +// if(keyLen == 0){ +// return TSDB_CODE_SML_INVALID_DATA; +// } +// +// if(*data == COMMA) return TSDB_CODE_SML_INVALID_DATA; +// const char *value = data; +// int32_t valueLen = 0; +// while(*data != '\0'){ +// if(*data == COMMA && *(data-1) != SLASH){ +// valueLen = data - value; +// data ++; +// break; +// } +// data++; +// } +// if(valueLen == 0){ +// return TSDB_CODE_SML_INVALID_DATA; +// } +// +// TAOS_SML_KV *kv = taosMemoryCalloc(sizeof(TAOS_SML_KV), 1); +// kv->key = key; +// kv->keyLen = keyLen; +// kv->value = value; +// kv->valueLen = valueLen; +// kv->type = TSDB_DATA_TYPE_NCHAR; +// if(cols) taosArrayPush(cols, &kv); +// } +// return TSDB_CODE_SUCCESS; +//} + +static bool smlUpdateMeta(SSmlSTableMeta* tableMeta, SArray *tags, SArray *cols, SSmlMsgBuf *msg){ + if(tags){ + for (int i = 0; i < taosArrayGetSize(tags); ++i) { + SSmlKv *kv = taosArrayGetP(tags, i); + ASSERT(kv->type == TSDB_DATA_TYPE_NCHAR); + + SSmlKv **value = taosHashGet(tableMeta->tagHash, kv->key, kv->keyLen); + if(value){ + ASSERT((*value)->type == TSDB_DATA_TYPE_NCHAR); + if(kv->valueLen > (*value)->valueLen){ // tags type is nchar + *value = kv; + } + }else{ + taosHashPut(tableMeta->tagHash, kv->key, kv->keyLen, &kv, POINTER_BYTES); + } + } + } + + if(cols){ + for (int i = 1; i < taosArrayGetSize(cols); ++i) { //jump timestamp + SSmlKv *kv = taosArrayGetP(cols, i); + SSmlKv **value = taosHashGet(tableMeta->fieldHash, kv->key, kv->keyLen); + if(value){ + if(kv->type != (*value)->type){ + smlBuildInvalidDataMsg(msg, "the type is not the same like before", kv->key); + return false; + }else{ + if(IS_VAR_DATA_TYPE(kv->type)){ // update string len, if bigger + if(kv->valueLen > (*value)->valueLen){ + *value = kv; + } + } + } + }else{ + taosHashPut(tableMeta->fieldHash, kv->key, kv->keyLen, &kv, POINTER_BYTES); + } + } + } + return true; +} + +static void smlInsertMeta(SSmlSTableMeta* tableMeta, SArray *tags, SArray *cols){ + if(tags){ + for (int i = 0; i < taosArrayGetSize(tags); ++i) { + SSmlKv *kv = taosArrayGetP(tags, i); + taosHashPut(tableMeta->tagHash, kv->key, kv->keyLen, &kv, POINTER_BYTES); + } + } + + if(cols){ + for (int i = 0; i < taosArrayGetSize(cols); ++i) { + SSmlKv *kv = taosArrayGetP(cols, i); + taosHashPut(tableMeta->fieldHash, kv->key, kv->keyLen, &kv, POINTER_BYTES); + } + } +} + +static SSmlTableInfo* smlBuildTableInfo(bool format){ + SSmlTableInfo *tag = taosMemoryCalloc(sizeof(SSmlTableInfo), 1); + if(!tag){ + return NULL; + } + + if(format){ + tag->colsFormat = taosArrayInit(16, POINTER_BYTES); + if (tag->colsFormat == NULL) { + uError("SML:smlParseLine failed to allocate memory"); + goto cleanup; + } + }else{ + tag->cols = taosArrayInit(16, POINTER_BYTES); + if (tag->cols == NULL) { + uError("SML:smlParseLine failed to allocate memory"); + goto cleanup; + } + + tag->columnsHash = taosHashInit(32, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_NO_LOCK); + if (tag->columnsHash == NULL) { + uError("SML:smlParseLine failed to allocate memory"); + goto cleanup; + } + } + + tag->tags = taosArrayInit(16, POINTER_BYTES); + if (tag->tags == NULL) { + uError("SML:smlParseLine failed to allocate memory"); + goto cleanup; + } + return tag; + +cleanup: + taosMemoryFreeClear(tag); + return NULL; +} + +static void smlDestroyBuildTableInfo(SSmlTableInfo *tag, bool format){ + if(format){ + taosArrayDestroy(tag->colsFormat); + }else{ + tag->cols = taosArrayInit(16, POINTER_BYTES); + for(size_t i = 0; i < taosArrayGetSize(tag->cols); i++){ + SHashObj *kvHash = taosArrayGetP(tag->cols, i); + void** p1 = taosHashIterate(kvHash, NULL); + while (p1) { + SSmlKv* kv = *p1; + taosMemoryFreeClear(kv); + p1 = taosHashIterate(kvHash, p1); + } + taosHashCleanup(kvHash); + } + taosHashCleanup(tag->columnsHash); + } + taosArrayDestroy(tag->tags); + taosMemoryFreeClear(tag); +} + +static int32_t smlDealCols(SSmlTableInfo* oneTable, bool dataFormat, SArray *cols){ + if(dataFormat){ + taosArrayPush(oneTable->colsFormat, &cols); + }else{ + SHashObj *kvHash = taosHashInit(32, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_NO_LOCK); + if(!kvHash){ + uError("SML:smlDealCols failed to allocate memory"); + return TSDB_CODE_TSC_OUT_OF_MEMORY; + } + for(size_t i = 0; i < taosArrayGetSize(cols); i++){ + SSmlKv *kv = taosArrayGetP(cols, i); + taosHashPut(kvHash, kv->key, kv->keyLen, &kv, POINTER_BYTES); // todo key need escape, like \=, because find by schema name later + + if(taosHashGet(oneTable->columnsHash, kv->key, kv->keyLen) != NULL){ + continue; + } + taosHashPut(oneTable->columnsHash, kv->key, kv->keyLen, &kv, POINTER_BYTES); + } + taosArrayPush(oneTable->cols, &kvHash); + } + return TSDB_CODE_SUCCESS; +} + +static SSmlSTableMeta* smlBuildSTableMeta(){ + SSmlSTableMeta* meta = taosMemoryCalloc(sizeof(SSmlSTableMeta), 1); + if(!meta){ + return NULL; + } + meta->tagHash = taosHashInit(32, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_NO_LOCK); + if (meta->tagHash == NULL) { + uError("SML:smlBuildSTableMeta failed to allocate memory"); + goto cleanup; + } + + meta->fieldHash = taosHashInit(32, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_NO_LOCK); + if (meta->fieldHash == NULL) { + uError("SML:smlBuildSTableMeta failed to allocate memory"); + goto cleanup; + } + return meta; + +cleanup: + taosMemoryFreeClear(meta); + return NULL; +} + +static void smlDestroySTableMeta(SSmlSTableMeta *meta){ + taosHashCleanup(meta->tagHash); + taosHashCleanup(meta->fieldHash); + taosMemoryFree(meta->tableMeta); +} + +static int32_t smlParseLine(SSmlHandle* info, const char* sql) { + SSmlLineInfo elements = {0}; + int ret = smlParseString(sql, &elements, &info->msgBuf); + if(ret != TSDB_CODE_SUCCESS){ + uError("SML:0x%"PRIx64" smlParseString failed", info->id); + return ret; + } + + SArray *cols = taosArrayInit(16, POINTER_BYTES); + if (cols == NULL) { + uError("SML:0x%"PRIx64" smlParseLine failed to allocate memory", info->id); + return TSDB_CODE_TSC_OUT_OF_MEMORY; + } + + ret = smlParseTS(info, elements.timestamp, elements.timestampLen, cols); + if(ret != TSDB_CODE_SUCCESS){ + uError("SML:0x%"PRIx64" smlParseTS failed", info->id); + return ret; + } + ret = smlParseCols(elements.cols, elements.colsLen, cols, false, &info->msgBuf); + if(ret != TSDB_CODE_SUCCESS){ + uError("SML:0x%"PRIx64" smlParseCols parse cloums fields failed", info->id); + return ret; + } + if(taosArrayGetSize(cols) > TSDB_MAX_COLUMNS){ + smlBuildInvalidDataMsg(&info->msgBuf, "too many columns than 4096", NULL); + return TSDB_CODE_SML_INVALID_DATA; + } + + SSmlTableInfo **oneTable = taosHashGet(info->childTables, elements.measure, elements.measureTagsLen); + if(oneTable){ + SSmlSTableMeta** tableMeta = taosHashGet(info->superTables, elements.measure, elements.measureLen); + ASSERT(tableMeta); + ret = smlUpdateMeta(*tableMeta, NULL, cols, &info->msgBuf); // update meta cols + if(!ret){ + uError("SML:0x%"PRIx64" smlUpdateMeta cols failed", info->id); + return TSDB_CODE_SML_INVALID_DATA; + } + ret = smlDealCols(*oneTable, info->dataFormat, cols); + if(ret != TSDB_CODE_SUCCESS){ + return ret; + } + }else{ + SSmlTableInfo *tag = smlBuildTableInfo(info->dataFormat); + if(!tag){ + return TSDB_CODE_TSC_OUT_OF_MEMORY; + } + ret = smlDealCols(tag, info->dataFormat, cols); + if(ret != TSDB_CODE_SUCCESS){ + return ret; + } + + ret = smlParseCols(elements.tags, elements.tagsLen, tag->tags, true, &info->msgBuf); + if(ret != TSDB_CODE_SUCCESS){ + uError("SML:0x%"PRIx64" smlParseCols parse tag fields failed", info->id); + return ret; + } + + if(taosArrayGetSize(tag->tags) > TSDB_MAX_TAGS){ + smlBuildInvalidDataMsg(&info->msgBuf, "too many tags than 128", NULL); + return TSDB_CODE_SML_INVALID_DATA; + } + + tag->sTableName = elements.measure; + tag->sTableNameLen = elements.measureLen; + smlBuildChildTableName(tag); + uDebug("SML:0x%"PRIx64" child table name: %s", info->id, tag->childTableName); + + SSmlSTableMeta** tableMeta = taosHashGet(info->superTables, elements.measure, elements.measureLen); + if(tableMeta){ // update meta + ret = smlUpdateMeta(*tableMeta, tag->tags, cols, &info->msgBuf); + if(!ret){ + uError("SML:0x%"PRIx64" smlUpdateMeta failed", info->id); + return TSDB_CODE_SML_INVALID_DATA; + } + }else{ + SSmlSTableMeta *meta = smlBuildSTableMeta(); + smlInsertMeta(meta, tag->tags, cols); + taosHashPut(info->superTables, elements.measure, elements.measureLen, &meta, POINTER_BYTES); + } + + taosHashPut(info->childTables, elements.measure, elements.measureTagsLen, &tag, POINTER_BYTES); + } + return TSDB_CODE_SUCCESS; +} + +static void smlDestroyInfo(SSmlHandle* info){ + if(!info) return; + qDestroyQuery(info->pQuery); + smlDestroyHandle(info->exec); + + // destroy info->childTables + void** p1 = taosHashIterate(info->childTables, NULL); + while (p1) { + SSmlTableInfo* oneTable = *p1; + smlDestroyBuildTableInfo(oneTable, info->dataFormat); + p1 = taosHashIterate(info->childTables, p1); + } + taosHashCleanup(info->childTables); + + // destroy info->superTables + p1 = taosHashIterate(info->superTables, NULL); + while (p1) { + SSmlSTableMeta* oneTable = *p1; + smlDestroySTableMeta(oneTable); + p1 = taosHashIterate(info->superTables, p1); + } + taosHashCleanup(info->superTables); + + // destroy info->pVgHash + taosHashCleanup(info->pVgHash); + + taosMemoryFreeClear(info); +} + +static SSmlHandle* smlBuildSmlInfo(TAOS* taos, SRequestObj* request, SMLProtocolType protocol, int8_t precision, bool dataFormat){ + int32_t code = TSDB_CODE_SUCCESS; + SSmlHandle* info = taosMemoryMalloc(sizeof(SSmlHandle)); + if (NULL == info) { + return NULL; + } + info->id = smlGenId(); + + info->pQuery = taosMemoryCalloc(1, sizeof(SQuery)); + if (NULL == info->pQuery) { + uError("SML:0x%"PRIx64" create info->pQuery error", info->id); + goto cleanup; + } + info->pQuery->execMode = QUERY_EXEC_MODE_SCHEDULE; + info->pQuery->haveResultSet = false; + info->pQuery->msgType = TDMT_VND_SUBMIT; + info->pQuery->pRoot = (SNode*)nodesMakeNode(QUERY_NODE_VNODE_MODIF_STMT); + if(NULL == info->pQuery->pRoot){ + uError("SML:0x%"PRIx64" create info->pQuery->pRoot error", info->id); + goto cleanup; + } + ((SVnodeModifOpStmt*)(info->pQuery->pRoot))->payloadType = PAYLOAD_TYPE_KV; + + info->taos = taos; + code = catalogGetHandle(info->taos->pAppInfo->clusterId, &info->pCatalog); + if(code != TSDB_CODE_SUCCESS){ + uError("SML:0x%"PRIx64" get catalog error %d", info->id, code); + goto cleanup; + } + + info->precision = precision; + info->protocol = protocol; + info->dataFormat = dataFormat; + info->pRequest = request; + info->msgBuf.buf = info->pRequest->msgBuf; + info->msgBuf.len = ERROR_MSG_BUF_DEFAULT_SIZE; + + info->exec = smlInitHandle(info->pQuery); + info->childTables = taosHashInit(32, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_NO_LOCK); + info->superTables = taosHashInit(32, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_NO_LOCK); + info->pVgHash = taosHashInit(16, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, HASH_NO_LOCK); + + if(NULL == info->exec || NULL == info->childTables + || NULL == info->superTables || NULL == info->pVgHash){ + uError("SML:0x%"PRIx64" create info failed", info->id); + goto cleanup; + } + + return info; +cleanup: + smlDestroyInfo(info); + return NULL; +} +static int32_t smlInsertData(SSmlHandle* info) { + int32_t code = TSDB_CODE_SUCCESS; + + SSmlTableInfo** oneTable = taosHashIterate(info->childTables, NULL); + while (oneTable) { + SSmlTableInfo* tableData = *oneTable; + + SName pName = {TSDB_TABLE_NAME_T, info->taos->acctId, {0}, {0}}; + strcpy(pName.dbname, info->pRequest->pDb); + memcpy(pName.tname, tableData->childTableName, strlen(tableData->childTableName)); + SEpSet ep = getEpSet_s(&info->taos->pAppInfo->mgmtEp); + SVgroupInfo vg; + code = catalogGetTableHashVgroup(info->pCatalog, info->taos->pAppInfo->pTransporter, &ep, &pName, &vg); + if (code != 0) { + uError("SML:0x%"PRIx64" catalogGetTableHashVgroup failed. table name: %s", info->id, tableData->childTableName); + return code; + } + taosHashPut(info->pVgHash, (const char*)&vg.vgId, sizeof(vg.vgId), (char*)&vg, sizeof(vg)); + + SSmlSTableMeta** pMeta = taosHashGet(info->superTables, tableData->sTableName, tableData->sTableNameLen); + ASSERT (NULL != pMeta && NULL != *pMeta); + + // use tablemeta of stable to save vgid and uid of child table + (*pMeta)->tableMeta->vgId = vg.vgId; + (*pMeta)->tableMeta->uid = tableData->uid; // one table merge data block together according uid + + code = smlBindData(info->exec, tableData->tags, tableData->colsFormat, tableData->columnsHash, + tableData->cols, info->dataFormat, (*pMeta)->tableMeta, tableData->childTableName, info->msgBuf.buf, info->msgBuf.len); + if(code != TSDB_CODE_SUCCESS){ + return code; + } + oneTable = taosHashIterate(info->childTables, oneTable); + } + + smlBuildOutput(info->exec, info->pVgHash); + launchQueryImpl(info->pRequest, info->pQuery, TSDB_CODE_SUCCESS, true); + + info->affectedRows = taos_affected_rows(info->pRequest); + return info->pRequest->code; +} + +static int smlInsertLines(SSmlHandle *info, char* lines[], int numLines) { + int32_t code = TSDB_CODE_SUCCESS; + + if (numLines <= 0 || numLines > 65536) { + uError("SML:0x%"PRIx64" smlInsertLines numLines should be between 1 and 65536. numLines: %d", info->id, numLines); + code = TSDB_CODE_TSC_APP_ERROR; + goto cleanup; + } + + for (int32_t i = 0; i < numLines; ++i) { + code = smlParseLine(info, lines[i]); + if (code != TSDB_CODE_SUCCESS) { + uError("SML:0x%"PRIx64" smlParseLine failed. line %d : %s", info->id, i, lines[i]); + goto cleanup; + } + } + uDebug("SML:0x%"PRIx64" smlInsertLines parse success. tables %d", info->id, taosHashGetSize(info->childTables)); + uDebug("SML:0x%"PRIx64" smlInsertLines parse success. super tables %d", info->id, taosHashGetSize(info->superTables)); + + code = smlModifyDBSchemas(info); + if (code != 0) { + uError("SML:0x%"PRIx64" smlModifyDBSchemas error : %s", info->id, tstrerror(code)); + goto cleanup; + } + + code = smlInsertData(info); + if (code != 0) { + uError("SML:0x%"PRIx64" smlInsertData error : %s", info->id, tstrerror(code)); + goto cleanup; + } + + uDebug("SML:0x%"PRIx64" smlInsertLines finish inserting %d lines.", info->id, numLines); + +cleanup: + return code; +} + +/** + * taos_schemaless_insert() parse and insert data points into database according to + * different protocol. + * + * @param $lines input array may contain multiple lines, each line indicates a data point. + * If protocol=2 is used input array should contain single JSON + * string(e.g. char *lines[] = {"$JSON_string"}). If need to insert + * multiple data points in JSON format, should include them in $JSON_string + * as a JSON array. + * @param $numLines indicates how many data points in $lines. + * If protocol = 2 is used this param will be ignored as $lines should + * contain single JSON string. + * @param $protocol indicates which protocol to use for parsing: + * 0 - influxDB line protocol + * 1 - OpenTSDB telnet line protocol + * 2 - OpenTSDB JSON format protocol + * @return return zero for successful insertion. Otherwise return none-zero error code of + * failure reason. + * + */ + +TAOS_RES* taos_schemaless_insert(TAOS* taos, char* lines[], int numLines, int protocol, int precision) { + SRequestObj* request = createRequest(taos, NULL, NULL, TSDB_SQL_INSERT); + if(!request){ + return NULL; + } + + SSmlHandle* info = smlBuildSmlInfo(taos, request, protocol, precision, false); + if(!info){ + return (TAOS_RES*)request; + } + + switch (protocol) { + case TSDB_SML_LINE_PROTOCOL:{ + smlInsertLines(info, lines, numLines); + break; + } + case TSDB_SML_TELNET_PROTOCOL: + //code = taos_insert_telnet_lines(taos, lines, numLines, protocol, tsType, &affected_rows); + break; + case TSDB_SML_JSON_PROTOCOL: + //code = taos_insert_json_payload(taos, *lines, protocol, tsType, &affected_rows); + break; + default: + break; + } + smlDestroyInfo(info); + +end: + return (TAOS_RES*)request; +} + diff --git a/source/client/src/clientStmt.c b/source/client/src/clientStmt.c index f7ef1f7e81..3c94de1cef 100644 --- a/source/client/src/clientStmt.c +++ b/source/client/src/clientStmt.c @@ -458,7 +458,7 @@ int stmtSetTbTags(TAOS_STMT *stmt, TAOS_MULTI_BIND *tags) { STMT_ERR_RET(TSDB_CODE_QRY_APP_ERROR); } - STMT_ERR_RET(qBindStmtTagsValue(*pDataBlock, pStmt->bInfo.boundTags, pStmt->bInfo.tbSuid, &pStmt->bInfo.sname, tags, pStmt->exec.pRequest->msgBuf, pStmt->exec.pRequest->msgBufLen)); + STMT_ERR_RET(qBindStmtTagsValue(*pDataBlock, pStmt->bInfo.boundTags, pStmt->bInfo.tbSuid, pStmt->bInfo.sname.tname, tags, pStmt->exec.pRequest->msgBuf, pStmt->exec.pRequest->msgBufLen)); return TSDB_CODE_SUCCESS; } diff --git a/source/client/test/CMakeLists.txt b/source/client/test/CMakeLists.txt index 9df6b260f6..3fc91d07b6 100644 --- a/source/client/test/CMakeLists.txt +++ b/source/client/test/CMakeLists.txt @@ -17,14 +17,27 @@ TARGET_LINK_LIBRARIES( PUBLIC os util common transport parser catalog scheduler function gtest taos_static qcom ) +ADD_EXECUTABLE(smlTest smlTest.cpp) +TARGET_LINK_LIBRARIES( + smlTest + PUBLIC os util common transport parser catalog scheduler function gtest taos_static qcom +) + TARGET_INCLUDE_DIRECTORIES( clientTest - PUBLIC "${TD_SOURCE_DIR}/include/libs/client/" - PRIVATE "${TD_SOURCE_DIR}/source/libs/client/inc" + PUBLIC "${TD_SOURCE_DIR}/include/client/" + PRIVATE "${TD_SOURCE_DIR}/source/client/inc" ) TARGET_INCLUDE_DIRECTORIES( tmqTest - PUBLIC "${TD_SOURCE_DIR}/include/libs/client/" - PRIVATE "${TD_SOURCE_DIR}/source/libs/client/inc" + PUBLIC "${TD_SOURCE_DIR}/include/client/" + PRIVATE "${TD_SOURCE_DIR}/source/client/inc" ) + +TARGET_INCLUDE_DIRECTORIES( + smlTest + PUBLIC "${TD_SOURCE_DIR}/include/client/" + PRIVATE "${TD_SOURCE_DIR}/source/client/inc" +) + diff --git a/source/client/test/smlTest.cpp b/source/client/test/smlTest.cpp new file mode 100644 index 0000000000..5f0f188b0b --- /dev/null +++ b/source/client/test/smlTest.cpp @@ -0,0 +1,498 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * 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 . + */ + +#include + +#include +#include +#include + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wwrite-strings" +#pragma GCC diagnostic ignored "-Wunused-function" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wsign-compare" + +#include "../src/clientSml.c" +#include "taos.h" + +int main(int argc, char **argv) { + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} + +TEST(testCase, smlParseString_Test) { + char msg[256] = {0}; + SSmlMsgBuf msgBuf; + msgBuf.buf = msg; + msgBuf.len = 256; + SSmlLineInfo elements = {0}; + + // case 1 + char *sql = "st,t1=3,t2=4,t3=t3 c1=3i64,c3=\"passit hello,c1=2\",c2=false,c4=4f64 1626006833639000000 ,32,c=3"; + int ret = smlParseString(sql, &elements, &msgBuf); + ASSERT_EQ(ret, 0); + ASSERT_EQ(elements.measure, sql); + ASSERT_EQ(elements.measureLen, strlen("st")); + ASSERT_EQ(elements.measureTagsLen, strlen("st,t1=3,t2=4,t3=t3")); + + ASSERT_EQ(elements.tags, sql + elements.measureLen + 1); + ASSERT_EQ(elements.tagsLen, strlen("t1=3,t2=4,t3=t3")); + + ASSERT_EQ(elements.cols, sql + elements.measureTagsLen + 1); + ASSERT_EQ(elements.colsLen, strlen("c1=3i64,c3=\"passit hello,c1=2\",c2=false,c4=4f64")); + + ASSERT_EQ(elements.timestamp, sql + elements.measureTagsLen + 1 + elements.colsLen + 1); + ASSERT_EQ(elements.timestampLen, strlen("1626006833639000000")); + + // case 2 false + sql = "st,t1=3,t2=4,t3=t3 c1=3i64,c3=\"passit hello,c1=2,c2=false,c4=4f64 1626006833639000000"; + memset(&elements, 0, sizeof(SSmlLineInfo)); + ret = smlParseString(sql, &elements, &msgBuf); + ASSERT_NE(ret, 0); + + // case 3 false + sql = "st, t1=3,t2=4,t3=t3 c1=3i64,c3=\"passit hello,c1=2,c2=false,c4=4f64 1626006833639000000"; + memset(&elements, 0, sizeof(SSmlLineInfo)); + ret = smlParseString(sql, &elements, &msgBuf); + ASSERT_EQ(ret, 0); + ASSERT_EQ(elements.cols, sql + elements.measureTagsLen + 2); + ASSERT_EQ(elements.colsLen, strlen("t1=3,t2=4,t3=t3")); + + // case 4 tag is null + sql = "st, c1=3i64,c3=\"passit hello,c1=2\",c2=false,c4=4f64 1626006833639000000"; + memset(&elements, 0, sizeof(SSmlLineInfo)); + ret = smlParseString(sql, &elements, &msgBuf); + ASSERT_EQ(ret, 0); + ASSERT_EQ(elements.measure, sql); + ASSERT_EQ(elements.measureLen, strlen("st")); + ASSERT_EQ(elements.measureTagsLen, strlen("st")); + + ASSERT_EQ(elements.tags, sql + elements.measureLen + 1); + ASSERT_EQ(elements.tagsLen, 0); + + ASSERT_EQ(elements.cols, sql + elements.measureTagsLen + 2); + ASSERT_EQ(elements.colsLen, strlen("c1=3i64,c3=\"passit hello,c1=2\",c2=false,c4=4f64")); + + ASSERT_EQ(elements.timestamp, sql + elements.measureTagsLen + 2 + elements.colsLen + 1); + ASSERT_EQ(elements.timestampLen, strlen("1626006833639000000")); + + // case 5 tag is null + sql = " st c1=3i64,c3=\"passit hello,c1=2\",c2=false,c4=4f64 1626006833639000000 "; + memset(&elements, 0, sizeof(SSmlLineInfo)); + ret = smlParseString(sql, &elements, &msgBuf); + sql++; + ASSERT_EQ(ret, 0); + ASSERT_EQ(elements.measure, sql); + ASSERT_EQ(elements.measureLen, strlen("st")); + ASSERT_EQ(elements.measureTagsLen, strlen("st")); + + ASSERT_EQ(elements.tags, sql + elements.measureLen); + ASSERT_EQ(elements.tagsLen, 0); + + ASSERT_EQ(elements.cols, sql + elements.measureTagsLen + 3); + ASSERT_EQ(elements.colsLen, strlen("c1=3i64,c3=\"passit hello,c1=2\",c2=false,c4=4f64")); + + ASSERT_EQ(elements.timestamp, sql + elements.measureTagsLen + 3 + elements.colsLen + 2); + ASSERT_EQ(elements.timestampLen, strlen("1626006833639000000")); + + // case 6 + sql = " st c1=3i64,c3=\"passit hello,c1=2\",c2=false,c4=4f64 "; + memset(&elements, 0, sizeof(SSmlLineInfo)); + ret = smlParseString(sql, &elements, &msgBuf); + ASSERT_EQ(ret, 0); + + // case 7 + sql = " st , "; + memset(&elements, 0, sizeof(SSmlLineInfo)); + ret = smlParseString(sql, &elements, &msgBuf); + sql++; + ASSERT_EQ(ret, 0); + ASSERT_EQ(elements.cols, sql + elements.measureTagsLen + 3); + ASSERT_EQ(elements.colsLen, strlen(",")); + + // case 8 false + sql = ", st , "; + memset(&elements, 0, sizeof(SSmlLineInfo)); + ret = smlParseString(sql, &elements, &msgBuf); + ASSERT_NE(ret, 0); +} + +TEST(testCase, smlParseCols_Error_Test) { + const char *data[] = { + "c=\"89sd", // binary, nchar + "c=j\"89sd\"", + "c=\"89sd\"k", + "c=u", // bool + "c=truet", + "c=f64", // double + "c=8f64f", + "c=8ef64", + "c=1.7976931348623158e+390f64", + "c=f32", // float + "c=8f32f", + "c=8wef32", + "c=-3.402823466e+39f32", + "c=", // float + "c=8f", + "c=8we", + "c=3.402823466e+39", + "c=i8", // tiny int + "c=-8i8f", + "c=8wei8", + "c=-999i8", + "c=u8", // u tiny int + "c=8fu8", + "c=8weu8", + "c=999u8", + "c=-8u8", + "c=i16", // small int + "c=8fi16u", + "c=8wei16", + "c=-67787i16", + "c=u16", // u small int + "c=8u16f", + "c=8weu16", + "c=-9u16", + "c=67787u16", + "c=i32", // int + "c=8i32f", + "c=8wei32", + "c=2147483649i32", + "c=u32", // u int + "c=8u32f", + "c=8weu32", + "c=-4u32", + "c=42949672958u32", + "c=i64", // big int + "c=8i64i", + "c=8wei64", + "c=-9223372036854775809i64", + "c=i", // big int + "c=8fi", + "c=8wei", + "c=9223372036854775808i", + "c=u64", // u big int + "c=8u64f", + "c=8weu64", + "c=-3.402823466e+39u64", + "c=-339u64", + "c=18446744073709551616u64", + }; + + for(int i = 0; i < sizeof(data)/sizeof(data[0]); i++){ + char msg[256] = {0}; + SSmlMsgBuf msgBuf; + msgBuf.buf = msg; + msgBuf.len = 256; + int32_t len = strlen(data[i]); + int32_t ret = smlParseCols(data[i], len, NULL, false, &msgBuf); + ASSERT_NE(ret, TSDB_CODE_SUCCESS); + } +} + +TEST(testCase, smlParseCols_tag_Test) { + char msg[256] = {0}; + SSmlMsgBuf msgBuf; + msgBuf.buf = msg; + msgBuf.len = 256; + + SArray *cols = taosArrayInit(16, POINTER_BYTES); + ASSERT_NE(cols, NULL); + + const char *data = + "cbin=\"passit hello,c=2\",cnch=L\"iisdfsf\",cbool=false,cf64=4.31f64,cf32_=8.32,cf32=8.23f32,ci8=-34i8,cu8=89u8,ci16=233i16,cu16=898u16,ci32=98289i32,cu32=12323u32,ci64=-89238i64,ci=989i,cu64=8989323u64,cbooltrue=true,cboolt=t,cboolf=f,cnch_=l\"iuwq\""; + int32_t len = strlen(data); + int32_t ret = smlParseCols(data, len, cols, true, &msgBuf); + ASSERT_EQ(ret, TSDB_CODE_SUCCESS); + int32_t size = taosArrayGetSize(cols); + ASSERT_EQ(size, 19); + + // nchar + SSmlKv *kv = taosArrayGetP(cols, 0); + ASSERT_EQ(strncasecmp(kv->key, "cbin", 4), 0); + ASSERT_EQ(kv->keyLen, 4); + ASSERT_EQ(kv->type, TSDB_DATA_TYPE_NCHAR); + ASSERT_EQ(kv->valueLen, 18); + ASSERT_EQ(strncasecmp(kv->value, "\"passit", 7), 0); + taosMemoryFree(kv); + + // nchar + kv = taosArrayGetP(cols, 3); + ASSERT_EQ(strncasecmp(kv->key, "cf64", 4), 0); + ASSERT_EQ(kv->keyLen, 4); + ASSERT_EQ(kv->type, TSDB_DATA_TYPE_NCHAR); + ASSERT_EQ(kv->valueLen, 7); + ASSERT_EQ(strncasecmp(kv->value, "4.31f64", 7), 0); + taosMemoryFree(kv); + + taosArrayClear(cols); + data = "t=3e"; + len = 0; + memset(msgBuf.buf, 0, msgBuf.len); + ret = smlParseCols(data, len, cols, true, &msgBuf); + ASSERT_EQ(ret, TSDB_CODE_SUCCESS); + size = taosArrayGetSize(cols); + ASSERT_EQ(size, 1); + + // nchar + kv = taosArrayGetP(cols, 0); + ASSERT_EQ(strncasecmp(kv->key, TAG, strlen(TAG)), 0); + ASSERT_EQ(kv->keyLen, strlen(TAG)); + ASSERT_EQ(kv->type, TSDB_DATA_TYPE_NCHAR); + ASSERT_EQ(kv->valueLen, strlen(TAG)); + ASSERT_EQ(strncasecmp(kv->value, TAG, strlen(TAG)), 0); + taosMemoryFree(kv); +} + +TEST(testCase, smlParseCols_Test) { + char msg[256] = {0}; + SSmlMsgBuf msgBuf; + msgBuf.buf = msg; + msgBuf.len = 256; + + SArray *cols = taosArrayInit(16, POINTER_BYTES); + ASSERT_NE(cols, NULL); + + const char *data = "cbin=\"passit hello,c=2\",cnch=L\"iisdfsf\",cbool=false,cf64=4.31f64,cf32_=8.32,cf32=8.23f32,ci8=-34i8,cu8=89u8,ci16=233i16,cu16=898u16,ci32=98289i32,cu32=12323u32,ci64=-89238i64,ci=989i,cu64=8989323u64,cbooltrue=true,cboolt=t,cboolf=f,cnch_=l\"iuwq\""; + int32_t len = strlen(data); + int32_t ret = smlParseCols(data, len, cols, false, &msgBuf); + ASSERT_EQ(ret, TSDB_CODE_SUCCESS); + int32_t size = taosArrayGetSize(cols); + ASSERT_EQ(size, 19); + + // binary + SSmlKv *kv = taosArrayGetP(cols, 0); + ASSERT_EQ(strncasecmp(kv->key, "cbin", 4), 0); + ASSERT_EQ(kv->keyLen, 4); + ASSERT_EQ(kv->type, TSDB_DATA_TYPE_BINARY); + ASSERT_EQ(kv->length, 16); + ASSERT_EQ(strncasecmp(kv->value, "passit", 6), 0); + taosMemoryFree(kv); + + // nchar + kv = taosArrayGetP(cols, 1); + ASSERT_EQ(strncasecmp(kv->key, "cnch", 4), 0); + ASSERT_EQ(kv->keyLen, 4); + ASSERT_EQ(kv->type, TSDB_DATA_TYPE_NCHAR); + ASSERT_EQ(kv->length, 7); + ASSERT_EQ(strncasecmp(kv->value, "iisd", 4), 0); + taosMemoryFree(kv); + + // bool + kv = taosArrayGetP(cols, 2); + ASSERT_EQ(strncasecmp(kv->key, "cbool", 5), 0); + ASSERT_EQ(kv->keyLen, 5); + ASSERT_EQ(kv->type, TSDB_DATA_TYPE_BOOL); + ASSERT_EQ(kv->length, 1); + ASSERT_EQ(kv->i, false); + taosMemoryFree(kv); + + // double + kv = taosArrayGetP(cols, 3); + ASSERT_EQ(strncasecmp(kv->key, "cf64", 4), 0); + ASSERT_EQ(kv->keyLen, 4); + ASSERT_EQ(kv->type, TSDB_DATA_TYPE_DOUBLE); + ASSERT_EQ(kv->length, 8); + //ASSERT_EQ(kv->d, 4.31); + printf("4.31 = kv->f:%f\n", kv->d); + taosMemoryFree(kv); + + // float + kv = taosArrayGetP(cols, 4); + ASSERT_EQ(strncasecmp(kv->key, "cf32_", 5), 0); + ASSERT_EQ(kv->keyLen, 5); + ASSERT_EQ(kv->type, TSDB_DATA_TYPE_FLOAT); + ASSERT_EQ(kv->length, 4); + //ASSERT_EQ(kv->f, 8.32); + printf("8.32 = kv->f:%f\n", kv->f); + taosMemoryFree(kv); + + // float + kv = taosArrayGetP(cols, 5); + ASSERT_EQ(strncasecmp(kv->key, "cf32", 4), 0); + ASSERT_EQ(kv->keyLen, 4); + ASSERT_EQ(kv->type, TSDB_DATA_TYPE_FLOAT); + ASSERT_EQ(kv->length, 4); + //ASSERT_EQ(kv->f, 8.23); + printf("8.23 = kv->f:%f\n", kv->f); + taosMemoryFree(kv); + + // tiny int + kv = taosArrayGetP(cols, 6); + ASSERT_EQ(strncasecmp(kv->key, "ci8", 3), 0); + ASSERT_EQ(kv->keyLen, 3); + ASSERT_EQ(kv->type, TSDB_DATA_TYPE_TINYINT); + ASSERT_EQ(kv->length, 1); + ASSERT_EQ(kv->i, -34); + taosMemoryFree(kv); + + // unsigned tiny int + kv = taosArrayGetP(cols, 7); + ASSERT_EQ(strncasecmp(kv->key, "cu8", 3), 0); + ASSERT_EQ(kv->keyLen, 3); + ASSERT_EQ(kv->type, TSDB_DATA_TYPE_UTINYINT); + ASSERT_EQ(kv->length, 1); + ASSERT_EQ(kv->u, 89); + taosMemoryFree(kv); + + // small int + kv = taosArrayGetP(cols, 8); + ASSERT_EQ(strncasecmp(kv->key, "ci16", 4), 0); + ASSERT_EQ(kv->keyLen, 4); + ASSERT_EQ(kv->type, TSDB_DATA_TYPE_SMALLINT); + ASSERT_EQ(kv->length, 2); + ASSERT_EQ(kv->u, 233); + taosMemoryFree(kv); + + // unsigned smallint + kv = taosArrayGetP(cols, 9); + ASSERT_EQ(strncasecmp(kv->key, "cu16", 4), 0); + ASSERT_EQ(kv->keyLen, 4); + ASSERT_EQ(kv->type, TSDB_DATA_TYPE_USMALLINT); + ASSERT_EQ(kv->length, 2); + ASSERT_EQ(kv->u, 898); + taosMemoryFree(kv); + + // int + kv = taosArrayGetP(cols, 10); + ASSERT_EQ(strncasecmp(kv->key, "ci32", 4), 0); + ASSERT_EQ(kv->keyLen, 4); + ASSERT_EQ(kv->type, TSDB_DATA_TYPE_INT); + ASSERT_EQ(kv->length, 4); + ASSERT_EQ(kv->u, 98289); + taosMemoryFree(kv); + + // unsigned int + kv = taosArrayGetP(cols, 11); + ASSERT_EQ(strncasecmp(kv->key, "cu32", 4), 0); + ASSERT_EQ(kv->keyLen, 4); + ASSERT_EQ(kv->type, TSDB_DATA_TYPE_UINT); + ASSERT_EQ(kv->length, 4); + ASSERT_EQ(kv->u, 12323); + taosMemoryFree(kv); + + + // bigint + kv = taosArrayGetP(cols, 12); + ASSERT_EQ(strncasecmp(kv->key, "ci64", 4), 0); + ASSERT_EQ(kv->keyLen, 4); + ASSERT_EQ(kv->type, TSDB_DATA_TYPE_BIGINT); + ASSERT_EQ(kv->length, 8); + ASSERT_EQ(kv->i, -89238); + taosMemoryFree(kv); + + // bigint + kv = taosArrayGetP(cols, 13); + ASSERT_EQ(strncasecmp(kv->key, "ci", 2), 0); + ASSERT_EQ(kv->keyLen, 2); + ASSERT_EQ(kv->type, TSDB_DATA_TYPE_BIGINT); + ASSERT_EQ(kv->length, 8); + ASSERT_EQ(kv->i, 989); + taosMemoryFree(kv); + + // unsigned bigint + kv = taosArrayGetP(cols, 14); + ASSERT_EQ(strncasecmp(kv->key, "cu64", 4), 0); + ASSERT_EQ(kv->keyLen, 4); + ASSERT_EQ(kv->type, TSDB_DATA_TYPE_UBIGINT); + ASSERT_EQ(kv->length, 8); + ASSERT_EQ(kv->u, 8989323); + taosMemoryFree(kv); + + // bool + kv = taosArrayGetP(cols, 15); + ASSERT_EQ(strncasecmp(kv->key, "cbooltrue", 9), 0); + ASSERT_EQ(kv->keyLen, 9); + ASSERT_EQ(kv->type, TSDB_DATA_TYPE_BOOL); + ASSERT_EQ(kv->length, 1); + ASSERT_EQ(kv->i, true); + taosMemoryFree(kv); + + + // bool + kv = taosArrayGetP(cols, 16); + ASSERT_EQ(strncasecmp(kv->key, "cboolt", 6), 0); + ASSERT_EQ(kv->keyLen, 6); + ASSERT_EQ(kv->type, TSDB_DATA_TYPE_BOOL); + ASSERT_EQ(kv->length, 1); + ASSERT_EQ(kv->i, true); + taosMemoryFree(kv); + + // bool + kv = taosArrayGetP(cols, 17); + ASSERT_EQ(strncasecmp(kv->key, "cboolf", 6), 0); + ASSERT_EQ(kv->keyLen, 6); + ASSERT_EQ(kv->type, TSDB_DATA_TYPE_BOOL); + ASSERT_EQ(kv->length, 1); + ASSERT_EQ(kv->i, false); + taosMemoryFree(kv); + + // nchar + kv = taosArrayGetP(cols, 18); + ASSERT_EQ(strncasecmp(kv->key, "cnch_", 5), 0); + ASSERT_EQ(kv->keyLen, 5); + ASSERT_EQ(kv->type, TSDB_DATA_TYPE_NCHAR); + ASSERT_EQ(kv->length, 4); + ASSERT_EQ(strncasecmp(kv->value, "iuwq", 4), 0); + taosMemoryFree(kv); + + taosArrayDestroy(cols); +} + +TEST(testCase, smlParseLine_Test) { + TAOS *taos = taos_connect("localhost", "root", "taosdata", NULL, 0); + ASSERT_NE(taos, NULL); + + TAOS_RES* pRes = taos_query(taos, "create database if not exists sml_db"); + taos_free_result(pRes); + + pRes = taos_query(taos, "use sml_db"); + taos_free_result(pRes); + + SRequestObj *request = createRequest(taos, NULL, NULL, TSDB_SQL_INSERT); + ASSERT_NE(request, NULL); + + SSmlHandle *info = smlBuildSmlInfo(taos, request, TSDB_SML_LINE_PROTOCOL, TSDB_SML_TIMESTAMP_NANO_SECONDS, true); + ASSERT_NE(info, NULL); + + const char *sql[3] = { + "readings,name=truck_0,fleet=South,driver=Trish,model=H-2,device_version=v2.3 load_capacity=1500,fuel_capacity=150,nominal_fuel_consumption=12,latitude=52.31854,longitude=4.72037,elevation=124,velocity=0,heading=221,grade=0,fuel_consumption=25 1451606400000000000", + "readings,name=truck_1,fleet=South,driver=Albert,model=F-150,device_version=v1.5 load_capacity=2000,fuel_capacity=200,nominal_fuel_consumption=15,latitude=72.45258,longitude=68.83761,elevation=255,velocity=0,heading=181,grade=0,fuel_consumption=25 1451606400000000000", + "readings,name=truck_2,fleet=North,driver=Derek,model=F-150,device_version=v1.5 load_capacity=2000,fuel_capacity=200,nominal_fuel_consumption=15,latitude=24.5208,longitude=28.09377,elevation=428,velocity=0,heading=304,grade=0,fuel_consumption=25 1451606400000000000" + }; + smlInsertLines(info, sql, 3); +// for (int i = 0; i < 3; i++) { +// smlParseLine(info, sql[i]); +// } +} + +// TEST(testCase, smlParseTS_Test) { +// char msg[256] = {0}; +// SSmlMsgBuf msgBuf; +// msgBuf.buf = msg; +// msgBuf.len = 256; +// SSmlLineInfo elements = {0}; +// +// SSmlHandle* info = smlBuildSmlInfo(taos, request, protocol, precision, dataFormat); +// if(!info){ +// return (TAOS_RES*)request; +// } +// ret = smlParseTS(info, elements.timestamp, elements.timestampLen, cols); +// if(ret != TSDB_CODE_SUCCESS){ +// uError("SML:0x%"PRIx64" smlParseTS failed", info->id); +// return ret; +// } +// } diff --git a/source/common/src/tmsg.c b/source/common/src/tmsg.c index 6278b52a04..daa25719ad 100644 --- a/source/common/src/tmsg.c +++ b/source/common/src/tmsg.c @@ -594,7 +594,7 @@ int32_t tDeserializeSMDropStbReq(void *buf, int32_t bufLen, SMDropStbReq *pReq) return 0; } -int32_t tSerializeSMAlterStbReq(void *buf, int32_t bufLen, SMAltertbReq *pReq) { +int32_t tSerializeSMAlterStbReq(void *buf, int32_t bufLen, SMAlterStbReq *pReq) { SCoder encoder = {0}; tCoderInit(&encoder, TD_LITTLE_ENDIAN, buf, bufLen, TD_ENCODER); @@ -615,7 +615,7 @@ int32_t tSerializeSMAlterStbReq(void *buf, int32_t bufLen, SMAltertbReq *pReq) { return tlen; } -int32_t tDeserializeSMAlterStbReq(void *buf, int32_t bufLen, SMAltertbReq *pReq) { +int32_t tDeserializeSMAlterStbReq(void *buf, int32_t bufLen, SMAlterStbReq *pReq) { SCoder decoder = {0}; tCoderInit(&decoder, TD_LITTLE_ENDIAN, buf, bufLen, TD_DECODER); @@ -645,7 +645,7 @@ int32_t tDeserializeSMAlterStbReq(void *buf, int32_t bufLen, SMAltertbReq *pReq) return 0; } -void tFreeSMAltertbReq(SMAltertbReq *pReq) { +void tFreeSMAltertbReq(SMAlterStbReq *pReq) { taosArrayDestroy(pReq->pFields); pReq->pFields = NULL; } @@ -1255,7 +1255,6 @@ int32_t tDeserializeSGetUserAuthRspImpl(SCoder *pDecoder, SGetUserAuthRsp *pRsp) return 0; } - int32_t tDeserializeSGetUserAuthRsp(void *buf, int32_t bufLen, SGetUserAuthRsp *pRsp) { SCoder decoder = {0}; tCoderInit(&decoder, TD_LITTLE_ENDIAN, buf, bufLen, TD_DECODER); @@ -2091,7 +2090,7 @@ void tFreeSUseDbBatchRsp(SUseDbBatchRsp *pRsp) { taosArrayDestroy(pRsp->pArray); } -int32_t tSerializeSUserAuthBatchRsp(void* buf, int32_t bufLen, SUserAuthBatchRsp* pRsp){ +int32_t tSerializeSUserAuthBatchRsp(void *buf, int32_t bufLen, SUserAuthBatchRsp *pRsp) { SCoder encoder = {0}; tCoderInit(&encoder, TD_LITTLE_ENDIAN, buf, bufLen, TD_ENCODER); @@ -2110,7 +2109,7 @@ int32_t tSerializeSUserAuthBatchRsp(void* buf, int32_t bufLen, SUserAuthBatchRsp return tlen; } -int32_t tDeserializeSUserAuthBatchRsp(void* buf, int32_t bufLen, SUserAuthBatchRsp* pRsp){ +int32_t tDeserializeSUserAuthBatchRsp(void *buf, int32_t bufLen, SUserAuthBatchRsp *pRsp) { SCoder decoder = {0}; tCoderInit(&decoder, TD_LITTLE_ENDIAN, buf, bufLen, TD_DECODER); @@ -2136,7 +2135,7 @@ int32_t tDeserializeSUserAuthBatchRsp(void* buf, int32_t bufLen, SUserAuthBatchR return 0; } -void tFreeSUserAuthBatchRsp(SUserAuthBatchRsp* pRsp){ +void tFreeSUserAuthBatchRsp(SUserAuthBatchRsp *pRsp) { int32_t numOfBatch = taosArrayGetSize(pRsp->pArray); for (int32_t i = 0; i < numOfBatch; ++i) { SGetUserAuthRsp *pUserAuthRsp = taosArrayGet(pRsp->pArray, i); @@ -2146,7 +2145,6 @@ void tFreeSUserAuthBatchRsp(SUserAuthBatchRsp* pRsp){ taosArrayDestroy(pRsp->pArray); } - int32_t tSerializeSDbCfgReq(void *buf, int32_t bufLen, SDbCfgReq *pReq) { SCoder encoder = {0}; tCoderInit(&encoder, TD_LITTLE_ENDIAN, buf, bufLen, TD_ENCODER); @@ -3746,6 +3744,7 @@ STSchema *tdGetSTSChemaFromSSChema(SSchema **pSchema, int32_t nCols) { int tEncodeSVCreateTbReq(SCoder *pCoder, const SVCreateTbReq *pReq) { if (tStartEncode(pCoder) < 0) return -1; + if (tEncodeI32v(pCoder, pReq->flags) < 0) return -1; if (tEncodeI64(pCoder, pReq->uid) < 0) return -1; if (tEncodeI64(pCoder, pReq->ctime) < 0) return -1; @@ -3771,6 +3770,7 @@ int tDecodeSVCreateTbReq(SCoder *pCoder, SVCreateTbReq *pReq) { if (tStartDecode(pCoder) < 0) return -1; + if (tDecodeI32v(pCoder, &pReq->flags) < 0) return -1; if (tDecodeI64(pCoder, &pReq->uid) < 0) return -1; if (tDecodeI64(pCoder, &pReq->ctime) < 0) return -1; diff --git a/source/dnode/mgmt/mgmt_qnode/src/qmHandle.c b/source/dnode/mgmt/mgmt_qnode/src/qmHandle.c index 805b4c7264..11b91f0568 100644 --- a/source/dnode/mgmt/mgmt_qnode/src/qmHandle.c +++ b/source/dnode/mgmt/mgmt_qnode/src/qmHandle.c @@ -101,6 +101,7 @@ void qmInitMsgHandle(SMgmtWrapper *pWrapper) { dmSetMsgHandle(pWrapper, TDMT_VND_QUERY_CONTINUE, qmProcessQueryMsg, QNODE_HANDLE); dmSetMsgHandle(pWrapper, TDMT_VND_FETCH, qmProcessFetchMsg, QNODE_HANDLE); dmSetMsgHandle(pWrapper, TDMT_VND_FETCH_RSP, qmProcessFetchMsg, QNODE_HANDLE); + dmSetMsgHandle(pWrapper, TDMT_VND_QUERY_HEARTBEAT, qmProcessFetchMsg, QNODE_HANDLE); dmSetMsgHandle(pWrapper, TDMT_VND_RES_READY, qmProcessFetchMsg, QNODE_HANDLE); dmSetMsgHandle(pWrapper, TDMT_VND_TASKS_STATUS, qmProcessFetchMsg, QNODE_HANDLE); diff --git a/source/dnode/mgmt/mgmt_vnode/src/vmHandle.c b/source/dnode/mgmt/mgmt_vnode/src/vmHandle.c index e3816396c9..9329e7b15d 100644 --- a/source/dnode/mgmt/mgmt_vnode/src/vmHandle.c +++ b/source/dnode/mgmt/mgmt_vnode/src/vmHandle.c @@ -293,14 +293,10 @@ void vmInitMsgHandle(SMgmtWrapper *pWrapper) { dmSetMsgHandle(pWrapper, TDMT_VND_TASK_MERGE_EXEC, vmProcessMergeMsg, DEFAULT_HANDLE); dmSetMsgHandle(pWrapper, TDMT_VND_TASK_WRITE_EXEC, vmProcessWriteMsg, DEFAULT_HANDLE); dmSetMsgHandle(pWrapper, TDMT_VND_STREAM_TRIGGER, vmProcessFetchMsg, DEFAULT_HANDLE); - dmSetMsgHandle(pWrapper, TDMT_VND_ALTER_VNODE, vmProcessWriteMsg, DEFAULT_HANDLE); dmSetMsgHandle(pWrapper, TDMT_VND_COMPACT_VNODE, vmProcessWriteMsg, DEFAULT_HANDLE); - dmSetMsgHandle(pWrapper, TDMT_DND_CREATE_VNODE, vmProcessMgmtMsg, DEFAULT_HANDLE); dmSetMsgHandle(pWrapper, TDMT_DND_DROP_VNODE, vmProcessMgmtMsg, DEFAULT_HANDLE); - // dmSetMsgHandle(pWrapper, TDMT_DND_SYNC_VNODE, vmProcessMgmtMsg, DEFAULT_HANDLE); - // dmSetMsgHandle(pWrapper, TDMT_DND_COMPACT_VNODE, vmProcessMgmtMsg, DEFAULT_HANDLE); // sync integration dmSetMsgHandle(pWrapper, TDMT_VND_SYNC_TIMEOUT, (NodeMsgFp)vmProcessSyncMsg, DEFAULT_HANDLE); diff --git a/source/dnode/mnode/impl/inc/mndAuth.h b/source/dnode/mnode/impl/inc/mndAuth.h index ae7663a775..890879912f 100644 --- a/source/dnode/mnode/impl/inc/mndAuth.h +++ b/source/dnode/mnode/impl/inc/mndAuth.h @@ -31,6 +31,7 @@ int32_t mndCheckDropUserAuth(SUserObj *pOperUser); int32_t mndCheckNodeAuth(SUserObj *pOperUser); int32_t mndCheckFuncAuth(SUserObj *pOperUser); +int32_t mndCheckTransAuth(SUserObj *pOperUser); int32_t mndCheckCreateDbAuth(SUserObj *pOperUser); int32_t mndCheckAlterDropCompactDbAuth(SUserObj *pOperUser, SDbObj *pDb); diff --git a/source/dnode/mnode/impl/inc/mndDef.h b/source/dnode/mnode/impl/inc/mndDef.h index 89638524ae..bb0739805c 100644 --- a/source/dnode/mnode/impl/inc/mndDef.h +++ b/source/dnode/mnode/impl/inc/mndDef.h @@ -72,7 +72,7 @@ typedef enum { TRN_TYPE_DROP_USER = 1003, TRN_TYPE_CREATE_FUNC = 1004, TRN_TYPE_DROP_FUNC = 1005, - + TRN_TYPE_CREATE_SNODE = 1006, TRN_TYPE_DROP_SNODE = 1007, TRN_TYPE_CREATE_QNODE = 1008, @@ -115,7 +115,10 @@ typedef enum { TRN_TYPE_STB_SCOPE_END, } ETrnType; -typedef enum { TRN_POLICY_ROLLBACK = 0, TRN_POLICY_RETRY = 1 } ETrnPolicy; +typedef enum { + TRN_POLICY_ROLLBACK = 0, + TRN_POLICY_RETRY = 1, +} ETrnPolicy; typedef enum { DND_REASON_ONLINE = 0, @@ -131,6 +134,15 @@ typedef enum { DND_REASON_OTHERS } EDndReason; +typedef enum { + CONSUMER_UPDATE__TOUCH = 1, + CONSUMER_UPDATE__ADD, + CONSUMER_UPDATE__REMOVE, + CONSUMER_UPDATE__LOST, + CONSUMER_UPDATE__RECOVER, + CONSUMER_UPDATE__MODIFY, +} ECsmUpdateType; + typedef struct { int32_t id; ETrnStage stage; @@ -386,7 +398,6 @@ typedef struct { int32_t codeSize; char* pComment; char* pCode; - char pData[]; } SFuncObj; typedef struct { @@ -425,18 +436,8 @@ typedef struct { int64_t offset; } SMqOffsetObj; -static FORCE_INLINE int32_t tEncodeSMqOffsetObj(void** buf, const SMqOffsetObj* pOffset) { - int32_t tlen = 0; - tlen += taosEncodeString(buf, pOffset->key); - tlen += taosEncodeFixedI64(buf, pOffset->offset); - return tlen; -} - -static FORCE_INLINE void* tDecodeSMqOffsetObj(void* buf, SMqOffsetObj* pOffset) { - buf = taosDecodeStringTo(buf, pOffset->key); - buf = taosDecodeFixedI64(buf, &pOffset->offset); - return buf; -} +int32_t tEncodeSMqOffsetObj(void** buf, const SMqOffsetObj* pOffset); +void* tDecodeSMqOffsetObj(void* buf, SMqOffsetObj* pOffset); typedef struct { char name[TSDB_TOPIC_FNAME_LEN]; @@ -459,26 +460,15 @@ typedef struct { SSchemaWrapper schema; } SMqTopicObj; -enum { - CONSUMER_UPDATE__TOUCH = 1, - CONSUMER_UPDATE__ADD, - CONSUMER_UPDATE__REMOVE, - CONSUMER_UPDATE__LOST, - CONSUMER_UPDATE__RECOVER, - CONSUMER_UPDATE__MODIFY, -}; - typedef struct { - int64_t consumerId; - char cgroup[TSDB_CGROUP_LEN]; - char appId[TSDB_CGROUP_LEN]; - int8_t updateType; // used only for update - int32_t epoch; - int32_t status; - // hbStatus is not applicable to serialization - int32_t hbStatus; - // lock is used for topics update - SRWLatch lock; + int64_t consumerId; + char cgroup[TSDB_CGROUP_LEN]; + char appId[TSDB_CGROUP_LEN]; + int8_t updateType; // used only for update + int32_t epoch; + int32_t status; + int32_t hbStatus; // hbStatus is not applicable to serialization + SRWLatch lock; // lock is used for topics update SArray* currentTopics; // SArray SArray* rebNewTopics; // SArray SArray* rebRemovedTopics; // SArray @@ -492,7 +482,6 @@ typedef struct { int64_t upTime; int64_t subscribeTime; int64_t rebalanceTime; - } SMqConsumerObj; SMqConsumerObj* tNewSMqConsumerObj(int64_t consumerId, char cgroup[TSDB_CGROUP_LEN]); @@ -581,19 +570,18 @@ typedef struct { } SMqRebOutputObj; typedef struct { - char name[TSDB_TOPIC_FNAME_LEN]; - char sourceDb[TSDB_DB_FNAME_LEN]; - char targetDb[TSDB_DB_FNAME_LEN]; - char targetSTbName[TSDB_TABLE_FNAME_LEN]; - int64_t createTime; - int64_t updateTime; - int64_t uid; - int64_t dbUid; - int32_t version; - int32_t vgNum; - SRWLatch lock; - int8_t status; - // int32_t sqlLen; + char name[TSDB_TOPIC_FNAME_LEN]; + char sourceDb[TSDB_DB_FNAME_LEN]; + char targetDb[TSDB_DB_FNAME_LEN]; + char targetSTbName[TSDB_TABLE_FNAME_LEN]; + int64_t createTime; + int64_t updateTime; + int64_t uid; + int64_t dbUid; + int32_t version; + int32_t vgNum; + SRWLatch lock; + int8_t status; int8_t createdBy; // STREAM_CREATED_BY__USER or SMA int32_t fixedSinkVgId; // 0 for shuffle int64_t smaId; // 0 for unused @@ -601,7 +589,6 @@ typedef struct { int32_t triggerParam; int64_t waterMark; char* sql; - char* logicalPlan; char* physicalPlan; SArray* tasks; // SArray> SSchemaWrapper outputSchema; diff --git a/source/dnode/mnode/impl/inc/mndUser.h b/source/dnode/mnode/impl/inc/mndUser.h index 2140d0fa67..016ec3e6e9 100644 --- a/source/dnode/mnode/impl/inc/mndUser.h +++ b/source/dnode/mnode/impl/inc/mndUser.h @@ -29,7 +29,8 @@ void mndReleaseUser(SMnode *pMnode, SUserObj *pUser); // for trans test SSdbRaw *mndUserActionEncode(SUserObj *pUser); -int32_t mndValidateUserAuthInfo(SMnode *pMnode, SUserAuthVersion *pUsers, int32_t numOfUses, void **ppRsp, int32_t *pRspLen); +int32_t mndValidateUserAuthInfo(SMnode *pMnode, SUserAuthVersion *pUsers, int32_t numOfUses, void **ppRsp, + int32_t *pRspLen); #ifdef __cplusplus } diff --git a/source/dnode/mnode/impl/inc/mndVgroup.h b/source/dnode/mnode/impl/inc/mndVgroup.h index 8aecc22454..1e95859157 100644 --- a/source/dnode/mnode/impl/inc/mndVgroup.h +++ b/source/dnode/mnode/impl/inc/mndVgroup.h @@ -27,10 +27,14 @@ void mndCleanupVgroup(SMnode *pMnode); SVgObj *mndAcquireVgroup(SMnode *pMnode, int32_t vgId); void mndReleaseVgroup(SMnode *pMnode, SVgObj *pVgroup); SSdbRaw *mndVgroupActionEncode(SVgObj *pVgroup); -int32_t mndAllocVgroup(SMnode *pMnode, SDbObj *pDb, SVgObj **ppVgroups); SEpSet mndGetVgroupEpset(SMnode *pMnode, const SVgObj *pVgroup); int32_t mndGetVnodesNum(SMnode *pMnode, int32_t dnodeId); +int32_t mndAllocVgroup(SMnode *pMnode, SDbObj *pDb, SVgObj **ppVgroups); +SArray *mndBuildDnodesArray(SMnode *pMnode); +int32_t mndAddVnodeToVgroup(SMnode *pMnode, SVgObj *pVgroup, SArray *pArray); +int32_t mndRemoveVnodeFromVgroup(SMnode *pMnode, SVgObj *pVgroup, SArray *pArray, SVnodeGid *del1, SVnodeGid *del2); + void *mndBuildCreateVnodeReq(SMnode *pMnode, SDnodeObj *pDnode, SDbObj *pDb, SVgObj *pVgroup, int32_t *pContLen); void *mndBuildDropVnodeReq(SMnode *pMnode, SDnodeObj *pDnode, SDbObj *pDb, SVgObj *pVgroup, int32_t *pContLen); void *mndBuildAlterVnodeReq(SMnode *pMnode, SDnodeObj *pDnode, SDbObj *pDb, SVgObj *pVgroup, int32_t *pContLen); diff --git a/source/dnode/mnode/impl/src/mndAuth.c b/source/dnode/mnode/impl/src/mndAuth.c index 696d850266..8e5ec40c47 100644 --- a/source/dnode/mnode/impl/src/mndAuth.c +++ b/source/dnode/mnode/impl/src/mndAuth.c @@ -74,10 +74,7 @@ static int32_t mndProcessAuthReq(SNodeMsg *pReq) { } int32_t mndCheckCreateUserAuth(SUserObj *pOperUser) { - if (pOperUser->superUser) { - return 0; - } - + if (pOperUser->superUser) return 0; terrno = TSDB_CODE_MND_NO_RIGHTS; return -1; } @@ -118,28 +115,25 @@ int32_t mndCheckAlterUserAuth(SUserObj *pOperUser, SUserObj *pUser, SDbObj *pDb, } int32_t mndCheckDropUserAuth(SUserObj *pOperUser) { - if (pOperUser->superUser) { - return 0; - } - + if (pOperUser->superUser) return 0; terrno = TSDB_CODE_MND_NO_RIGHTS; return -1; } int32_t mndCheckNodeAuth(SUserObj *pOperUser) { - if (pOperUser->superUser) { - return 0; - } - + if (pOperUser->superUser) return 0; terrno = TSDB_CODE_MND_NO_RIGHTS; return -1; } int32_t mndCheckFuncAuth(SUserObj *pOperUser) { - if (pOperUser->superUser) { - return 0; - } + if (pOperUser->superUser) return 0; + terrno = TSDB_CODE_MND_NO_RIGHTS; + return -1; +} +int32_t mndCheckTransAuth(SUserObj *pOperUser) { + if (pOperUser->superUser) return 0; terrno = TSDB_CODE_MND_NO_RIGHTS; return -1; } diff --git a/source/dnode/mnode/impl/src/mndCluster.c b/source/dnode/mnode/impl/src/mndCluster.c index 257db0dcd4..96845fcd42 100644 --- a/source/dnode/mnode/impl/src/mndCluster.c +++ b/source/dnode/mnode/impl/src/mndCluster.c @@ -17,8 +17,8 @@ #include "mndCluster.h" #include "mndShow.h" -#define TSDB_CLUSTER_VER_NUMBE 1 -#define TSDB_CLUSTER_RESERVE_SIZE 64 +#define CLUSTER_VER_NUMBE 1 +#define CLUSTER_RESERVE_SIZE 64 static SSdbRaw *mndClusterActionEncode(SClusterObj *pCluster); static SSdbRow *mndClusterActionDecode(SSdbRaw *pRaw); @@ -30,14 +30,16 @@ static int32_t mndRetrieveClusters(SNodeMsg *pMsg, SShowObj *pShow, SSDataBlock static void mndCancelGetNextCluster(SMnode *pMnode, void *pIter); int32_t mndInitCluster(SMnode *pMnode) { - SSdbTable table = {.sdbType = SDB_CLUSTER, - .keyType = SDB_KEY_INT64, - .deployFp = (SdbDeployFp)mndCreateDefaultCluster, - .encodeFp = (SdbEncodeFp)mndClusterActionEncode, - .decodeFp = (SdbDecodeFp)mndClusterActionDecode, - .insertFp = (SdbInsertFp)mndClusterActionInsert, - .updateFp = (SdbUpdateFp)mndClusterActionUpdate, - .deleteFp = (SdbDeleteFp)mndClusterActionDelete}; + SSdbTable table = { + .sdbType = SDB_CLUSTER, + .keyType = SDB_KEY_INT64, + .deployFp = (SdbDeployFp)mndCreateDefaultCluster, + .encodeFp = (SdbEncodeFp)mndClusterActionEncode, + .decodeFp = (SdbDecodeFp)mndClusterActionDecode, + .insertFp = (SdbInsertFp)mndClusterActionInsert, + .updateFp = (SdbUpdateFp)mndClusterActionUpdate, + .deleteFp = (SdbDeleteFp)mndClusterActionDelete, + }; mndAddShowRetrieveHandle(pMnode, TSDB_MGMT_TABLE_CLUSTER, mndRetrieveClusters); mndAddShowFreeIterHandle(pMnode, TSDB_MGMT_TABLE_CLUSTER, mndCancelGetNextCluster); @@ -79,19 +81,19 @@ int64_t mndGetClusterId(SMnode *pMnode) { static SSdbRaw *mndClusterActionEncode(SClusterObj *pCluster) { terrno = TSDB_CODE_OUT_OF_MEMORY; - SSdbRaw *pRaw = sdbAllocRaw(SDB_CLUSTER, TSDB_CLUSTER_VER_NUMBE, sizeof(SClusterObj) + TSDB_CLUSTER_RESERVE_SIZE); - if (pRaw == NULL) goto CLUSTER_ENCODE_OVER; + SSdbRaw *pRaw = sdbAllocRaw(SDB_CLUSTER, CLUSTER_VER_NUMBE, sizeof(SClusterObj) + CLUSTER_RESERVE_SIZE); + if (pRaw == NULL) goto _OVER; int32_t dataPos = 0; - SDB_SET_INT64(pRaw, dataPos, pCluster->id, CLUSTER_ENCODE_OVER) - SDB_SET_INT64(pRaw, dataPos, pCluster->createdTime, CLUSTER_ENCODE_OVER) - SDB_SET_INT64(pRaw, dataPos, pCluster->updateTime, CLUSTER_ENCODE_OVER) - SDB_SET_BINARY(pRaw, dataPos, pCluster->name, TSDB_CLUSTER_ID_LEN, CLUSTER_ENCODE_OVER) - SDB_SET_RESERVE(pRaw, dataPos, TSDB_CLUSTER_RESERVE_SIZE, CLUSTER_ENCODE_OVER) + SDB_SET_INT64(pRaw, dataPos, pCluster->id, _OVER) + SDB_SET_INT64(pRaw, dataPos, pCluster->createdTime, _OVER) + SDB_SET_INT64(pRaw, dataPos, pCluster->updateTime, _OVER) + SDB_SET_BINARY(pRaw, dataPos, pCluster->name, TSDB_CLUSTER_ID_LEN, _OVER) + SDB_SET_RESERVE(pRaw, dataPos, CLUSTER_RESERVE_SIZE, _OVER) terrno = 0; -CLUSTER_ENCODE_OVER: +_OVER: if (terrno != 0) { mError("cluster:%" PRId64 ", failed to encode to raw:%p since %s", pCluster->id, pRaw, terrstr()); sdbFreeRaw(pRaw); @@ -106,29 +108,29 @@ static SSdbRow *mndClusterActionDecode(SSdbRaw *pRaw) { terrno = TSDB_CODE_OUT_OF_MEMORY; int8_t sver = 0; - if (sdbGetRawSoftVer(pRaw, &sver) != 0) goto CLUSTER_DECODE_OVER; + if (sdbGetRawSoftVer(pRaw, &sver) != 0) goto _OVER; - if (sver != TSDB_CLUSTER_VER_NUMBE) { + if (sver != CLUSTER_VER_NUMBE) { terrno = TSDB_CODE_SDB_INVALID_DATA_VER; - goto CLUSTER_DECODE_OVER; + goto _OVER; } SSdbRow *pRow = sdbAllocRow(sizeof(SClusterObj)); - if (pRow == NULL) goto CLUSTER_DECODE_OVER; + if (pRow == NULL) goto _OVER; SClusterObj *pCluster = sdbGetRowObj(pRow); - if (pCluster == NULL) goto CLUSTER_DECODE_OVER; + if (pCluster == NULL) goto _OVER; int32_t dataPos = 0; - SDB_GET_INT64(pRaw, dataPos, &pCluster->id, CLUSTER_DECODE_OVER) - SDB_GET_INT64(pRaw, dataPos, &pCluster->createdTime, CLUSTER_DECODE_OVER) - SDB_GET_INT64(pRaw, dataPos, &pCluster->updateTime, CLUSTER_DECODE_OVER) - SDB_GET_BINARY(pRaw, dataPos, pCluster->name, TSDB_CLUSTER_ID_LEN, CLUSTER_DECODE_OVER) - SDB_GET_RESERVE(pRaw, dataPos, TSDB_CLUSTER_RESERVE_SIZE, CLUSTER_DECODE_OVER) + SDB_GET_INT64(pRaw, dataPos, &pCluster->id, _OVER) + SDB_GET_INT64(pRaw, dataPos, &pCluster->createdTime, _OVER) + SDB_GET_INT64(pRaw, dataPos, &pCluster->updateTime, _OVER) + SDB_GET_BINARY(pRaw, dataPos, pCluster->name, TSDB_CLUSTER_ID_LEN, _OVER) + SDB_GET_RESERVE(pRaw, dataPos, CLUSTER_RESERVE_SIZE, _OVER) terrno = 0; -CLUSTER_DECODE_OVER: +_OVER: if (terrno != 0) { mError("cluster:%" PRId64 ", failed to decode from raw:%p since %s", pCluster->id, pRaw, terrstr()); taosMemoryFreeClear(pRow); @@ -161,7 +163,7 @@ static int32_t mndCreateDefaultCluster(SMnode *pMnode) { int32_t code = taosGetSystemUUID(clusterObj.name, TSDB_CLUSTER_ID_LEN); if (code != 0) { - strcpy(clusterObj.name, "tdengine2.0"); + strcpy(clusterObj.name, "tdengine3.0"); mError("failed to get name from system, set to default val %s", clusterObj.name); } @@ -190,8 +192,8 @@ static int32_t mndRetrieveClusters(SNodeMsg *pMsg, SShowObj *pShow, SSDataBlock if (pShow->pIter == NULL) break; cols = 0; - SColumnInfoData* pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char*) &pCluster->id, false); + SColumnInfoData *pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); + colDataAppend(pColInfo, numOfRows, (const char *)&pCluster->id, false); char buf[tListLen(pCluster->name) + VARSTR_HEADER_SIZE] = {0}; STR_WITH_MAXSIZE_TO_VARSTR(buf, pCluster->name, pShow->pMeta->pSchemas[cols].bytes); @@ -200,7 +202,7 @@ static int32_t mndRetrieveClusters(SNodeMsg *pMsg, SShowObj *pShow, SSDataBlock colDataAppend(pColInfo, numOfRows, buf, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char*) &pCluster->createdTime, false); + colDataAppend(pColInfo, numOfRows, (const char *)&pCluster->createdTime, false); sdbRelease(pSdb, pCluster); numOfRows++; diff --git a/source/dnode/mnode/impl/src/mndDb.c b/source/dnode/mnode/impl/src/mndDb.c index af7efb5543..70bdda5855 100644 --- a/source/dnode/mnode/impl/src/mndDb.c +++ b/source/dnode/mnode/impl/src/mndDb.c @@ -261,6 +261,104 @@ void mndReleaseDb(SMnode *pMnode, SDbObj *pDb) { sdbRelease(pSdb, pDb); } +static int32_t mndAddCreateVnodeAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup, SVnodeGid *pVgid, + bool isRedo) { + STransAction action = {0}; + + SDnodeObj *pDnode = mndAcquireDnode(pMnode, pVgid->dnodeId); + if (pDnode == NULL) return -1; + action.epSet = mndGetDnodeEpset(pDnode); + mndReleaseDnode(pMnode, pDnode); + + int32_t contLen = 0; + void *pReq = mndBuildCreateVnodeReq(pMnode, pDnode, pDb, pVgroup, &contLen); + if (pReq == NULL) return -1; + + action.pCont = pReq; + action.contLen = contLen; + action.msgType = TDMT_DND_CREATE_VNODE; + action.acceptableCode = TSDB_CODE_NODE_ALREADY_DEPLOYED; + + if (isRedo) { + if (mndTransAppendRedoAction(pTrans, &action) != 0) { + taosMemoryFree(pReq); + return -1; + } + } else { + if (mndTransAppendUndoAction(pTrans, &action) != 0) { + taosMemoryFree(pReq); + return -1; + } + } + + return 0; +} + +static int32_t mndAddAlterVnodeAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup, SVnodeGid *pVgid, + bool isRedo) { + STransAction action = {0}; + + SDnodeObj *pDnode = mndAcquireDnode(pMnode, pVgid->dnodeId); + if (pDnode == NULL) return -1; + action.epSet = mndGetDnodeEpset(pDnode); + mndReleaseDnode(pMnode, pDnode); + + int32_t contLen = 0; + void *pReq = mndBuildAlterVnodeReq(pMnode, pDnode, pDb, pVgroup, &contLen); + if (pReq == NULL) return -1; + + action.pCont = pReq; + action.contLen = contLen; + action.msgType = TDMT_VND_ALTER_VNODE; + + if (isRedo) { + if (mndTransAppendRedoAction(pTrans, &action) != 0) { + taosMemoryFree(pReq); + return -1; + } + } else { + if (mndTransAppendUndoAction(pTrans, &action) != 0) { + taosMemoryFree(pReq); + return -1; + } + } + + return 0; +} + +static int32_t mndAddDropVnodeAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup, SVnodeGid *pVgid, + bool isRedo) { + STransAction action = {0}; + + SDnodeObj *pDnode = mndAcquireDnode(pMnode, pVgid->dnodeId); + if (pDnode == NULL) return -1; + action.epSet = mndGetDnodeEpset(pDnode); + mndReleaseDnode(pMnode, pDnode); + + int32_t contLen = 0; + void *pReq = mndBuildDropVnodeReq(pMnode, pDnode, pDb, pVgroup, &contLen); + if (pReq == NULL) return -1; + + action.pCont = pReq; + action.contLen = contLen; + action.msgType = TDMT_DND_DROP_VNODE; + action.acceptableCode = TSDB_CODE_NODE_NOT_DEPLOYED; + + if (isRedo) { + if (mndTransAppendRedoAction(pTrans, &action) != 0) { + taosMemoryFree(pReq); + return -1; + } + } else { + if (mndTransAppendUndoAction(pTrans, &action) != 0) { + taosMemoryFree(pReq); + return -1; + } + } + + return 0; +} + static int32_t mndCheckDbName(const char *dbName, SUserObj *pUser) { char *pos = strstr(dbName, TS_PATH_DELIMITER); if (pos == NULL) { @@ -278,6 +376,8 @@ static int32_t mndCheckDbName(const char *dbName, SUserObj *pUser) { } static int32_t mndCheckDbCfg(SMnode *pMnode, SDbCfg *pCfg) { + terrno = TSDB_CODE_MND_INVALID_DB_OPTION; + if (pCfg->numOfVgroups < TSDB_MIN_VNODES_PER_DB || pCfg->numOfVgroups > TSDB_MAX_VNODES_PER_DB) return -1; if (pCfg->numOfStables < TSDB_DB_STREAM_MODE_OFF || pCfg->numOfStables > TSDB_DB_STREAM_MODE_ON) return -1; if (pCfg->buffer < TSDB_MIN_BUFFER_PER_VNODE || pCfg->buffer > TSDB_MAX_BUFFER_PER_VNODE) return -1; @@ -299,10 +399,12 @@ static int32_t mndCheckDbCfg(SMnode *pMnode, SDbCfg *pCfg) { if (pCfg->compression < TSDB_MIN_COMP_LEVEL || pCfg->compression > TSDB_MAX_COMP_LEVEL) return -1; if (pCfg->replications < TSDB_MIN_DB_REPLICA || pCfg->replications > TSDB_MAX_DB_REPLICA) return -1; if (pCfg->replications > mndGetDnodeSize(pMnode)) return -1; + if (pCfg->replications != 1 && pCfg->replications != 3) return -1; if (pCfg->strict < TSDB_DB_STRICT_OFF || pCfg->strict > TSDB_DB_STRICT_ON) return -1; - if (pCfg->strict > pCfg->replications) return -1; if (pCfg->cacheLastRow < TSDB_MIN_DB_CACHE_LAST_ROW || pCfg->cacheLastRow > TSDB_MAX_DB_CACHE_LAST_ROW) return -1; if (pCfg->hashMethod != 1) return -1; + + terrno = 0; return TSDB_CODE_SUCCESS; } @@ -381,24 +483,8 @@ static int32_t mndSetCreateDbRedoActions(SMnode *pMnode, STrans *pTrans, SDbObj SVgObj *pVgroup = pVgroups + vg; for (int32_t vn = 0; vn < pVgroup->replica; ++vn) { - STransAction action = {0}; - SVnodeGid *pVgid = pVgroup->vnodeGid + vn; - - SDnodeObj *pDnode = mndAcquireDnode(pMnode, pVgid->dnodeId); - if (pDnode == NULL) return -1; - action.epSet = mndGetDnodeEpset(pDnode); - mndReleaseDnode(pMnode, pDnode); - - int32_t contLen = 0; - void *pReq = mndBuildCreateVnodeReq(pMnode, pDnode, pDb, pVgroup, &contLen); - if (pReq == NULL) return -1; - - action.pCont = pReq; - action.contLen = contLen; - action.msgType = TDMT_DND_CREATE_VNODE; - action.acceptableCode = TSDB_CODE_NODE_ALREADY_DEPLOYED; - if (mndTransAppendRedoAction(pTrans, &action) != 0) { - taosMemoryFree(pReq); + SVnodeGid *pVgid = pVgroup->vnodeGid + vn; + if (mndAddCreateVnodeAction(pMnode, pTrans, pDb, pVgroup, pVgid, true) != 0) { return -1; } } @@ -412,24 +498,8 @@ static int32_t mndSetCreateDbUndoActions(SMnode *pMnode, STrans *pTrans, SDbObj SVgObj *pVgroup = pVgroups + vg; for (int32_t vn = 0; vn < pVgroup->replica; ++vn) { - STransAction action = {0}; - SVnodeGid *pVgid = pVgroup->vnodeGid + vn; - - SDnodeObj *pDnode = mndAcquireDnode(pMnode, pVgid->dnodeId); - if (pDnode == NULL) return -1; - action.epSet = mndGetDnodeEpset(pDnode); - mndReleaseDnode(pMnode, pDnode); - - int32_t contLen = 0; - void *pReq = mndBuildDropVnodeReq(pMnode, pDnode, pDb, pVgroup, &contLen); - if (pReq == NULL) return -1; - - action.pCont = pReq; - action.contLen = contLen; - action.msgType = TDMT_DND_DROP_VNODE; - action.acceptableCode = TSDB_CODE_NODE_NOT_DEPLOYED; - if (mndTransAppendUndoAction(pTrans, &action) != 0) { - taosMemoryFree(pReq); + SVnodeGid *pVgid = pVgroup->vnodeGid + vn; + if (mndAddDropVnodeAction(pMnode, pTrans, pDb, pVgroup, pVgid, false) != 0) { return -1; } } @@ -482,7 +552,6 @@ static int32_t mndCreateDb(SMnode *pMnode, SNodeMsg *pReq, SCreateDbReq *pCreate } if (mndCheckDbCfg(pMnode, &dbObj.cfg) != 0) { - terrno = TSDB_CODE_MND_INVALID_DB_OPTION; mError("db:%s, failed to create since %s", pCreate->db, terrstr()); return -1; } @@ -570,37 +639,37 @@ _OVER: static int32_t mndSetDbCfgFromAlterDbReq(SDbObj *pDb, SAlterDbReq *pAlter) { terrno = TSDB_CODE_MND_DB_OPTION_UNCHANGED; - if (pAlter->buffer >= 0 && pAlter->buffer != pDb->cfg.buffer) { + if (pAlter->buffer > 0 && pAlter->buffer != pDb->cfg.buffer) { pDb->cfg.buffer = pAlter->buffer; terrno = 0; } - if (pAlter->pages >= 0 && pAlter->pages != pDb->cfg.pages) { + if (pAlter->pages > 0 && pAlter->pages != pDb->cfg.pages) { pDb->cfg.pages = pAlter->pages; terrno = 0; } - if (pAlter->pageSize >= 0 && pAlter->pageSize != pDb->cfg.pageSize) { + if (pAlter->pageSize > 0 && pAlter->pageSize != pDb->cfg.pageSize) { pDb->cfg.pageSize = pAlter->pageSize; terrno = 0; } - if (pAlter->daysPerFile >= 0 && pAlter->daysPerFile != pDb->cfg.daysPerFile) { + if (pAlter->daysPerFile > 0 && pAlter->daysPerFile != pDb->cfg.daysPerFile) { pDb->cfg.daysPerFile = pAlter->daysPerFile; terrno = 0; } - if (pAlter->daysToKeep0 >= 0 && pAlter->daysToKeep0 != pDb->cfg.daysToKeep0) { + if (pAlter->daysToKeep0 > 0 && pAlter->daysToKeep0 != pDb->cfg.daysToKeep0) { pDb->cfg.daysToKeep0 = pAlter->daysToKeep0; terrno = 0; } - if (pAlter->daysToKeep1 >= 0 && pAlter->daysToKeep1 != pDb->cfg.daysToKeep1) { + if (pAlter->daysToKeep1 > 0 && pAlter->daysToKeep1 != pDb->cfg.daysToKeep1) { pDb->cfg.daysToKeep1 = pAlter->daysToKeep1; terrno = 0; } - if (pAlter->daysToKeep2 >= 0 && pAlter->daysToKeep2 != pDb->cfg.daysToKeep2) { + if (pAlter->daysToKeep2 > 0 && pAlter->daysToKeep2 != pDb->cfg.daysToKeep2) { pDb->cfg.daysToKeep2 = pAlter->daysToKeep2; terrno = 0; } @@ -625,8 +694,9 @@ static int32_t mndSetDbCfgFromAlterDbReq(SDbObj *pDb, SAlterDbReq *pAlter) { terrno = 0; } - if (pAlter->replications >= 0 && pAlter->replications != pDb->cfg.replications) { + if (pAlter->replications > 0 && pAlter->replications != pDb->cfg.replications) { pDb->cfg.replications = pAlter->replications; + pDb->vgVersion++; terrno = 0; } @@ -651,35 +721,57 @@ static int32_t mndSetAlterDbCommitLogs(SMnode *pMnode, STrans *pTrans, SDbObj *p return 0; } -static int32_t mndBuildAlterVgroupAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup) { - for (int32_t vn = 0; vn < pVgroup->replica; ++vn) { - STransAction action = {0}; - SVnodeGid *pVgid = pVgroup->vnodeGid + vn; - - SDnodeObj *pDnode = mndAcquireDnode(pMnode, pVgid->dnodeId); - if (pDnode == NULL) return -1; - action.epSet = mndGetDnodeEpset(pDnode); - mndReleaseDnode(pMnode, pDnode); - - int32_t contLen = 0; - void *pReq = mndBuildAlterVnodeReq(pMnode, pDnode, pDb, pVgroup, &contLen); - if (pReq == NULL) return -1; - - action.pCont = pReq; - action.contLen = contLen; - action.msgType = TDMT_VND_ALTER_VNODE; - if (mndTransAppendRedoAction(pTrans, &action) != 0) { - taosMemoryFree(pReq); - return -1; +static int32_t mndBuildAlterVgroupAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup, SArray *pArray) { + if (pVgroup->replica <= 0 || pVgroup->replica == pDb->cfg.replications) { + for (int32_t vn = 0; vn < pVgroup->replica; ++vn) { + SVnodeGid *pVgid = pVgroup->vnodeGid + vn; + if (mndAddAlterVnodeAction(pMnode, pTrans, pDb, pVgroup, pVgid, true) != 0) { + return -1; + } } + } else { + SVgObj newVgroup = {0}; + memcpy(&newVgroup, pVgroup, sizeof(SVgObj)); + if (newVgroup.replica < pDb->cfg.replications) { + mInfo("db:%s, vgId:%d, will add 2 vnodes, vn:0 dnode:%d", pVgroup->dbName, pVgroup->vgId, + pVgroup->vnodeGid[0].dnodeId); + + if (mndAddVnodeToVgroup(pMnode, &newVgroup, pArray) != 0) { + mError("db:%s, failed to add vnode to vgId:%d since %s", pDb->name, newVgroup.vgId, terrstr()); + return -1; + } + newVgroup.replica = pDb->cfg.replications; + if (mndAddAlterVnodeAction(pMnode, pTrans, pDb, &newVgroup, &newVgroup.vnodeGid[0], true) != 0) return -1; + if (mndAddCreateVnodeAction(pMnode, pTrans, pDb, &newVgroup, &newVgroup.vnodeGid[1], true) != 0) return -1; + if (mndAddCreateVnodeAction(pMnode, pTrans, pDb, &newVgroup, &newVgroup.vnodeGid[2], true) != 0) return -1; + } else { + mInfo("db:%s, vgId:%d, will remove 2 vnodes", pVgroup->dbName, pVgroup->vgId); + + SVnodeGid del1 = {0}; + SVnodeGid del2 = {0}; + if (mndRemoveVnodeFromVgroup(pMnode, &newVgroup, pArray, &del1, &del2) != 0) { + mError("db:%s, failed to remove vnode from vgId:%d since %s", pDb->name, newVgroup.vgId, terrstr()); + return -1; + } + newVgroup.replica = pDb->cfg.replications; + if (mndAddAlterVnodeAction(pMnode, pTrans, pDb, &newVgroup, &newVgroup.vnodeGid[0], true) != 0) return -1; + if (mndAddDropVnodeAction(pMnode, pTrans, pDb, &newVgroup, &del1, true) != 0) return -1; + if (mndAddDropVnodeAction(pMnode, pTrans, pDb, &newVgroup, &del2, true) != 0) return -1; + } + + SSdbRaw *pVgRaw = mndVgroupActionEncode(&newVgroup); + if (pVgRaw == NULL) return -1; + if (mndTransAppendCommitlog(pTrans, pVgRaw) != 0) return -1; + if (sdbSetRawStatus(pVgRaw, SDB_STATUS_READY) != 0) return -1; } return 0; } static int32_t mndSetAlterDbRedoActions(SMnode *pMnode, STrans *pTrans, SDbObj *pOld, SDbObj *pNew) { - SSdb *pSdb = pMnode->pSdb; - void *pIter = NULL; + SSdb *pSdb = pMnode->pSdb; + void *pIter = NULL; + SArray *pArray = mndBuildDnodesArray(pMnode); while (1) { SVgObj *pVgroup = NULL; @@ -687,9 +779,10 @@ static int32_t mndSetAlterDbRedoActions(SMnode *pMnode, STrans *pTrans, SDbObj * if (pIter == NULL) break; if (pVgroup->dbUid == pNew->uid) { - if (mndBuildAlterVgroupAction(pMnode, pTrans, pNew, pVgroup) != 0) { + if (mndBuildAlterVgroupAction(pMnode, pTrans, pNew, pVgroup, pArray) != 0) { sdbCancelFetch(pSdb, pIter); sdbRelease(pSdb, pVgroup); + taosArrayDestroy(pArray); return -1; } } @@ -697,6 +790,7 @@ static int32_t mndSetAlterDbRedoActions(SMnode *pMnode, STrans *pTrans, SDbObj * sdbRelease(pSdb, pVgroup); } + taosArrayDestroy(pArray); return 0; } @@ -726,6 +820,7 @@ static int32_t mndProcessAlterDbReq(SNodeMsg *pReq) { SDbObj *pDb = NULL; SUserObj *pUser = NULL; SAlterDbReq alterReq = {0}; + SDbObj dbObj = {0}; if (tDeserializeSAlterDbReq(pReq->rpcMsg.pCont, pReq->rpcMsg.contLen, &alterReq) != 0) { terrno = TSDB_CODE_INVALID_MSG; @@ -749,15 +844,17 @@ static int32_t mndProcessAlterDbReq(SNodeMsg *pReq) { goto _OVER; } - SDbObj dbObj = {0}; memcpy(&dbObj, pDb, sizeof(SDbObj)); - dbObj.cfg.numOfRetensions = 0; - dbObj.cfg.pRetensions = NULL; + if (dbObj.cfg.pRetensions != NULL) { + dbObj.cfg.pRetensions = taosArrayDup(pDb->cfg.pRetensions); + if (dbObj.cfg.pRetensions == NULL) goto _OVER; + } code = mndSetDbCfgFromAlterDbReq(&dbObj, &alterReq); - if (code != 0) { - goto _OVER; - } + if (code != 0) goto _OVER; + + code = mndCheckDbCfg(pMnode, &dbObj.cfg); + if (code != 0) goto _OVER; dbObj.cfgVersion++; dbObj.updateTime = taosGetTimestampMs(); @@ -771,6 +868,7 @@ _OVER: mndReleaseDb(pMnode, pDb); mndReleaseUser(pMnode, pUser); + taosArrayDestroy(dbObj.cfg.pRetensions); return code; } @@ -899,24 +997,8 @@ static int32_t mndSetDropDbCommitLogs(SMnode *pMnode, STrans *pTrans, SDbObj *pD static int32_t mndBuildDropVgroupAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup) { for (int32_t vn = 0; vn < pVgroup->replica; ++vn) { - STransAction action = {0}; - SVnodeGid *pVgid = pVgroup->vnodeGid + vn; - - SDnodeObj *pDnode = mndAcquireDnode(pMnode, pVgid->dnodeId); - if (pDnode == NULL) return -1; - action.epSet = mndGetDnodeEpset(pDnode); - mndReleaseDnode(pMnode, pDnode); - - int32_t contLen = 0; - void *pReq = mndBuildDropVnodeReq(pMnode, pDnode, pDb, pVgroup, &contLen); - if (pReq == NULL) return -1; - - action.pCont = pReq; - action.contLen = contLen; - action.msgType = TDMT_DND_DROP_VNODE; - action.acceptableCode = TSDB_CODE_NODE_NOT_DEPLOYED; - if (mndTransAppendRedoAction(pTrans, &action) != 0) { - taosMemoryFree(pReq); + SVnodeGid *pVgid = pVgroup->vnodeGid + vn; + if (mndAddDropVnodeAction(pMnode, pTrans, pDb, pVgroup, pVgid, true) != 0) { return -1; } } @@ -988,6 +1070,17 @@ static int32_t mndDropDb(SMnode *pMnode, SNodeMsg *pReq, SDbObj *pDb) { /*if (mndDropTopicByDB(pMnode, pTrans, pDb) != 0) goto _OVER;*/ if (mndSetDropDbRedoActions(pMnode, pTrans, pDb) != 0) goto _OVER; + SUserObj *pUser = mndAcquireUser(pMnode, pDb->createUser); + if (pUser != NULL) { + pUser->authVersion++; + SSdbRaw *pCommitRaw = mndUserActionEncode(pUser); + if (pCommitRaw == NULL || mndTransAppendCommitlog(pTrans, pCommitRaw) != 0) { + mError("trans:%d, failed to append redo log since %s", pTrans->id, terrstr()); + goto _OVER; + } + sdbSetRawStatus(pCommitRaw, SDB_STATUS_READY); + } + int32_t rspLen = 0; void *pRsp = NULL; if (mndBuildDropDbRsp(pDb, &rspLen, &pRsp, false) < 0) goto _OVER; diff --git a/source/dnode/mnode/impl/src/mndDef.c b/source/dnode/mnode/impl/src/mndDef.c index 5bce6ac218..b8c120905c 100644 --- a/source/dnode/mnode/impl/src/mndDef.c +++ b/source/dnode/mnode/impl/src/mndDef.c @@ -13,12 +13,14 @@ * along with this program. If not, see . */ +#define _DEFAULT_SOURCE #include "mndDef.h" #include "mndConsumer.h" SMqConsumerObj *tNewSMqConsumerObj(int64_t consumerId, char cgroup[TSDB_CGROUP_LEN]) { SMqConsumerObj *pConsumer = taosMemoryCalloc(1, sizeof(SMqConsumerObj)); if (pConsumer == NULL) { + terrno = TSDB_CODE_OUT_OF_MEMORY; return NULL; } @@ -515,3 +517,16 @@ int32_t tDecodeSStreamObj(SCoder *pDecoder, SStreamObj *pObj) { #endif return 0; } + +int32_t tEncodeSMqOffsetObj(void **buf, const SMqOffsetObj *pOffset) { + int32_t tlen = 0; + tlen += taosEncodeString(buf, pOffset->key); + tlen += taosEncodeFixedI64(buf, pOffset->offset); + return tlen; +} + +void *tDecodeSMqOffsetObj(void *buf, SMqOffsetObj *pOffset) { + buf = taosDecodeStringTo(buf, pOffset->key); + buf = taosDecodeFixedI64(buf, &pOffset->offset); + return buf; +} \ No newline at end of file diff --git a/source/dnode/mnode/impl/src/mndSma.c b/source/dnode/mnode/impl/src/mndSma.c index 8619df978b..02a8eaa832 100644 --- a/source/dnode/mnode/impl/src/mndSma.c +++ b/source/dnode/mnode/impl/src/mndSma.c @@ -21,7 +21,7 @@ #include "mndInfoSchema.h" #include "mndMnode.h" #include "mndShow.h" -#include "mndStb.c" +#include "mndStb.h" #include "mndStream.h" #include "mndTrans.h" #include "mndUser.h" @@ -419,7 +419,6 @@ static int32_t mndCreateSma(SMnode *pMnode, SNodeMsg *pReq, SMCreateSmaReq *pCre streamObj.fixedSinkVgId = smaObj.dstVgId; streamObj.smaId = smaObj.uid; /*streamObj.physicalPlan = "";*/ - streamObj.logicalPlan = "not implemented"; int32_t code = -1; STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_TYPE_CREATE_SMA, &pReq->rpcMsg); diff --git a/source/dnode/mnode/impl/src/mndStb.c b/source/dnode/mnode/impl/src/mndStb.c index cd76c7c8bb..b6912d0777 100644 --- a/source/dnode/mnode/impl/src/mndStb.c +++ b/source/dnode/mnode/impl/src/mndStb.c @@ -13,6 +13,7 @@ * along with this program. If not, see . */ +#define _DEFAULT_SOURCE #include "mndStb.h" #include "mndAuth.h" #include "mndDb.h" @@ -27,8 +28,8 @@ #include "mndVgroup.h" #include "tname.h" -#define TSDB_STB_VER_NUMBER 1 -#define TSDB_STB_RESERVE_SIZE 64 +#define STB_VER_NUMBER 1 +#define STB_RESERVE_SIZE 64 static SSdbRow *mndStbActionDecode(SSdbRaw *pRaw); static int32_t mndStbActionInsert(SSdb *pSdb, SStbObj *pStb); @@ -45,13 +46,15 @@ static int32_t mndRetrieveStb(SNodeMsg *pReq, SShowObj *pShow, SSDataBlock *pBl static void mndCancelGetNextStb(SMnode *pMnode, void *pIter); int32_t mndInitStb(SMnode *pMnode) { - SSdbTable table = {.sdbType = SDB_STB, - .keyType = SDB_KEY_BINARY, - .encodeFp = (SdbEncodeFp)mndStbActionEncode, - .decodeFp = (SdbDecodeFp)mndStbActionDecode, - .insertFp = (SdbInsertFp)mndStbActionInsert, - .updateFp = (SdbUpdateFp)mndStbActionUpdate, - .deleteFp = (SdbDeleteFp)mndStbActionDelete}; + SSdbTable table = { + .sdbType = SDB_STB, + .keyType = SDB_KEY_BINARY, + .encodeFp = (SdbEncodeFp)mndStbActionEncode, + .decodeFp = (SdbDecodeFp)mndStbActionDecode, + .insertFp = (SdbInsertFp)mndStbActionInsert, + .updateFp = (SdbUpdateFp)mndStbActionUpdate, + .deleteFp = (SdbDeleteFp)mndStbActionDelete, + }; mndSetMsgHandle(pMnode, TDMT_MND_CREATE_STB, mndProcessMCreateStbReq); mndSetMsgHandle(pMnode, TDMT_MND_ALTER_STB, mndProcessMAlterStbReq); @@ -73,8 +76,8 @@ SSdbRaw *mndStbActionEncode(SStbObj *pStb) { terrno = TSDB_CODE_OUT_OF_MEMORY; int32_t size = sizeof(SStbObj) + (pStb->numOfColumns + pStb->numOfTags) * sizeof(SSchema) + +pStb->commentLen + - pStb->ast1Len + pStb->ast2Len + TSDB_STB_RESERVE_SIZE; - SSdbRaw *pRaw = sdbAllocRaw(SDB_STB, TSDB_STB_VER_NUMBER, size); + pStb->ast1Len + pStb->ast2Len + STB_RESERVE_SIZE; + SSdbRaw *pRaw = sdbAllocRaw(SDB_STB, STB_VER_NUMBER, size); if (pRaw == NULL) goto _OVER; int32_t dataPos = 0; @@ -98,6 +101,7 @@ SSdbRaw *mndStbActionEncode(SStbObj *pStb) { for (int32_t i = 0; i < pStb->numOfColumns; ++i) { SSchema *pSchema = &pStb->pColumns[i]; SDB_SET_INT8(pRaw, dataPos, pSchema->type, _OVER) + SDB_SET_INT8(pRaw, dataPos, pSchema->flags, _OVER) SDB_SET_INT16(pRaw, dataPos, pSchema->colId, _OVER) SDB_SET_INT32(pRaw, dataPos, pSchema->bytes, _OVER) SDB_SET_BINARY(pRaw, dataPos, pSchema->name, TSDB_COL_NAME_LEN, _OVER) @@ -106,6 +110,7 @@ SSdbRaw *mndStbActionEncode(SStbObj *pStb) { for (int32_t i = 0; i < pStb->numOfTags; ++i) { SSchema *pSchema = &pStb->pTags[i]; SDB_SET_INT8(pRaw, dataPos, pSchema->type, _OVER) + SDB_SET_INT8(pRaw, dataPos, pSchema->flags, _OVER) SDB_SET_INT16(pRaw, dataPos, pSchema->colId, _OVER) SDB_SET_INT32(pRaw, dataPos, pSchema->bytes, _OVER) SDB_SET_BINARY(pRaw, dataPos, pSchema->name, TSDB_COL_NAME_LEN, _OVER) @@ -120,7 +125,7 @@ SSdbRaw *mndStbActionEncode(SStbObj *pStb) { if (pStb->ast2Len > 0) { SDB_SET_BINARY(pRaw, dataPos, pStb->pAst2, pStb->ast2Len, _OVER) } - SDB_SET_RESERVE(pRaw, dataPos, TSDB_STB_RESERVE_SIZE, _OVER) + SDB_SET_RESERVE(pRaw, dataPos, STB_RESERVE_SIZE, _OVER) SDB_SET_DATALEN(pRaw, dataPos, _OVER) terrno = 0; @@ -142,7 +147,7 @@ static SSdbRow *mndStbActionDecode(SSdbRaw *pRaw) { int8_t sver = 0; if (sdbGetRawSoftVer(pRaw, &sver) != 0) goto _OVER; - if (sver != TSDB_STB_VER_NUMBER) { + if (sver != STB_VER_NUMBER) { terrno = TSDB_CODE_SDB_INVALID_DATA_VER; goto _OVER; } @@ -182,6 +187,7 @@ static SSdbRow *mndStbActionDecode(SSdbRaw *pRaw) { for (int32_t i = 0; i < pStb->numOfColumns; ++i) { SSchema *pSchema = &pStb->pColumns[i]; SDB_GET_INT8(pRaw, dataPos, &pSchema->type, _OVER) + SDB_GET_INT8(pRaw, dataPos, &pSchema->flags, _OVER) SDB_GET_INT16(pRaw, dataPos, &pSchema->colId, _OVER) SDB_GET_INT32(pRaw, dataPos, &pSchema->bytes, _OVER) SDB_GET_BINARY(pRaw, dataPos, pSchema->name, TSDB_COL_NAME_LEN, _OVER) @@ -190,6 +196,7 @@ static SSdbRow *mndStbActionDecode(SSdbRaw *pRaw) { for (int32_t i = 0; i < pStb->numOfTags; ++i) { SSchema *pSchema = &pStb->pTags[i]; SDB_GET_INT8(pRaw, dataPos, &pSchema->type, _OVER) + SDB_GET_INT8(pRaw, dataPos, &pSchema->flags, _OVER) SDB_GET_INT16(pRaw, dataPos, &pSchema->colId, _OVER) SDB_GET_INT32(pRaw, dataPos, &pSchema->bytes, _OVER) SDB_GET_BINARY(pRaw, dataPos, pSchema->name, TSDB_COL_NAME_LEN, _OVER) @@ -210,7 +217,7 @@ static SSdbRow *mndStbActionDecode(SSdbRaw *pRaw) { if (pStb->pAst2 == NULL) goto _OVER; SDB_GET_BINARY(pRaw, dataPos, pStb->pAst2, pStb->ast2Len, _OVER) } - SDB_GET_RESERVE(pRaw, dataPos, TSDB_STB_RESERVE_SIZE, _OVER) + SDB_GET_RESERVE(pRaw, dataPos, STB_RESERVE_SIZE, _OVER) terrno = 0; @@ -487,7 +494,7 @@ int32_t mndCheckCreateStbReq(SMCreateStbReq *pCreate) { for (int32_t i = 0; i < pCreate->numOfColumns; ++i) { SField *pField1 = taosArrayGet(pCreate->pColumns, i); - if (pField->type < 0) { + if (pField1->type < 0) { terrno = TSDB_CODE_MND_INVALID_STB_OPTION; return -1; } @@ -573,6 +580,7 @@ static int32_t mndSetCreateStbRedoActions(SMnode *pMnode, STrans *pTrans, SDbObj action.pCont = pReq; action.contLen = contLen; action.msgType = TDMT_VND_CREATE_STB; + action.acceptableCode = TSDB_CODE_TDB_STB_ALREADY_EXIST; if (mndTransAppendRedoAction(pTrans, &action) != 0) { taosMemoryFree(pReq); sdbCancelFetch(pSdb, pIter); @@ -612,6 +620,7 @@ static int32_t mndSetCreateStbUndoActions(SMnode *pMnode, STrans *pTrans, SDbObj action.pCont = pReq; action.contLen = contLen; action.msgType = TDMT_VND_DROP_STB; + action.acceptableCode = TSDB_CODE_TDB_STB_NOT_EXIST; if (mndTransAppendUndoAction(pTrans, &action) != 0) { taosMemoryFree(pReq); sdbCancelFetch(pSdb, pIter); @@ -732,6 +741,7 @@ _OVER: mndTransDrop(pTrans); return code; } + int32_t mndAddStbToTrans(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SStbObj *pStb) { mndTransSetDbInfo(pTrans, pDb); if (mndSetCreateStbRedoLogs(pMnode, pTrans, pDb, pStb) != 0) return -1; @@ -791,7 +801,10 @@ static int32_t mndProcessMCreateStbReq(SNodeMsg *pReq) { } int32_t numOfStbs = -1; - mndGetNumOfStbs(pMnode, pDb->name, &numOfStbs); + if (mndGetNumOfStbs(pMnode, pDb->name, &numOfStbs) != 0) { + goto _OVER; + } + if (pDb->cfg.numOfStables == 1 && numOfStbs != 0) { terrno = TSDB_CODE_MND_SINGLE_STB_MODE_DB; goto _OVER; @@ -818,7 +831,7 @@ static int32_t mndProcessVCreateStbRsp(SNodeMsg *pRsp) { return 0; } -static int32_t mndCheckAlterStbReq(SMAltertbReq *pAlter) { +static int32_t mndCheckAlterStbReq(SMAlterStbReq *pAlter) { if (pAlter->numOfFields < 1 || pAlter->numOfFields != (int32_t)taosArrayGetSize(pAlter->pFields)) { terrno = TSDB_CODE_MND_INVALID_STB_OPTION; return -1; @@ -1169,7 +1182,7 @@ static int32_t mndSetAlterStbRedoActions(SMnode *pMnode, STrans *pTrans, SDbObj return 0; } -static int32_t mndAlterStb(SMnode *pMnode, SNodeMsg *pReq, const SMAltertbReq *pAlter, SDbObj *pDb, SStbObj *pOld) { +static int32_t mndAlterStb(SMnode *pMnode, SNodeMsg *pReq, const SMAlterStbReq *pAlter, SDbObj *pDb, SStbObj *pOld) { SStbObj stbObj = {0}; taosRLockLatch(&pOld->lock); memcpy(&stbObj, pOld, sizeof(SStbObj)); @@ -1233,12 +1246,12 @@ _OVER: } static int32_t mndProcessMAlterStbReq(SNodeMsg *pReq) { - SMnode *pMnode = pReq->pNode; - int32_t code = -1; - SDbObj *pDb = NULL; - SStbObj *pStb = NULL; - SUserObj *pUser = NULL; - SMAltertbReq alterReq = {0}; + SMnode *pMnode = pReq->pNode; + int32_t code = -1; + SDbObj *pDb = NULL; + SStbObj *pStb = NULL; + SUserObj *pUser = NULL; + SMAlterStbReq alterReq = {0}; if (tDeserializeSMAlterStbReq(pReq->rpcMsg.pCont, pReq->rpcMsg.contLen, &alterReq) != 0) { terrno = TSDB_CODE_INVALID_MSG; diff --git a/source/dnode/mnode/impl/src/mndStream.c b/source/dnode/mnode/impl/src/mndStream.c index 1404b1cd94..2c767619a1 100644 --- a/source/dnode/mnode/impl/src/mndStream.c +++ b/source/dnode/mnode/impl/src/mndStream.c @@ -290,7 +290,7 @@ int32_t mndAddStreamToTrans(SMnode *pMnode, SStreamObj *pStream, const char *ast return 0; } -static SStbObj *mndCreateStbForStream(SMnode *pMnode, STrans *pTrans, const SStreamObj *pStream, const char *user) { +static int32_t mndCreateStbForStream(SMnode *pMnode, STrans *pTrans, const SStreamObj *pStream, const char *user) { SStbObj *pStb = NULL; SDbObj *pDb = NULL; SUserObj *pUser = NULL; @@ -301,7 +301,22 @@ static SStbObj *mndCreateStbForStream(SMnode *pMnode, STrans *pTrans, const SStr createReq.numOfTags = 1; // group id createReq.pColumns = taosArrayInit(createReq.numOfColumns, sizeof(SField)); // build fields + taosArraySetSize(createReq.pColumns, createReq.numOfColumns); + for (int32_t i = 0; i < createReq.numOfColumns; i++) { + SField *pField = taosArrayGet(createReq.pColumns, i); + tstrncpy(pField->name, pStream->outputSchema.pSchema[i].name, TSDB_COL_NAME_LEN); + pField->flags = pStream->outputSchema.pSchema[i].flags; + pField->type = pStream->outputSchema.pSchema[i].type; + pField->bytes = pStream->outputSchema.pSchema[i].bytes; + } + createReq.pTags = taosArrayInit(createReq.numOfTags, sizeof(SField)); + taosArraySetSize(createReq.pTags, 1); // build tags + SField *pField = taosArrayGet(createReq.pTags, 0); + strcpy(pField->name, "group_id"); + pField->type = TSDB_DATA_TYPE_UBIGINT; + pField->flags = 0; + pField->bytes = 8; if (mndCheckCreateStbReq(&createReq) != 0) { terrno = TSDB_CODE_INVALID_MSG; @@ -330,7 +345,10 @@ static SStbObj *mndCreateStbForStream(SMnode *pMnode, STrans *pTrans, const SStr } int32_t numOfStbs = -1; - mndGetNumOfStbs(pMnode, pDb->name, &numOfStbs); + if (mndGetNumOfStbs(pMnode, pDb->name, &numOfStbs) != 0) { + goto _OVER; + } + if (pDb->cfg.numOfStables == 1 && numOfStbs != 0) { terrno = TSDB_CODE_MND_SINGLE_STB_MODE_DB; goto _OVER; @@ -342,18 +360,14 @@ static SStbObj *mndCreateStbForStream(SMnode *pMnode, STrans *pTrans, const SStr goto _OVER; } - if (mndBuildStbFromReq(pMnode, pStb, &createReq, pDb) != 0) { - goto _OVER; - } - if (mndAddStbToTrans(pMnode, pTrans, pDb, &stbObj) < 0) goto _OVER; - return pStb; + return 0; _OVER: mndReleaseStb(pMnode, pStb); mndReleaseDb(pMnode, pDb); mndReleaseUser(pMnode, pUser); - return NULL; + return -1; } static int32_t mndCreateStream(SMnode *pMnode, SNodeMsg *pReq, SCMCreateStreamReq *pCreate, SDbObj *pDb) { @@ -373,7 +387,6 @@ static int32_t mndCreateStream(SMnode *pMnode, SNodeMsg *pReq, SCMCreateStreamRe streamObj.fixedSinkVgId = 0; streamObj.smaId = 0; /*streamObj.physicalPlan = "";*/ - streamObj.logicalPlan = "not implemented"; streamObj.trigger = pCreate->triggerType; streamObj.waterMark = pCreate->watermark; @@ -384,16 +397,14 @@ static int32_t mndCreateStream(SMnode *pMnode, SNodeMsg *pReq, SCMCreateStreamRe } mDebug("trans:%d, used to create stream:%s", pTrans->id, pCreate->name); -#if 0 - if (mndCreateStbForStream(pMnode, pTrans, &streamObj, pReq->user) < 0) { + if (mndAddStreamToTrans(pMnode, &streamObj, pCreate->ast, pCreate->triggerType, pCreate->watermark, pTrans) != 0) { mError("trans:%d, failed to add stream since %s", pTrans->id, terrstr()); mndTransDrop(pTrans); return -1; } -#endif - if (mndAddStreamToTrans(pMnode, &streamObj, pCreate->ast, pCreate->triggerType, pCreate->watermark, pTrans) != 0) { - mError("trans:%d, failed to add stream since %s", pTrans->id, terrstr()); + if (streamObj.targetSTbName[0] && mndCreateStbForStream(pMnode, pTrans, &streamObj, pReq->user) < 0) { + mError("trans:%d, failed to create stb for stream since %s", pTrans->id, terrstr()); mndTransDrop(pTrans); return -1; } diff --git a/source/dnode/mnode/impl/src/mndTrans.c b/source/dnode/mnode/impl/src/mndTrans.c index 43e2735984..e57e9a0461 100644 --- a/source/dnode/mnode/impl/src/mndTrans.c +++ b/source/dnode/mnode/impl/src/mndTrans.c @@ -1336,8 +1336,7 @@ static int32_t mndProcessKillTransReq(SNodeMsg *pReq) { goto _OVER; } - if (!pUser->superUser) { - terrno = TSDB_CODE_MND_NO_RIGHTS; + if (mndCheckTransAuth(pUser) != 0) { goto _OVER; } diff --git a/source/dnode/mnode/impl/src/mndUser.c b/source/dnode/mnode/impl/src/mndUser.c index 8b5fa06faf..81ded4ef8b 100644 --- a/source/dnode/mnode/impl/src/mndUser.c +++ b/source/dnode/mnode/impl/src/mndUser.c @@ -106,6 +106,7 @@ SSdbRaw *mndUserActionEncode(SUserObj *pUser) { SDB_SET_INT64(pRaw, dataPos, pUser->createdTime, _OVER) SDB_SET_INT64(pRaw, dataPos, pUser->updateTime, _OVER) SDB_SET_INT8(pRaw, dataPos, pUser->superUser, _OVER) + SDB_SET_INT32(pRaw, dataPos, pUser->authVersion, _OVER) SDB_SET_INT32(pRaw, dataPos, numOfReadDbs, _OVER) SDB_SET_INT32(pRaw, dataPos, numOfWriteDbs, _OVER) @@ -161,6 +162,7 @@ static SSdbRow *mndUserActionDecode(SSdbRaw *pRaw) { SDB_GET_INT64(pRaw, dataPos, &pUser->createdTime, _OVER) SDB_GET_INT64(pRaw, dataPos, &pUser->updateTime, _OVER) SDB_GET_INT8(pRaw, dataPos, &pUser->superUser, _OVER) + SDB_GET_INT32(pRaw, dataPos, &pUser->authVersion, _OVER) int32_t numOfReadDbs = 0; int32_t numOfWriteDbs = 0; @@ -588,7 +590,7 @@ _OVER: return code; } -static int32_t mndSetUserAuthRsp(SMnode *pMnode, SUserObj *pUser, SGetUserAuthRsp *pRsp) { +static int32_t mndSetUserAuthRsp(SMnode *pMnode, SUserObj *pUser, SGetUserAuthRsp *pRsp) { memcpy(pRsp->user, pUser->user, TSDB_USER_LEN); pRsp->superAuth = pUser->superUser; pRsp->version = pUser->authVersion; @@ -601,7 +603,7 @@ static int32_t mndSetUserAuthRsp(SMnode *pMnode, SUserObj *pUser, SGetUser terrno = TSDB_CODE_OUT_OF_MEMORY; return -1; } - + SSdb *pSdb = pMnode->pSdb; void *pIter = NULL; while (1) { @@ -659,7 +661,7 @@ static int32_t mndProcessGetUserAuthReq(SNodeMsg *pReq) { code = 0; _OVER: - + mndReleaseUser(pMnode, pUser); tFreeSGetUserAuthRsp(&authRsp); @@ -711,7 +713,8 @@ static void mndCancelGetNextUser(SMnode *pMnode, void *pIter) { sdbCancelFetch(pSdb, pIter); } -int32_t mndValidateUserAuthInfo(SMnode *pMnode, SUserAuthVersion *pUsers, int32_t numOfUses, void **ppRsp, int32_t *pRspLen) { +int32_t mndValidateUserAuthInfo(SMnode *pMnode, SUserAuthVersion *pUsers, int32_t numOfUses, void **ppRsp, + int32_t *pRspLen) { SUserAuthBatchRsp batchRsp = {0}; batchRsp.pArray = taosArrayInit(numOfUses, sizeof(SGetUserAuthRsp)); if (batchRsp.pArray == NULL) { @@ -731,7 +734,7 @@ int32_t mndValidateUserAuthInfo(SMnode *pMnode, SUserAuthVersion *pUsers, int32_ mndReleaseUser(pMnode, pUser); continue; } - + SGetUserAuthRsp rsp = {0}; code = mndSetUserAuthRsp(pMnode, pUser, &rsp); if (code) { @@ -740,7 +743,6 @@ int32_t mndValidateUserAuthInfo(SMnode *pMnode, SUserAuthVersion *pUsers, int32_ goto _OVER; } - taosArrayPush(batchRsp.pArray, &rsp); mndReleaseUser(pMnode, pUser); } @@ -748,7 +750,7 @@ int32_t mndValidateUserAuthInfo(SMnode *pMnode, SUserAuthVersion *pUsers, int32_ if (taosArrayGetSize(batchRsp.pArray) <= 0) { *ppRsp = NULL; *pRspLen = 0; - + tFreeSUserAuthBatchRsp(&batchRsp); return 0; } @@ -772,10 +774,7 @@ _OVER: *ppRsp = NULL; *pRspLen = 0; - + tFreeSUserAuthBatchRsp(&batchRsp); return code; } - - - diff --git a/source/dnode/mnode/impl/src/mndVgroup.c b/source/dnode/mnode/impl/src/mndVgroup.c index d1e4be1161..48a475ec63 100644 --- a/source/dnode/mnode/impl/src/mndVgroup.c +++ b/source/dnode/mnode/impl/src/mndVgroup.c @@ -370,7 +370,7 @@ static bool mndBuildDnodesArrayFp(SMnode *pMnode, void *pObj, void *p1, void *p2 return true; } -static SArray *mndBuildDnodesArray(SMnode *pMnode) { +SArray *mndBuildDnodesArray(SMnode *pMnode) { SSdb *pSdb = pMnode->pSdb; int32_t numOfDnodes = mndGetDnodeSize(pMnode); @@ -421,7 +421,7 @@ static int32_t mndGetAvailableDnode(SMnode *pMnode, SVgObj *pVgroup, SArray *pAr pVgid->role = TAOS_SYNC_STATE_FOLLOWER; } - mDebug("db:%s, vgId:%d, vn:%d dnode:%d is alloced", pVgroup->dbName, pVgroup->vgId, v, pVgid->dnodeId); + mInfo("db:%s, vgId:%d, vn:%d dnode:%d is alloced", pVgroup->dbName, pVgroup->vgId, v, pVgid->dnodeId); pDnode->numOfVnodes++; } @@ -440,12 +440,10 @@ int32_t mndAllocVgroup(SMnode *pMnode, SDbObj *pDb, SVgObj **ppVgroups) { } pArray = mndBuildDnodesArray(pMnode); - if (pArray == NULL) { - goto _OVER; - } + if (pArray == NULL) goto _OVER; - mDebug("db:%s, total %d dnodes used to create %d vgroups (%d vnodes)", pDb->name, (int32_t)taosArrayGetSize(pArray), - pDb->cfg.numOfVgroups, pDb->cfg.numOfVgroups * pDb->cfg.replications); + mInfo("db:%s, total %d dnodes used to create %d vgroups (%d vnodes)", pDb->name, (int32_t)taosArrayGetSize(pArray), + pDb->cfg.numOfVgroups, pDb->cfg.numOfVgroups * pDb->cfg.replications); int32_t allocedVgroups = 0; int32_t maxVgId = sdbGetMaxId(pMnode->pSdb, SDB_VGROUP); @@ -483,7 +481,7 @@ int32_t mndAllocVgroup(SMnode *pMnode, SDbObj *pDb, SVgObj **ppVgroups) { *ppVgroups = pVgroups; code = 0; - mDebug("db:%s, %d vgroups is alloced, replica:%d", pDb->name, pDb->cfg.numOfVgroups, pDb->cfg.replications); + mInfo("db:%s, %d vgroups is alloced, replica:%d", pDb->name, pDb->cfg.numOfVgroups, pDb->cfg.replications); _OVER: if (code != 0) taosMemoryFree(pVgroups); @@ -491,6 +489,88 @@ _OVER: return code; } +int32_t mndAddVnodeToVgroup(SMnode *pMnode, SVgObj *pVgroup, SArray *pArray) { + taosArraySort(pArray, (__compar_fn_t)mndCompareDnodeVnodes); + for (int32_t i = 0; i < taosArrayGetSize(pArray); ++i) { + SDnodeObj *pDnode = taosArrayGet(pArray, i); + mDebug("dnode:%d, equivalent vnodes:%d", pDnode->id, pDnode->numOfVnodes); + } + + int32_t maxPos = 1; + for (int32_t d = 0; d < taosArrayGetSize(pArray); ++d) { + SDnodeObj *pDnode = taosArrayGet(pArray, d); + + bool used = false; + for (int32_t vn = 0; vn < maxPos; ++vn) { + if (pDnode->id == pVgroup->vnodeGid[vn].dnodeId) { + used = true; + break; + } + } + if (used) continue; + + if (pDnode == NULL || pDnode->numOfVnodes > pDnode->numOfSupportVnodes) { + terrno = TSDB_CODE_MND_NO_ENOUGH_DNODES; + return -1; + } + + SVnodeGid *pVgid = &pVgroup->vnodeGid[maxPos]; + pVgid->dnodeId = pDnode->id; + pVgid->role = TAOS_SYNC_STATE_FOLLOWER; + pDnode->numOfVnodes++; + + mInfo("db:%s, vgId:%d, vn:%d dnode:%d is added", pVgroup->dbName, pVgroup->vgId, maxPos, pVgid->dnodeId); + maxPos++; + if (maxPos == 3) return 0; + } + + terrno = TSDB_CODE_MND_NO_ENOUGH_DNODES; + return -1; +} + +int32_t mndRemoveVnodeFromVgroup(SMnode *pMnode, SVgObj *pVgroup, SArray *pArray, SVnodeGid *del1, SVnodeGid *del2) { + int32_t removedNum = 0; + + taosArraySort(pArray, (__compar_fn_t)mndCompareDnodeVnodes); + for (int32_t i = 0; i < taosArrayGetSize(pArray); ++i) { + SDnodeObj *pDnode = taosArrayGet(pArray, i); + mDebug("dnode:%d, equivalent vnodes:%d", pDnode->id, pDnode->numOfVnodes); + } + + for (int32_t d = taosArrayGetSize(pArray) - 1; d >= 0; --d) { + SDnodeObj *pDnode = taosArrayGet(pArray, d); + + for (int32_t vn = 0; vn < TSDB_MAX_REPLICA; ++vn) { + SVnodeGid *pVgid = &pVgroup->vnodeGid[vn]; + if (pVgid->dnodeId == pDnode->id) { + if (removedNum == 0) *del1 = *pVgid; + if (removedNum == 1) *del2 = *pVgid; + + mInfo("db:%s, vgId:%d, vn:%d dnode:%d is removed", pVgroup->dbName, pVgroup->vgId, vn, pVgid->dnodeId); + memset(pVgid, 0, sizeof(SVnodeGid)); + removedNum++; + pDnode->numOfVnodes--; + + if (removedNum == 2) goto _OVER; + } + } + } + +_OVER: + if (removedNum != 2) return -1; + + for (int32_t vn = 1; vn < TSDB_MAX_REPLICA; ++vn) { + SVnodeGid *pVgid = &pVgroup->vnodeGid[vn]; + if (pVgid->dnodeId != 0) { + memcpy(&pVgroup->vnodeGid[0], pVgid, sizeof(SVnodeGid)); + memset(pVgid, 0, sizeof(SVnodeGid)); + } + } + + mInfo("db:%s, vgId:%d, dnode:%d is keeped", pVgroup->dbName, pVgroup->vgId, pVgroup->vnodeGid[0].dnodeId); + return 0; +} + SEpSet mndGetVgroupEpset(SMnode *pMnode, const SVgObj *pVgroup) { SEpSet epset = {0}; diff --git a/source/dnode/mnode/impl/test/db/db.cpp b/source/dnode/mnode/impl/test/db/db.cpp index 3c5bf5c083..545f9f22bb 100644 --- a/source/dnode/mnode/impl/test/db/db.cpp +++ b/source/dnode/mnode/impl/test/db/db.cpp @@ -73,14 +73,19 @@ TEST_F(MndTestDb, 02_Create_Alter_Drop_Db) { { SAlterDbReq alterdbReq = {0}; strcpy(alterdbReq.db, "1.d1"); + alterdbReq.buffer = 12; - alterdbReq.daysToKeep0 = 300; - alterdbReq.daysToKeep1 = 400; - alterdbReq.daysToKeep2 = 500; + alterdbReq.pageSize = -1; + alterdbReq.pages = -1; + alterdbReq.daysPerFile = -1; + alterdbReq.daysToKeep0 = -1; + alterdbReq.daysToKeep1 = -1; + alterdbReq.daysToKeep2 = -1; alterdbReq.fsyncPeriod = 4000; alterdbReq.walLevel = 2; - alterdbReq.strict = 2; + alterdbReq.strict = 1; alterdbReq.cacheLastRow = 1; + alterdbReq.replications = 1; int32_t contLen = tSerializeSAlterDbReq(NULL, 0, &alterdbReq); void* pReq = rpcMallocCont(contLen); diff --git a/source/dnode/mnode/impl/test/dnode/mdnode.cpp b/source/dnode/mnode/impl/test/dnode/mdnode.cpp index a4cbc201a9..15ade8166f 100644 --- a/source/dnode/mnode/impl/test/dnode/mdnode.cpp +++ b/source/dnode/mnode/impl/test/dnode/mdnode.cpp @@ -266,4 +266,96 @@ TEST_F(MndTestDnode, 05_Create_Drop_Restart_Dnode) { taosMsleep(1300); test.SendShowReq(TSDB_MGMT_TABLE_DNODE, "dnodes", ""); EXPECT_EQ(test.GetShowRows(), 4); + + // alter replica +#if 0 + { + SCreateDbReq createReq = {0}; + strcpy(createReq.db, "1.d2"); + createReq.numOfVgroups = 2; + createReq.buffer = -1; + createReq.pageSize = -1; + createReq.pages = -1; + createReq.daysPerFile = 1000; + createReq.daysToKeep0 = 3650; + createReq.daysToKeep1 = 3650; + createReq.daysToKeep2 = 3650; + createReq.minRows = 100; + createReq.maxRows = 4096; + createReq.fsyncPeriod = 3000; + createReq.walLevel = 1; + createReq.precision = 0; + createReq.compression = 2; + createReq.replications = 1; + createReq.strict = 1; + createReq.cacheLastRow = 0; + createReq.ignoreExist = 1; + createReq.numOfStables = 0; + createReq.numOfRetensions = 0; + + int32_t contLen = tSerializeSCreateDbReq(NULL, 0, &createReq); + void* pReq = rpcMallocCont(contLen); + tSerializeSCreateDbReq(pReq, contLen, &createReq); + + SRpcMsg* pRsp = test.SendReq(TDMT_MND_CREATE_DB, pReq, contLen); + ASSERT_NE(pRsp, nullptr); + ASSERT_EQ(pRsp->code, 0); + + test.SendShowReq(TSDB_MGMT_TABLE_DB, "user_databases", ""); + EXPECT_EQ(test.GetShowRows(), 3); + } + + { + SAlterDbReq alterdbReq = {0}; + strcpy(alterdbReq.db, "1.d2"); + + alterdbReq.buffer = 12; + alterdbReq.pageSize = -1; + alterdbReq.pages = -1; + alterdbReq.daysPerFile = -1; + alterdbReq.daysToKeep0 = -1; + alterdbReq.daysToKeep1 = -1; + alterdbReq.daysToKeep2 = -1; + alterdbReq.fsyncPeriod = 4000; + alterdbReq.walLevel = 2; + alterdbReq.strict = 1; + alterdbReq.cacheLastRow = 1; + alterdbReq.replications = 3; + + int32_t contLen = tSerializeSAlterDbReq(NULL, 0, &alterdbReq); + void* pReq = rpcMallocCont(contLen); + tSerializeSAlterDbReq(pReq, contLen, &alterdbReq); + + SRpcMsg* pRsp = test.SendReq(TDMT_MND_ALTER_DB, pReq, contLen); + ASSERT_NE(pRsp, nullptr); + ASSERT_EQ(pRsp->code, 0); + } + + { + SAlterDbReq alterdbReq = {0}; + strcpy(alterdbReq.db, "1.d2"); + + alterdbReq.buffer = 12; + alterdbReq.pageSize = -1; + alterdbReq.pages = -1; + alterdbReq.daysPerFile = -1; + alterdbReq.daysToKeep0 = -1; + alterdbReq.daysToKeep1 = -1; + alterdbReq.daysToKeep2 = -1; + alterdbReq.fsyncPeriod = 4000; + alterdbReq.walLevel = 2; + alterdbReq.strict = 1; + alterdbReq.cacheLastRow = 1; + alterdbReq.replications = 1; + + int32_t contLen = tSerializeSAlterDbReq(NULL, 0, &alterdbReq); + void* pReq = rpcMallocCont(contLen); + tSerializeSAlterDbReq(pReq, contLen, &alterdbReq); + + SRpcMsg* pRsp = test.SendReq(TDMT_MND_ALTER_DB, pReq, contLen); + ASSERT_NE(pRsp, nullptr); + ASSERT_EQ(pRsp->code, 0); + } + +#endif } diff --git a/source/dnode/mnode/impl/test/stb/stb.cpp b/source/dnode/mnode/impl/test/stb/stb.cpp index 220a73def6..16974ad541 100644 --- a/source/dnode/mnode/impl/test/stb/stb.cpp +++ b/source/dnode/mnode/impl/test/stb/stb.cpp @@ -137,7 +137,7 @@ void* MndTestStb::BuildCreateStbReq(const char* stbname, int32_t* pContLen) { } void* MndTestStb::BuildAlterStbAddTagReq(const char* stbname, const char* tagname, int32_t* pContLen) { - SMAltertbReq req = {0}; + SMAlterStbReq req = {0}; strcpy(req.name, stbname); req.numOfFields = 1; req.pFields = taosArrayInit(1, sizeof(SField)); @@ -158,7 +158,7 @@ void* MndTestStb::BuildAlterStbAddTagReq(const char* stbname, const char* tagnam } void* MndTestStb::BuildAlterStbDropTagReq(const char* stbname, const char* tagname, int32_t* pContLen) { - SMAltertbReq req = {0}; + SMAlterStbReq req = {0}; strcpy(req.name, stbname); req.numOfFields = 1; req.pFields = taosArrayInit(1, sizeof(SField)); @@ -180,7 +180,7 @@ void* MndTestStb::BuildAlterStbDropTagReq(const char* stbname, const char* tagna void* MndTestStb::BuildAlterStbUpdateTagNameReq(const char* stbname, const char* tagname, const char* newtagname, int32_t* pContLen) { - SMAltertbReq req = {0}; + SMAlterStbReq req = {0}; strcpy(req.name, stbname); req.numOfFields = 2; req.pFields = taosArrayInit(2, sizeof(SField)); @@ -208,7 +208,7 @@ void* MndTestStb::BuildAlterStbUpdateTagNameReq(const char* stbname, const char* void* MndTestStb::BuildAlterStbUpdateTagBytesReq(const char* stbname, const char* tagname, int32_t bytes, int32_t* pContLen) { - SMAltertbReq req = {0}; + SMAlterStbReq req = {0}; strcpy(req.name, stbname); req.numOfFields = 1; req.pFields = taosArrayInit(1, sizeof(SField)); @@ -229,7 +229,7 @@ void* MndTestStb::BuildAlterStbUpdateTagBytesReq(const char* stbname, const char } void* MndTestStb::BuildAlterStbAddColumnReq(const char* stbname, const char* colname, int32_t* pContLen) { - SMAltertbReq req = {0}; + SMAlterStbReq req = {0}; strcpy(req.name, stbname); req.numOfFields = 1; req.pFields = taosArrayInit(1, sizeof(SField)); @@ -250,7 +250,7 @@ void* MndTestStb::BuildAlterStbAddColumnReq(const char* stbname, const char* col } void* MndTestStb::BuildAlterStbDropColumnReq(const char* stbname, const char* colname, int32_t* pContLen) { - SMAltertbReq req = {0}; + SMAlterStbReq req = {0}; strcpy(req.name, stbname); req.numOfFields = 1; req.pFields = taosArrayInit(1, sizeof(SField)); @@ -272,7 +272,7 @@ void* MndTestStb::BuildAlterStbDropColumnReq(const char* stbname, const char* co void* MndTestStb::BuildAlterStbUpdateColumnBytesReq(const char* stbname, const char* colname, int32_t bytes, int32_t* pContLen) { - SMAltertbReq req = {0}; + SMAlterStbReq req = {0}; strcpy(req.name, stbname); req.numOfFields = 1; req.pFields = taosArrayInit(1, sizeof(SField)); diff --git a/source/dnode/qnode/src/qnode.c b/source/dnode/qnode/src/qnode.c index 7a226a4c6b..b21141001a 100644 --- a/source/dnode/qnode/src/qnode.c +++ b/source/dnode/qnode/src/qnode.c @@ -84,6 +84,8 @@ int32_t qndProcessFetchMsg(SQnode *pQnode, SRpcMsg *pMsg) { // return vnodeGetTableMeta(pQnode, pMsg); case TDMT_VND_CONSUME: // return tqProcessConsumeReq(pQnode->pTq, pMsg); + case TDMT_VND_QUERY_HEARTBEAT: + return qWorkerProcessHbMsg(pQnode, pQnode->pQuery, pMsg); default: qError("unknown msg type:%d in fetch queue", pMsg->msgType); return TSDB_CODE_VND_APP_ERROR; diff --git a/source/dnode/vnode/src/inc/tsdb.h b/source/dnode/vnode/src/inc/tsdb.h index d84c1b1d07..58003a97d7 100644 --- a/source/dnode/vnode/src/inc/tsdb.h +++ b/source/dnode/vnode/src/inc/tsdb.h @@ -325,9 +325,8 @@ typedef struct { typedef struct { int16_t colId; uint16_t type : 6; - uint16_t blen : 10; // bitmap length(TODO: full UT for the bitmap compress of various data input) - uint32_t bitmap : 1; // 0: no bitmap if all rows are NORM, 1: has bitmap if has NULL/NORM rows - uint32_t len : 31; // data length + bitmap length + uint16_t blen : 10; // 0 no bitmap if all rows are NORM, > 0 bitmap length + uint32_t len; // data length + bitmap length uint32_t offset; } SBlockColV0; diff --git a/source/dnode/vnode/src/meta/metaTable.c b/source/dnode/vnode/src/meta/metaTable.c index 397e074061..a68e176fa9 100644 --- a/source/dnode/vnode/src/meta/metaTable.c +++ b/source/dnode/vnode/src/meta/metaTable.c @@ -196,12 +196,12 @@ int metaDropTable(SMeta *pMeta, int64_t version, SVDropTbReq *pReq) { int8_t type; int64_t ctime; tb_uid_t suid; - int c, ret; + int c = 0, ret; // search & delete the name idx tdbDbcOpen(pMeta->pNameIdx, &pNameIdxc, &pMeta->txn); ret = tdbDbcMoveTo(pNameIdxc, pReq->name, strlen(pReq->name) + 1, &c); - if (ret < 0 || c) { + if (ret < 0 || !tdbDbcIsValid(pNameIdxc) || c) { tdbDbcClose(pNameIdxc); terrno = TSDB_CODE_VND_TABLE_NOT_EXIST; return -1; diff --git a/source/dnode/vnode/src/tq/tqRead.c b/source/dnode/vnode/src/tq/tqRead.c index 5ec3ab0b47..f531d3f5fb 100644 --- a/source/dnode/vnode/src/tq/tqRead.c +++ b/source/dnode/vnode/src/tq/tqRead.c @@ -173,7 +173,7 @@ int32_t tqRetrieveDataBlock(SArray** ppCols, STqReadHandle* pHandle, uint64_t* p int32_t curRow = 0; tInitSubmitBlkIter(&pHandle->msgIter, pHandle->pBlock, &pHandle->blkIter); - *pUid = pHandle->pBlock->uid; // set the uid of table for submit block + *pUid = pHandle->msgIter.uid; // set the uid of table for submit block while ((row = tGetSubmitBlkNext(&pHandle->blkIter)) != NULL) { tdSTSRowIterReset(&iter, row); diff --git a/source/dnode/vnode/src/tsdb/tsdbCommit.c b/source/dnode/vnode/src/tsdb/tsdbCommit.c index a008c4a0e5..f0b1baf1da 100644 --- a/source/dnode/vnode/src/tsdb/tsdbCommit.c +++ b/source/dnode/vnode/src/tsdb/tsdbCommit.c @@ -943,16 +943,16 @@ int tsdbWriteBlockImpl(STsdb *pRepo, STable *pTable, SDFile *pDFile, SDFile *pDF &(pAggrBlkCol->numOfNull)); if (pAggrBlkCol->numOfNull == 0) { - TD_SET_COL_ROWS_NORM(pBlockCol); + pBlockCol->blen = 0; } else { - TD_SET_COL_ROWS_MISC(pBlockCol); + pBlockCol->blen = 1; } ++nColsOfBlockSma; } else if (tdIsBitmapBlkNorm(pDataCol->pBitmap, rowsToWrite, pDataCols->bitmapMode)) { // check if all rows normal - TD_SET_COL_ROWS_NORM(pBlockCol); + pBlockCol->blen = 0; } else { - TD_SET_COL_ROWS_MISC(pBlockCol); + pBlockCol->blen = 1; } ++nColsNotAllNull; @@ -985,7 +985,7 @@ int tsdbWriteBlockImpl(STsdb *pRepo, STable *pTable, SDFile *pDFile, SDFile *pDF #ifdef TD_SUPPORT_BITMAP int32_t tBitmaps = 0; int32_t tBitmapsLen = 0; - if ((ncol != 0) && !TD_COL_ROWS_NORM(pBlockCol)) { + if ((ncol != 0) && (pBlockCol->blen > 0)) { tBitmaps = isSuper ? sBitmaps : nBitmaps; } #endif diff --git a/source/dnode/vnode/src/tsdb/tsdbMemTable2.c b/source/dnode/vnode/src/tsdb/tsdbMemTable2.c index ae0d4630d1..e7b733369a 100644 --- a/source/dnode/vnode/src/tsdb/tsdbMemTable2.c +++ b/source/dnode/vnode/src/tsdb/tsdbMemTable2.c @@ -15,10 +15,11 @@ #include "tsdb.h" -typedef struct SMemTable SMemTable; -typedef struct SMemData SMemData; -typedef struct SMemSkipList SMemSkipList; -typedef struct SMemSkipListCfg SMemSkipListCfg; +typedef struct SMemTable SMemTable; +typedef struct SMemData SMemData; +typedef struct SMemSkipList SMemSkipList; +typedef struct SMemSkipListNode SMemSkipListNode; +typedef struct SMemSkipListCurosr SMemSkipListCurosr; struct SMemTable { STsdb *pTsdb; @@ -32,15 +33,17 @@ struct SMemTable { SMemData **pBuckets; }; -struct SMemSkipListCfg { - int8_t maxLevel; - int32_t nKey; - int32_t nData; +struct SMemSkipListNode { + int8_t level; + SMemSkipListNode *forwards[]; }; struct SMemSkipList { - int8_t level; - uint32_t seed; + uint32_t seed; + int8_t maxLevel; + int8_t level; + int32_t size; + SMemSkipListNode pHead[]; }; struct SMemData { @@ -55,6 +58,20 @@ struct SMemData { SMemSkipList sl; }; +struct SMemSkipListCurosr { + SMemSkipList *pSl; + SMemSkipListNode *pNodeC; +}; + +#define SL_NODE_SIZE(l) (sizeof(SMemSkipListNode) + sizeof(SMemSkipListNode *) * (l)*2) +#define SL_NODE_HALF_SIZE(l) (sizeof(SMemSkipListNode) + sizeof(SMemSkipListNode *) * (l)) +#define SL_NODE_FORWARD(n, l) ((n)->forwards[l]) +#define SL_NODE_BACKWARD(n, l) ((n)->forwards[(n)->level + (l)]) +#define SL_NODE_DATA(n) (&SL_NODE_BACKWARD(n, (n)->level)) + +#define SL_HEAD_NODE(sl) ((sl)->pHead) +#define SL_TAIL_NODE(sl) ((SMemSkipListNode *)&SL_NODE_FORWARD(SL_HEAD_NODE(sl), (sl)->maxLevel)) + // SMemTable int32_t tsdbMemTableCreate2(STsdb *pTsdb, SMemTable **ppMemTb) { SMemTable *pMemTb = NULL; @@ -76,6 +93,7 @@ int32_t tsdbMemTableCreate2(STsdb *pTsdb, SMemTable **ppMemTb) { pMemTb->pBuckets = taosMemoryCalloc(pMemTb->nBucket, sizeof(*pMemTb->pBuckets)); if (pMemTb->pBuckets == NULL) { terrno = TSDB_CODE_OUT_OF_MEMORY; + taosMemoryFree(pMemTb); return -1; } @@ -83,8 +101,121 @@ int32_t tsdbMemTableCreate2(STsdb *pTsdb, SMemTable **ppMemTb) { return 0; } -int32_t tsdbMemTableDestroy2(STsdb *pTsdb, SMemTable *pMT) { - // TODO +int32_t tsdbMemTableDestroy2(STsdb *pTsdb, SMemTable *pMemTb) { + if (pMemTb) { + // loop to destroy the contents (todo) + taosMemoryFree(pMemTb->pBuckets); + taosMemoryFree(pMemTb); + } + return 0; +} + +int32_t tsdbInsertData2(SMemTable *pMemTb, int64_t version, const SVSubmitBlk *pSubmitBlk) { + SMemData *pMemData; + STsdb *pTsdb = pMemTb->pTsdb; + SVnode *pVnode = pTsdb->pVnode; + SVBufPool *pPool = pVnode->inUse; + int32_t hash; + int32_t tlen; + uint8_t buf[16]; + int32_t rlen; + const uint8_t *p; + SMemSkipListNode *pSlNode; + const STSRow *pTSRow; + SMemSkipListCurosr slc = {0}; + + // search hash + hash = (pSubmitBlk->suid + pSubmitBlk->uid) % pMemTb->nBucket; + for (pMemData = pMemTb->pBuckets[hash]; pMemData; pMemData = pMemData->pHashNext) { + if (pMemData->suid == pSubmitBlk->suid && pMemData->uid == pSubmitBlk->uid) break; + } + + // create pMemData if need + if (pMemData == NULL) { + int8_t maxLevel = pVnode->config.tsdbCfg.slLevel; + int32_t tsize = sizeof(*pMemData) + SL_NODE_HALF_SIZE(maxLevel) * 2; + SMemSkipListNode *pHead, *pTail; + + pMemData = vnodeBufPoolMalloc(pPool, tsize); + if (pMemData == NULL) { + terrno = TSDB_CODE_OUT_OF_MEMORY; + return -1; + } + + pMemData->pHashNext = NULL; + pMemData->suid = pSubmitBlk->suid; + pMemData->uid = pSubmitBlk->uid; + pMemData->minKey = TSKEY_MAX; + pMemData->maxKey = TSKEY_MIN; + pMemData->minVer = -1; + pMemData->maxVer = -1; + pMemData->nRows = 0; + pMemData->sl.seed = taosRand(); + pMemData->sl.maxLevel = maxLevel; + pMemData->sl.level = 0; + pMemData->sl.size = 0; + pHead = SL_HEAD_NODE(&pMemData->sl); + pTail = SL_TAIL_NODE(&pMemData->sl); + pHead->level = maxLevel; + pTail->level = maxLevel; + for (int iLevel = 0; iLevel < maxLevel; iLevel++) { + SL_NODE_FORWARD(pHead, iLevel) = pTail; + SL_NODE_FORWARD(pTail, iLevel) = pHead; + } + + // add to MemTable + hash = (pMemData->suid + pMemData->uid) % pMemTb->nBucket; + pMemData->pHashNext = pMemTb->pBuckets[hash]; + pMemTb->pBuckets[hash] = pMemData; + pMemTb->nHash++; + } + +// loop to insert data to skiplist +#if 0 + tsdbMemSkipListCursorOpen(&slc, &pMemData->sl); + p = pSubmitBlk->pData; + for (;;) { + if (p - (uint8_t *)pSubmitBlk->pData >= pSubmitBlk->nData) break; + + const uint8_t *pt = p; + p = tGetBinary(p, &pTSRow, &rlen); + + // check the row (todo) + + // move the cursor to position to write (todo) + int32_t c; + tsdbMemSkipListCursorMoveTo(&slc, pTSRow, version, &c); + ASSERT(c); + + // encode row + int8_t level = tsdbMemSkipListRandLevel(&pMemData->sl); + int32_t tsize = SL_NODE_SIZE(level) + sizeof(version) + (p - pt); + pSlNode = vnodeBufPoolMalloc(pPool, tsize); + pSlNode->level = level; + + uint8_t *pData = SL_NODE_DATA(pSlNode); + *(int64_t *)pData = version; + pData += sizeof(version); + memcpy(pData, pt, p - pt); + + // insert row + tsdbMemSkipListCursorPut(&slc, pSlNode); + + // update status + if (pTSRow->ts < pMemData->minKey) pMemData->minKey = pTSRow->ts; + if (pTSRow->ts > pMemData->maxKey) pMemData->maxKey = pTSRow->ts; + } + tsdbMemSkipListCursorClose(&slc); +#endif + + if (pMemData->minVer == -1) pMemData->minVer = version; + if (pMemData->maxVer == -1 || pMemData->maxVer < version) pMemData->maxVer = version; + + if (pMemTb->minKey < pMemData->minKey) pMemTb->minKey = pMemData->minKey; + if (pMemTb->maxKey < pMemData->maxKey) pMemTb->maxKey = pMemData->maxKey; + if (pMemTb->minVer == -1) pMemTb->minVer = version; + if (pMemTb->maxVer == -1 || pMemTb->maxVer < version) pMemTb->maxVer = version; + return 0; } diff --git a/source/dnode/vnode/src/tsdb/tsdbRead.c b/source/dnode/vnode/src/tsdb/tsdbRead.c index aa305dd71c..0b9f21dbcf 100644 --- a/source/dnode/vnode/src/tsdb/tsdbRead.c +++ b/source/dnode/vnode/src/tsdb/tsdbRead.c @@ -1619,7 +1619,7 @@ static int32_t mergeTwoRowFromMem(STsdbReadHandle* pTsdbReadHandle, int32_t capa SCellVal sVal = {0}; TSKEY rowKey = TSKEY_INITIAL_VAL; int32_t nResult = 0; - bool isMerge = true; + int32_t mergeOption = 0; // 0 discard 1 overwrite 2 merge // the schema version info is embeded in STSRow int32_t numOfColsOfRow1 = 0; @@ -1715,12 +1715,18 @@ static int32_t mergeTwoRowFromMem(STsdbReadHandle* pTsdbReadHandle, int32_t capa if (colId == PRIMARYKEY_TIMESTAMP_COL_ID) { rowKey = *(TSKEY*)sVal.val; if (rowKey != *lastRowKey) { - isMerge = false; + mergeOption = 1; if (*lastRowKey != TSKEY_INITIAL_VAL) { ++(*curRow); } ++nResult; + } else if (update){ + mergeOption = 2; + } else { + mergeOption = 0; + break; } + *lastRowKey = rowKey; } } else { @@ -1730,11 +1736,16 @@ static int32_t mergeTwoRowFromMem(STsdbReadHandle* pTsdbReadHandle, int32_t capa tdSKvRowGetVal(row, PRIMARYKEY_TIMESTAMP_COL_ID, -1, -1, &sVal); rowKey = *(TSKEY*)sVal.val; if (rowKey != *lastRowKey) { - isMerge = false; + mergeOption = 1; if (*lastRowKey != TSKEY_INITIAL_VAL) { ++(*curRow); } ++nResult; + } else if(update) { + mergeOption = 2; + } else { + mergeOption = 0; + break; } *lastRowKey = rowKey; } else { @@ -1754,7 +1765,7 @@ static int32_t mergeTwoRowFromMem(STsdbReadHandle* pTsdbReadHandle, int32_t capa colDataAppend(pColInfo, *curRow, NULL, true); } else if (tdValTypeIsNone(sVal.valType)) { // TODO: Set null if nothing append for this row - if (!isMerge) { + if (mergeOption == 1) { colDataAppend(pColInfo, *curRow, NULL, true); } } else { @@ -1769,14 +1780,14 @@ static int32_t mergeTwoRowFromMem(STsdbReadHandle* pTsdbReadHandle, int32_t capa ++k; } } else { - if (!isMerge) { + if (mergeOption == 1) { colDataAppend(pColInfo, *curRow, NULL, true); } ++i; } } - if (*lastRowKey != rowKey) { + if (mergeOption == 1) { while (i < numOfCols) { // the remain columns are all null data SColumnInfoData* pColInfo = taosArrayGet(pTsdbReadHandle->pColumns, i); colDataAppend(pColInfo, *curRow, NULL, true); @@ -2008,7 +2019,7 @@ static void doMergeTwoLevelData(STsdbReadHandle* pTsdbReadHandle, STableCheckInf } numOfRows += mergeTwoRowFromMem(pTsdbReadHandle, pTsdbReadHandle->outputCapacity, &curRow, row1, row2, numOfCols, - pCheckInfo->tableId, pSchema1, pSchema2, true, &lastRowKey); + pCheckInfo->tableId, pSchema1, pSchema2, pCfg->update, &lastRowKey); // numOfRows += 1; if (cur->win.skey == TSKEY_INITIAL_VAL) { cur->win.skey = key; @@ -2065,7 +2076,7 @@ static void doMergeTwoLevelData(STsdbReadHandle* pTsdbReadHandle, STableCheckInf } numOfRows += mergeTwoRowFromMem(pTsdbReadHandle, pTsdbReadHandle->outputCapacity, &curRow, row1, row2, numOfCols, - pCheckInfo->tableId, pSchema1, pSchema2, true, &lastRowKey); + pCheckInfo->tableId, pSchema1, pSchema2, pCfg->update, &lastRowKey); // ++numOfRows; if (cur->win.skey == TSKEY_INITIAL_VAL) { cur->win.skey = key; @@ -2747,7 +2758,7 @@ static int tsdbReadRowsFromCache(STableCheckInfo* pCheckInfo, TSKEY maxKey, int rv = TD_ROW_SVER(row); } numOfRows += mergeTwoRowFromMem(pTsdbReadHandle, maxRowsToRead, &curRows, row, NULL, numOfCols, pCheckInfo->tableId, pSchema, - NULL, true, &lastRowKey); + NULL, pCfg->update, &lastRowKey); if (numOfRows >= maxRowsToRead) { moveToNextRowInMem(pCheckInfo); diff --git a/source/dnode/vnode/src/tsdb/tsdbReadImpl.c b/source/dnode/vnode/src/tsdb/tsdbReadImpl.c index 49d02adc3a..bebdfb3b63 100644 --- a/source/dnode/vnode/src/tsdb/tsdbReadImpl.c +++ b/source/dnode/vnode/src/tsdb/tsdbReadImpl.c @@ -616,7 +616,7 @@ static int tsdbLoadBlockDataImpl(SReadH *pReadh, SBlock *pBlock, SDataCols *pDat tcolId = pBlockCol->colId; toffset = tsdbGetBlockColOffset(pBlockCol); tlen = pBlockCol->len; - pDataCol->bitmap = pBlockCol->bitmap; + pDataCol->bitmap = pBlockCol->blen > 0 ? 1 : 0; } else { ASSERT(pDataCol->colId == tcolId); TD_SET_COL_ROWS_NORM(pDataCol); @@ -624,17 +624,8 @@ static int tsdbLoadBlockDataImpl(SReadH *pReadh, SBlock *pBlock, SDataCols *pDat // int32_t tBitmaps = 0; int32_t tLenBitmap = 0; - if ((dcol != 0) && !TD_COL_ROWS_NORM(pBlockCol)) { + if ((dcol != 0) && (pBlockCol->blen > 0)) { tLenBitmap = nBitmaps; -#if 0 - if (IS_VAR_DATA_TYPE(pDataCol->type)) { - tBitmaps = nBitmaps; - tLenBitmap = tBitmaps; - } else { - tBitmaps = (int32_t)ceil((double)nBitmaps / TYPE_BYTES[pDataCol->type]); - tLenBitmap = tBitmaps * TYPE_BYTES[pDataCol->type]; - } -#endif } if (tcolId == pDataCol->colId) { @@ -784,8 +775,7 @@ static int tsdbLoadBlockDataColsImpl(SReadH *pReadh, SBlock *pBlock, SDataCols * if (colId == PRIMARYKEY_TIMESTAMP_COL_ID) { // load the key row blockCol.colId = colId; - TD_SET_COL_ROWS_NORM(&blockCol); // default is NORM for the primary key column - blockCol.blen = 0; + blockCol.blen = 0; // default is NORM for the primary key column blockCol.len = pBlock->keyLen; blockCol.type = pDataCol->type; blockCol.offset = TSDB_KEY_COL_OFFSET; @@ -815,7 +805,7 @@ static int tsdbLoadBlockDataColsImpl(SReadH *pReadh, SBlock *pBlock, SDataCols * ASSERT(pBlockCol->colId == pDataCol->colId); } // set the bitmap - pDataCol->bitmap = pBlockCol->bitmap; + pDataCol->bitmap = pBlockCol->blen > 0 ? 1 : 0; if (tsdbLoadColData(pReadh, pDFile, pBlock, pBlockCol, pDataCol) < 0) return -1; } @@ -833,17 +823,8 @@ static int tsdbLoadColData(SReadH *pReadh, SDFile *pDFile, SBlock *pBlock, SBloc // int32_t tBitmaps = 0; int32_t tLenBitmap = 0; - if (!TD_COL_ROWS_NORM(pBlockCol)) { + if (pBlockCol->blen) { tLenBitmap = nBitmaps; -#if 0 - if (IS_VAR_DATA_TYPE(pDataCol->type)) { - tBitmaps = nBitmaps; - tLenBitmap = tBitmaps; - } else { - tBitmaps = (int32_t)ceil((double)nBitmaps / TYPE_BYTES[pDataCol->type]); - tLenBitmap = tBitmaps * TYPE_BYTES[pDataCol->type]; - } -#endif } int tsize = pDataCol->bytes * pBlock->numOfRows + tLenBitmap + 2 * COMP_OVERFLOW_BYTES; diff --git a/source/dnode/vnode/src/vnd/vnodeSvr.c b/source/dnode/vnode/src/vnd/vnodeSvr.c index 8460400b59..403c02b440 100644 --- a/source/dnode/vnode/src/vnd/vnodeSvr.c +++ b/source/dnode/vnode/src/vnd/vnodeSvr.c @@ -360,7 +360,11 @@ static int vnodeProcessCreateTbReq(SVnode *pVnode, int64_t version, void *pReq, // do create table if (metaCreateTable(pVnode->pMeta, version, pCreateReq) < 0) { - cRsp.code = terrno; + if (pCreateReq->flags & TD_CREATE_IF_NOT_EXISTS && terrno == TSDB_CODE_TDB_TABLE_ALREADY_EXIST) { + cRsp.code = TSDB_CODE_SUCCESS; + } else { + cRsp.code = terrno; + } } else { cRsp.code = TSDB_CODE_SUCCESS; tsdbFetchTbUidList(pVnode->pTsdb, &pStore, pCreateReq->ctb.suid, pCreateReq->uid); @@ -529,6 +533,13 @@ static int vnodeProcessSubmitReq(SVnode *pVnode, int64_t version, void *pReq, in } } + msgIter.uid = createTbReq.uid; + if (createTbReq.type == TSDB_CHILD_TABLE) { + msgIter.suid = createTbReq.ctb.suid; + } else { + msgIter.suid = 0; + } + tCoderClear(&coder); } diff --git a/source/libs/CMakeLists.txt b/source/libs/CMakeLists.txt index b1e8be6528..ade2487239 100644 --- a/source/libs/CMakeLists.txt +++ b/source/libs/CMakeLists.txt @@ -17,4 +17,4 @@ add_subdirectory(tfs) add_subdirectory(monitor) add_subdirectory(nodes) add_subdirectory(scalar) -add_subdirectory(command) +add_subdirectory(command) \ No newline at end of file diff --git a/source/libs/executor/inc/executorimpl.h b/source/libs/executor/inc/executorimpl.h index 3b5d0c209f..9eed76a0fe 100644 --- a/source/libs/executor/inc/executorimpl.h +++ b/source/libs/executor/inc/executorimpl.h @@ -325,10 +325,15 @@ typedef struct SExchangeInfo { SLoadRemoteDataInfo loadInfo; } SExchangeInfo; +#define COL_MATCH_FROM_COL_ID 0x1 +#define COL_MATCH_FROM_SLOT_ID 0x2 + typedef struct SColMatchInfo { + int32_t srcSlotId; // source slot id int32_t colId; int32_t targetSlotId; bool output; + int32_t matchType; // determinate the source according to col id or slot id } SColMatchInfo; typedef struct SScanInfo { diff --git a/source/libs/executor/src/dataSinkMgt.c b/source/libs/executor/src/dataSinkMgt.c index 997397314f..64206fc10a 100644 --- a/source/libs/executor/src/dataSinkMgt.c +++ b/source/libs/executor/src/dataSinkMgt.c @@ -60,4 +60,5 @@ void dsScheduleProcess(void* ahandle, void* pItem) { void dsDestroyDataSinker(DataSinkHandle handle) { SDataSinkHandle* pHandleImpl = (SDataSinkHandle*)handle; pHandleImpl->fDestroy(pHandleImpl); + taosMemoryFree(pHandleImpl); } diff --git a/source/libs/executor/src/executorimpl.c b/source/libs/executor/src/executorimpl.c index 943d4b2783..6d13a8a42b 100644 --- a/source/libs/executor/src/executorimpl.c +++ b/source/libs/executor/src/executorimpl.c @@ -4687,7 +4687,7 @@ static SExecTaskInfo* createExecTaskInfo(uint64_t queryId, uint64_t taskId, EOPT char* p = taosMemoryCalloc(1, 128); snprintf(p, 128, "TID:0x%" PRIx64 " QID:0x%" PRIx64, taskId, queryId); - pTaskInfo->id.str = strdup(p); + pTaskInfo->id.str = p; return pTaskInfo; } @@ -4699,10 +4699,9 @@ static int32_t doCreateTableGroup(void* metaHandle, int32_t tableType, uint64_t uint64_t queryId, uint64_t taskId); static SArray* extractTableIdList(const STableGroupInfo* pTableGroupInfo); static SArray* extractColumnInfo(SNodeList* pNodeList); -static SArray* extractColMatchInfo(SNodeList* pNodeList, SDataBlockDescNode* pOutputNodeList, int32_t* numOfOutputCols); +static SArray* extractColMatchInfo(SNodeList* pNodeList, SDataBlockDescNode* pOutputNodeList, int32_t* numOfOutputCols, int32_t type); static SArray* createSortInfo(SNodeList* pNodeList); -static SArray* createIndexMap(SNodeList* pNodeList); static SArray* extractPartitionColInfo(SNodeList* pNodeList); static int32_t initQueryTableDataCond(SQueryTableDataCond* pCond, const STableScanPhysiNode* pTableScanNode); static void setJoinColumnInfo(SColumnInfo* pInfo, const SColumnNode* pLeftNode); @@ -4734,9 +4733,10 @@ SOperatorInfo* createOperatorTree(SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo return NULL; } - SArray* pColList = - extractColMatchInfo(pScanPhyNode->pScanCols, pScanPhyNode->node.pOutputDataBlockDesc, &numOfCols); - SSDataBlock* pResBlock = createResDataBlock(pScanPhyNode->node.pOutputDataBlockDesc); + SDataBlockDescNode* pDescNode = pScanPhyNode->node.pOutputDataBlockDesc; + + SArray* pColList = extractColMatchInfo(pScanPhyNode->pScanCols, pDescNode, &numOfCols, COL_MATCH_FROM_COL_ID); + SSDataBlock* pResBlock = createResDataBlock(pDescNode); SQueryTableDataCond cond = {0}; int32_t code = initQueryTableDataCond(&cond, pTableScanNode); @@ -4761,10 +4761,11 @@ SOperatorInfo* createOperatorTree(SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo int32_t code = doCreateTableGroup(pHandle->meta, pScanPhyNode->tableType, pScanPhyNode->uid, pTableGroupInfo, queryId, taskId); SArray* tableIdList = extractTableIdList(pTableGroupInfo); - SSDataBlock* pResBlock = createResDataBlock(pScanPhyNode->node.pOutputDataBlockDesc); + SDataBlockDescNode* pDescNode = pScanPhyNode->node.pOutputDataBlockDesc; + SSDataBlock* pResBlock = createResDataBlock(pDescNode); int32_t numOfCols = 0; - SArray* pCols = extractColMatchInfo(pScanPhyNode->pScanCols, pScanPhyNode->node.pOutputDataBlockDesc, &numOfCols); + SArray* pCols = extractColMatchInfo(pScanPhyNode->pScanCols, pDescNode, &numOfCols, COL_MATCH_FROM_COL_ID); SOperatorInfo* pOperator = createStreamScanOperatorInfo(pHandle->reader, pResBlock, pCols, tableIdList, pTaskInfo, pScanPhyNode->node.pConditions); taosArrayDestroy(tableIdList); @@ -4773,18 +4774,22 @@ SOperatorInfo* createOperatorTree(SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo SSystemTableScanPhysiNode* pSysScanPhyNode = (SSystemTableScanPhysiNode*)pPhyNode; SScanPhysiNode* pScanNode = &pSysScanPhyNode->scan; - SSDataBlock* pResBlock = createResDataBlock(pScanNode->node.pOutputDataBlockDesc); + SDataBlockDescNode* pDescNode = pScanNode->node.pOutputDataBlockDesc; + + SSDataBlock* pResBlock = createResDataBlock(pDescNode); int32_t numOfOutputCols = 0; - SArray* colList = - extractColMatchInfo(pScanNode->pScanCols, pScanNode->node.pOutputDataBlockDesc, &numOfOutputCols); + SArray* colList = extractColMatchInfo(pScanNode->pScanCols, pDescNode, &numOfOutputCols, COL_MATCH_FROM_COL_ID); SOperatorInfo* pOperator = createSysTableScanOperatorInfo( pHandle, pResBlock, &pScanNode->tableName, pScanNode->node.pConditions, pSysScanPhyNode->mgmtEpSet, colList, pTaskInfo, pSysScanPhyNode->showRewrite, pSysScanPhyNode->accountId); return pOperator; } else if (QUERY_NODE_PHYSICAL_PLAN_TAG_SCAN == type) { STagScanPhysiNode* pScanPhyNode = (STagScanPhysiNode*) pPhyNode; - SSDataBlock* pResBlock = createResDataBlock(pScanPhyNode->node.pOutputDataBlockDesc); + + SDataBlockDescNode* pDescNode = pScanPhyNode->node.pOutputDataBlockDesc; + + SSDataBlock* pResBlock = createResDataBlock(pDescNode); int32_t code = doCreateTableGroup(pHandle->meta, pScanPhyNode->tableType, pScanPhyNode->uid, pTableGroupInfo, queryId, taskId); @@ -4796,8 +4801,7 @@ SOperatorInfo* createOperatorTree(SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo SExprInfo* pExprInfo = createExprInfo(pScanPhyNode->pScanPseudoCols, NULL, &num); int32_t numOfOutputCols = 0; - SArray* colList = - extractColMatchInfo(pScanPhyNode->pScanPseudoCols, pScanPhyNode->node.pOutputDataBlockDesc, &numOfOutputCols); + SArray* colList = extractColMatchInfo(pScanPhyNode->pScanPseudoCols, pDescNode, &numOfOutputCols, COL_MATCH_FROM_COL_ID); SOperatorInfo* pOperator = createTagScanOperatorInfo(pHandle, pExprInfo, num, pResBlock, colList, pTableGroupInfo, pTaskInfo); return pOperator; @@ -4869,15 +4873,16 @@ SOperatorInfo* createOperatorTree(SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo } else if (QUERY_NODE_PHYSICAL_PLAN_SORT == type) { SSortPhysiNode* pSortPhyNode = (SSortPhysiNode*)pPhyNode; - SSDataBlock* pResBlock = createResDataBlock(pPhyNode->pOutputDataBlockDesc); + SDataBlockDescNode* pDescNode = pPhyNode->pOutputDataBlockDesc; + + SSDataBlock* pResBlock = createResDataBlock(pDescNode); SArray* info = createSortInfo(pSortPhyNode->pSortKeys); int32_t numOfCols = 0; SExprInfo* pExprInfo = createExprInfo(pSortPhyNode->pExprs, NULL, &numOfCols); int32_t numOfOutputCols = 0; - SArray* pColList = - extractColMatchInfo(pSortPhyNode->pTargets, pSortPhyNode->node.pOutputDataBlockDesc, &numOfOutputCols); + SArray* pColList = extractColMatchInfo(pSortPhyNode->pTargets, pDescNode, &numOfOutputCols, COL_MATCH_FROM_SLOT_ID); pOptr = createSortOperatorInfo(ops[0], pResBlock, info, pExprInfo, numOfCols, pColList, pTaskInfo); } else if (QUERY_NODE_PHYSICAL_PLAN_SESSION_WINDOW == type) { @@ -5059,25 +5064,7 @@ SArray* createSortInfo(SNodeList* pNodeList) { return pList; } -SArray* createIndexMap(SNodeList* pNodeList) { - size_t numOfCols = LIST_LENGTH(pNodeList); - SArray* pList = taosArrayInit(numOfCols, sizeof(int32_t)); - if (pList == NULL) { - terrno = TSDB_CODE_OUT_OF_MEMORY; - return pList; - } - - for (int32_t i = 0; i < numOfCols; ++i) { - STargetNode* pTarget = (STargetNode*)nodesListGetNode(pNodeList, i); - - SColumnNode* pColNode = (SColumnNode*)pTarget->pExpr; - taosArrayPush(pList, &pColNode->slotId); - } - - return pList; -} - -SArray* extractColMatchInfo(SNodeList* pNodeList, SDataBlockDescNode* pOutputNodeList, int32_t* numOfOutputCols) { +SArray* extractColMatchInfo(SNodeList* pNodeList, SDataBlockDescNode* pOutputNodeList, int32_t* numOfOutputCols, int32_t type) { size_t numOfCols = LIST_LENGTH(pNodeList); SArray* pList = taosArrayInit(numOfCols, sizeof(SColMatchInfo)); if (pList == NULL) { @@ -5090,8 +5077,10 @@ SArray* extractColMatchInfo(SNodeList* pNodeList, SDataBlockDescNode* pOutputNod SColumnNode* pColNode = (SColumnNode*)pNode->pExpr; SColMatchInfo c = {0}; - c.output = true; - c.colId = pColNode->colId; + c.output = true; + c.colId = pColNode->colId; + c.srcSlotId = pColNode->slotId; + c.matchType = type; c.targetSlotId = pNode->slotId; taosArrayPush(pList, &c); } @@ -5301,6 +5290,7 @@ void doDestroyTask(SExecTaskInfo* pTaskInfo) { // taosArrayDestroy(pTaskInfo->summary.queryProfEvents); // taosHashCleanup(pTaskInfo->summary.operatorProfResults); + destroyOperatorInfo(pTaskInfo->pRoot); taosMemoryFreeClear(pTaskInfo->sql); taosMemoryFreeClear(pTaskInfo->id.str); taosMemoryFreeClear(pTaskInfo); diff --git a/source/libs/executor/src/groupoperator.c b/source/libs/executor/src/groupoperator.c index 58efd75a0b..183cb9dbe6 100644 --- a/source/libs/executor/src/groupoperator.c +++ b/source/libs/executor/src/groupoperator.c @@ -129,6 +129,7 @@ static void recordNewGroupKeys(SArray* pGroupCols, SArray* pGroupColVals, SSData char* val = colDataGetData(pColInfoData, rowIndex); if (IS_VAR_DATA_TYPE(pkey->type)) { memcpy(pkey->pData, val, varDataTLen(val)); + ASSERT(varDataTLen(val) <= pkey->bytes); } else { memcpy(pkey->pData, val, pkey->bytes); } diff --git a/source/libs/executor/src/sortoperator.c b/source/libs/executor/src/sortoperator.c index b34889ec46..a654876513 100644 --- a/source/libs/executor/src/sortoperator.c +++ b/source/libs/executor/src/sortoperator.c @@ -87,17 +87,13 @@ SSDataBlock* getSortedBlockData(SSortHandle* pHandle, SSDataBlock* pDataBlock, i if (p->info.rows > 0) { int32_t numOfCols = taosArrayGetSize(pColMatchInfo); - for(int32_t i = 0; i < numOfCols; ++i) { + for (int32_t i = 0; i < numOfCols; ++i) { SColMatchInfo* pmInfo = taosArrayGet(pColMatchInfo, i); + ASSERT(pmInfo->matchType == COL_MATCH_FROM_SLOT_ID); - for(int32_t j = 0; j < p->info.numOfCols; ++j) { - SColumnInfoData* pSrc = taosArrayGet(p->pDataBlock, j); - if (pSrc->info.colId == pmInfo->colId) { - SColumnInfoData* pDst = taosArrayGet(pDataBlock->pDataBlock, pmInfo->targetSlotId); - colDataAssign(pDst, pSrc, p->info.rows); - break; - } - } + SColumnInfoData* pSrc = taosArrayGet(p->pDataBlock, pmInfo->srcSlotId); + SColumnInfoData* pDst = taosArrayGet(pDataBlock->pDataBlock, pmInfo->targetSlotId); + colDataAssign(pDst, pSrc, p->info.rows); } pDataBlock->info.rows = p->info.rows; diff --git a/source/libs/function/src/builtins.c b/source/libs/function/src/builtins.c index 8fa4bd0c4d..b22a9866c3 100644 --- a/source/libs/function/src/builtins.c +++ b/source/libs/function/src/builtins.c @@ -241,7 +241,7 @@ static int32_t translateHistogram(SFunctionNode* pFunc, char* pErrBuf, int32_t l return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName); } - pFunc->node.resType = (SDataType) { .bytes = tDataTypes[TSDB_DATA_TYPE_DOUBLE].bytes, .type = TSDB_DATA_TYPE_DOUBLE }; + pFunc->node.resType = (SDataType) { .bytes = 512, .type = TSDB_DATA_TYPE_BINARY }; return TSDB_CODE_SUCCESS; } diff --git a/source/libs/function/src/builtinsimpl.c b/source/libs/function/src/builtinsimpl.c index 3c9eca85dd..909659701c 100644 --- a/source/libs/function/src/builtinsimpl.c +++ b/source/libs/function/src/builtinsimpl.c @@ -14,13 +14,14 @@ */ #include "builtinsimpl.h" +#include "cJSON.h" #include "function.h" #include "querynodes.h" #include "taggfunction.h" #include "tdatablock.h" #include "tpercentile.h" -#define HISTOGRAM_MAX_BINS_NUM 100 +#define HISTOGRAM_MAX_BINS_NUM 100 typedef struct SSumRes { union { @@ -106,6 +107,13 @@ typedef struct SHistoFuncInfo { SHistoFuncBin bins[]; } SHistoFuncInfo; +typedef enum { + UNKNOWN_BIN = 0, + USER_INPUT_BIN, + LINEAR_BIN, + LOG_BIN +} EHistoBinType; + #define SET_VAL(_info, numOfElem, res) \ do { \ @@ -1801,28 +1809,225 @@ bool getHistogramFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) return true; } -bool histogramFunctionSetup(SqlFunctionCtx *pCtx, SResultRowEntryInfo* pResultInfo) { +static int8_t getHistogramBinType(char *binTypeStr) { + int8_t binType; + if (strcasecmp(binTypeStr, "user_input") == 0) { + binType = USER_INPUT_BIN; + } else if (strcasecmp(binTypeStr, "linear_bin") == 0) { + binType = LINEAR_BIN; + } else if (strcasecmp(binTypeStr, "log_bin") == 0) { + binType = LOG_BIN; + } else { + binType = UNKNOWN_BIN; + } + + return binType; +} + +static bool getHistogramBinDesc(SHistoFuncInfo *pInfo, char *binDescStr, int8_t binType, bool normalized) { + cJSON* binDesc = cJSON_Parse(binDescStr); + int32_t numOfBins; + double* intervals; + if (cJSON_IsObject(binDesc)) { /* linaer/log bins */ + int32_t numOfParams = cJSON_GetArraySize(binDesc); + int32_t startIndex; + if (numOfParams != 4) { + return false; + } + + cJSON* start = cJSON_GetObjectItem(binDesc, "start"); + cJSON* factor = cJSON_GetObjectItem(binDesc, "factor"); + cJSON* width = cJSON_GetObjectItem(binDesc, "width"); + cJSON* count = cJSON_GetObjectItem(binDesc, "count"); + cJSON* infinity = cJSON_GetObjectItem(binDesc, "infinity"); + + if (!cJSON_IsNumber(start) || !cJSON_IsNumber(count) || !cJSON_IsBool(infinity)) { + return false; + } + + if (count->valueint <= 0 || count->valueint > 1000) { // limit count to 1000 + return false; + } + + if (isinf(start->valuedouble) || (width != NULL && isinf(width->valuedouble)) || + (factor != NULL && isinf(factor->valuedouble)) || (count != NULL && isinf(count->valuedouble))) { + return false; + } + + int32_t counter = (int32_t)count->valueint; + if (infinity->valueint == false) { + startIndex = 0; + numOfBins = counter + 1; + } else { + startIndex = 1; + numOfBins = counter + 3; + } + + intervals = taosMemoryCalloc(numOfBins, sizeof(double)); + if (cJSON_IsNumber(width) && factor == NULL && binType == LINEAR_BIN) { + // linear bin process + if (width->valuedouble == 0) { + taosMemoryFree(intervals); + return false; + } + for (int i = 0; i < counter + 1; ++i) { + intervals[startIndex] = start->valuedouble + i * width->valuedouble; + if (isinf(intervals[startIndex])) { + taosMemoryFree(intervals); + return false; + } + startIndex++; + } + } else if (cJSON_IsNumber(factor) && width == NULL && binType == LOG_BIN) { + // log bin process + if (start->valuedouble == 0) { + taosMemoryFree(intervals); + return false; + } + if (factor->valuedouble < 0 || factor->valuedouble == 0 || factor->valuedouble == 1) { + taosMemoryFree(intervals); + return false; + } + for (int i = 0; i < counter + 1; ++i) { + intervals[startIndex] = start->valuedouble * pow(factor->valuedouble, i * 1.0); + if (isinf(intervals[startIndex])) { + taosMemoryFree(intervals); + return false; + } + startIndex++; + } + } else { + taosMemoryFree(intervals); + return false; + } + + if (infinity->valueint == true) { + intervals[0] = -INFINITY; + intervals[numOfBins - 1] = INFINITY; + // in case of desc bin orders, -inf/inf should be swapped + ASSERT(numOfBins >= 4); + if (intervals[1] > intervals[numOfBins - 2]) { + TSWAP(intervals[0], intervals[numOfBins - 1]); + } + } + } else if (cJSON_IsArray(binDesc)) { /* user input bins */ + if (binType != USER_INPUT_BIN) { + return false; + } + numOfBins = cJSON_GetArraySize(binDesc); + intervals = taosMemoryCalloc(numOfBins, sizeof(double)); + cJSON* bin = binDesc->child; + if (bin == NULL) { + taosMemoryFree(intervals); + return false; + } + int i = 0; + while (bin) { + intervals[i] = bin->valuedouble; + if (!cJSON_IsNumber(bin)) { + taosMemoryFree(intervals); + return false; + } + if (i != 0 && intervals[i] <= intervals[i - 1]) { + taosMemoryFree(intervals); + return false; + } + bin = bin->next; + i++; + } + } else { + return false; + } + + pInfo->numOfBins = numOfBins - 1; + pInfo->normalized = normalized; + for (int32_t i = 0; i < pInfo->numOfBins; ++i) { + pInfo->bins[i].lower = intervals[i] < intervals[i + 1] ? intervals[i] : intervals[i + 1]; + pInfo->bins[i].upper = intervals[i + 1] > intervals[i] ? intervals[i + 1] : intervals[i]; + pInfo->bins[i].count = 0; + } + + taosMemoryFree(intervals); + return true; +} + +bool histogramFunctionSetup(SqlFunctionCtx *pCtx, SResultRowEntryInfo *pResultInfo) { if (!functionSetup(pCtx, pResultInfo)) { return false; } - SHistoFuncInfo* pInfo = GET_ROWCELL_INTERBUF(pResultInfo); - char* binType = pCtx->param[1].param.pz; - char* binDesc = pCtx->param[2].param.pz; - int64_t nornalized = pCtx->param[3].param.i; + SHistoFuncInfo *pInfo = GET_ROWCELL_INTERBUF(pResultInfo); + int8_t binType = getHistogramBinType(varDataVal(pCtx->param[1].param.pz)); + if (binType == UNKNOWN_BIN) { + return false; + } + char* binDesc = varDataVal(pCtx->param[2].param.pz); + int64_t normalized = pCtx->param[3].param.i; + if (!getHistogramBinDesc(pInfo, binDesc, binType, (bool)normalized)) { + return false; + } return true; } int32_t histogramFunction(SqlFunctionCtx *pCtx) { + int32_t numOfElems = 0; + SHistoFuncInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx)); + + SInputColumnInfoData* pInput = &pCtx->input; + SColumnInfoData* pCol = pInput->pData[0]; + + int32_t type = pInput->pData[0]->info.type; + + int32_t start = pInput->startRowIndex; + int32_t numOfRows = pInput->numOfRows; + + for (int32_t i = start; i < numOfRows + start; ++i) { + if (pCol->hasNull && colDataIsNull_f(pCol->nullbitmap, i)) { + continue; + } + + numOfElems++; + + char* data = colDataGetData(pCol, i); + double v; + GET_TYPED_DATA(v, double, type, data); + + for (int32_t k = 0; k < pInfo->numOfBins; ++k) { + if (v > pInfo->bins[k].lower && v <= pInfo->bins[k].upper) { + pInfo->bins[k].count++; + break; + } + } + } + + SET_VAL(GET_RES_INFO(pCtx), numOfElems, pInfo->numOfBins); return TSDB_CODE_SUCCESS; } int32_t histogramFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) { + SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx); SHistoFuncInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx)); - //if (pInfo->hasResult == true) { - // SET_DOUBLE_VAL(&pInfo->result, pInfo->max - pInfo->min); - //} - return functionFinalize(pCtx, pBlock); + int32_t slotId = pCtx->pExpr->base.resSchema.slotId; + SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId); + + int32_t currentRow = pBlock->info.rows; + + for (int32_t i = 0; i < pResInfo->numOfRes; ++i) { + int32_t len; + char buf[512] = {0}; + if (!pInfo->normalized) { + len = sprintf(buf + VARSTR_HEADER_SIZE, "{\"lower_bin\":%g, \"upper_bin\":%g, \"count\":%"PRId64"}", + pInfo->bins[i].lower, pInfo->bins[i].upper, pInfo->bins[i].count); + } else { + len = sprintf(buf + VARSTR_HEADER_SIZE, "{\"lower_bin\":%g, \"upper_bin\":%g, \"count\":%lf}", + pInfo->bins[i].lower, pInfo->bins[i].upper, pInfo->bins[i].percentage); + } + varDataSetLen(buf, len); + colDataAppend(pCol, currentRow, buf, false); + currentRow++; + } + + return pResInfo->numOfRes; } diff --git a/source/libs/nodes/src/nodesUtilFuncs.c b/source/libs/nodes/src/nodesUtilFuncs.c index 0bceb84f4a..319b680161 100644 --- a/source/libs/nodes/src/nodesUtilFuncs.c +++ b/source/libs/nodes/src/nodesUtilFuncs.c @@ -1337,7 +1337,9 @@ void valueNodeToVariant(const SValueNode* pNode, SVariant* pVal) { case TSDB_DATA_TYPE_NCHAR: case TSDB_DATA_TYPE_VARCHAR: case TSDB_DATA_TYPE_VARBINARY: - pVal->pz = pNode->datum.p; + pVal->pz = taosMemoryMalloc(pVal->nLen + VARSTR_HEADER_SIZE + 1); + memcpy(pVal->pz, pNode->datum.p, pVal->nLen + VARSTR_HEADER_SIZE); + pVal->pz[pVal->nLen + VARSTR_HEADER_SIZE] = 0; break; case TSDB_DATA_TYPE_JSON: case TSDB_DATA_TYPE_DECIMAL: diff --git a/source/libs/parser/inc/parInsertData.h b/source/libs/parser/inc/parInsertData.h index 02be32a49e..0627ed1066 100644 --- a/source/libs/parser/inc/parInsertData.h +++ b/source/libs/parser/inc/parInsertData.h @@ -133,15 +133,15 @@ static FORCE_INLINE int32_t setBlockInfo(SSubmitBlk *pBlocks, STableDataBlocks * int32_t schemaIdxCompar(const void *lhs, const void *rhs); int32_t boundIdxCompar(const void *lhs, const void *rhs); void setBoundColumnInfo(SParsedDataColInfo *pColList, SSchema *pSchema, col_id_t numOfCols); -void destroyBlockArrayList(SArray *pDataBlockList); -void destroyBlockHashmap(SHashObj *pDataBlockHash); -int initRowBuilder(SRowBuilder *pBuilder, int16_t schemaVer, SParsedDataColInfo *pColInfo); -int32_t allocateMemIfNeed(STableDataBlocks *pDataBlock, int32_t rowSize, int32_t *numOfRows); -int32_t getDataBlockFromList(SHashObj *pHashList, int64_t id, int32_t size, int32_t startOffset, int32_t rowSize, - const STableMeta *pTableMeta, STableDataBlocks **dataBlocks, SArray *pBlockList, - SVCreateTbReq *pCreateTbReq); -int32_t mergeTableDataBlocks(SHashObj *pHashObj, uint8_t payloadType, SArray **pVgDataBlocks); -int32_t buildCreateTbMsg(STableDataBlocks *pBlocks, SVCreateTbReq *pCreateTbReq); +void destroyBlockArrayList(SArray* pDataBlockList); +void destroyBlockHashmap(SHashObj* pDataBlockHash); +int initRowBuilder(SRowBuilder *pBuilder, int16_t schemaVer, SParsedDataColInfo *pColInfo); +int32_t allocateMemIfNeed(STableDataBlocks *pDataBlock, int32_t rowSize, int32_t * numOfRows); +int32_t getDataBlockFromList(SHashObj* pHashList, int64_t id, int32_t size, int32_t startOffset, int32_t rowSize, + STableMeta* pTableMeta, STableDataBlocks** dataBlocks, SArray* pBlockList, SVCreateTbReq* pCreateTbReq); +int32_t mergeTableDataBlocks(SHashObj* pHashObj, uint8_t payloadType, SArray** pVgDataBlocks); +int32_t buildCreateTbMsg(STableDataBlocks* pBlocks, SVCreateTbReq* pCreateTbReq); + int32_t allocateMemForSize(STableDataBlocks *pDataBlock, int32_t allSize); #endif // TDENGINE_DATABLOCKMGT_H diff --git a/source/libs/parser/inc/parUtil.h b/source/libs/parser/inc/parUtil.h index 62d197d611..c146d42e05 100644 --- a/source/libs/parser/inc/parUtil.h +++ b/source/libs/parser/inc/parUtil.h @@ -41,7 +41,6 @@ int32_t generateSyntaxErrMsg(SMsgBuf* pBuf, int32_t errCode, ...); int32_t buildInvalidOperationMsg(SMsgBuf* pMsgBuf, const char* msg); int32_t buildSyntaxErrMsg(SMsgBuf* pBuf, const char* additionalInfo, const char* sourceStr); -STableMeta* tableMetaDup(const STableMeta* pTableMeta); SSchema* getTableColumnSchema(const STableMeta* pTableMeta); SSchema* getTableTagSchema(const STableMeta* pTableMeta); int32_t getNumOfColumns(const STableMeta* pTableMeta); diff --git a/source/libs/parser/src/parInsert.c b/source/libs/parser/src/parInsert.c index e82873b923..05d247c037 100644 --- a/source/libs/parser/src/parInsert.c +++ b/source/libs/parser/src/parInsert.c @@ -279,6 +279,7 @@ static void buildMsgHeader(STableDataBlocks* src, SVgDataBlocks* blocks) { int32_t numOfBlocks = blocks->numOfTables; while (numOfBlocks--) { int32_t dataLen = blk->dataLen; + int32_t schemaLen = blk->schemaLen; blk->uid = htobe64(blk->uid); blk->suid = htobe64(blk->suid); blk->padding = htonl(blk->padding); @@ -286,7 +287,7 @@ static void buildMsgHeader(STableDataBlocks* src, SVgDataBlocks* blocks) { blk->dataLen = htonl(blk->dataLen); blk->schemaLen = htonl(blk->schemaLen); blk->numOfRows = htons(blk->numOfRows); - blk = (SSubmitBlk*)(blk->data + dataLen); + blk = (SSubmitBlk*)(blk->data + schemaLen + dataLen); } } @@ -761,11 +762,9 @@ static int32_t KvRowAppend(SMsgBuf* pMsgBuf, const void* value, int32_t len, voi return TSDB_CODE_SUCCESS; } -static int32_t buildCreateTbReq(SVCreateTbReq* pTbReq, const SName* pName, SKVRow row, int64_t suid) { - char dbFName[TSDB_DB_FNAME_LEN] = {0}; - tNameGetFullDbName(pName, dbFName); +static int32_t buildCreateTbReq(SVCreateTbReq *pTbReq, const char* tname, SKVRow row, int64_t suid) { pTbReq->type = TD_CHILD_TABLE; - pTbReq->name = strdup(pName->tname); + pTbReq->name = strdup(tname); pTbReq->ctb.suid = suid; pTbReq->ctb.pTag = row; @@ -773,7 +772,7 @@ static int32_t buildCreateTbReq(SVCreateTbReq* pTbReq, const SName* pName, SKVRo } // pSql -> tag1_value, ...) -static int32_t parseTagsClause(SInsertParseContext* pCxt, SSchema* pSchema, uint8_t precision, const SName* pName) { +static int32_t parseTagsClause(SInsertParseContext* pCxt, SSchema* pSchema, uint8_t precision, const char* tName) { if (tdInitKVRowBuilder(&pCxt->tagsBuilder) < 0) { return TSDB_CODE_TSC_OUT_OF_MEMORY; } @@ -814,7 +813,7 @@ static int32_t parseTagsClause(SInsertParseContext* pCxt, SSchema* pSchema, uint } tdSortKVRowByColIdx(row); - return buildCreateTbReq(&pCxt->createTblReq, pName, row, pCxt->pTableMeta->suid); + return buildCreateTbReq(&pCxt->createTblReq, tName, row, pCxt->pTableMeta->suid); } static int32_t cloneTableMeta(STableMeta* pSrc, STableMeta** pDst) { @@ -883,7 +882,7 @@ static int32_t parseUsingClause(SInsertParseContext* pCxt, SToken* pTbnameToken) if (TK_NK_LP != sToken.type) { return buildSyntaxErrMsg(&pCxt->msg, "( is expected", sToken.z); } - CHECK_CODE(parseTagsClause(pCxt, pCxt->pTableMeta->schema, getTableInfo(pCxt->pTableMeta).precision, &name)); + CHECK_CODE(parseTagsClause(pCxt, pCxt->pTableMeta->schema, getTableInfo(pCxt->pTableMeta).precision, name.tname)); NEXT_TOKEN(pCxt->pSql, sToken); if (TK_NK_RP != sToken.type) { return buildSyntaxErrMsg(&pCxt->msg, ") is expected", sToken.z); @@ -1037,11 +1036,6 @@ static void destroyDataBlock(STableDataBlocks* pDataBlock) { taosMemoryFreeClear(pDataBlock->pData); if (!pDataBlock->cloned) { - // free the refcount for metermeta - if (pDataBlock->pTableMeta != NULL) { - taosMemoryFreeClear(pDataBlock->pTableMeta); - } - destroyBoundColumnInfo(&pDataBlock->boundColumnInfo); } taosMemoryFreeClear(pDataBlock); @@ -1269,10 +1263,9 @@ int32_t qBuildStmtOutput(SQuery* pQuery, SHashObj* pVgHash, SHashObj* pBlockHash return TSDB_CODE_SUCCESS; } -int32_t qBindStmtTagsValue(void* pBlock, void* boundTags, int64_t suid, SName* pName, TAOS_MULTI_BIND* bind, - char* msgBuf, int32_t msgBufLen) { - STableDataBlocks* pDataBlock = (STableDataBlocks*)pBlock; - SMsgBuf pBuf = {.buf = msgBuf, .len = msgBufLen}; +int32_t qBindStmtTagsValue(void *pBlock, void *boundTags, int64_t suid, char *tName, TAOS_MULTI_BIND *bind, char *msgBuf, int32_t msgBufLen){ + STableDataBlocks *pDataBlock = (STableDataBlocks *)pBlock; + SMsgBuf pBuf = {.buf = msgBuf, .len = msgBufLen}; SParsedDataColInfo* tags = (SParsedDataColInfo*)boundTags; if (NULL == tags) { return TSDB_CODE_QRY_APP_ERROR; @@ -1311,7 +1304,7 @@ int32_t qBindStmtTagsValue(void* pBlock, void* boundTags, int64_t suid, SName* p tdSortKVRowByColIdx(row); SVCreateTbReq tbReq = {0}; - CHECK_CODE(buildCreateTbReq(&tbReq, pName, row, suid)); + CHECK_CODE(buildCreateTbReq(&tbReq, tName, row, suid)); CHECK_CODE(buildCreateTbMsg(pDataBlock, &tbReq)); destroyCreateSubTbReq(&tbReq); @@ -1543,3 +1536,265 @@ int32_t qBuildStmtColFields(void* pBlock, int32_t* fieldNum, TAOS_FIELD** fields return TSDB_CODE_SUCCESS; } + +// schemaless logic start + +typedef struct SmlExecHandle { + SHashObj* pBlockHash; + + SParsedDataColInfo tags; // each table + SKVRowBuilder tagsBuilder; // each table + SVCreateTbReq createTblReq; // each table + + SQuery* pQuery; +} SSmlExecHandle; + +static int32_t smlBoundColumns(SArray *cols, SParsedDataColInfo* pColList, SSchema* pSchema) { + col_id_t nCols = pColList->numOfCols; + + pColList->numOfBound = 0; + pColList->boundNullLen = 0; + memset(pColList->boundColumns, 0, sizeof(col_id_t) * nCols); + for (col_id_t i = 0; i < nCols; ++i) { + pColList->cols[i].valStat = VAL_STAT_NONE; + } + + bool isOrdered = true; + col_id_t lastColIdx = -1; // last column found + for (int i = 0; i < taosArrayGetSize(cols); ++i) { + SSmlKv *kv = taosArrayGetP(cols, i); + SToken sToken = {.n=kv->keyLen, .z=(char*)kv->key}; + col_id_t t = lastColIdx + 1; + col_id_t index = findCol(&sToken, t, nCols, pSchema); + if (index < 0 && t > 0) { + index = findCol(&sToken, 0, t, pSchema); + isOrdered = false; + } + if (index < 0) { + return TSDB_CODE_SML_INVALID_DATA; + } + if (pColList->cols[index].valStat == VAL_STAT_HAS) { + return TSDB_CODE_SML_INVALID_DATA; + } + lastColIdx = index; + pColList->cols[index].valStat = VAL_STAT_HAS; + pColList->boundColumns[pColList->numOfBound] = index + PRIMARYKEY_TIMESTAMP_COL_ID; + ++pColList->numOfBound; + switch (pSchema[t].type) { + case TSDB_DATA_TYPE_BINARY: + pColList->boundNullLen += (sizeof(VarDataOffsetT) + VARSTR_HEADER_SIZE + CHAR_BYTES); + break; + case TSDB_DATA_TYPE_NCHAR: + pColList->boundNullLen += (sizeof(VarDataOffsetT) + VARSTR_HEADER_SIZE + TSDB_NCHAR_SIZE); + break; + default: + pColList->boundNullLen += TYPE_BYTES[pSchema[t].type]; + break; + } + } + + pColList->orderStatus = isOrdered ? ORDER_STATUS_ORDERED : ORDER_STATUS_DISORDERED; + + if (!isOrdered) { + pColList->colIdxInfo = taosMemoryCalloc(pColList->numOfBound, sizeof(SBoundIdxInfo)); + if (NULL == pColList->colIdxInfo) { + return TSDB_CODE_TSC_OUT_OF_MEMORY; + } + SBoundIdxInfo* pColIdx = pColList->colIdxInfo; + for (col_id_t i = 0; i < pColList->numOfBound; ++i) { + pColIdx[i].schemaColIdx = pColList->boundColumns[i]; + pColIdx[i].boundIdx = i; + } + qsort(pColIdx, pColList->numOfBound, sizeof(SBoundIdxInfo), schemaIdxCompar); + for (col_id_t i = 0; i < pColList->numOfBound; ++i) { + pColIdx[i].finalIdx = i; + } + qsort(pColIdx, pColList->numOfBound, sizeof(SBoundIdxInfo), boundIdxCompar); + } + + if(pColList->numOfCols > pColList->numOfBound){ + memset(&pColList->boundColumns[pColList->numOfBound], 0, + sizeof(col_id_t) * (pColList->numOfCols - pColList->numOfBound)); + } + + return TSDB_CODE_SUCCESS; +} + +static int32_t smlBoundTags(SArray *cols, SKVRowBuilder *tagsBuilder, SParsedDataColInfo* tags, SSchema* pSchema, SKVRow *row, SMsgBuf *msg) { + if (tdInitKVRowBuilder(tagsBuilder) < 0) { + return TSDB_CODE_TSC_OUT_OF_MEMORY; + } + + SKvParam param = {.builder = tagsBuilder}; + for (int i = 0; i < tags->numOfBound; ++i) { + SSchema* pTagSchema = &pSchema[tags->boundColumns[i] - 1]; // colId starts with 1 + param.schema = pTagSchema; + SSmlKv *kv = taosArrayGetP(cols, i); + KvRowAppend(msg, kv->value, kv->valueLen, ¶m) ; + } + + + *row = tdGetKVRowFromBuilder(tagsBuilder); + if(*row == NULL){ + return TSDB_CODE_SML_INVALID_DATA; + } + tdSortKVRowByColIdx(*row); + return TSDB_CODE_SUCCESS; +} + +int32_t smlBindData(void *handle, SArray *tags, SArray *colsFormat, SHashObj *colsHash, SArray *cols, bool format, + STableMeta *pTableMeta, char *tableName, char *msgBuf, int16_t msgBufLen) { + SMsgBuf pBuf = {.buf = msgBuf, .len = msgBufLen}; + + SSmlExecHandle *smlHandle = (SSmlExecHandle *)handle; + SSchema* pTagsSchema = getTableTagSchema(pTableMeta); + setBoundColumnInfo(&smlHandle->tags, pTagsSchema, getNumOfTags(pTableMeta)); + int ret = smlBoundColumns(tags, &smlHandle->tags, pTagsSchema); + if(ret != TSDB_CODE_SUCCESS){ + buildInvalidOperationMsg(&pBuf, "bound tags error"); + return ret; + } + SKVRow row = NULL; + ret = smlBoundTags(tags, &smlHandle->tagsBuilder, &smlHandle->tags, pTagsSchema, &row, &pBuf); + if(ret != TSDB_CODE_SUCCESS){ + return ret; + } + + buildCreateTbReq(&smlHandle->createTblReq, tableName, row, pTableMeta->suid); + + STableDataBlocks* pDataBlock = NULL; + ret = getDataBlockFromList(smlHandle->pBlockHash, pTableMeta->uid, TSDB_DEFAULT_PAYLOAD_SIZE, + sizeof(SSubmitBlk), getTableInfo(pTableMeta).rowSize, pTableMeta, + &pDataBlock, NULL, &smlHandle->createTblReq); + if(ret != TSDB_CODE_SUCCESS){ + buildInvalidOperationMsg(&pBuf, "create data block error"); + return ret; + } + + SSchema* pSchema = getTableColumnSchema(pTableMeta); + + + if(format){ + ret = smlBoundColumns(taosArrayGetP(colsFormat, 0), &pDataBlock->boundColumnInfo, pSchema); + }else{ + SArray *columns = taosArrayInit(16, POINTER_BYTES); + void **p1 = taosHashIterate(colsHash, NULL); + while (p1) { + SSmlKv* kv = *p1; + taosArrayPush(columns, &kv); + p1 = taosHashIterate(colsHash, p1); + } + ret = smlBoundColumns(columns, &pDataBlock->boundColumnInfo, pSchema); + taosArrayDestroy(columns); + } + + if(ret != TSDB_CODE_SUCCESS){ + buildInvalidOperationMsg(&pBuf, "bound cols error"); + return ret; + } + int32_t extendedRowSize = getExtendedRowSize(pDataBlock); + SParsedDataColInfo* spd = &pDataBlock->boundColumnInfo; + SRowBuilder* pBuilder = &pDataBlock->rowBuilder; + SMemParam param = {.rb = pBuilder}; + + initRowBuilder(&pDataBlock->rowBuilder, pDataBlock->pTableMeta->sversion, &pDataBlock->boundColumnInfo); + + int32_t rowNum = format ? taosArrayGetSize(colsFormat) : taosArrayGetSize(cols); + if(rowNum <= 0) { + return buildInvalidOperationMsg(&pBuf, "cols size <= 0"); + } + ret = allocateMemForSize(pDataBlock, extendedRowSize * rowNum); + if(ret != TSDB_CODE_SUCCESS){ + buildInvalidOperationMsg(&pBuf, "allocate memory error"); + return ret; + } + for (int32_t r = 0; r < rowNum; ++r) { + STSRow* row = (STSRow*)(pDataBlock->pData + pDataBlock->size); // skip the SSubmitBlk header + tdSRowResetBuf(pBuilder, row); + void *rowData = NULL; + if(format){ + rowData = taosArrayGetP(colsFormat, r); + }else{ + rowData = taosArrayGetP(cols, r); + } + + // 1. set the parsed value from sql string + for (int c = 0; c < spd->numOfBound; ++c) { + SSchema* pColSchema = &pSchema[spd->boundColumns[c] - 1]; + + param.schema = pColSchema; + getSTSRowAppendInfo(pBuilder->rowType, spd, c, ¶m.toffset, ¶m.colIdx); + + SSmlKv *kv = NULL; + if(format){ + kv = taosArrayGetP(rowData, c); + if (!kv){ + char msg[64] = {0}; + sprintf(msg, "cols num not the same like before:%d", r); + return buildInvalidOperationMsg(&pBuf, msg); + } + }else{ + void **p =taosHashGet(rowData, pColSchema->name, strlen(pColSchema->name)); + kv = *p; + } + + if (kv->length == 0) { + MemRowAppend(&pBuf, NULL, 0, ¶m); + } else { + int32_t colLen = pColSchema->bytes; + if (IS_VAR_DATA_TYPE(pColSchema->type)) { + colLen = kv->length; + } + + MemRowAppend(&pBuf, &(kv->value), colLen, ¶m); + } + + if (PRIMARYKEY_TIMESTAMP_COL_ID == pColSchema->colId) { + TSKEY tsKey = TD_ROW_KEY(row); + checkTimestamp(pDataBlock, (const char *)&tsKey); + } + } + + // set the null value for the columns that do not assign values + if ((spd->numOfBound < spd->numOfCols) && TD_IS_TP_ROW(row)) { + for (int32_t i = 0; i < spd->numOfCols; ++i) { + if (spd->cols[i].valStat == VAL_STAT_NONE) { // the primary TS key is not VAL_STAT_NONE + tdAppendColValToTpRow(pBuilder, TD_VTYPE_NONE, getNullValue(pSchema[i].type), true, pSchema[i].type, i, + spd->cols[i].toffset); + } + } + } + + pDataBlock->size += extendedRowSize; + } + + SSubmitBlk *pBlocks = (SSubmitBlk *)(pDataBlock->pData); + if (TSDB_CODE_SUCCESS != setBlockInfo(pBlocks, pDataBlock, rowNum)) { + return buildInvalidOperationMsg(&pBuf, "too many rows in sql, total number of rows should be less than 32767"); + } + + return TSDB_CODE_SUCCESS; +} + +void* smlInitHandle(SQuery *pQuery){ + SSmlExecHandle *handle = taosMemoryCalloc(1, sizeof(SSmlExecHandle)); + if(!handle) return NULL; + handle->pBlockHash = taosHashInit(16, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), true, false); + handle->pQuery = pQuery; + + return handle; +} + +void smlDestroyHandle(void *pHandle){ + if(!pHandle) return; + SSmlExecHandle *handle = (SSmlExecHandle *)pHandle; + destroyBlockHashmap(handle->pBlockHash); + taosMemoryFree(handle); +} + +int32_t smlBuildOutput(void* handle, SHashObj* pVgHash) { + SSmlExecHandle *smlHandle = (SSmlExecHandle *)handle; + return qBuildStmtOutput(smlHandle->pQuery, pVgHash, smlHandle->pBlockHash); +} +// schemaless logic end + diff --git a/source/libs/parser/src/parInsertData.c b/source/libs/parser/src/parInsertData.c index 4a96301d95..ac197077a4 100644 --- a/source/libs/parser/src/parInsertData.c +++ b/source/libs/parser/src/parInsertData.c @@ -115,7 +115,7 @@ void destroyBoundColumnInfo(void* pBoundInfo) { taosMemoryFreeClear(pColList->colIdxInfo); } -static int32_t createDataBlock(size_t defaultSize, int32_t rowSize, int32_t startOffset, const STableMeta* pTableMeta, +static int32_t createDataBlock(size_t defaultSize, int32_t rowSize, int32_t startOffset, STableMeta* pTableMeta, STableDataBlocks** dataBlocks) { STableDataBlocks* dataBuf = (STableDataBlocks*)taosMemoryCalloc(1, sizeof(STableDataBlocks)); if (dataBuf == NULL) { @@ -137,8 +137,7 @@ static int32_t createDataBlock(size_t defaultSize, int32_t rowSize, int32_t star } memset(dataBuf->pData, 0, sizeof(SSubmitBlk)); - // Here we keep the tableMeta to avoid it to be remove by other threads. - dataBuf->pTableMeta = tableMetaDup(pTableMeta); + dataBuf->pTableMeta = pTableMeta; SParsedDataColInfo* pColInfo = &dataBuf->boundColumnInfo; SSchema* pSchema = getTableColumnSchema(dataBuf->pTableMeta); @@ -187,7 +186,7 @@ int32_t buildCreateTbMsg(STableDataBlocks* pBlocks, SVCreateTbReq* pCreateTbReq) } int32_t getDataBlockFromList(SHashObj* pHashList, int64_t id, int32_t size, int32_t startOffset, int32_t rowSize, - const STableMeta* pTableMeta, STableDataBlocks** dataBlocks, SArray* pBlockList, + STableMeta* pTableMeta, STableDataBlocks** dataBlocks, SArray* pBlockList, SVCreateTbReq* pCreateTbReq) { *dataBlocks = NULL; STableDataBlocks** t1 = (STableDataBlocks**)taosHashGet(pHashList, (const char*)&id, sizeof(id)); @@ -238,9 +237,9 @@ static void destroyDataBlock(STableDataBlocks* pDataBlock) { taosMemoryFreeClear(pDataBlock->pData); if (!pDataBlock->cloned) { // free the refcount for metermeta - if (pDataBlock->pTableMeta != NULL) { - taosMemoryFreeClear(pDataBlock->pTableMeta); - } +// if (pDataBlock->pTableMeta != NULL) { +// taosMemoryFreeClear(pDataBlock->pTableMeta); +// } destroyBoundColumnInfo(&pDataBlock->boundColumnInfo); } @@ -456,6 +455,7 @@ int32_t mergeTableDataBlocks(SHashObj* pHashObj, uint8_t payloadType, SArray** p SSubmitBlk* pBlocks = (SSubmitBlk*)pOneTableBlock->pData; if (pBlocks->numOfRows > 0) { STableDataBlocks* dataBuf = NULL; + pOneTableBlock->pTableMeta->vgId = pOneTableBlock->vgId; // for schemaless, restore origin vgId int32_t ret = getDataBlockFromList(pVnodeDataBlockHashList, pOneTableBlock->vgId, TSDB_PAYLOAD_SIZE, INSERT_HEAD_SIZE, 0, pOneTableBlock->pTableMeta, &dataBuf, pVnodeDataBlockList, NULL); diff --git a/source/libs/parser/src/parTranslater.c b/source/libs/parser/src/parTranslater.c index 6874b5b7d4..bd614d0165 100644 --- a/source/libs/parser/src/parTranslater.c +++ b/source/libs/parser/src/parTranslater.c @@ -2596,7 +2596,7 @@ static int32_t translateDropSuperTable(STranslateContext* pCxt, SDropSuperTableS pStmt->ignoreNotExists); } -static int32_t setAlterTableField(SAlterTableStmt* pStmt, SMAltertbReq* pAlterReq) { +static int32_t setAlterTableField(SAlterTableStmt* pStmt, SMAlterStbReq* pAlterReq) { pAlterReq->pFields = taosArrayInit(2, sizeof(TAOS_FIELD)); if (NULL == pAlterReq->pFields) { return TSDB_CODE_OUT_OF_MEMORY; @@ -2632,8 +2632,8 @@ static int32_t setAlterTableField(SAlterTableStmt* pStmt, SMAltertbReq* pAlterRe } static int32_t translateAlterTable(STranslateContext* pCxt, SAlterTableStmt* pStmt) { - SMAltertbReq alterReq = {0}; - SName tableName; + SMAlterStbReq alterReq = {0}; + SName tableName; tNameExtractFullName(toName(pCxt->pParseCxt->acctId, pStmt->dbName, pStmt->tableName, &tableName), alterReq.name); alterReq.alterType = pStmt->alterType; alterReq.numOfFields = 1; diff --git a/source/libs/parser/src/parUtil.c b/source/libs/parser/src/parUtil.c index e37dbd1edd..715b9b97e6 100644 --- a/source/libs/parser/src/parUtil.c +++ b/source/libs/parser/src/parUtil.c @@ -191,27 +191,7 @@ int32_t buildSyntaxErrMsg(SMsgBuf* pBuf, const char* additionalInfo, const char* return TSDB_CODE_TSC_SQL_SYNTAX_ERROR; } -static uint32_t getTableMetaSize(const STableMeta* pTableMeta) { - assert(pTableMeta != NULL); - - int32_t totalCols = 0; - if (pTableMeta->tableInfo.numOfColumns >= 0) { - totalCols = pTableMeta->tableInfo.numOfColumns + pTableMeta->tableInfo.numOfTags; - } - - return sizeof(STableMeta) + totalCols * sizeof(SSchema); -} - -STableMeta* tableMetaDup(const STableMeta* pTableMeta) { - assert(pTableMeta != NULL); - size_t size = getTableMetaSize(pTableMeta); - - STableMeta* p = taosMemoryMalloc(size); - memcpy(p, pTableMeta, size); - return p; -} - -SSchema* getTableColumnSchema(const STableMeta* pTableMeta) { +SSchema *getTableColumnSchema(const STableMeta *pTableMeta) { assert(pTableMeta != NULL); return (SSchema*)pTableMeta->schema; } diff --git a/source/libs/qworker/inc/qworkerInt.h b/source/libs/qworker/inc/qworkerInt.h index ca471262ff..3ecf987811 100644 --- a/source/libs/qworker/inc/qworkerInt.h +++ b/source/libs/qworker/inc/qworkerInt.h @@ -25,6 +25,7 @@ extern "C" { #include "tlockfree.h" #include "ttimer.h" #include "tref.h" +#include "plannodes.h" #define QW_DEFAULT_SCHEDULER_NUMBER 10000 #define QW_DEFAULT_TASK_NUMBER 10000 @@ -131,8 +132,9 @@ typedef struct SQWTaskCtx { int8_t events[QW_EVENT_MAX]; - void *taskHandle; - void *sinkHandle; + void *taskHandle; + void *sinkHandle; + SSubplan *plan; } SQWTaskCtx; typedef struct SQWSchStatus { diff --git a/source/libs/qworker/src/qworker.c b/source/libs/qworker/src/qworker.c index bd7ee6321a..717958c033 100644 --- a/source/libs/qworker/src/qworker.c +++ b/source/libs/qworker/src/qworker.c @@ -424,6 +424,11 @@ void qwFreeTask(QW_FPARAMS_DEF, SQWTaskCtx *ctx) { dsDestroyDataSinker(ctx->sinkHandle); ctx->sinkHandle = NULL; } + + if (ctx->plan) { + nodesDestroyNode(ctx->plan); + ctx->plan = NULL; + } } int32_t qwDropTaskCtx(QW_FPARAMS_DEF) { @@ -440,6 +445,7 @@ int32_t qwDropTaskCtx(QW_FPARAMS_DEF) { atomic_store_ptr(&ctx->taskHandle, NULL); atomic_store_ptr(&ctx->sinkHandle, NULL); + atomic_store_ptr(&ctx->plan, NULL); QW_SET_EVENT_PROCESSED(ctx, QW_EVENT_DROP); @@ -922,7 +928,7 @@ _return: int32_t qwProcessQuery(QW_FPARAMS_DEF, SQWMsg *qwMsg, int8_t taskType, int8_t explain) { int32_t code = 0; bool queryRsped = false; - struct SSubplan *plan = NULL; + SSubplan* plan = NULL; SQWPhaseInput input = {0}; qTaskInfo_t pTaskInfo = NULL; DataSinkHandle sinkHandle = NULL; @@ -950,6 +956,8 @@ int32_t qwProcessQuery(QW_FPARAMS_DEF, SQWMsg *qwMsg, int8_t taskType, int8_t ex QW_ERR_JRET(code); } + ctx->plan = plan; + code = qCreateExecTask(qwMsg->node, mgmt->nodeId, tId, plan, &pTaskInfo, &sinkHandle, OPTR_EXEC_MODEL_BATCH); if (code) { QW_TASK_ELOG("qCreateExecTask failed, code:%x - %s", code, tstrerror(code)); @@ -1428,6 +1436,10 @@ void qwCloseRef(void) { taosWUnLockLatch(&gQwMgmt.lock); } +void qwDestroySchStatus(SQWSchStatus *pStatus) { + taosHashCleanup(pStatus->tasksHash); +} + void qwDestroyImpl(void *pMgmt) { SQWorker *mgmt = (SQWorker *)pMgmt; @@ -1439,6 +1451,13 @@ void qwDestroyImpl(void *pMgmt) { // TODO FREE ALL taosHashCleanup(mgmt->ctxHash); + + void *pIter = taosHashIterate(mgmt->schHash, NULL); + while (pIter) { + SQWSchStatus *sch = (SQWSchStatus *)pIter; + qwDestroySchStatus(sch); + pIter = taosHashIterate(mgmt->schHash, pIter); + } taosHashCleanup(mgmt->schHash); taosMemoryFree(mgmt); diff --git a/source/libs/scalar/test/scalar/scalarTests.cpp b/source/libs/scalar/test/scalar/scalarTests.cpp index ed52e48f6d..49a5f5b9a4 100644 --- a/source/libs/scalar/test/scalar/scalarTests.cpp +++ b/source/libs/scalar/test/scalar/scalarTests.cpp @@ -166,7 +166,6 @@ void scltMakeColumnNode(SNode **pNode, SSDataBlock **block, int32_t dataType, in idata.pData = (char *)taosMemoryCalloc(1, size); colInfoDataEnsureCapacity(&idata, 0, rowNum); taosArrayPush(res->pDataBlock, &idata); - SColumnInfoData *pColumn = (SColumnInfoData *)taosArrayGetLast(res->pDataBlock); for (int32_t i = 0; i < rowNum; ++i) { colDataAppend(pColumn, i, (const char *)value, false); diff --git a/source/libs/sync/src/syncRaftLog.c b/source/libs/sync/src/syncRaftLog.c index 6bf17b8a82..031722ab3c 100644 --- a/source/libs/sync/src/syncRaftLog.c +++ b/source/libs/sync/src/syncRaftLog.c @@ -57,8 +57,13 @@ int32_t logStoreAppendEntry(SSyncLogStore* pLogStore, SSyncRaftEntry* pEntry) { syncMeta.seqNum = pEntry->seqNum; syncMeta.term = pEntry->term; code = walWriteWithSyncInfo(pWal, pEntry->index, pEntry->originalRpcType, syncMeta, pEntry->data, pEntry->dataLen); - if (code < 0) perror("wal write error: "); - assert(code == 0); + if (code != 0) { + int32_t err = terrno; + const char *errStr = tstrerror(err); + sError("walWriteWithSyncInfo error, err:%d, msg:%s", err, errStr); + ASSERT(0); + } + //assert(code == 0); walFsync(pWal, true); return code; @@ -70,7 +75,14 @@ SSyncRaftEntry* logStoreGetEntry(SSyncLogStore* pLogStore, SyncIndex index) { if (index >= SYNC_INDEX_BEGIN && index <= logStoreLastIndex(pLogStore)) { SWalReadHandle* pWalHandle = walOpenReadHandle(pWal); - assert(walReadWithHandle(pWalHandle, index) == 0); + int32_t code = walReadWithHandle(pWalHandle, index); + if (code != 0) { + int32_t err = terrno; + const char *errStr = tstrerror(err); + sError("walReadWithHandle error, err:%d, msg:%s", err, errStr); + ASSERT(0); + } + //assert(walReadWithHandle(pWalHandle, index) == 0); SSyncRaftEntry* pEntry = syncEntryBuild(pWalHandle->pHead->head.bodyLen); assert(pEntry != NULL); diff --git a/source/libs/tdb/inc/tdb.h b/source/libs/tdb/inc/tdb.h index 18f8ddec5c..90b07fb6ae 100644 --- a/source/libs/tdb/inc/tdb.h +++ b/source/libs/tdb/inc/tdb.h @@ -49,6 +49,7 @@ int tdbDbPGet(TDB *pDb, const void *pKey, int kLen, void **ppKey, int *pkLen, vo // TDBC int tdbDbcOpen(TDB *pDb, TDBC **ppDbc, TXN *pTxn); int tdbDbcClose(TDBC *pDbc); +int tdbDbcIsValid(TDBC *pDbc); int tdbDbcMoveTo(TDBC *pDbc, const void *pKey, int kLen, int *c); int tdbDbcMoveToFirst(TDBC *pDbc); int tdbDbcMoveToLast(TDBC *pDbc); diff --git a/source/libs/tdb/src/db/tdbBtree.c b/source/libs/tdb/src/db/tdbBtree.c index 0d13ec4d2b..43822cd311 100644 --- a/source/libs/tdb/src/db/tdbBtree.c +++ b/source/libs/tdb/src/db/tdbBtree.c @@ -1678,6 +1678,14 @@ int tdbBtcClose(SBTC *pBtc) { return 0; } + +int tdbBtcIsValid(SBTC *pBtc) { + if (pBtc->idx < 0) { + return 0; + } else { + return 1; + } +} // TDB_BTREE_CURSOR // TDB_BTREE_DEBUG ===================== diff --git a/source/libs/tdb/src/db/tdbDb.c b/source/libs/tdb/src/db/tdbDb.c index 553bb2c646..ceaac6dff1 100644 --- a/source/libs/tdb/src/db/tdbDb.c +++ b/source/libs/tdb/src/db/tdbDb.c @@ -141,3 +141,5 @@ int tdbDbcClose(TDBC *pDbc) { return 0; } + +int tdbDbcIsValid(TDBC *pDbc) { return tdbBtcIsValid(&pDbc->btc); } \ No newline at end of file diff --git a/source/libs/tdb/src/inc/tdbInt.h b/source/libs/tdb/src/inc/tdbInt.h index 76dacf7b84..ee431ac638 100644 --- a/source/libs/tdb/src/inc/tdbInt.h +++ b/source/libs/tdb/src/inc/tdbInt.h @@ -136,6 +136,7 @@ int tdbBtreePGet(SBTree *pBt, const void *pKey, int kLen, void **ppKey, int *pkL // SBTC int tdbBtcOpen(SBTC *pBtc, SBTree *pBt, TXN *pTxn); int tdbBtcClose(SBTC *pBtc); +int tdbBtcIsValid(SBTC *pBtc); int tdbBtcMoveTo(SBTC *pBtc, const void *pKey, int kLen, int *pCRst); int tdbBtcMoveToFirst(SBTC *pBtc); int tdbBtcMoveToLast(SBTC *pBtc); diff --git a/source/libs/transport/src/transSrv.c b/source/libs/transport/src/transSrv.c index 56b5ddd38a..6047643881 100644 --- a/source/libs/transport/src/transSrv.c +++ b/source/libs/transport/src/transSrv.c @@ -791,6 +791,10 @@ static void uvDestroyConn(uv_handle_t* handle) { } QUEUE_REMOVE(&conn->queue); taosMemoryFree(conn->pTcp); + if (conn->regArg.init == 1) { + transFreeMsg(conn->regArg.msg.pCont); + conn->regArg.init = 0; + } taosMemoryFree(conn); if (thrd->quit && QUEUE_IS_EMPTY(&thrd->conn)) { diff --git a/source/libs/wal/src/walRead.c b/source/libs/wal/src/walRead.c index 70a3559cd9..4fe07029f1 100644 --- a/source/libs/wal/src/walRead.c +++ b/source/libs/wal/src/walRead.c @@ -49,7 +49,10 @@ void walCloseReadHandle(SWalReadHandle *pRead) { taosMemoryFree(pRead); } -int32_t walRegisterRead(SWalReadHandle *pRead, int64_t ver) { return 0; } +int32_t walRegisterRead(SWalReadHandle *pRead, int64_t ver) { + // TODO + return 0; +} static int32_t walReadSeekFilePos(SWalReadHandle *pRead, int64_t fileFirstVer, int64_t ver) { int code = 0; diff --git a/source/util/src/terror.c b/source/util/src/terror.c index 1470496c68..4b3c99d321 100644 --- a/source/util/src/terror.c +++ b/source/util/src/terror.c @@ -326,6 +326,9 @@ TAOS_DEFINE_ERROR(TSDB_CODE_TDB_INVALID_TABLE_ID, "Invalid table ID") TAOS_DEFINE_ERROR(TSDB_CODE_TDB_INVALID_TABLE_TYPE, "Invalid table type") TAOS_DEFINE_ERROR(TSDB_CODE_TDB_IVD_TB_SCHEMA_VERSION, "Invalid table schema version") TAOS_DEFINE_ERROR(TSDB_CODE_TDB_TABLE_ALREADY_EXIST, "Table already exists") +TAOS_DEFINE_ERROR(TSDB_CODE_TDB_TABLE_NOT_EXIST, "Table not exists") +TAOS_DEFINE_ERROR(TSDB_CODE_TDB_STB_ALREADY_EXIST, "Stable already exists") +TAOS_DEFINE_ERROR(TSDB_CODE_TDB_STB_NOT_EXIST, "Stable not exists") TAOS_DEFINE_ERROR(TSDB_CODE_TDB_INVALID_CONFIG, "Invalid configuration") TAOS_DEFINE_ERROR(TSDB_CODE_TDB_INIT_FAILED, "Tsdb init failed") TAOS_DEFINE_ERROR(TSDB_CODE_TDB_NO_DISKSPACE, "No diskspace for tsdb") @@ -449,6 +452,11 @@ TAOS_DEFINE_ERROR(TSDB_CODE_PAR_TABLE_NOT_EXIST, "Table does not exist" //planner TAOS_DEFINE_ERROR(TSDB_CODE_PLAN_INTERNAL_ERROR, "planner internal error") +//schemaless +TAOS_DEFINE_ERROR(TSDB_CODE_SML_INVALID_PROTOCOL_TYPE, "Invalid line protocol type") +TAOS_DEFINE_ERROR(TSDB_CODE_SML_INVALID_PRECISION_TYPE, "Invalid timestamp precision type") +TAOS_DEFINE_ERROR(TSDB_CODE_SML_INVALID_DATA, "Invalid data type") + #ifdef TAOS_ERROR_C }; #endif diff --git a/tests/script/api/batchprepare.c b/tests/script/api/batchprepare.c index 828216d1d3..99e546fcd0 100644 --- a/tests/script/api/batchprepare.c +++ b/tests/script/api/batchprepare.c @@ -398,7 +398,7 @@ void bpAppendOperatorParam(BindData *data, int32_t *len, int32_t dataType, int32 } } -void generateQuerySQL(BindData *data, int32_t tblIdx) { +void generateQueryCondSQL(BindData *data, int32_t tblIdx) { int32_t len = sprintf(data->sql, "select * from %s%d where ", bpTbPrefix, tblIdx); if (!gCurCase->fullCol) { for (int c = 0; c < gCurCase->bindColNum; ++c) { @@ -462,6 +462,72 @@ void generateQuerySQL(BindData *data, int32_t tblIdx) { } } + +void generateQueryMiscSQL(BindData *data, int32_t tblIdx) { + int32_t len = sprintf(data->sql, "select * from %s%d where ", bpTbPrefix, tblIdx); + if (!gCurCase->fullCol) { + for (int c = 0; c < gCurCase->bindColNum; ++c) { + if (c) { + len += sprintf(data->sql + len, " and "); + } + switch (data->pBind[c].buffer_type) { + case TSDB_DATA_TYPE_BOOL: + len += sprintf(data->sql + len, "booldata"); + break; + case TSDB_DATA_TYPE_TINYINT: + len += sprintf(data->sql + len, "tinydata"); + break; + case TSDB_DATA_TYPE_SMALLINT: + len += sprintf(data->sql + len, "smalldata"); + break; + case TSDB_DATA_TYPE_INT: + len += sprintf(data->sql + len, "intdata"); + break; + case TSDB_DATA_TYPE_BIGINT: + len += sprintf(data->sql + len, "bigdata"); + break; + case TSDB_DATA_TYPE_FLOAT: + len += sprintf(data->sql + len, "floatdata"); + break; + case TSDB_DATA_TYPE_DOUBLE: + len += sprintf(data->sql + len, "doubledata"); + break; + case TSDB_DATA_TYPE_VARCHAR: + len += sprintf(data->sql + len, "binarydata"); + break; + case TSDB_DATA_TYPE_TIMESTAMP: + len += sprintf(data->sql + len, "ts"); + break; + case TSDB_DATA_TYPE_NCHAR: + len += sprintf(data->sql + len, "nchardata"); + break; + case TSDB_DATA_TYPE_UTINYINT: + len += sprintf(data->sql + len, "utinydata"); + break; + case TSDB_DATA_TYPE_USMALLINT: + len += sprintf(data->sql + len, "usmalldata"); + break; + case TSDB_DATA_TYPE_UINT: + len += sprintf(data->sql + len, "uintdata"); + break; + case TSDB_DATA_TYPE_UBIGINT: + len += sprintf(data->sql + len, "ubigdata"); + break; + default: + printf("!!!invalid col type:%d", data->pBind[c].buffer_type); + exit(1); + } + + bpAppendOperatorParam(data, &len, data->pBind[c].buffer_type, c); + } + } + + if (gCaseCtrl.printStmtSql) { + printf("\tSTMT SQL: %s\n", data->sql); + } +} + + void generateErrorSQL(BindData *data, int32_t tblIdx) { int32_t len = 0; data->sql = taosMemoryCalloc(1, 1024); @@ -677,7 +743,7 @@ int32_t prepareInsertData(BindData *data) { return 0; } -int32_t prepareQueryData(BindData *data, int32_t tblIdx) { +int32_t prepareQueryCondData(BindData *data, int32_t tblIdx) { static int64_t tsData = 1591060628000; uint64_t bindNum = gCurCase->rowNum / gCurCase->bindRowNum; @@ -735,6 +801,63 @@ int32_t prepareQueryData(BindData *data, int32_t tblIdx) { } +int32_t prepareQueryMiscData(BindData *data, int32_t tblIdx) { + static int64_t tsData = 1591060628000; + uint64_t bindNum = gCurCase->rowNum / gCurCase->bindRowNum; + + data->colNum = 0; + data->colTypes = taosMemoryCalloc(30, sizeof(int32_t)); + data->sql = taosMemoryCalloc(1, 1024); + data->pBind = taosMemoryCalloc(bindNum*gCurCase->bindColNum, sizeof(TAOS_MULTI_BIND)); + data->tsData = taosMemoryMalloc(bindNum * sizeof(int64_t)); + data->boolData = taosMemoryMalloc(bindNum * sizeof(bool)); + data->tinyData = taosMemoryMalloc(bindNum * sizeof(int8_t)); + data->utinyData = taosMemoryMalloc(bindNum * sizeof(uint8_t)); + data->smallData = taosMemoryMalloc(bindNum * sizeof(int16_t)); + data->usmallData = taosMemoryMalloc(bindNum * sizeof(uint16_t)); + data->intData = taosMemoryMalloc(bindNum * sizeof(int32_t)); + data->uintData = taosMemoryMalloc(bindNum * sizeof(uint32_t)); + data->bigData = taosMemoryMalloc(bindNum * sizeof(int64_t)); + data->ubigData = taosMemoryMalloc(bindNum * sizeof(uint64_t)); + data->floatData = taosMemoryMalloc(bindNum * sizeof(float)); + data->doubleData = taosMemoryMalloc(bindNum * sizeof(double)); + data->binaryData = taosMemoryMalloc(bindNum * gVarCharSize); + data->binaryLen = taosMemoryMalloc(bindNum * sizeof(int32_t)); + if (gCurCase->bindNullNum) { + data->isNull = taosMemoryCalloc(bindNum, sizeof(char)); + } + + for (int32_t i = 0; i < bindNum; ++i) { + data->tsData[i] = tsData + tblIdx*gCurCase->rowNum + rand()%gCurCase->rowNum; + data->boolData[i] = (bool)(tblIdx*gCurCase->rowNum + rand() % gCurCase->rowNum); + data->tinyData[i] = (int8_t)(tblIdx*gCurCase->rowNum + rand() % gCurCase->rowNum); + data->utinyData[i] = (uint8_t)(tblIdx*gCurCase->rowNum + rand() % gCurCase->rowNum); + data->smallData[i] = (int16_t)(tblIdx*gCurCase->rowNum + rand() % gCurCase->rowNum); + data->usmallData[i] = (uint16_t)(tblIdx*gCurCase->rowNum + rand() % gCurCase->rowNum); + data->intData[i] = (int32_t)(tblIdx*gCurCase->rowNum + rand() % gCurCase->rowNum); + data->uintData[i] = (uint32_t)(tblIdx*gCurCase->rowNum + rand() % gCurCase->rowNum); + data->bigData[i] = (int64_t)(tblIdx*gCurCase->rowNum + rand() % gCurCase->rowNum); + data->ubigData[i] = (uint64_t)(tblIdx*gCurCase->rowNum + rand() % gCurCase->rowNum); + data->floatData[i] = (float)(tblIdx*gCurCase->rowNum + rand() % gCurCase->rowNum); + data->doubleData[i] = (double)(tblIdx*gCurCase->rowNum + rand() % gCurCase->rowNum); + memset(data->binaryData + gVarCharSize * i, 'a'+i%26, gVarCharLen); + if (gCurCase->bindNullNum) { + data->isNull[i] = i % 2; + } + data->binaryLen[i] = gVarCharLen; + } + + for (int b = 0; b < bindNum; b++) { + for (int c = 0; c < gCurCase->bindColNum; ++c) { + prepareColData(data, b*gCurCase->bindColNum+c, b*gCurCase->bindRowNum, c); + } + } + + generateQueryMiscSQL(data, tblIdx); + + return 0; +} + void destroyData(BindData *data) { @@ -1385,7 +1508,7 @@ int querySUBTTest1(TAOS_STMT *stmt, TAOS *taos) { for (int32_t t = 0; t< gCurCase->tblNum; ++t) { memset(&data, 0, sizeof(data)); - prepareQueryData(&data, t); + prepareQueryCondData(&data, t); int code = taos_stmt_prepare(stmt, data.sql, 0); if (code != 0){ @@ -1431,7 +1554,7 @@ int querySUBTTest2(TAOS_STMT *stmt, TAOS *taos) { for (int32_t t = 0; t< gCurCase->tblNum; ++t) { memset(&data, 0, sizeof(data)); - prepareQueryData(&data, t); + prepareQueryMiscData(&data, t); int code = taos_stmt_prepare(stmt, data.sql, 0); if (code != 0){ diff --git a/tests/script/general/stable/testSuite.sim b/tests/script/general/stable/testSuite.sim deleted file mode 100644 index e786ac9ca4..0000000000 --- a/tests/script/general/stable/testSuite.sim +++ /dev/null @@ -1,5 +0,0 @@ -run general/stable/disk.sim -run general/stable/dnode3.sim -run general/stable/metrics.sim -run general/stable/values.sim -run general/stable/vnode3.sim diff --git a/tests/system-test/0-others/telemetry.py b/tests/system-test/0-others/telemetry.py new file mode 100644 index 0000000000..3ab39f9e7b --- /dev/null +++ b/tests/system-test/0-others/telemetry.py @@ -0,0 +1,197 @@ +import taos +import sys +import time +import socket +import pexpect +import os +import http.server +import gzip +import threading +import json + +from util.log import * +from util.sql import * +from util.cases import * +from util.dnodes import * + +telemetryPort = '80' + +#{ +# "instanceId": "5cf4cd7a-acd4-43ba-8b0d-e84395b76a65", +# "reportVersion": 1, +# "os": "Ubuntu 20.04.3 LTS", +# "cpuModel": "Intel(R) Xeon(R) CPU E5-2620 v3 @ 2.40GHz", +# "numOfCpu": 6, +# "memory": "65860292 kB", +# "version": "3.0.0.0", +# "buildInfo": "Built at 2022-05-07 14:09:02", +# "gitInfo": "2139ccceb0946cde86b6b553b11e338f1ba437e5", +# "email": "user@taosdata.com", +# "numOfDnode": 1, +# "numOfMnode": 1, +# "numOfVgroup": 32, +# "numOfDatabase": 2, +# "numOfSuperTable": 0, +# "numOfChildTable": 100, +# "numOfColumn": 200, +# "numOfPoint": 300, +# "totalStorage": 400, +# "compStorage": 500 +#} + +def telemetryInfoCheck(infoDict=''): + if "instanceId" not in infoDict or len(infoDict["instanceId"]) == 0: + tdLog.exit("instanceId is null!") + + if "reportVersion" not in infoDict or infoDict["reportVersion"] != 1: + tdLog.exit("reportVersion is null!") + + if "os" not in infoDict: + tdLog.exit("os is null!") + + if "cpuModel" not in infoDict: + tdLog.exit("cpuModel is null!") + + if "numOfCpu" not in infoDict or infoDict["numOfCpu"] == 0: + tdLog.exit("numOfCpu is null!") + + if "memory" not in infoDict: + tdLog.exit("memory is null!") + + if "version" not in infoDict: + tdLog.exit("version is null!") + + if "buildInfo" not in infoDict: + tdLog.exit("buildInfo is null!") + + if "gitInfo" not in infoDict: + tdLog.exit("gitInfo is null!") + + if "email" not in infoDict: + tdLog.exit("email is not exists!") + + if "numOfDnode" not in infoDict or infoDict["numOfDnode"] < 1: + tdLog.exit("numOfDnode is null!") + + if "numOfMnode" not in infoDict or infoDict["numOfMnode"] < 1: + tdLog.exit("numOfMnode is null!") + + if "numOfVgroup" not in infoDict or infoDict["numOfVgroup"] <= 0: + tdLog.exit("numOfVgroup is null!") + + if "numOfDatabase" not in infoDict or infoDict["numOfDatabase"] <= 0: + tdLog.exit("numOfDatabase is null!") + + if "numOfSuperTable" not in infoDict or infoDict["numOfSuperTable"] < 0: + tdLog.exit("numOfSuperTable is null!") + + if "numOfChildTable" not in infoDict or infoDict["numOfChildTable"] < 0: + tdLog.exit("numOfChildTable is null!") + + if "numOfColumn" not in infoDict or infoDict["numOfColumn"] < 0: + tdLog.exit("numOfColumn is null!") + + if "numOfPoint" not in infoDict or infoDict["numOfPoint"] < 0: + tdLog.exit("numOfPoint is null!") + + if "totalStorage" not in infoDict or infoDict["totalStorage"] < 0: + tdLog.exit("totalStorage is null!") + + if "compStorage" not in infoDict or infoDict["compStorage"] < 0: + tdLog.exit("compStorage is null!") + + +class RequestHandlerImpl(http.server.BaseHTTPRequestHandler): + def do_GET(self): + """ + process GET request + """ + + def do_POST(self): + """ + process POST request + """ + contentEncoding = self.headers["Content-Encoding"] + + if contentEncoding == 'gzip': + req_body = self.rfile.read(int(self.headers["Content-Length"])) + plainText = gzip.decompress(req_body).decode() + else: + plainText = self.rfile.read(int(self.headers["Content-Length"])).decode() + + print("monitor info:\n%s"%plainText) + + # 1. send response code and header + self.send_response(200) + self.send_header("Content-Type", "text/html; charset=utf-8") + self.end_headers() + + # 2. send response content + #self.wfile.write(("Hello World: " + req_body + "\n").encode("utf-8")) + + # 3. check request body info + infoDict = json.loads(plainText) + #print("================") + #print(infoDict) + telemetryInfoCheck(infoDict) + + # 4. shutdown the server and exit case + assassin = threading.Thread(target=httpServer.shutdown) + assassin.daemon = True + assassin.start() + print ("==== shutdown http server ====") + +class TDTestCase: + hostname = socket.gethostname() + serverPort = '7080' + rpcDebugFlagVal = '143' + clientCfgDict = {'serverPort': '', 'firstEp': '', 'secondEp':'', 'rpcDebugFlag':'135', 'fqdn':''} + clientCfgDict["serverPort"] = serverPort + clientCfgDict["firstEp"] = hostname + ':' + serverPort + clientCfgDict["secondEp"] = hostname + ':' + serverPort + clientCfgDict["rpcDebugFlag"] = rpcDebugFlagVal + clientCfgDict["fqdn"] = hostname + + updatecfgDict = {'clientCfg': {}, 'serverPort': '', 'firstEp': '', 'secondEp':'', 'rpcDebugFlag':'135', 'fqdn':''} + updatecfgDict["clientCfg"] = clientCfgDict + updatecfgDict["serverPort"] = serverPort + updatecfgDict["firstEp"] = hostname + ':' + serverPort + updatecfgDict["secondEp"] = hostname + ':' + serverPort + updatecfgDict["fqdn"] = hostname + + updatecfgDict["telemetryReporting"] = '1' + updatecfgDict["telemetryServer"] = hostname + updatecfgDict["telemetryPort"] = telemetryPort + updatecfgDict["telemetryInterval"] = "3" + + print ("===================: ", updatecfgDict) + + def init(self, conn, logSql): + tdLog.debug(f"start to excute {__file__}") + tdSql.init(conn.cursor()) + + def run(self): # sourcery skip: extract-duplicate-method, remove-redundant-fstring + tdSql.prepare() + # time.sleep(2) + vgroups = "30" + sql = "create database db3 vgroups " + vgroups + tdSql.query(sql) + + # loop to wait request + httpServer.serve_forever() + + def stop(self): + tdSql.close() + tdLog.success(f"{__file__} successfully executed") + +# create http server: bing ip/port , and request processor +serverAddress = ("", int(telemetryPort)) +httpServer = http.server.HTTPServer(serverAddress, RequestHandlerImpl) + +tdCases.addLinux(__file__, TDTestCase()) +tdCases.addWindows(__file__, TDTestCase()) + + + + + diff --git a/tools/shell/src/shellCommand.c b/tools/shell/src/shellCommand.c index 6813e9b2f7..f4f7c893c4 100644 --- a/tools/shell/src/shellCommand.c +++ b/tools/shell/src/shellCommand.c @@ -151,8 +151,8 @@ void shellGetPrevCharSize(const char *str, int32_t pos, int32_t *size, int32_t * if (str[pos] > 0 || shellCountPrefixOnes((uint8_t)str[pos]) > 1) break; } - int32_t rc = taosMbToWchar(&wc, str + pos, MB_CUR_MAX); - assert(rc == *size); + taosMbToWchar(&wc, str + pos, MB_CUR_MAX); + // assert(rc == *size); // it will be core, if str is encode by utf8 and taos charset is gbk *width = taosWcharWidth(wc); } diff --git a/tools/shell/src/shellEngine.c b/tools/shell/src/shellEngine.c index 08fe2cbc32..21fd3d0359 100644 --- a/tools/shell/src/shellEngine.c +++ b/tools/shell/src/shellEngine.c @@ -118,66 +118,27 @@ int32_t shellRunCommand(char *command) { } } - bool esc = false; - char quote = 0, *cmd = command, *p = command; + char quote = 0, *cmd = command; for (char c = *command++; c != 0; c = *command++) { - if (esc) { - switch (c) { - case 'n': - c = '\n'; - break; - case 'r': - c = '\r'; - break; - case 't': - c = '\t'; - break; - case 'G': - *p++ = '\\'; - break; - case '\'': - case '"': - if (quote) { - *p++ = '\\'; - } - break; - default: - *p++ = '\\'; - break; - } - *p++ = c; - esc = false; + if (c == '\\' && (*command == '\'' || *command == '"' || *command == '`')) { + command ++; continue; } - if (c == '\\') { - if (quote != 0 && (*command == '_' || *command == '\\')) { - // DO nothing - } else { - esc = true; - continue; - } - } - if (quote == c) { quote = 0; - } else if (quote == 0 && (c == '\'' || c == '"')) { + } else if (quote == 0 && (c == '\'' || c == '"' || c == '`')) { quote = c; - } - - *p++ = c; - if (c == ';' && quote == 0) { - c = *p; - *p = 0; + } else if (c == ';' && quote == 0) { + c = *command; + *command = 0; if (shellRunSingleCommand(cmd) < 0) { return -1; } - *p = c; - p = cmd; + *command = c; + cmd = command; } } - - *p = 0; return shellRunSingleCommand(cmd); } diff --git a/tools/taos-tools b/tools/taos-tools index 59e0ebaf49..2f3dfddd4d 160000 --- a/tools/taos-tools +++ b/tools/taos-tools @@ -1 +1 @@ -Subproject commit 59e0ebaf4905e4cb6d95a01c58b3fa507abc5a20 +Subproject commit 2f3dfddd4d9a869e706ba3cf98fb6d769404cd7c