diff --git a/source/client/inc/clientSml.h b/source/client/inc/clientSml.h index b74d0b3494..11f72efeaf 100644 --- a/source/client/inc/clientSml.h +++ b/source/client/inc/clientSml.h @@ -69,6 +69,7 @@ extern "C" { #define VALUE "_value" #define VALUE_LEN 6 +#define OTD_JSON_FIELDS_NUM 4 #define MAX_RETRY_TIMES 5 typedef TSDB_SML_PROTOCOL_TYPE SMLProtocolType; @@ -177,12 +178,14 @@ typedef struct { int32_t lineNum; SSmlMsgBuf msgBuf; -// cJSON *root; // for parse json - int8_t offset[4]; + cJSON *root; // for parse json + int8_t offset[OTD_JSON_FIELDS_NUM]; SSmlLineInfo *lines; // element is SSmlLineInfo + bool parseJsonByLib; // SArray *preLineTagKV; + SArray *maxTagKVs; SArray *preLineColKV; SSmlLineInfo preLine; @@ -197,7 +200,7 @@ typedef struct { #define IS_SAME_SUPER_TABLE (elements->measureLen == info->preLine.measureLen \ && memcmp(elements->measure, info->preLine.measure, elements->measureLen) == 0) -#define IS_SAME_KEY (preKV->keyLen == kv.keyLen && memcmp(preKV->key, kv.key, kv.keyLen) == 0) +#define IS_SAME_KEY (maxKV->keyLen == kv.keyLen && memcmp(maxKV->key, kv.key, kv.keyLen) == 0) extern int64_t smlFactorNS[3]; extern int64_t smlFactorS[3]; @@ -206,9 +209,9 @@ typedef int32_t (*_equal_fn_sml)(const void *, const void *); SSmlHandle *smlBuildSmlInfo(TAOS *taos); void smlDestroyInfo(SSmlHandle *info); -void smlJsonParseObjFirst(char **start, SSmlLineInfo *element, int8_t *offset); -void smlJsonParseObj(char **start, SSmlLineInfo *element, int8_t *offset); -SArray *smlJsonParseTags(char *start, char *end); +int smlJsonParseObjFirst(char **start, SSmlLineInfo *element, int8_t *offset); +int smlJsonParseObj(char **start, SSmlLineInfo *element, int8_t *offset); +//SArray *smlJsonParseTags(char *start, char *end); bool smlParseNumberOld(SSmlKv *kvVal, SSmlMsgBuf *msg); void* nodeListGet(NodeList* list, const void *key, int32_t len, _equal_fn_sml fn); int nodeListSet(NodeList** list, const void *key, int32_t len, void* value, _equal_fn_sml fn); @@ -226,6 +229,7 @@ int32_t is_same_child_table_telnet(const void *a, const void *b); int64_t smlParseOpenTsdbTime(SSmlHandle *info, const char *data, int32_t len); int32_t smlClearForRerun(SSmlHandle *info); int32_t smlParseValue(SSmlKv *pVal, SSmlMsgBuf *msg); +uint8_t smlGetTimestampLen(int64_t num); int32_t smlParseInfluxString(SSmlHandle *info, char *sql, char *sqlEnd, SSmlLineInfo *elements); int32_t smlParseTelnetString(SSmlHandle *info, char *sql, char *sqlEnd, SSmlLineInfo *elements); diff --git a/source/client/src/clientSml.c b/source/client/src/clientSml.c index ba154c95bd..ca6395b52b 100644 --- a/source/client/src/clientSml.c +++ b/source/client/src/clientSml.c @@ -1008,12 +1008,16 @@ static int32_t smlUpdateMeta(SHashObj *metaHash, SArray *metaArray, SArray *cols return TSDB_CODE_SUCCESS; } -static void smlDestroyTableInfo(SSmlTableInfo *tag) { +static void smlDestroyTableInfo(SSmlHandle *info, SSmlTableInfo *tag) { for (size_t i = 0; i < taosArrayGetSize(tag->cols); i++) { SHashObj *kvHash = (SHashObj *)taosArrayGetP(tag->cols, i); taosHashCleanup(kvHash); } + if(info->parseJsonByLib){ + SSmlLineInfo *key = (SSmlLineInfo *)(tag->key); + if(key != NULL) taosMemoryFree(key->tags); + } taosMemoryFree(tag->key); taosArrayDestroy(tag->cols); taosArrayDestroy(tag->tags); @@ -1028,7 +1032,7 @@ void smlDestroyInfo(SSmlHandle *info) { NodeList *tmp = info->childTables; while (tmp) { if (tmp->data.used) { - smlDestroyTableInfo((SSmlTableInfo *)tmp->data.value); + smlDestroyTableInfo(info, (SSmlTableInfo *)tmp->data.value); } NodeList *t = tmp->next; taosMemoryFree(tmp); @@ -1050,11 +1054,15 @@ void smlDestroyInfo(SSmlHandle *info) { taosHashCleanup(info->pVgHash); taosArrayDestroy(info->preLineTagKV); + taosArrayDestroy(info->maxTagKVs); taosArrayDestroy(info->preLineColKV); if (!info->dataFormat) { for (int i = 0; i < info->lineNum; i++) { taosArrayDestroy(info->lines[i].colArray); + if(info->parseJsonByLib){ + taosMemoryFree(info->lines[i].tags); + } } taosMemoryFree(info->lines); } @@ -1083,6 +1091,7 @@ SSmlHandle *smlBuildSmlInfo(TAOS *taos) { info->dataFormat = true; info->preLineTagKV = taosArrayInit(8, sizeof(SSmlKv)); + info->maxTagKVs = taosArrayInit(8, sizeof(SSmlKv)); info->preLineColKV = taosArrayInit(8, sizeof(SSmlKv)); if (NULL == info->pVgHash) { @@ -1251,7 +1260,7 @@ int32_t smlClearForRerun(SSmlHandle *info) { NodeList *pList = info->childTables; while (pList) { if (pList->data.used) { - smlDestroyTableInfo((SSmlTableInfo *)pList->data.value); + smlDestroyTableInfo(info, (SSmlTableInfo *)pList->data.value); pList->data.used = false; } pList = pList->next; @@ -1267,11 +1276,13 @@ int32_t smlClearForRerun(SSmlHandle *info) { pList = pList->next; } - if (unlikely(info->lines != NULL)) { - uError("SML:0x%" PRIx64 " info->lines != NULL", info->id); - return TSDB_CODE_SML_INVALID_DATA; + if (!info->dataFormat){ + if (unlikely(info->lines != NULL)) { + uError("SML:0x%" PRIx64 " info->lines != NULL", info->id); + return TSDB_CODE_SML_INVALID_DATA; + } + info->lines = (SSmlLineInfo *)taosMemoryCalloc(info->lineNum, sizeof(SSmlLineInfo)); } - info->lines = (SSmlLineInfo *)taosMemoryCalloc(info->lineNum, sizeof(SSmlLineInfo)); memset(&info->preLine, 0, sizeof(SSmlLineInfo)); info->currSTableMeta = NULL; diff --git a/source/client/src/clientSmlJson.c b/source/client/src/clientSmlJson.c index 3de1397f72..60e29638f5 100644 --- a/source/client/src/clientSmlJson.c +++ b/source/client/src/clientSmlJson.c @@ -19,6 +19,8 @@ #include #include "clientSml.h" +#define OTD_JSON_SUB_FIELDS_NUM 2 + #define JUMP_JSON_SPACE(start) \ while(*(start)){\ if(unlikely(*(start) > 32))\ @@ -27,188 +29,193 @@ while(*(start)){\ (start)++;\ } -SArray *smlJsonParseTags(char *start, char *end){ - SArray *tags = taosArrayInit(4, sizeof(SSmlKv)); - while(start < end){ - SSmlKv kv = {0}; - kv.type = TSDB_DATA_TYPE_NCHAR; - bool isInQuote = false; - while(start < end){ - if(unlikely(!isInQuote && *start == '"')){ - start++; - kv.key = start; - isInQuote = true; - continue; - } - if(unlikely(isInQuote && *start == '"')){ - kv.keyLen = start - kv.key; - start++; - break; - } - start++; - } - bool hasColon = false; - while(start < end){ - if(unlikely(!hasColon && *start == ':')){ - start++; - hasColon = true; - continue; - } - if(unlikely(hasColon && kv.value == NULL && (*start > 32 && *start != '"'))){ - kv.value = start; - start++; - continue; - } +//SArray *smlJsonParseTags(char *start, char *end){ +// SArray *tags = taosArrayInit(4, sizeof(SSmlKv)); +// while(start < end){ +// SSmlKv kv = {0}; +// kv.type = TSDB_DATA_TYPE_NCHAR; +// bool isInQuote = false; +// while(start < end){ +// if(unlikely(!isInQuote && *start == '"')){ +// start++; +// kv.key = start; +// isInQuote = true; +// continue; +// } +// if(unlikely(isInQuote && *start == '"')){ +// kv.keyLen = start - kv.key; +// start++; +// break; +// } +// start++; +// } +// bool hasColon = false; +// while(start < end){ +// if(unlikely(!hasColon && *start == ':')){ +// start++; +// hasColon = true; +// continue; +// } +// if(unlikely(hasColon && kv.value == NULL && (*start > 32 && *start != '"'))){ +// kv.value = start; +// start++; +// continue; +// } +// +// if(unlikely(hasColon && kv.value != NULL && (*start == '"' || *start == ',' || *start == '}'))){ +// kv.length = start - kv.value; +// taosArrayPush(tags, &kv); +// start++; +// break; +// } +// start++; +// } +// } +// return tags; +//} - if(unlikely(hasColon && kv.value != NULL && (*start == '"' || *start == ',' || *start == '}'))){ - kv.length = start - kv.value; - taosArrayPush(tags, &kv); - start++; - break; - } - start++; - } - } - return tags; -} - -static int32_t smlParseTagsFromJSON(SSmlHandle *info, SSmlLineInfo *elements) { - int32_t ret = TSDB_CODE_SUCCESS; - - if(is_same_child_table_telnet(elements, &info->preLine) == 0){ - return TSDB_CODE_SUCCESS; - } - - bool isSameMeasure = IS_SAME_SUPER_TABLE; - - int cnt = 0; - SArray *preLineKV = info->preLineTagKV; - bool isSuperKVInit = true; - SArray *superKV = NULL; - if(info->dataFormat){ - if(unlikely(!isSameMeasure)){ - SSmlSTableMeta *sMeta = (SSmlSTableMeta *)nodeListGet(info->superTables, elements->measure, elements->measureLen, NULL); - - if(unlikely(sMeta == NULL)){ - sMeta = smlBuildSTableMeta(info->dataFormat); - STableMeta * pTableMeta = smlGetMeta(info, elements->measure, elements->measureLen); - sMeta->tableMeta = pTableMeta; - if(pTableMeta == NULL){ - info->dataFormat = false; - info->reRun = true; - return TSDB_CODE_SUCCESS; - } - nodeListSet(&info->superTables, elements->measure, elements->measureLen, sMeta, NULL); - } - info->currSTableMeta = sMeta->tableMeta; - superKV = sMeta->tags; - - if(unlikely(taosArrayGetSize(superKV) == 0)){ - isSuperKVInit = false; - } - taosArraySetSize(preLineKV, 0); - } - }else{ - taosArraySetSize(preLineKV, 0); - } - - SArray *tags = smlJsonParseTags(elements->tags, elements->tags + elements->tagsLen); - int32_t tagNum = taosArrayGetSize(tags); - for (int32_t i = 0; i < tagNum; ++i) { - SSmlKv kv = *(SSmlKv*)taosArrayGet(tags, i); - - if(info->dataFormat){ - if(unlikely(cnt + 1 > info->currSTableMeta->tableInfo.numOfTags)){ - info->dataFormat = false; - info->reRun = true; - taosArrayDestroy(tags); - return TSDB_CODE_SUCCESS; - } - - if(isSameMeasure){ - if(unlikely(cnt >= taosArrayGetSize(preLineKV))) { - info->dataFormat = false; - info->reRun = true; - taosArrayDestroy(tags); - return TSDB_CODE_SUCCESS; - } - SSmlKv *preKV = (SSmlKv *)taosArrayGet(preLineKV, cnt); - if(unlikely(kv.length > preKV->length)){ - preKV->length = kv.length; - SSmlSTableMeta *tableMeta = (SSmlSTableMeta *)nodeListGet(info->superTables, elements->measure, elements->measureLen, NULL); - ASSERT(tableMeta != NULL); - - SSmlKv *oldKV = (SSmlKv *)taosArrayGet(tableMeta->tags, cnt); - oldKV->length = kv.length; - info->needModifySchema = true; - } - if(unlikely(!IS_SAME_KEY)){ - info->dataFormat = false; - info->reRun = true; - taosArrayDestroy(tags); - return TSDB_CODE_SUCCESS; - } - }else{ - if(isSuperKVInit){ - if(unlikely(cnt >= taosArrayGetSize(superKV))) { - info->dataFormat = false; - info->reRun = true; - taosArrayDestroy(tags); - return TSDB_CODE_SUCCESS; - } - SSmlKv *preKV = (SSmlKv *)taosArrayGet(superKV, cnt); - if(unlikely(kv.length > preKV->length)) { - preKV->length = kv.length; - }else{ - kv.length = preKV->length; - } - info->needModifySchema = true; - - if(unlikely(!IS_SAME_KEY)){ - info->dataFormat = false; - info->reRun = true; - taosArrayDestroy(tags); - return TSDB_CODE_SUCCESS; - } - }else{ - taosArrayPush(superKV, &kv); - } - taosArrayPush(preLineKV, &kv); - } - }else{ - taosArrayPush(preLineKV, &kv); - } - cnt++; - } - taosArrayDestroy(tags); - - SSmlTableInfo *tinfo = (SSmlTableInfo *)nodeListGet(info->childTables, elements, POINTER_BYTES, is_same_child_table_telnet); - if (unlikely(tinfo == NULL)) { - tinfo = smlBuildTableInfo(1, elements->measure, elements->measureLen); - if (unlikely(!tinfo)) { - return TSDB_CODE_OUT_OF_MEMORY; - } - tinfo->tags = taosArrayDup(preLineKV, NULL); - - smlSetCTableName(tinfo); - if (info->dataFormat) { - info->currSTableMeta->uid = tinfo->uid; - tinfo->tableDataCtx = smlInitTableDataCtx(info->pQuery, info->currSTableMeta); - if (tinfo->tableDataCtx == NULL) { - smlBuildInvalidDataMsg(&info->msgBuf, "smlInitTableDataCtx error", NULL); - return TSDB_CODE_SML_INVALID_DATA; - } - } - - SSmlLineInfo *key = (SSmlLineInfo *)taosMemoryMalloc(sizeof(SSmlLineInfo)); - *key = *elements; - tinfo->key = key; - nodeListSet(&info->childTables, key, POINTER_BYTES, tinfo, is_same_child_table_telnet); - } - if (info->dataFormat) info->currTableDataCtx = tinfo->tableDataCtx; - - return ret; -} +//static int32_t smlParseTagsFromJSON(SSmlHandle *info, SSmlLineInfo *elements) { +// int32_t ret = TSDB_CODE_SUCCESS; +// +// if(is_same_child_table_telnet(elements, &info->preLine) == 0){ +// return TSDB_CODE_SUCCESS; +// } +// +// bool isSameMeasure = IS_SAME_SUPER_TABLE; +// +// int cnt = 0; +// SArray *preLineKV = info->preLineTagKV; +// bool isSuperKVInit = true; +// SArray *superKV = NULL; +// if(info->dataFormat){ +// if(unlikely(!isSameMeasure)){ +// SSmlSTableMeta *sMeta = (SSmlSTableMeta *)nodeListGet(info->superTables, elements->measure, elements->measureLen, NULL); +// +// if(unlikely(sMeta == NULL)){ +// sMeta = smlBuildSTableMeta(info->dataFormat); +// STableMeta * pTableMeta = smlGetMeta(info, elements->measure, elements->measureLen); +// sMeta->tableMeta = pTableMeta; +// if(pTableMeta == NULL){ +// info->dataFormat = false; +// info->reRun = true; +// return TSDB_CODE_SUCCESS; +// } +// nodeListSet(&info->superTables, elements->measure, elements->measureLen, sMeta, NULL); +// } +// info->currSTableMeta = sMeta->tableMeta; +// superKV = sMeta->tags; +// +// if(unlikely(taosArrayGetSize(superKV) == 0)){ +// isSuperKVInit = false; +// } +// taosArraySetSize(preLineKV, 0); +// } +// }else{ +// taosArraySetSize(preLineKV, 0); +// } +// +// SArray *tags = smlJsonParseTags(elements->tags, elements->tags + elements->tagsLen); +// int32_t tagNum = taosArrayGetSize(tags); +// if (tagNum == 0) { +// uError("SML:tag is empty:%s", elements->tags) +// taosArrayDestroy(tags); +// return TSDB_CODE_SML_INVALID_DATA; +// } +// for (int32_t i = 0; i < tagNum; ++i) { +// SSmlKv kv = *(SSmlKv*)taosArrayGet(tags, i); +// +// if(info->dataFormat){ +// if(unlikely(cnt + 1 > info->currSTableMeta->tableInfo.numOfTags)){ +// info->dataFormat = false; +// info->reRun = true; +// taosArrayDestroy(tags); +// return TSDB_CODE_SUCCESS; +// } +// +// if(isSameMeasure){ +// if(unlikely(cnt >= taosArrayGetSize(preLineKV))) { +// info->dataFormat = false; +// info->reRun = true; +// taosArrayDestroy(tags); +// return TSDB_CODE_SUCCESS; +// } +// SSmlKv *preKV = (SSmlKv *)taosArrayGet(preLineKV, cnt); +// if(unlikely(kv.length > preKV->length)){ +// preKV->length = kv.length; +// SSmlSTableMeta *tableMeta = (SSmlSTableMeta *)nodeListGet(info->superTables, elements->measure, elements->measureLen, NULL); +// ASSERT(tableMeta != NULL); +// +// SSmlKv *oldKV = (SSmlKv *)taosArrayGet(tableMeta->tags, cnt); +// oldKV->length = kv.length; +// info->needModifySchema = true; +// } +// if(unlikely(!IS_SAME_KEY)){ +// info->dataFormat = false; +// info->reRun = true; +// taosArrayDestroy(tags); +// return TSDB_CODE_SUCCESS; +// } +// }else{ +// if(isSuperKVInit){ +// if(unlikely(cnt >= taosArrayGetSize(superKV))) { +// info->dataFormat = false; +// info->reRun = true; +// taosArrayDestroy(tags); +// return TSDB_CODE_SUCCESS; +// } +// SSmlKv *preKV = (SSmlKv *)taosArrayGet(superKV, cnt); +// if(unlikely(kv.length > preKV->length)) { +// preKV->length = kv.length; +// }else{ +// kv.length = preKV->length; +// } +// info->needModifySchema = true; +// +// if(unlikely(!IS_SAME_KEY)){ +// info->dataFormat = false; +// info->reRun = true; +// taosArrayDestroy(tags); +// return TSDB_CODE_SUCCESS; +// } +// }else{ +// taosArrayPush(superKV, &kv); +// } +// taosArrayPush(preLineKV, &kv); +// } +// }else{ +// taosArrayPush(preLineKV, &kv); +// } +// cnt++; +// } +// taosArrayDestroy(tags); +// +// SSmlTableInfo *tinfo = (SSmlTableInfo *)nodeListGet(info->childTables, elements, POINTER_BYTES, is_same_child_table_telnet); +// if (unlikely(tinfo == NULL)) { +// tinfo = smlBuildTableInfo(1, elements->measure, elements->measureLen); +// if (unlikely(!tinfo)) { +// return TSDB_CODE_OUT_OF_MEMORY; +// } +// tinfo->tags = taosArrayDup(preLineKV, NULL); +// +// smlSetCTableName(tinfo); +// if (info->dataFormat) { +// info->currSTableMeta->uid = tinfo->uid; +// tinfo->tableDataCtx = smlInitTableDataCtx(info->pQuery, info->currSTableMeta); +// if (tinfo->tableDataCtx == NULL) { +// smlBuildInvalidDataMsg(&info->msgBuf, "smlInitTableDataCtx error", NULL); +// return TSDB_CODE_SML_INVALID_DATA; +// } +// } +// +// SSmlLineInfo *key = (SSmlLineInfo *)taosMemoryMalloc(sizeof(SSmlLineInfo)); +// *key = *elements; +// tinfo->key = key; +// nodeListSet(&info->childTables, key, POINTER_BYTES, tinfo, is_same_child_table_telnet); +// } +// if (info->dataFormat) info->currTableDataCtx = tinfo->tableDataCtx; +// +// return ret; +//} static char* smlJsonGetObj(char *payload){ int leftBracketCnt = 0; @@ -233,7 +240,7 @@ static char* smlJsonGetObj(char *payload){ return NULL; } -void smlJsonParseObjFirst(char **start, SSmlLineInfo *element, int8_t *offset){ +int smlJsonParseObjFirst(char **start, SSmlLineInfo *element, int8_t *offset){ int index = 0; while(*(*start)){ if((*start)[0] != '"'){ @@ -241,10 +248,11 @@ void smlJsonParseObjFirst(char **start, SSmlLineInfo *element, int8_t *offset){ continue; } - if(unlikely(index >= 4)) { - uError("index >= 4, %s", *start) + if(unlikely(index >= OTD_JSON_FIELDS_NUM)) { + uError("index >= %d, %s", OTD_JSON_FIELDS_NUM, *start) break; } + char *sTmp = *start; if((*start)[1] == 'm' && (*start)[2] == 'e' && (*start)[3] == 't' && (*start)[4] == 'r' && (*start)[5] == 'i' && (*start)[6] == 'c' && (*start)[7] == '"'){ @@ -333,9 +341,15 @@ void smlJsonParseObjFirst(char **start, SSmlLineInfo *element, int8_t *offset){ } (*start)++; } + + if(unlikely(index != OTD_JSON_FIELDS_NUM) || element->tags == NULL || element->cols == NULL || element->measure == NULL || element->timestamp == NULL) { + uError("elements != %d or element parse null", OTD_JSON_FIELDS_NUM) + return -1; + } + return 0; } -void smlJsonParseObj(char **start, SSmlLineInfo *element, int8_t *offset){ +int smlJsonParseObj(char **start, SSmlLineInfo *element, int8_t *offset){ int index = 0; while(*(*start)){ if((*start)[0] != '"'){ @@ -343,10 +357,11 @@ void smlJsonParseObj(char **start, SSmlLineInfo *element, int8_t *offset){ continue; } - if(unlikely(index >= 4)) { - uError("index >= 4, %s", *start) + if(unlikely(index >= OTD_JSON_FIELDS_NUM)) { + uError("index >= %d, %s", OTD_JSON_FIELDS_NUM, *start) break; } + if((*start)[1] == 'm'){ (*start) += offset[index++]; element->measure = *start; @@ -393,30 +408,716 @@ void smlJsonParseObj(char **start, SSmlLineInfo *element, int8_t *offset){ } (*start)++; } + + if(unlikely(index != 0 && index != OTD_JSON_FIELDS_NUM)) { + uError("elements != %d", OTD_JSON_FIELDS_NUM) + return -1; + } + return 0; +} + +static inline int32_t smlParseMetricFromJSON(SSmlHandle *info, cJSON *metric, SSmlLineInfo *elements) { + elements->measureLen = strlen(metric->valuestring); + if (IS_INVALID_TABLE_LEN(elements->measureLen)) { + uError("OTD:0x%" PRIx64 " Metric lenght is 0 or large than 192", info->id); + return TSDB_CODE_TSC_INVALID_TABLE_ID_LENGTH; + } + + elements->measure = metric->valuestring; + return TSDB_CODE_SUCCESS; +} + +const char *jsonName[OTD_JSON_FIELDS_NUM] = {"metric", "timestamp", "value", "tags"}; +static int32_t smlGetJsonElements(cJSON *root, cJSON ***marks){ + for (int i = 0; i < OTD_JSON_FIELDS_NUM; ++i) { + cJSON *child = root->child; + while(child != NULL) + { + if(strcasecmp(child->string, jsonName[i]) == 0){ + *marks[i] = child; + break; + } + child = child->next; + } + if(*marks[i] == NULL){ + uError("smlGetJsonElements error, not find mark:%d:%s", i, jsonName[i]); + return -1; + } + } + return TSDB_CODE_SUCCESS; +} + +static int32_t smlConvertJSONBool(SSmlKv *pVal, char *typeStr, cJSON *value) { + if (strcasecmp(typeStr, "bool") != 0) { + uError("OTD:invalid type(%s) for JSON Bool", typeStr); + return TSDB_CODE_TSC_INVALID_JSON_TYPE; + } + pVal->type = TSDB_DATA_TYPE_BOOL; + pVal->length = (int16_t)tDataTypes[pVal->type].bytes; + pVal->i = value->valueint; + + return TSDB_CODE_SUCCESS; +} + +static int32_t smlConvertJSONNumber(SSmlKv *pVal, char *typeStr, cJSON *value) { + // tinyint + if (strcasecmp(typeStr, "i8") == 0 || strcasecmp(typeStr, "tinyint") == 0) { + if (!IS_VALID_TINYINT(value->valuedouble)) { + uError("OTD:JSON value(%f) cannot fit in type(tinyint)", value->valuedouble); + return TSDB_CODE_TSC_VALUE_OUT_OF_RANGE; + } + pVal->type = TSDB_DATA_TYPE_TINYINT; + pVal->length = (int16_t)tDataTypes[pVal->type].bytes; + pVal->i = value->valuedouble; + return TSDB_CODE_SUCCESS; + } + // smallint + if (strcasecmp(typeStr, "i16") == 0 || strcasecmp(typeStr, "smallint") == 0) { + if (!IS_VALID_SMALLINT(value->valuedouble)) { + uError("OTD:JSON value(%f) cannot fit in type(smallint)", value->valuedouble); + return TSDB_CODE_TSC_VALUE_OUT_OF_RANGE; + } + pVal->type = TSDB_DATA_TYPE_SMALLINT; + pVal->length = (int16_t)tDataTypes[pVal->type].bytes; + pVal->i = value->valuedouble; + return TSDB_CODE_SUCCESS; + } + // int + if (strcasecmp(typeStr, "i32") == 0 || strcasecmp(typeStr, "int") == 0) { + if (!IS_VALID_INT(value->valuedouble)) { + uError("OTD:JSON value(%f) cannot fit in type(int)", value->valuedouble); + return TSDB_CODE_TSC_VALUE_OUT_OF_RANGE; + } + pVal->type = TSDB_DATA_TYPE_INT; + pVal->length = (int16_t)tDataTypes[pVal->type].bytes; + pVal->i = value->valuedouble; + return TSDB_CODE_SUCCESS; + } + // bigint + if (strcasecmp(typeStr, "i64") == 0 || strcasecmp(typeStr, "bigint") == 0) { + pVal->type = TSDB_DATA_TYPE_BIGINT; + pVal->length = (int16_t)tDataTypes[pVal->type].bytes; + if (value->valuedouble >= (double)INT64_MAX) { + pVal->i = INT64_MAX; + } else if (value->valuedouble <= (double)INT64_MIN) { + pVal->i = INT64_MIN; + } else { + pVal->i = value->valuedouble; + } + return TSDB_CODE_SUCCESS; + } + // float + if (strcasecmp(typeStr, "f32") == 0 || strcasecmp(typeStr, "float") == 0) { + if (!IS_VALID_FLOAT(value->valuedouble)) { + uError("OTD:JSON value(%f) cannot fit in type(float)", value->valuedouble); + return TSDB_CODE_TSC_VALUE_OUT_OF_RANGE; + } + pVal->type = TSDB_DATA_TYPE_FLOAT; + pVal->length = (int16_t)tDataTypes[pVal->type].bytes; + pVal->f = value->valuedouble; + return TSDB_CODE_SUCCESS; + } + // double + if (strcasecmp(typeStr, "f64") == 0 || strcasecmp(typeStr, "double") == 0) { + pVal->type = TSDB_DATA_TYPE_DOUBLE; + pVal->length = (int16_t)tDataTypes[pVal->type].bytes; + pVal->d = value->valuedouble; + return TSDB_CODE_SUCCESS; + } + + // if reach here means type is unsupported + uError("OTD:invalid type(%s) for JSON Number", typeStr); + return TSDB_CODE_TSC_INVALID_JSON_TYPE; +} + +static int32_t smlConvertJSONString(SSmlKv *pVal, char *typeStr, cJSON *value) { + if (strcasecmp(typeStr, "binary") == 0) { + pVal->type = TSDB_DATA_TYPE_BINARY; + } else if (strcasecmp(typeStr, "nchar") == 0) { + pVal->type = TSDB_DATA_TYPE_NCHAR; + } else { + uError("OTD:invalid type(%s) for JSON String", typeStr); + return TSDB_CODE_TSC_INVALID_JSON_TYPE; + } + pVal->length = (int16_t)strlen(value->valuestring); + + if (pVal->type == TSDB_DATA_TYPE_BINARY && pVal->length > TSDB_MAX_BINARY_LEN - VARSTR_HEADER_SIZE) { + return TSDB_CODE_PAR_INVALID_VAR_COLUMN_LEN; + } + if (pVal->type == TSDB_DATA_TYPE_NCHAR && + pVal->length > (TSDB_MAX_NCHAR_LEN - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE) { + return TSDB_CODE_PAR_INVALID_VAR_COLUMN_LEN; + } + + pVal->value = value->valuestring; + return TSDB_CODE_SUCCESS; +} + +static int32_t smlParseValueFromJSONObj(cJSON *root, SSmlKv *kv) { + int32_t ret = TSDB_CODE_SUCCESS; + int32_t size = cJSON_GetArraySize(root); + + if (size != OTD_JSON_SUB_FIELDS_NUM) { + return TSDB_CODE_TSC_INVALID_JSON; + } + + cJSON *value = cJSON_GetObjectItem(root, "value"); + if (value == NULL) { + return TSDB_CODE_TSC_INVALID_JSON; + } + + cJSON *type = cJSON_GetObjectItem(root, "type"); + if (!cJSON_IsString(type)) { + return TSDB_CODE_TSC_INVALID_JSON; + } + + switch (value->type) { + case cJSON_True: + case cJSON_False: { + ret = smlConvertJSONBool(kv, type->valuestring, value); + if (ret != TSDB_CODE_SUCCESS) { + return ret; + } + break; + } + case cJSON_Number: { + ret = smlConvertJSONNumber(kv, type->valuestring, value); + if (ret != TSDB_CODE_SUCCESS) { + return ret; + } + break; + } + case cJSON_String: { + ret = smlConvertJSONString(kv, type->valuestring, value); + if (ret != TSDB_CODE_SUCCESS) { + return ret; + } + break; + } + default: + return TSDB_CODE_TSC_INVALID_JSON_TYPE; + } + + return TSDB_CODE_SUCCESS; +} + +static int32_t smlParseValueFromJSON(cJSON *root, SSmlKv *kv) { + switch (root->type) { + case cJSON_True: + case cJSON_False: { + kv->type = TSDB_DATA_TYPE_BOOL; + kv->length = (int16_t)tDataTypes[kv->type].bytes; + kv->i = root->valueint; + break; + } + case cJSON_Number: { + kv->type = TSDB_DATA_TYPE_DOUBLE; + kv->length = (int16_t)tDataTypes[kv->type].bytes; + kv->d = root->valuedouble; + break; + } + case cJSON_String: { + /* set default JSON type to binary/nchar according to + * user configured parameter tsDefaultJSONStrType + */ + + char *tsDefaultJSONStrType = "nchar"; // todo + smlConvertJSONString(kv, tsDefaultJSONStrType, root); + break; + } + case cJSON_Object: { + int32_t ret = smlParseValueFromJSONObj(root, kv); + if (ret != TSDB_CODE_SUCCESS) { + uError("OTD:Failed to parse value from JSON Obj"); + return ret; + } + break; + } + default: + return TSDB_CODE_TSC_INVALID_JSON; + } + + return TSDB_CODE_SUCCESS; +} + +static int32_t smlParseTagsFromJSON(SSmlHandle *info, cJSON *tags, SSmlLineInfo *elements) { + int32_t ret = TSDB_CODE_SUCCESS; + + bool isSameMeasure = IS_SAME_SUPER_TABLE; + + int cnt = 0; + SArray *preLineKV = info->preLineTagKV; + SArray *maxKVs = info->maxTagKVs; + bool isSuperKVInit = true; + SArray *superKV = NULL; + if(info->dataFormat){ + if(unlikely(!isSameMeasure)){ + SSmlSTableMeta *sMeta = (SSmlSTableMeta *)nodeListGet(info->superTables, elements->measure, elements->measureLen, NULL); + + if(unlikely(sMeta == NULL)){ + sMeta = smlBuildSTableMeta(info->dataFormat); + STableMeta * pTableMeta = smlGetMeta(info, elements->measure, elements->measureLen); + sMeta->tableMeta = pTableMeta; + if(pTableMeta == NULL){ + info->dataFormat = false; + info->reRun = true; + return TSDB_CODE_SUCCESS; + } + nodeListSet(&info->superTables, elements->measure, elements->measureLen, sMeta, NULL); + } + info->currSTableMeta = sMeta->tableMeta; + superKV = sMeta->tags; + + if(unlikely(taosArrayGetSize(superKV) == 0)){ + isSuperKVInit = false; + } + taosArraySetSize(maxKVs, 0); + } + }else{ + taosArraySetSize(maxKVs, 0); + } + taosArraySetSize(preLineKV, 0); + + int32_t tagNum = cJSON_GetArraySize(tags); + if(unlikely(tagNum == 0)){ + uError("SML:Tag should not be empty"); + return TSDB_CODE_TSC_INVALID_JSON; + } + for (int32_t i = 0; i < tagNum; ++i) { + cJSON *tag = cJSON_GetArrayItem(tags, i); + if (unlikely(tag == NULL)) { + return TSDB_CODE_TSC_INVALID_JSON; + } +// if(unlikely(tag == cMeasure)) continue; + size_t keyLen = strlen(tag->string); + if (unlikely(IS_INVALID_COL_LEN(keyLen))) { + uError("OTD:Tag key length is 0 or too large than 64"); + return TSDB_CODE_TSC_INVALID_COLUMN_LENGTH; + } + + // add kv to SSmlKv + SSmlKv kv ={.key = tag->string, .keyLen = keyLen}; + // value + ret = smlParseValueFromJSON(tag, &kv); + if (unlikely(ret != TSDB_CODE_SUCCESS)) { + return ret; + } + + if(info->dataFormat){ + if(unlikely(cnt + 1 > info->currSTableMeta->tableInfo.numOfTags)){ + info->dataFormat = false; + info->reRun = true; + return TSDB_CODE_SUCCESS; + } + + if(isSameMeasure){ + if(unlikely(cnt >= taosArrayGetSize(maxKVs))) { + info->dataFormat = false; + info->reRun = true; + return TSDB_CODE_SUCCESS; + } + SSmlKv *maxKV = (SSmlKv *)taosArrayGet(maxKVs, cnt); + if(unlikely(kv.length > maxKV->length)){ + maxKV->length = kv.length; + SSmlSTableMeta *tableMeta = (SSmlSTableMeta *)nodeListGet(info->superTables, elements->measure, elements->measureLen, NULL); + ASSERT(tableMeta != NULL); + + SSmlKv *oldKV = (SSmlKv *)taosArrayGet(tableMeta->tags, cnt); + oldKV->length = kv.length; + info->needModifySchema = true; + } + if(unlikely(!IS_SAME_KEY)){ + info->dataFormat = false; + info->reRun = true; + return TSDB_CODE_SUCCESS; + } + }else{ + if(isSuperKVInit){ + if(unlikely(cnt >= taosArrayGetSize(superKV))) { + info->dataFormat = false; + info->reRun = true; + return TSDB_CODE_SUCCESS; + } + SSmlKv *maxKV = (SSmlKv *)taosArrayGet(superKV, cnt); + if(unlikely(kv.length > maxKV->length)) { + maxKV->length = kv.length; + }else{ + kv.length = maxKV->length; + } + info->needModifySchema = true; + + if(unlikely(!IS_SAME_KEY)){ + info->dataFormat = false; + info->reRun = true; + return TSDB_CODE_SUCCESS; + } + }else{ + taosArrayPush(superKV, &kv); + } + taosArrayPush(maxKVs, &kv); + } + }else{ + taosArrayPush(maxKVs, &kv); + } + taosArrayPush(preLineKV, &kv); + cnt++; + } + + SSmlTableInfo *tinfo = (SSmlTableInfo *)nodeListGet(info->childTables, elements, POINTER_BYTES, is_same_child_table_telnet); + if (unlikely(tinfo == NULL)) { + tinfo = smlBuildTableInfo(1, elements->measure, elements->measureLen); + if (unlikely(!tinfo)) { + return TSDB_CODE_OUT_OF_MEMORY; + } + tinfo->tags = taosArrayDup(preLineKV, NULL); + + smlSetCTableName(tinfo); + if (info->dataFormat) { + info->currSTableMeta->uid = tinfo->uid; + tinfo->tableDataCtx = smlInitTableDataCtx(info->pQuery, info->currSTableMeta); + if (tinfo->tableDataCtx == NULL) { + smlBuildInvalidDataMsg(&info->msgBuf, "smlInitTableDataCtx error", NULL); + return TSDB_CODE_SML_INVALID_DATA; + } + } + + SSmlLineInfo *key = (SSmlLineInfo *)taosMemoryMalloc(sizeof(SSmlLineInfo)); + *key = *elements; + if(info->parseJsonByLib){ + key->tags = taosMemoryMalloc(elements->tagsLen + 1); + memcpy(key->tags, elements->tags, elements->tagsLen); + key->tags[elements->tagsLen] = 0; + } + tinfo->key = key; + nodeListSet(&info->childTables, key, POINTER_BYTES, tinfo, is_same_child_table_telnet); + } + if (info->dataFormat) info->currTableDataCtx = tinfo->tableDataCtx; + + return ret; +} + +static int64_t smlParseTSFromJSONObj(SSmlHandle *info, cJSON *root, int32_t toPrecision) { + int32_t size = cJSON_GetArraySize(root); + if (unlikely(size != OTD_JSON_SUB_FIELDS_NUM)) { + smlBuildInvalidDataMsg(&info->msgBuf, "invalidate json", NULL); + return -1; + } + + cJSON *value = cJSON_GetObjectItem(root, "value"); + if (unlikely(!cJSON_IsNumber(value))) { + smlBuildInvalidDataMsg(&info->msgBuf, "invalidate json", NULL); + return -1; + } + + cJSON *type = cJSON_GetObjectItem(root, "type"); + if (unlikely(!cJSON_IsString(type))) { + smlBuildInvalidDataMsg(&info->msgBuf, "invalidate json", NULL); + return -1; + } + + double timeDouble = value->valuedouble; + if (unlikely(smlDoubleToInt64OverFlow(timeDouble))) { + smlBuildInvalidDataMsg(&info->msgBuf, "timestamp is too large", NULL); + return -1; + } + + if (timeDouble == 0) { + return taosGetTimestampNs()/smlFactorNS[toPrecision]; + } + + if (timeDouble < 0) { + return timeDouble; + } + + int64_t tsInt64 = timeDouble; + size_t typeLen = strlen(type->valuestring); + if (typeLen == 1 && (type->valuestring[0] == 's' || type->valuestring[0] == 'S')) { + // seconds + int8_t fromPrecision = TSDB_TIME_PRECISION_SECONDS; + if(smlFactorS[toPrecision] < INT64_MAX / tsInt64){ + return tsInt64 * smlFactorS[toPrecision]; + } + return -1; + } else if (typeLen == 2 && (type->valuestring[1] == 's' || type->valuestring[1] == 'S')) { + switch (type->valuestring[0]) { + case 'm': + case 'M': + // milliseconds + return convertTimePrecision(tsInt64, TSDB_TIME_PRECISION_MILLI, toPrecision); + break; + case 'u': + case 'U': + // microseconds + return convertTimePrecision(tsInt64, TSDB_TIME_PRECISION_MICRO, toPrecision); + break; + case 'n': + case 'N': + return convertTimePrecision(tsInt64, TSDB_TIME_PRECISION_NANO, toPrecision); + break; + default: + return -1; + } + } else { + return -1; + } +} + +uint8_t smlGetTimestampLen(int64_t num) { + uint8_t len = 0; + while ((num /= 10) != 0) { + len++; + } + len++; + return len; +} + +static int64_t smlParseTSFromJSON(SSmlHandle *info, cJSON *timestamp) { + // Timestamp must be the first KV to parse + int32_t toPrecision = info->currSTableMeta ? info->currSTableMeta->tableInfo.precision : TSDB_TIME_PRECISION_NANO; + if (cJSON_IsNumber(timestamp)) { + // timestamp value 0 indicates current system time + double timeDouble = timestamp->valuedouble; + if (unlikely(smlDoubleToInt64OverFlow(timeDouble))) { + smlBuildInvalidDataMsg(&info->msgBuf, "timestamp is too large", NULL); + return -1; + } + + if (unlikely(timeDouble < 0)) { + smlBuildInvalidDataMsg(&info->msgBuf, + "timestamp is negative", NULL); + return timeDouble; + }else if (unlikely(timeDouble == 0)) { + return taosGetTimestampNs()/smlFactorNS[toPrecision]; + } + + uint8_t tsLen = smlGetTimestampLen((int64_t)timeDouble); + + int8_t fromPrecision = smlGetTsTypeByLen(tsLen); + if (unlikely(fromPrecision == -1)) { + smlBuildInvalidDataMsg(&info->msgBuf, + "timestamp precision can only be seconds(10 digits) or milli seconds(13 digits)", NULL); + return -1; + } + int64_t tsInt64 = timeDouble; + if(fromPrecision == TSDB_TIME_PRECISION_SECONDS){ + if(smlFactorS[toPrecision] < INT64_MAX / tsInt64){ + return tsInt64 * smlFactorS[toPrecision]; + } + return -1; + }else{ + return convertTimePrecision(timeDouble, fromPrecision, toPrecision); + } + } else if (cJSON_IsObject(timestamp)) { + return smlParseTSFromJSONObj(info, timestamp, toPrecision); + } else { + smlBuildInvalidDataMsg(&info->msgBuf, + "invalidate json", NULL); + return -1; + } +} + +static int32_t smlParseJSONStringExt(SSmlHandle *info, cJSON *root, SSmlLineInfo *elements) { + int32_t ret = TSDB_CODE_SUCCESS; + + cJSON *metricJson = NULL; + cJSON *tsJson = NULL; + cJSON *valueJson = NULL; + cJSON *tagsJson = NULL; + char* rootStr = cJSON_PrintUnformatted(root); + uError("rootStr:%s", rootStr); + taosMemoryFree(rootStr); + + int32_t size = cJSON_GetArraySize(root); + // outmost json fields has to be exactly 4 + if (size != OTD_JSON_FIELDS_NUM) { + uError("OTD:0x%" PRIx64 " Invalid number of JSON fields in data point %d", info->id, size); + return TSDB_CODE_TSC_INVALID_JSON; + } + + cJSON **marks[OTD_JSON_FIELDS_NUM] = {&metricJson, &tsJson, &valueJson, &tagsJson}; + ret = smlGetJsonElements(root, marks); + if (unlikely(ret != TSDB_CODE_SUCCESS)) { + return ret; + } + + // Parse metric + ret = smlParseMetricFromJSON(info, metricJson, elements); + if (unlikely(ret != TSDB_CODE_SUCCESS)) { + uError("OTD:0x%" PRIx64 " Unable to parse metric from JSON payload", info->id); + return ret; + } + + // Parse metric value + SSmlKv kv = {.key = VALUE, .keyLen = VALUE_LEN}; + ret = smlParseValueFromJSON(valueJson, &kv); + if (unlikely(ret)) { + uError("OTD:0x%" PRIx64 " Unable to parse metric value from JSON payload", info->id); + return ret; + } + + // Parse tags + elements->tags = cJSON_PrintUnformatted(tagsJson); + elements->tagsLen = strlen(elements->tags); + if(is_same_child_table_telnet(elements, &info->preLine) != 0) { + ret = smlParseTagsFromJSON(info, tagsJson, elements); + if (unlikely(ret)) { + uError("OTD:0x%" PRIx64 " Unable to parse tags from JSON payload", info->id); + taosMemoryFree(elements->tags); + elements->tags = NULL; + return ret; + } + } + + if(info->dataFormat){ + taosMemoryFree(elements->tags); + elements->tags = NULL; + } + + if(unlikely(info->reRun)){ + return TSDB_CODE_SUCCESS; + } + + // Parse timestamp + // notice!!! put ts back to tag to ensure get meta->precision + int64_t ts = smlParseTSFromJSON(info, tsJson); + if (unlikely(ts < 0)) { + uError("OTD:0x%" PRIx64 " Unable to parse timestamp from JSON payload", info->id); + return TSDB_CODE_INVALID_TIMESTAMP; + } + SSmlKv kvTs = { .key = TS, .keyLen = TS_LEN, .type = TSDB_DATA_TYPE_TIMESTAMP, .i = ts, .length = (size_t)tDataTypes[TSDB_DATA_TYPE_TIMESTAMP].bytes}; + + if(info->dataFormat){ + ret = smlBuildCol(info->currTableDataCtx, info->currSTableMeta->schema, &kvTs, 0); + if(ret == TSDB_CODE_SUCCESS){ + ret = smlBuildCol(info->currTableDataCtx, info->currSTableMeta->schema, &kv, 1); + } + if(ret == TSDB_CODE_SUCCESS){ + ret = smlBuildRow(info->currTableDataCtx); + } + if (unlikely(ret != TSDB_CODE_SUCCESS)) { + smlBuildInvalidDataMsg(&info->msgBuf, "smlBuildCol error", NULL); + return ret; + } + }else{ + if(elements->colArray == NULL){ + elements->colArray = taosArrayInit(16, sizeof(SSmlKv)); + } + taosArrayPush(elements->colArray, &kvTs); + taosArrayPush(elements->colArray, &kv); + } + info->preLine = *elements; + + return TSDB_CODE_SUCCESS; +} + +static int32_t smlParseJSONExt(SSmlHandle *info, char *payload) { + int32_t payloadNum = 0; + int32_t ret = TSDB_CODE_SUCCESS; + + if (unlikely(payload == NULL)) { + uError("SML:0x%" PRIx64 " empty JSON Payload", info->id); + return TSDB_CODE_TSC_INVALID_JSON; + } + + info->root = cJSON_Parse(payload); + if (unlikely(info->root == NULL)) { + uError("SML:0x%" PRIx64 " parse json failed:%s", info->id, payload); + return TSDB_CODE_TSC_INVALID_JSON; + } + + // multiple data points must be sent in JSON array + if (cJSON_IsArray(info->root)) { + payloadNum = cJSON_GetArraySize(info->root); + } else if (cJSON_IsObject(info->root)) { + payloadNum = 1; + } else { + uError("SML:0x%" PRIx64 " Invalid JSON Payload 3:%s", info->id, payload); + return TSDB_CODE_TSC_INVALID_JSON; + } + + info->lineNum = payloadNum; + info->dataFormat = true; + if (unlikely(info->lines != NULL)) { + taosMemoryFree(info->lines); + info->lines = NULL; + } + ret = smlClearForRerun(info); + if(ret != TSDB_CODE_SUCCESS){ + return ret; + } + + info->parseJsonByLib = true; + cJSON *head = (payloadNum == 1 && cJSON_IsObject(info->root)) ? info->root : info->root->child; + + int cnt = 0; + cJSON *dataPoint = head; + while (dataPoint) { + if(info->dataFormat) { + SSmlLineInfo element = {0}; + ret = smlParseJSONStringExt(info, dataPoint, &element); + }else{ + ret = smlParseJSONStringExt(info, dataPoint, info->lines + cnt); + } + if (unlikely(ret != TSDB_CODE_SUCCESS)) { + uError("SML:0x%" PRIx64 " Invalid JSON Payload 2:%s", info->id, payload); + return ret; + } + + if(unlikely(info->reRun)){ + cnt = 0; + dataPoint = head; + info->lineNum = payloadNum; + ret = smlClearForRerun(info); + if(ret != TSDB_CODE_SUCCESS){ + return ret; + } + continue; + } + cnt++; + dataPoint = dataPoint->next; + } + + return TSDB_CODE_SUCCESS; } static int32_t smlParseJSONString(SSmlHandle *info, char **start, SSmlLineInfo *elements) { int32_t ret = TSDB_CODE_SUCCESS; if(info->offset[0] == 0){ - smlJsonParseObjFirst(start, elements, info->offset); + ret = smlJsonParseObjFirst(start, elements, info->offset); }else{ - smlJsonParseObj(start, elements, info->offset); + ret = smlJsonParseObj(start, elements, info->offset); } - if(**start == '\0') return TSDB_CODE_SUCCESS; + + if (ret != TSDB_CODE_SUCCESS) { + return TSDB_CODE_TSC_INVALID_VALUE; + } + + if(unlikely(**start == '\0' && elements->measure == NULL)) return TSDB_CODE_SUCCESS; SSmlKv kv = {.key = VALUE, .keyLen = VALUE_LEN, .value = elements->cols, .length = (size_t)elements->colsLen}; - if (smlParseNumber(&kv, &info->msgBuf)) { - kv.length = (int16_t)tDataTypes[kv.type].bytes; - }else{ + if (elements->colsLen == 0 || smlParseValue(&kv, &info->msgBuf) != TSDB_CODE_SUCCESS) { + uError("SML:cols invalidate:%s", elements->cols); return TSDB_CODE_TSC_INVALID_VALUE; } // Parse tags - ret = smlParseTagsFromJSON(info, elements); - if (unlikely(ret)) { - uError("OTD:0x%" PRIx64 " Unable to parse tags from JSON payload", info->id); - return ret; + if(is_same_child_table_telnet(elements, &info->preLine) != 0){ + char tmp = *(elements->tags + elements->tagsLen); + *(elements->tags + elements->tagsLen) = 0; + cJSON* tagsJson = cJSON_Parse(elements->tags); + *(elements->tags + elements->tagsLen) = tmp; + if (unlikely(tagsJson == NULL)) { + uError("SML:0x%" PRIx64 " parse json failed:%s", info->id, elements->tags); + return TSDB_CODE_TSC_INVALID_JSON; + } + + ret = smlParseTagsFromJSON(info, tagsJson, elements); + cJSON_free(tagsJson); + if (unlikely(ret)) { + uError("OTD:0x%" PRIx64 " Unable to parse tags from JSON payload", info->id); + return ret; + } } if(unlikely(info->reRun)){ @@ -460,6 +1161,7 @@ int32_t smlParseJSON(SSmlHandle *info, char *payload) { int32_t payloadNum = 1 << 15; int32_t ret = TSDB_CODE_SUCCESS; + uDebug("SML:0x%" PRIx64 "json:%s", info->id, payload); int cnt = 0; char *dataPointStart = payload; while (1) { @@ -472,17 +1174,16 @@ int32_t smlParseJSON(SSmlHandle *info, char *payload) { void* tmp = taosMemoryRealloc(info->lines, payloadNum * sizeof(SSmlLineInfo)); if(tmp != NULL){ info->lines = (SSmlLineInfo*)tmp; + memset(info->lines + cnt, 0, (payloadNum - cnt) * sizeof(SSmlLineInfo)); } } ret = smlParseJSONString(info, &dataPointStart, info->lines + cnt); } if (unlikely(ret != TSDB_CODE_SUCCESS)) { - uError("SML:0x%" PRIx64 " Invalid JSON Payload", info->id); - return ret; + uError("SML:0x%" PRIx64 " Invalid JSON Payload 1:%s", info->id, payload); + return smlParseJSONExt(info, payload); } - if(*dataPointStart == '\0') break; - if(unlikely(info->reRun)){ cnt = 0; dataPointStart = payload; @@ -493,6 +1194,8 @@ int32_t smlParseJSON(SSmlHandle *info, char *payload) { } continue; } + + if(*dataPointStart == '\0') break; cnt++; } info->lineNum = cnt; diff --git a/source/client/src/clientSmlLine.c b/source/client/src/clientSmlLine.c index f56ad34fc5..d93fdf198f 100644 --- a/source/client/src/clientSmlLine.c +++ b/source/client/src/clientSmlLine.c @@ -57,52 +57,6 @@ uint8_t smlPrecisionConvert[7] = {TSDB_TIME_PRECISION_NANO, TSDB_TIME_PRECISION_ TSDB_TIME_PRECISION_SECONDS, TSDB_TIME_PRECISION_MILLI, TSDB_TIME_PRECISION_MICRO, TSDB_TIME_PRECISION_NANO}; -static bool smlParseBool(SSmlKv *kvVal) { - const char *pVal = kvVal->value; - int32_t len = kvVal->length; - if ((len == 1) && (pVal[0] == 't' || pVal[0] == 'T')) { - kvVal->i = TSDB_TRUE; - return true; - } - - if ((len == 1) && (pVal[0] == 'f' || pVal[0] == 'F')) { - kvVal->i = TSDB_FALSE; - return true; - } - - if ((len == 4) && !strncasecmp(pVal, "true", len)) { - kvVal->i = TSDB_TRUE; - return true; - } - if ((len == 5) && !strncasecmp(pVal, "false", len)) { - kvVal->i = TSDB_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[1] == '"' && pVal[len - 1] == '"' && (pVal[0] == 'l' || pVal[0] == 'L')) { - return true; - } - return false; -} - static int64_t smlParseInfluxTime(SSmlHandle *info, const char *data, int32_t len) { uint8_t toPrecision = info->currSTableMeta ? info->currSTableMeta->tableInfo.precision : TSDB_TIME_PRECISION_NANO; @@ -189,6 +143,7 @@ static int32_t smlParseTagKv(SSmlHandle *info, char **sql, char *sqlEnd, int cnt = 0; SArray *preLineKV = info->preLineTagKV; + SArray *maxKVs = info->maxTagKVs; bool isSuperKVInit = true; SArray *superKV = NULL; if(info->dataFormat){ @@ -212,12 +167,12 @@ static int32_t smlParseTagKv(SSmlHandle *info, char **sql, char *sqlEnd, if(unlikely(taosArrayGetSize(superKV) == 0)){ isSuperKVInit = false; } - taosArraySetSize(preLineKV, 0); + taosArraySetSize(maxKVs, 0); } }else{ - taosArraySetSize(preLineKV, 0); + taosArraySetSize(maxKVs, 0); } - + taosArraySetSize(preLineKV, 0); while (*sql < sqlEnd) { if (unlikely(IS_SPACE(*sql))) { @@ -295,14 +250,14 @@ static int32_t smlParseTagKv(SSmlHandle *info, char **sql, char *sqlEnd, } if(isSameMeasure){ - if(unlikely(cnt >= taosArrayGetSize(preLineKV))) { + if(unlikely(cnt >= taosArrayGetSize(maxKVs))) { info->dataFormat = false; info->reRun = true; return TSDB_CODE_SUCCESS; } - SSmlKv *preKV = (SSmlKv *)taosArrayGet(preLineKV, cnt); - if(unlikely(kv.length > preKV->length)){ - preKV->length = kv.length; + SSmlKv *maxKV = (SSmlKv *)taosArrayGet(maxKVs, cnt); + if(unlikely(kv.length > maxKV->length)){ + maxKV->length = kv.length; SSmlSTableMeta *tableMeta = (SSmlSTableMeta *)nodeListGet(info->superTables, currElement->measure, currElement->measureLen, NULL); ASSERT(tableMeta != NULL); @@ -322,11 +277,11 @@ static int32_t smlParseTagKv(SSmlHandle *info, char **sql, char *sqlEnd, info->reRun = true; return TSDB_CODE_SUCCESS; } - SSmlKv *preKV = (SSmlKv *)taosArrayGet(superKV, cnt); - if(unlikely(kv.length > preKV->length)) { - preKV->length = kv.length; + SSmlKv *maxKV = (SSmlKv *)taosArrayGet(superKV, cnt); + if(unlikely(kv.length > maxKV->length)) { + maxKV->length = kv.length; }else{ - kv.length = preKV->length; + kv.length = maxKV->length; } info->needModifySchema = true; @@ -338,11 +293,12 @@ static int32_t smlParseTagKv(SSmlHandle *info, char **sql, char *sqlEnd, }else{ taosArrayPush(superKV, &kv); } - taosArrayPush(preLineKV, &kv); + taosArrayPush(maxKVs, &kv); } }else{ - taosArrayPush(preLineKV, &kv); + taosArrayPush(maxKVs, &kv); } + taosArrayPush(preLineKV, &kv); cnt++; if(IS_SPACE(*sql)){ @@ -518,15 +474,15 @@ static int32_t smlParseColKv(SSmlHandle *info, char **sql, char *sqlEnd, info->reRun = true; return TSDB_CODE_SUCCESS; } - SSmlKv *preKV = (SSmlKv *)taosArrayGet(preLineKV, cnt); - if(kv.type != preKV->type){ + SSmlKv *maxKV = (SSmlKv *)taosArrayGet(preLineKV, cnt); + if(kv.type != maxKV->type){ info->dataFormat = false; info->reRun = true; return TSDB_CODE_SUCCESS; } - if(unlikely(IS_VAR_DATA_TYPE(kv.type) && kv.length > preKV->length)){ - preKV->length = kv.length; + if(unlikely(IS_VAR_DATA_TYPE(kv.type) && kv.length > maxKV->length)){ + maxKV->length = kv.length; SSmlSTableMeta *tableMeta = (SSmlSTableMeta *)nodeListGet(info->superTables, currElement->measure, currElement->measureLen, NULL); ASSERT(tableMeta != NULL); @@ -546,18 +502,18 @@ static int32_t smlParseColKv(SSmlHandle *info, char **sql, char *sqlEnd, info->reRun = true; return TSDB_CODE_SUCCESS; } - SSmlKv *preKV = (SSmlKv *)taosArrayGet(superKV, cnt); - if(unlikely(kv.type != preKV->type)){ + SSmlKv *maxKV = (SSmlKv *)taosArrayGet(superKV, cnt); + if(unlikely(kv.type != maxKV->type)){ info->dataFormat = false; info->reRun = true; return TSDB_CODE_SUCCESS; } if(IS_VAR_DATA_TYPE(kv.type)){ - if(kv.length > preKV->length) { - preKV->length = kv.length; + if(kv.length > maxKV->length) { + maxKV->length = kv.length; }else{ - kv.length = preKV->length; + kv.length = maxKV->length; } info->needModifySchema = true; } diff --git a/source/client/src/clientSmlTelnet.c b/source/client/src/clientSmlTelnet.c index 53a7e3e81e..71d4e21400 100644 --- a/source/client/src/clientSmlTelnet.c +++ b/source/client/src/clientSmlTelnet.c @@ -23,6 +23,11 @@ int32_t is_same_child_table_telnet(const void *a, const void *b){ SSmlLineInfo *t1 = (SSmlLineInfo *)a; SSmlLineInfo *t2 = (SSmlLineInfo *)b; +// uError("is_same_child_table_telnet len:%d,%d %s,%s @@@ len:%d,%d %s,%s", t1->measureLen, t2->measureLen, +// t1->measure, t2->measure, t1->tagsLen, t2->tagsLen, t1->tags, t2->tags); + if(t1 == NULL || t2 == NULL || t1->measure == NULL || t2->measure == NULL + || t1->tags == NULL || t2->tags == NULL) + return 1; return (((t1->measureLen == t2->measureLen) && memcmp(t1->measure, t2->measure, t1->measureLen) == 0) && ((t1->tagsLen == t2->tagsLen) && memcmp(t1->tags, t2->tags, t1->tagsLen) == 0)) ? 0 : 1; } @@ -73,6 +78,7 @@ static int32_t smlParseTelnetTags(SSmlHandle *info, char *data, char *sqlEnd, SS int cnt = 0; SArray *preLineKV = info->preLineTagKV; + SArray *maxKVs = info->maxTagKVs; bool isSuperKVInit = true; SArray *superKV = NULL; if(info->dataFormat){ @@ -96,12 +102,13 @@ static int32_t smlParseTelnetTags(SSmlHandle *info, char *data, char *sqlEnd, SS if(unlikely(taosArrayGetSize(superKV) == 0)){ isSuperKVInit = false; } - taosArraySetSize(preLineKV, 0); + taosArraySetSize(maxKVs, 0); } }else{ - taosArraySetSize(preLineKV, 0); + taosArraySetSize(maxKVs, 0); } + taosArraySetSize(preLineKV, 0); const char *sql = data; while (sql < sqlEnd) { JUMP_SPACE(sql, sqlEnd) @@ -168,14 +175,14 @@ static int32_t smlParseTelnetTags(SSmlHandle *info, char *data, char *sqlEnd, SS } if(isSameMeasure){ - if(unlikely(cnt >= taosArrayGetSize(preLineKV))) { + if(unlikely(cnt >= taosArrayGetSize(maxKVs))) { info->dataFormat = false; info->reRun = true; return TSDB_CODE_SUCCESS; } - SSmlKv *preKV = (SSmlKv *)taosArrayGet(preLineKV, cnt); - if(unlikely(kv.length > preKV->length)){ - preKV->length = kv.length; + SSmlKv *maxKV = (SSmlKv *)taosArrayGet(maxKVs, cnt); + if(unlikely(kv.length > maxKV->length)){ + maxKV->length = kv.length; SSmlSTableMeta *tableMeta = (SSmlSTableMeta *)nodeListGet(info->superTables, elements->measure, elements->measureLen, NULL); ASSERT(tableMeta != NULL); @@ -195,11 +202,11 @@ static int32_t smlParseTelnetTags(SSmlHandle *info, char *data, char *sqlEnd, SS info->reRun = true; return TSDB_CODE_SUCCESS; } - SSmlKv *preKV = (SSmlKv *)taosArrayGet(superKV, cnt); - if(unlikely(kv.length > preKV->length)) { - preKV->length = kv.length; + SSmlKv *maxKV = (SSmlKv *)taosArrayGet(superKV, cnt); + if(unlikely(kv.length > maxKV->length)) { + maxKV->length = kv.length; }else{ - kv.length = preKV->length; + kv.length = maxKV->length; } info->needModifySchema = true; @@ -211,11 +218,12 @@ static int32_t smlParseTelnetTags(SSmlHandle *info, char *data, char *sqlEnd, SS }else{ taosArrayPush(superKV, &kv); } - taosArrayPush(preLineKV, &kv); + taosArrayPush(maxKVs, &kv); } }else{ - taosArrayPush(preLineKV, &kv); + taosArrayPush(maxKVs, &kv); } + taosArrayPush(preLineKV, &kv); cnt++; } SSmlTableInfo *tinfo = (SSmlTableInfo *)nodeListGet(info->childTables, elements, POINTER_BYTES, is_same_child_table_telnet); diff --git a/source/client/test/smlTest.cpp b/source/client/test/smlTest.cpp index d608447506..76911e229a 100644 --- a/source/client/test/smlTest.cpp +++ b/source/client/test/smlTest.cpp @@ -411,28 +411,28 @@ TEST(testCase, smlParseCols_Test) { smlDestroyInfo(info); } -//TEST(testCase, smlGetTimestampLen_Test) { -// uint8_t len = smlGetTimestampLen(0); -// ASSERT_EQ(len, 1); -// -// len = smlGetTimestampLen(1); -// ASSERT_EQ(len, 1); -// -// len = smlGetTimestampLen(10); -// ASSERT_EQ(len, 2); -// -// len = smlGetTimestampLen(390); -// ASSERT_EQ(len, 3); -// -// len = smlGetTimestampLen(-1); -// ASSERT_EQ(len, 1); -// -// len = smlGetTimestampLen(-10); -// ASSERT_EQ(len, 2); -// -// len = smlGetTimestampLen(-390); -// ASSERT_EQ(len, 3); -//} +TEST(testCase, smlGetTimestampLen_Test) { + uint8_t len = smlGetTimestampLen(0); + ASSERT_EQ(len, 1); + + len = smlGetTimestampLen(1); + ASSERT_EQ(len, 1); + + len = smlGetTimestampLen(10); + ASSERT_EQ(len, 2); + + len = smlGetTimestampLen(390); + ASSERT_EQ(len, 3); + + len = smlGetTimestampLen(-1); + ASSERT_EQ(len, 1); + + len = smlGetTimestampLen(-10); + ASSERT_EQ(len, 2); + + len = smlGetTimestampLen(-390); + ASSERT_EQ(len, 3); +} TEST(testCase, smlParseNumber_Test) { SSmlKv kv = {0}; @@ -503,35 +503,35 @@ TEST(testCase, smlParseTelnetLine_Test) { smlDestroyInfo(info); } -TEST(testCase, smlParseTelnetLine_diff_json_type2_Test) { - SSmlHandle *info = smlBuildSmlInfo(NULL); - info->protocol = TSDB_SML_JSON_PROTOCOL; - ASSERT_NE(info, nullptr); - - const char *sql[] = { - "[{\"metric\":\"sys.cpu.nice\",\"timestamp\": 1346846400,\"value\": 18,\"tags\": {\"host\": \"lga\"}},{\"metric\": \"sys.sdfa\",\"timestamp\": 1346846400,\"value\": \"18\",\"tags\": {\"host\": 8932}},]", - }; - for (int i = 0; i < sizeof(sql) / sizeof(sql[0]); i++) { - char *dataPointStart = (char *)sql[i]; - int8_t offset[4] = {0}; - while (1) { - SSmlLineInfo elements = {0}; - if(offset[0] == 0){ - smlJsonParseObjFirst(&dataPointStart, &elements, offset); - }else{ - smlJsonParseObj(&dataPointStart, &elements, offset); - } - if(*dataPointStart == '\0') break; - - SArray *tags = smlJsonParseTags(elements.tags, elements.tags + elements.tagsLen); - size_t num = taosArrayGetSize(tags); - ASSERT_EQ(num, 1); - - taosArrayDestroy(tags); - } - } - smlDestroyInfo(info); -} +//TEST(testCase, smlParseTelnetLine_diff_json_type2_Test) { +// SSmlHandle *info = smlBuildSmlInfo(NULL); +// info->protocol = TSDB_SML_JSON_PROTOCOL; +// ASSERT_NE(info, nullptr); +// +// const char *sql[] = { +// "[{\"metric\":\"sys.cpu.nice\",\"timestamp\": 1346846400,\"value\": 18,\"tags\": {\"host\": \"lga\"}},{\"metric\": \"sys.sdfa\",\"timestamp\": 1346846400,\"value\": \"18\",\"tags\": {\"host\": 8932}},]", +// }; +// for (int i = 0; i < sizeof(sql) / sizeof(sql[0]); i++) { +// char *dataPointStart = (char *)sql[i]; +// int8_t offset[4] = {0}; +// while (1) { +// SSmlLineInfo elements = {0}; +// if(offset[0] == 0){ +// smlJsonParseObjFirst(&dataPointStart, &elements, offset); +// }else{ +// smlJsonParseObj(&dataPointStart, &elements, offset); +// } +// if(*dataPointStart == '\0') break; +// +// SArray *tags = smlJsonParseTags(elements.tags, elements.tags + elements.tagsLen); +// size_t num = taosArrayGetSize(tags); +// ASSERT_EQ(num, 1); +// +// taosArrayDestroy(tags); +// } +// } +// smlDestroyInfo(info); +//} TEST(testCase, smlParseNumber_performance_Test) { char msg[256] = {0}; diff --git a/source/libs/parser/src/parInsertSml.c b/source/libs/parser/src/parInsertSml.c index b5baa54f77..e613739f26 100644 --- a/source/libs/parser/src/parInsertSml.c +++ b/source/libs/parser/src/parInsertSml.c @@ -189,14 +189,23 @@ int32_t smlBuildCol(STableDataCxt* pTableCxt, SSchema* schema, void* data, int32 SSchema* pColSchema = schema + index; SColVal* pVal = taosArrayGet(pTableCxt->pValues, index); SSmlKv* kv = (SSmlKv*)data; + if(kv->keyLen != strlen(pColSchema->name) || memcmp(kv->key, pColSchema->name, kv->keyLen) != 0){ + ret = TSDB_CODE_SML_INVALID_DATA; + goto end; + } if (kv->type == TSDB_DATA_TYPE_NCHAR) { int32_t len = 0; - char* pUcs4 = taosMemoryCalloc(1, pColSchema->bytes - VARSTR_HEADER_SIZE); + int64_t size = pColSchema->bytes - VARSTR_HEADER_SIZE; + if(size <= 0){ + ret = TSDB_CODE_SML_INVALID_DATA; + goto end; + } + char* pUcs4 = taosMemoryCalloc(1, size); if (NULL == pUcs4) { ret = TSDB_CODE_OUT_OF_MEMORY; goto end; } - if (!taosMbsToUcs4(kv->value, kv->length, (TdUcs4*)pUcs4, pColSchema->bytes - VARSTR_HEADER_SIZE, &len)) { + if (!taosMbsToUcs4(kv->value, kv->length, (TdUcs4*)pUcs4, size, &len)) { if (errno == E2BIG) { ret = TSDB_CODE_PAR_VALUE_TOO_LONG; goto end; diff --git a/tests/parallel_test/cases.task b/tests/parallel_test/cases.task index ac207003b5..f8911d2b29 100644 --- a/tests/parallel_test/cases.task +++ b/tests/parallel_test/cases.task @@ -423,8 +423,8 @@ ,,n,system-test,python3 ./test.py -f 0-others/compatibility.py ,,y,system-test,./pytest.sh python3 ./test.py -f 1-insert/alter_database.py ,,y,system-test,./pytest.sh python3 ./test.py -f 1-insert/influxdb_line_taosc_insert.py -,,y,system-test,./pytest.sh python3 ./test.py -f 1-insert/opentsdb_telnet_line_taosc_insert.py -,,y,system-test,./pytest.sh python3 ./test.py -f 1-insert/opentsdb_json_taosc_insert.py +,,n,system-test,./pytest.sh python3 ./test.py -f 1-insert/opentsdb_telnet_line_taosc_insert.py +,,n,system-test,./pytest.sh python3 ./test.py -f 1-insert/opentsdb_json_taosc_insert.py ,,y,system-test,./pytest.sh python3 ./test.py -f 1-insert/test_stmt_muti_insert_query.py ,,y,system-test,./pytest.sh python3 ./test.py -f 1-insert/test_stmt_set_tbname_tag.py ,,y,system-test,./pytest.sh python3 ./test.py -f 1-insert/alter_stable.py @@ -1037,7 +1037,7 @@ ,,y,system-test,./pytest.sh python3 ./test.py -f 99-TDcase/TD-20582.py #develop test -#,,n,develop-test,python3 ./test.py -f 5-taos-tools/taosbenchmark/auto_create_table_json.py +,,n,develop-test,python3 ./test.py -f 5-taos-tools/taosbenchmark/auto_create_table_json.py ,,n,develop-test,python3 ./test.py -f 5-taos-tools/taosbenchmark/custom_col_tag.py ,,n,develop-test,python3 ./test.py -f 5-taos-tools/taosbenchmark/default_json.py ,,n,develop-test,python3 ./test.py -f 5-taos-tools/taosbenchmark/demo.py @@ -1046,7 +1046,7 @@ ,,n,develop-test,python3 ./test.py -f 5-taos-tools/taosbenchmark/json_tag.py ,,n,develop-test,python3 ./test.py -f 5-taos-tools/taosbenchmark/query_json.py ,,n,develop-test,python3 ./test.py -f 5-taos-tools/taosbenchmark/sample_csv_json.py -#,,n,develop-test,python3 ./test.py -f 5-taos-tools/taosbenchmark/sml_json_alltypes.py +,,n,develop-test,python3 ./test.py -f 5-taos-tools/taosbenchmark/sml_json_alltypes.py ,,n,develop-test,python3 ./test.py -f 5-taos-tools/taosbenchmark/taosdemoTestQueryWithJson.py -R ,,n,develop-test,python3 ./test.py -f 5-taos-tools/taosbenchmark/telnet_tcp.py -R diff --git a/tests/system-test/1-insert/opentsdb_json_taosc_insert.py b/tests/system-test/1-insert/opentsdb_json_taosc_insert.py index 93f3c7410d..5e493eab0a 100644 --- a/tests/system-test/1-insert/opentsdb_json_taosc_insert.py +++ b/tests/system-test/1-insert/opentsdb_json_taosc_insert.py @@ -1432,9 +1432,9 @@ class TDTestCase: self._conn.schemaless_insert([json.dumps(input_json)], TDSmlProtocolType.JSON.value, None) query_sql = 'select * from `rFa$sta`' query_res = tdSql.query(query_sql, True) - tdSql.checkEqual(query_res, [(datetime.datetime(2021, 7, 11, 20, 33, 54), True, 'rFas$ta_1', 'ncharTagValue', 2147483647, 9223372036854775807, 22.123456789, 'binaryTagValue', 32767, 11.12345027923584, False, 127)]) + tdSql.checkEqual(query_res, [(datetime.datetime(2021, 7, 11, 20, 33, 54), True, False, 127, 32767, 2147483647, 9223372036854775807, 11.12345027923584, 22.123456789, 'binaryTagValue', 'ncharTagValue', 'rFas$ta_1')]) col_tag_res = tdSql.getColNameList(query_sql) - tdSql.checkEqual(col_tag_res, ['_ts', '_value', 'id', 't!@#$%^&*()_+[];:<>?,9', 't$3', 't%4', 't&6', 't*7', 't@2', 't^5', 'Tt!0', 'tT@1']) + tdSql.checkEqual(col_tag_res, ['_ts', '_value', 'Tt!0', 'tT@1', 't@2', 't$3', 't%4', 't^5', 't&6', 't*7', 't!@#$%^&*()_+[];:<>?,9', 'id']) tdSql.execute('drop table `rFa$sta`') def pointTransCheckCase(self, value_type="obj"): @@ -1719,7 +1719,6 @@ class TDTestCase: print(err.errno) def runAll(self): - """ for value_type in ["obj", "default"]: self.initCheckCase(value_type) self.symbolsCheckCase(value_type) @@ -1772,7 +1771,7 @@ class TDTestCase: # self.sStbStbDdataDtsMtInsertMultiThreadCheckCase() # self.sStbDtbDdataDtsMtInsertMultiThreadCheckCase() # self.lengthIcreaseCrashCheckCase() - """ + def run(self): print("running {}".format(__file__)) self.createDb() diff --git a/tests/system-test/1-insert/opentsdb_telnet_line_taosc_insert.py b/tests/system-test/1-insert/opentsdb_telnet_line_taosc_insert.py index a17a2d9514..351cf49e3a 100644 --- a/tests/system-test/1-insert/opentsdb_telnet_line_taosc_insert.py +++ b/tests/system-test/1-insert/opentsdb_telnet_line_taosc_insert.py @@ -243,7 +243,7 @@ class TDTestCase: if t_add_tag is not None: sql_seq = f'{stb_name} {ts} {value} t0={t0} t1={t1} t2={t2} t3={t3} t4={t4} t5={t5} t6={t6} t7={t7} t8={t8} t9={t8}' if id_change_tag is not None: - sql_seq = f'{stb_name} {ts} {value} t0={t0} {id}={tb_name} t1={t1} t2={t2} t3={t3} t4={t4} t5={t5} t6={t6} t7={t7} t8={t8}' + sql_seq = f'{stb_name} {ts} {value} {id}={tb_name} t0={t0} t1={t1} t2={t2} t3={t3} t4={t4} t5={t5} t6={t6} t7={t7} t8={t8}' if id_double_tag is not None: sql_seq = f'{stb_name} {ts} {value} {id}=\"{tb_name}_1\" t0={t0} t1={t1} {id}=\"{tb_name}_2\" t2={t2} t3={t3} t4={t4} t5={t5} t6={t6} t7={t7} t8={t8}' if t_add_tag is not None: @@ -1126,9 +1126,9 @@ class TDTestCase: self._conn.schemaless_insert([input_sql], TDSmlProtocolType.TELNET.value, None) query_sql = 'select * from `rFa$sta`' query_res = tdSql.query(query_sql, True) - tdSql.checkEqual(query_res, [(datetime.datetime(2021, 7, 11, 20, 33, 54), 9.223372036854776e+18, '2147483647i32', 'L"ncharTagValue"', '32767i16', '9223372036854775807i64', '22.123456789f64', '"ddzhiksj"', '11.12345f32', 'true', '127Ii8')]) + tdSql.checkEqual(query_res, [(datetime.datetime(2021, 7, 11, 20, 33, 54), 9.223372036854776e+18, 'true', '127Ii8', '32767i16', '2147483647i32', '9223372036854775807i64', '11.12345f32', '22.123456789f64', '"ddzhiksj"', 'L"ncharTagValue"')]) col_tag_res = tdSql.getColNameList(query_sql) - tdSql.checkEqual(col_tag_res, ['_ts', '_value', '"t$3"', 't!@#$%^&*()_+[];:<>?,9', 't#2', 't%4', 't&6', 't*7', 't^5', 'Tt!0', 'tT@1']) + tdSql.checkEqual(col_tag_res, ['_ts', '_value', 'Tt!0', 'tT@1', 't#2', '"t$3"', 't%4', 't^5', 't&6', 't*7', 't!@#$%^&*()_+[];:<>?,9']) tdSql.execute('drop table `rFa$sta`') def tcpKeywordsCheckCase(self, protocol="telnet-tcp"): @@ -1207,7 +1207,6 @@ class TDTestCase: tdLog.info(f'{sys._getframe().f_code.co_name}() function is running') tdCom.cleanTb(dbname="test") input_sql = self.genSqlList()[0] - print(input_sql) self.multiThreadRun(self.genMultiThreadSeq(input_sql)) tdSql.query(f"show tables;") tdSql.checkRows(5) @@ -1416,8 +1415,8 @@ class TDTestCase: self.symbolsCheckCase() self.tsCheckCase() self.openTstbTelnetTsCheckCase() - #self.idSeqCheckCase() - #self.idLetterCheckCase() + # self.idSeqCheckCase() + self.idLetterCheckCase() self.noIdCheckCase() self.maxColTagCheckCase() self.stbTbNameCheckCase() @@ -1450,7 +1449,7 @@ class TDTestCase: self.spellCheckCase() self.pointTransCheckCase() self.defaultTypeCheckCase() - #self.tbnameTagsColsNameCheckCase() + self.tbnameTagsColsNameCheckCase() # # # MultiThreads # self.stbInsertMultiThreadCheckCase() # self.sStbStbDdataInsertMultiThreadCheckCase() diff --git a/tests/system-test/2-query/sml.py b/tests/system-test/2-query/sml.py index 8ad1982b55..d5439d05de 100644 --- a/tests/system-test/2-query/sml.py +++ b/tests/system-test/2-query/sml.py @@ -71,23 +71,26 @@ class TDTestCase: tdSql.checkData(0, 2, "web01") tdSql.query(f"select distinct tbname from {dbname}.`sys.cpu.nice`") - tdSql.checkRows(2) + tdSql.checkRows(3) tdSql.query(f"select * from {dbname}.`sys.cpu.nice` order by _ts") - tdSql.checkRows(2) - tdSql.checkData(0, 1, 9.000000000) - tdSql.checkData(0, 2, "web02") + tdSql.checkRows(4) + tdSql.checkData(0, 1, 13.000000000) + tdSql.checkData(0, 2, "web01") tdSql.checkData(0, 3, None) tdSql.checkData(0, 4, "lga") - tdSql.checkData(1, 1, 18.000000000) - tdSql.checkData(1, 2, "web01") - tdSql.checkData(1, 3, "t1") + tdSql.checkData(1, 1, 9.000000000) + tdSql.checkData(1, 2, "web02") + tdSql.checkData(3, 3, "t1") tdSql.checkData(0, 4, "lga") tdSql.query(f"select * from {dbname}.macylr") tdSql.checkRows(2) + tdSql.query(f"select * from {dbname}.qelhxo") + tdSql.checkRows(5) + tdSql.query(f"desc {dbname}.macylr") tdSql.checkRows(25) return diff --git a/utils/test/c/sml_test.c b/utils/test/c/sml_test.c index 49885c0aea..30d0ab27d8 100644 --- a/utils/test/c/sml_test.c +++ b/utils/test/c/sml_test.c @@ -78,21 +78,23 @@ int smlProcess_telnet_Test() { pRes = taos_query(taos, "use sml_db"); taos_free_result(pRes); - char *sql[4] = {0}; - sql[0] = taosMemoryCalloc(1, 128); - sql[1] = taosMemoryCalloc(1, 128); - sql[2] = taosMemoryCalloc(1, 128); - sql[3] = taosMemoryCalloc(1, 128); +// char *sql[4] = {0}; +// sql[0] = taosMemoryCalloc(1, 128); +// sql[1] = taosMemoryCalloc(1, 128); +// sql[2] = taosMemoryCalloc(1, 128); +// sql[3] = taosMemoryCalloc(1, 128); const char *sql1[] = {"sys.if.bytes.out 1479496100 1.3E0 host=web01 interface=eth0", "sys.if.bytes.out 1479496101 1.3E1 interface=eth0 host=web01 ", "sys.if.bytes.out 1479496102 1.3E3 network=tcp", " sys.procs.running 1479496100 42 host=web01 "}; - for(int i = 0; i < 4; i++){ - strncpy(sql[i], sql1[i], 128); - } +// for(int i = 0; i < 4; i++){ +// strncpy(sql[i], sql1[i], 128); +// } - pRes = taos_schemaless_insert(taos, (char **)sql, sizeof(sql) / sizeof(sql[0]), TSDB_SML_TELNET_PROTOCOL, +// pRes = taos_schemaless_insert(taos, (char **)sql, sizeof(sql) / sizeof(sql[0]), TSDB_SML_TELNET_PROTOCOL, +// TSDB_SML_TIMESTAMP_NANO_SECONDS); + pRes = taos_schemaless_insert(taos, (char **)sql1, sizeof(sql1) / sizeof(sql1[0]), TSDB_SML_TELNET_PROTOCOL, TSDB_SML_TIMESTAMP_NANO_SECONDS); printf("%s result:%s\n", __FUNCTION__, taos_errstr(pRes)); int code = taos_errno(pRes); @@ -112,13 +114,53 @@ int smlProcess_json1_Test() { taos_free_result(pRes); const char *sql[] = { - "[{\"metric\":\"sys.cpu.nice\",\"timestamp\":0,\"value\":18,\"tags\":{\"host\":\"web01\",\"id\":\"t1\",\"dc\":\"lga\"}},{\"metric\":\"sys.cpu.nice\",\"timestamp\":1662344042,\"value\":9,\"tags\":{\"host\":\"web02\",\"dc\":\"lga\"}}]" + "[{\"metric\":\"sys.cpu.nice\",\"timestamp\":0,\"value\":18,\"tags\":{\"host\":\"web01\",\"id\":\"t1\",\"dc\":\"lga\"}},{\"metric\":\"sys.cpu.nice\",\"timestamp\":1662344045,\"value\":9,\"tags\":{\"host\":\"web02\",\"dc\":\"lga\"}}]" }; - pRes = taos_schemaless_insert(taos, (char **)sql, sizeof(sql) / sizeof(sql[0]), TSDB_SML_JSON_PROTOCOL, + + char *sql1[1] = {0}; + for(int i = 0; i < 1; i++){ + sql1[i] = taosMemoryCalloc(1, 1024); + strncpy(sql1[i], sql[i], 1023); + } + + pRes = taos_schemaless_insert(taos, (char **)sql1, sizeof(sql1) / sizeof(sql1[0]), TSDB_SML_JSON_PROTOCOL, TSDB_SML_TIMESTAMP_NANO_SECONDS); - printf("%s result:%s\n", __FUNCTION__, taos_errstr(pRes)); int code = taos_errno(pRes); + if(code != 0){ + printf("%s result:%s\n", __FUNCTION__, taos_errstr(pRes)); + }else{ + printf("%s result:success\n", __FUNCTION__); + } taos_free_result(pRes); + + for(int i = 0; i < 1; i++){ + taosMemoryFree(sql1[i]); + } + + const char *sql2[] = { + "[{\"metric\":\"sys.cpu.nice\",\"timestamp\":1662344041,\"value\":13,\"tags\":{\"host\":\"web01\",\"dc\":\"lga\"}},{\"metric\":\"sys.cpu.nice\",\"timestamp\":1662344042,\"value\":9,\"tags\":{\"host\":\"web02\",\"dc\":\"lga\"}}]", + }; + + char *sql3[1] = {0}; + for(int i = 0; i < 1; i++){ + sql3[i] = taosMemoryCalloc(1, 1024); + strncpy(sql3[i], sql2[i], 1023); + } + + pRes = taos_schemaless_insert(taos, (char **)sql3, sizeof(sql3) / sizeof(sql3[0]), TSDB_SML_JSON_PROTOCOL, + TSDB_SML_TIMESTAMP_NANO_SECONDS); + code = taos_errno(pRes); + if(code != 0){ + printf("%s result:%s\n", __FUNCTION__, taos_errstr(pRes)); + }else{ + printf("%s result:success\n", __FUNCTION__); + } + taos_free_result(pRes); + + for(int i = 0; i < 1; i++){ + taosMemoryFree(sql3[i]); + } + taos_close(taos); return code; @@ -136,13 +178,26 @@ int smlProcess_json2_Test() { const char *sql[] = { "{\"metric\":\"meter_current0\",\"timestamp\":{\"value\":1662344042,\"type\":\"s\"},\"value\":{\"value\":10.3,\"type\":\"i64\"},\"tags\":{\"groupid\":{\"value\":2,\"type\":\"bigint\"},\"location\":{\"value\":\"北京\",\"type\":\"binary\"},\"id\":\"d1001\"}}" }; - pRes = taos_schemaless_insert(taos, (char **)sql, sizeof(sql) / sizeof(sql[0]), TSDB_SML_JSON_PROTOCOL, + char *sql1[1] = {0}; + for(int i = 0; i < 1; i++){ + sql1[i] = taosMemoryCalloc(1, 1024); + strncpy(sql1[i], sql[i], 1023); + } + + pRes = taos_schemaless_insert(taos, (char **)sql1, sizeof(sql1) / sizeof(sql1[0]), TSDB_SML_JSON_PROTOCOL, TSDB_SML_TIMESTAMP_NANO_SECONDS); - printf("%s result:%s\n", __FUNCTION__, taos_errstr(pRes)); int code = taos_errno(pRes); + if(code != 0){ + printf("%s result:%s\n", __FUNCTION__, taos_errstr(pRes)); + }else{ + printf("%s result:success\n", __FUNCTION__); + } taos_free_result(pRes); taos_close(taos); + for(int i = 0; i < 1; i++){ + taosMemoryFree(sql1[i]); + } return code; } @@ -156,15 +211,29 @@ int smlProcess_json3_Test() { taos_free_result(pRes); const char *sql[] = { - "[{\"metric\":\"sys.cpu.nice\",\"timestamp\":0,\"value\":\"18\",\"tags\":{\"host\":\"web01\",\"id\":\"t1\",\"dc\":\"lga\"}}]" +// "[{\"metric\":\"sys.cpu.nice3\",\"timestamp\":0,\"value\":\"18\",\"tags\":{\"host\":\"web01\",\"id\":\"t1\",\"dc\":\"lga\"}}]" + "{\"metric\": \"dcxnmr\", \"timestamp\": {\"value\": 1626006833639000000, \"type\": \"ns\"}, \"value\": {\"value\": false, \"type\": \"bool\"}, \"tags\": {\"t0\": {\"value\": false, \"type\": \"bool\"}, \"t1\": {\"value\": 127, \"type\": \"tinyint\"}, \"t2\": {\"value\": 32767, \"type\": \"smallint\"}, \"t3\": {\"value\": 2147483647, \"type\": \"int\"}, \"t4\": {\"value\": 9223372036854775807, \"type\": \"bigint\"}, \"t5\": {\"value\": 11.12345027923584, \"type\": \"float\"}, \"t6\": {\"value\": 22.123456789, \"type\": \"double\"}, \"t7\": {\"value\": \"binaryTagValue\", \"type\": \"binary\"}, \"t8\": {\"value\": \"abc{aaa\", \"type\": \"nchar\"}}}" }; - pRes = taos_schemaless_insert(taos, (char **)sql, sizeof(sql) / sizeof(sql[0]), TSDB_SML_JSON_PROTOCOL, + char *sql1[1] = {0}; + for(int i = 0; i < 1; i++){ + sql1[i] = taosMemoryCalloc(1, 1024); + strncpy(sql1[i], sql[i], 1023); + } + + pRes = taos_schemaless_insert(taos, (char **)sql1, sizeof(sql1) / sizeof(sql1[0]), TSDB_SML_JSON_PROTOCOL, TSDB_SML_TIMESTAMP_NANO_SECONDS); - printf("%s result:%s\n", __FUNCTION__, taos_errstr(pRes)); int code = taos_errno(pRes); + if(code != 0){ + printf("%s result:%s\n", __FUNCTION__, taos_errstr(pRes)); + }else{ + printf("%s result:success\n", __FUNCTION__); + } taos_free_result(pRes); taos_close(taos); + for(int i = 0; i < 1; i++){ + taosMemoryFree(sql1[i]); + } return code; } @@ -233,7 +302,7 @@ int sml_16384_Test() { if(code) return code; const char *sql1[] = { - "qelhxo,id=pnnqhsa,t0=t,t1=127i8 c0=f,c1=127i8,c11=L\"ncharColValue\",c10=t 1626006833639000000", + "qelhxo,id=pnnqhsa,t0=t,t1=127i8 c0=f,c1=127i8,c11=L\"ncharColValue\",c10=t 1626006833631000000", }; pRes = taos_schemaless_insert(taos, (char **)sql1, 1, TSDB_SML_LINE_PROTOCOL, 0); printf("%s result:%s\n", __FUNCTION__, taos_errstr(pRes)); @@ -797,7 +866,7 @@ int sml_19221_Test() { taos_free_result(pRes); const char *sql[] = { - "qelhxo,id=pnnqhsa,t0=t,t1=127i8 c11=L\"ncharColValue\",c0=t,c1=127i8 1626006833639000000\nqelhxo,id=pnnhsa,t0=t,t1=127i8 c11=L\"ncharColValue\",c0=t,c1=127i8 1626006833639000000\n#comment\nqelhxo,id=pnqhsa,t0=t,t1=127i8 c11=L\"ncharColValue\",c0=t,c1=127i8 1626006833639000000", + "qelhxo,id=pnnqhsa,t0=t,t1=127i8 c11=L\"ncharColValue\",c0=t,c1=127i8 1626006833632000000\nqelhxo,id=pnnhsa,t0=t,t1=127i8 c11=L\"ncharColValue\",c0=t,c1=127i8 1626006833633000000\n#comment\nqelhxo,id=pnqhsa,t0=t,t1=127i8 c11=L\"ncharColValue\",c0=t,c1=127i8 1626006833634000000", }; pRes = taos_query(taos, "use sml_db"); @@ -936,9 +1005,9 @@ int main(int argc, char *argv[]) { ret = smlProcess_json1_Test(); ASSERT(!ret); ret = smlProcess_json2_Test(); - ASSERT(ret); + ASSERT(!ret); ret = smlProcess_json3_Test(); - ASSERT(ret); + ASSERT(!ret); ret = sml_TD15662_Test(); ASSERT(!ret); ret = sml_TD15742_Test();