未验证 提交 ab24035c 编写于 作者: D dapan1121 提交者: GitHub

Merge pull request #7763 from taosdata/fix/TD-6442

[TD-6442]<feature>: Support OpenTSDB telnet style data import format
/*
* Copyright (c) 2021 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TDENGINE_TSCPARSELINE_H
#define TDENGINE_TSCPARSELINE_H
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
char* key;
uint8_t type;
int16_t length;
char* value;
} TAOS_SML_KV;
typedef struct {
char* stableName;
char* childTableName;
TAOS_SML_KV* tags;
int32_t tagNum;
// first kv must be timestamp
TAOS_SML_KV* fields;
int32_t fieldNum;
} TAOS_SML_DATA_POINT;
typedef enum {
SML_TIME_STAMP_NOW,
SML_TIME_STAMP_SECONDS,
SML_TIME_STAMP_MILLI_SECONDS,
SML_TIME_STAMP_MICRO_SECONDS,
SML_TIME_STAMP_NANO_SECONDS
} SMLTimeStampType;
typedef struct {
uint64_t id;
SHashObj* smlDataToSchema;
} SSmlLinesInfo;
int tscSmlInsert(TAOS* taos, TAOS_SML_DATA_POINT* points, int numPoint, SSmlLinesInfo* info);
bool checkDuplicateKey(char *key, SHashObj *pHash, SSmlLinesInfo* info);
int32_t isValidChildTableName(const char *pTbName, int16_t len);
bool convertSmlValueType(TAOS_SML_KV *pVal, char *value,
uint16_t len, SSmlLinesInfo* info);
int32_t convertSmlTimeStamp(TAOS_SML_KV *pVal, char *value,
uint16_t len, SSmlLinesInfo* info);
void destroySmlDataPoint(TAOS_SML_DATA_POINT* point);
#ifdef __cplusplus
}
#endif
#endif // TDENGINE_TSCPARSELINE_H
......@@ -17,6 +17,7 @@
#include "tscLog.h"
#include "taos.h"
#include "tscParseLine.h"
typedef struct {
char sTableName[TSDB_TABLE_NAME_LEN];
......@@ -27,38 +28,6 @@ typedef struct {
uint8_t precision;
} SSmlSTableSchema;
typedef struct {
char* key;
uint8_t type;
int16_t length;
char* value;
} TAOS_SML_KV;
typedef struct {
char* stableName;
char* childTableName;
TAOS_SML_KV* tags;
int32_t tagNum;
// first kv must be timestamp
TAOS_SML_KV* fields;
int32_t fieldNum;
} TAOS_SML_DATA_POINT;
typedef enum {
SML_TIME_STAMP_NOW,
SML_TIME_STAMP_SECONDS,
SML_TIME_STAMP_MILLI_SECONDS,
SML_TIME_STAMP_MICRO_SECONDS,
SML_TIME_STAMP_NANO_SECONDS
} SMLTimeStampType;
typedef struct {
uint64_t id;
SHashObj* smlDataToSchema;
} SSmlLinesInfo;
//=================================================================================================
static uint64_t linesSmlHandleId = 0;
......@@ -1565,8 +1534,8 @@ static bool convertStrToNumber(TAOS_SML_KV *pVal, char*str, SSmlLinesInfo* info)
return true;
}
//len does not include '\0' from value.
static bool convertSmlValueType(TAOS_SML_KV *pVal, char *value,
uint16_t len, SSmlLinesInfo* info) {
bool convertSmlValueType(TAOS_SML_KV *pVal, char *value,
uint16_t len, SSmlLinesInfo* info) {
if (len <= 0) {
return false;
}
......@@ -1708,7 +1677,7 @@ static int32_t getTimeStampValue(char *value, uint16_t len,
if (len >= 2) {
for (int i = 0; i < len - 2; ++i) {
if(!isdigit(value[i])) {
return TSDB_CODE_TSC_LINE_SYNTAX_ERROR;
return TSDB_CODE_TSC_INVALID_TIME_STAMP;
}
}
}
......@@ -1743,20 +1712,20 @@ static int32_t getTimeStampValue(char *value, uint16_t len,
break;
}
default: {
return TSDB_CODE_TSC_LINE_SYNTAX_ERROR;
return TSDB_CODE_TSC_INVALID_TIME_STAMP;
}
}
return TSDB_CODE_SUCCESS;
}
static int32_t convertSmlTimeStamp(TAOS_SML_KV *pVal, char *value,
uint16_t len, SSmlLinesInfo* info) {
int32_t convertSmlTimeStamp(TAOS_SML_KV *pVal, char *value,
uint16_t len, SSmlLinesInfo* info) {
int32_t ret;
SMLTimeStampType type;
int64_t tsVal;
if (!isTimeStamp(value, len, &type)) {
return TSDB_CODE_TSC_LINE_SYNTAX_ERROR;
return TSDB_CODE_TSC_INVALID_TIME_STAMP;
}
ret = getTimeStampValue(value, len, type, &tsVal);
......@@ -1805,7 +1774,7 @@ static int32_t parseSmlTimeStamp(TAOS_SML_KV **pTS, const char **index, SSmlLine
return ret;
}
static bool checkDuplicateKey(char *key, SHashObj *pHash, SSmlLinesInfo* info) {
bool checkDuplicateKey(char *key, SHashObj *pHash, SSmlLinesInfo* info) {
char *val = NULL;
char *cur = key;
char keyLower[TSDB_COL_NAME_LEN];
......@@ -1842,7 +1811,7 @@ static int32_t parseSmlKey(TAOS_SML_KV *pKV, const char **index, SHashObj *pHash
while (*cur != '\0') {
if (len > TSDB_COL_NAME_LEN) {
tscError("SML:0x%"PRIx64" Key field cannot exceeds 65 characters", info->id);
return TSDB_CODE_TSC_LINE_SYNTAX_ERROR;
return TSDB_CODE_TSC_INVALID_COLUMN_LENGTH;
}
//unescaped '=' identifies a tag key
if (*cur == '=' && *(cur - 1) != '\\') {
......@@ -1902,7 +1871,7 @@ static bool parseSmlValue(TAOS_SML_KV *pKV, const char **index,
free(pKV->key);
pKV->key = NULL;
free(value);
return TSDB_CODE_TSC_LINE_SYNTAX_ERROR;
return TSDB_CODE_TSC_INVALID_VALUE;
}
free(value);
......@@ -1931,7 +1900,7 @@ static int32_t parseSmlMeasurement(TAOS_SML_DATA_POINT *pSml, const char **index
tscError("SML:0x%"PRIx64" Measurement field cannot exceeds 193 characters", info->id);
free(pSml->stableName);
pSml->stableName = NULL;
return TSDB_CODE_TSC_LINE_SYNTAX_ERROR;
return TSDB_CODE_TSC_INVALID_TABLE_ID_LENGTH;
}
//first unescaped comma or space identifies measurement
//if space detected first, meaning no tag in the input
......@@ -1958,7 +1927,7 @@ static int32_t parseSmlMeasurement(TAOS_SML_DATA_POINT *pSml, const char **index
}
//Table name can only contain digits(0-9),alphebet(a-z),underscore(_)
static int32_t isValidChildTableName(const char *pTbName, int16_t len) {
int32_t isValidChildTableName(const char *pTbName, int16_t len) {
const char *cur = pTbName;
for (int i = 0; i < len; ++i) {
if(!isdigit(cur[i]) && !isalpha(cur[i]) && (cur[i] != '_')) {
......@@ -2146,14 +2115,14 @@ int32_t tscParseLines(char* lines[], int numLines, SArray* points, SArray* faile
if (code != TSDB_CODE_SUCCESS) {
tscError("SML:0x%"PRIx64" data point line parse failed. line %d : %s", info->id, i, lines[i]);
destroySmlDataPoint(&point);
return TSDB_CODE_TSC_LINE_SYNTAX_ERROR;
return code;
} else {
tscDebug("SML:0x%"PRIx64" data point line parse success. line %d", info->id, i);
}
taosArrayPush(points, &point);
}
return 0;
return TSDB_CODE_SUCCESS;
}
int taos_insert_lines(TAOS* taos, char* lines[], int numLines) {
......
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "hash.h"
#include "taos.h"
#include "tscUtil.h"
#include "tsclient.h"
#include "tscLog.h"
#include "tscParseLine.h"
#define MAX_TELNET_FILEDS_NUM 2
#define OTS_TIMESTAMP_COLUMN_NAME "ts"
#define OTS_METRIC_VALUE_COLUMN_NAME "value"
/* telnet style API parser */
static uint64_t HandleId = 0;
static uint64_t genUID() {
uint64_t id;
do {
id = atomic_add_fetch_64(&HandleId, 1);
} while (id == 0);
return id;
}
static int32_t parseTelnetMetric(TAOS_SML_DATA_POINT *pSml, const char **index, SSmlLinesInfo* info) {
const char *cur = *index;
uint16_t len = 0;
pSml->stableName = tcalloc(TSDB_TABLE_NAME_LEN + 1, 1); // +1 to avoid 1772 line over write
if (pSml->stableName == NULL){
return TSDB_CODE_TSC_OUT_OF_MEMORY;
}
if (isdigit(*cur)) {
tscError("OTD:0x%"PRIx64" Metric cannnot start with digit", info->id);
tfree(pSml->stableName);
return TSDB_CODE_TSC_LINE_SYNTAX_ERROR;
}
while (*cur != '\0') {
if (len > TSDB_TABLE_NAME_LEN) {
tscError("OTD:0x%"PRIx64" Metric cannot exceeds 193 characters", info->id);
tfree(pSml->stableName);
return TSDB_CODE_TSC_INVALID_TABLE_ID_LENGTH;
}
if (*cur == ' ') {
break;
}
pSml->stableName[len] = *cur;
cur++;
len++;
}
if (len == 0 || *cur == '\0') {
tfree(pSml->stableName);
return TSDB_CODE_TSC_LINE_SYNTAX_ERROR;
}
pSml->stableName[len] = '\0';
*index = cur + 1;
tscDebug("OTD:0x%"PRIx64" Stable name in metric:%s|len:%d", info->id, pSml->stableName, len);
return TSDB_CODE_SUCCESS;
}
static int32_t parseTelnetTimeStamp(TAOS_SML_KV **pTS, int *num_kvs, const char **index, SSmlLinesInfo* info) {
//Timestamp must be the first KV to parse
assert(*num_kvs == 0);
const char *start, *cur;
int32_t ret = TSDB_CODE_SUCCESS;
int len = 0;
char key[] = OTS_TIMESTAMP_COLUMN_NAME;
char *value = NULL;
start = cur = *index;
//allocate fields for timestamp and value
*pTS = tcalloc(MAX_TELNET_FILEDS_NUM, sizeof(TAOS_SML_KV));
while(*cur != '\0') {
if (*cur == ' ') {
break;
}
cur++;
len++;
}
if (len > 0 && *cur != '\0') {
value = tcalloc(len + 1, 1);
memcpy(value, start, len);
} else {
tfree(*pTS);
return TSDB_CODE_TSC_LINE_SYNTAX_ERROR;
}
ret = convertSmlTimeStamp(*pTS, value, len, info);
if (ret) {
tfree(value);
tfree(*pTS);
return ret;
}
tfree(value);
(*pTS)->key = tcalloc(sizeof(key), 1);
memcpy((*pTS)->key, key, sizeof(key));
*num_kvs += 1;
*index = cur + 1;
return ret;
}
static int32_t parseTelnetMetricValue(TAOS_SML_KV **pKVs, int *num_kvs, const char **index, SSmlLinesInfo* info) {
//skip timestamp
TAOS_SML_KV *pVal = *pKVs + 1;
const char *start, *cur;
int32_t ret = TSDB_CODE_SUCCESS;
int len = 0;
char key[] = OTS_METRIC_VALUE_COLUMN_NAME;
char *value = NULL;
start = cur = *index;
while(*cur != '\0') {
if (*cur == ' ') {
break;
}
cur++;
len++;
}
if (len > 0 && *cur != '\0') {
value = tcalloc(len + 1, 1);
memcpy(value, start, len);
} else {
return TSDB_CODE_TSC_LINE_SYNTAX_ERROR;
}
if (!convertSmlValueType(pVal, value, len, info)) {
tscError("OTD:0x%"PRIx64" Failed to convert metric value string(%s) to any type",
info->id, value);
tfree(value);
return TSDB_CODE_TSC_INVALID_VALUE;
}
tfree(value);
pVal->key = tcalloc(sizeof(key), 1);
memcpy(pVal->key, key, sizeof(key));
*num_kvs += 1;
*index = cur + 1;
return ret;
}
static int32_t parseTelnetTagKey(TAOS_SML_KV *pKV, const char **index, SHashObj *pHash, SSmlLinesInfo* info) {
const char *cur = *index;
char key[TSDB_COL_NAME_LEN + 1]; // +1 to avoid key[len] over write
uint16_t len = 0;
//key field cannot start with digit
if (isdigit(*cur)) {
tscError("OTD:0x%"PRIx64" Tag key cannnot start with digit", info->id);
return TSDB_CODE_TSC_LINE_SYNTAX_ERROR;
}
while (*cur != '\0') {
if (len > TSDB_COL_NAME_LEN) {
tscError("OTD:0x%"PRIx64" Tag key cannot exceeds 65 characters", info->id);
return TSDB_CODE_TSC_INVALID_COLUMN_LENGTH;
}
if (*cur == '=') {
break;
}
key[len] = *cur;
cur++;
len++;
}
if (len == 0 || *cur == '\0') {
return TSDB_CODE_TSC_LINE_SYNTAX_ERROR;
}
key[len] = '\0';
if (checkDuplicateKey(key, pHash, info)) {
return TSDB_CODE_TSC_DUP_TAG_NAMES;
}
pKV->key = tcalloc(len + 1, 1);
memcpy(pKV->key, key, len + 1);
//tscDebug("OTD:0x%"PRIx64" Key:%s|len:%d", info->id, pKV->key, len);
*index = cur + 1;
return TSDB_CODE_SUCCESS;
}
static int32_t parseTelnetTagValue(TAOS_SML_KV *pKV, const char **index,
bool *is_last_kv, SSmlLinesInfo* info) {
const char *start, *cur;
char *value = NULL;
uint16_t len = 0;
start = cur = *index;
while (1) {
// ',' or '\0' identifies a value
if (*cur == ',' || *cur == '\0') {
// '\0' indicates end of value
*is_last_kv = (*cur == '\0') ? true : false;
break;
}
cur++;
len++;
}
if (len == 0) {
tfree(pKV->key);
return TSDB_CODE_TSC_LINE_SYNTAX_ERROR;
}
value = tcalloc(len + 1, 1);
memcpy(value, start, len);
value[len] = '\0';
if (!convertSmlValueType(pKV, value, len, info)) {
tscError("OTD:0x%"PRIx64" Failed to convert sml value string(%s) to any type",
info->id, value);
//free previous alocated key field
tfree(pKV->key);
tfree(value);
return TSDB_CODE_TSC_INVALID_VALUE;
}
tfree(value);
*index = (*cur == '\0') ? cur : cur + 1;
return TSDB_CODE_SUCCESS;
}
static int32_t parseTelnetTagKvs(TAOS_SML_KV **pKVs, int *num_kvs,
const char **index, char **childTableName,
SHashObj *pHash, SSmlLinesInfo* info) {
const char *cur = *index;
int32_t ret = TSDB_CODE_SUCCESS;
TAOS_SML_KV *pkv;
bool is_last_kv = false;
int32_t capacity = 4;
*pKVs = tcalloc(capacity, sizeof(TAOS_SML_KV));
pkv = *pKVs;
while (*cur != '\0') {
ret = parseTelnetTagKey(pkv, &cur, pHash, info);
if (ret) {
tscError("OTD:0x%"PRIx64" Unable to parse key", info->id);
return ret;
}
ret = parseTelnetTagValue(pkv, &cur, &is_last_kv, info);
if (ret) {
tscError("OTD:0x%"PRIx64" Unable to parse value", info->id);
return ret;
}
if ((strcasecmp(pkv->key, "ID") == 0) && pkv->type == TSDB_DATA_TYPE_BINARY) {
ret = isValidChildTableName(pkv->value, pkv->length);
if (ret) {
return ret;
}
*childTableName = malloc(pkv->length + 1);
memcpy(*childTableName, pkv->value, pkv->length);
(*childTableName)[pkv->length] = '\0';
tfree(pkv->key);
tfree(pkv->value);
} else {
*num_kvs += 1;
}
if (is_last_kv) {
break;
}
//reallocate addtional memory for more kvs
if ((*num_kvs + 1) > capacity) {
TAOS_SML_KV *more_kvs = NULL;
capacity *= 3; capacity /= 2;
more_kvs = realloc(*pKVs, capacity * sizeof(TAOS_SML_KV));
if (!more_kvs) {
return TSDB_CODE_TSC_OUT_OF_MEMORY;
}
*pKVs = more_kvs;
}
//move pKV points to next TAOS_SML_KV block
pkv = *pKVs + *num_kvs;
}
return ret;
}
int32_t tscParseTelnetLine(const char* line, TAOS_SML_DATA_POINT* smlData, SSmlLinesInfo* info) {
const char* index = line;
int32_t ret = TSDB_CODE_SUCCESS;
//Parse metric
ret = parseTelnetMetric(smlData, &index, info);
if (ret) {
tscError("OTD:0x%"PRIx64" Unable to parse metric", info->id);
return ret;
}
tscDebug("OTD:0x%"PRIx64" Parse metric finished", info->id);
//Parse timestamp
ret = parseTelnetTimeStamp(&smlData->fields, &smlData->fieldNum, &index, info);
if (ret) {
tscError("OTD:0x%"PRIx64" Unable to parse timestamp", info->id);
return ret;
}
tscDebug("OTD:0x%"PRIx64" Parse timestamp finished", info->id);
//Parse value
ret = parseTelnetMetricValue(&smlData->fields, &smlData->fieldNum, &index, info);
if (ret) {
tscError("OTD:0x%"PRIx64" Unable to parse metric value", info->id);
return ret;
}
tscDebug("OTD:0x%"PRIx64" Parse metric value finished", info->id);
//Parse tagKVs
SHashObj *keyHashTable = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, false);
ret = parseTelnetTagKvs(&smlData->tags, &smlData->tagNum, &index, &smlData->childTableName, keyHashTable, info);
if (ret) {
tscError("OTD:0x%"PRIx64" Unable to parse tags", info->id);
taosHashCleanup(keyHashTable);
return ret;
}
tscDebug("OTD:0x%"PRIx64" Parse tags finished", info->id);
taosHashCleanup(keyHashTable);
return TSDB_CODE_SUCCESS;
}
int32_t tscParseTelnetLines(char* lines[], int numLines, SArray* points, SArray* failedLines, SSmlLinesInfo* info) {
for (int32_t i = 0; i < numLines; ++i) {
TAOS_SML_DATA_POINT point = {0};
int32_t code = tscParseTelnetLine(lines[i], &point, info);
if (code != TSDB_CODE_SUCCESS) {
tscError("OTD:0x%"PRIx64" data point line parse failed. line %d : %s", info->id, i, lines[i]);
destroySmlDataPoint(&point);
return code;
} else {
tscDebug("OTD:0x%"PRIx64" data point line parse success. line %d", info->id, i);
}
taosArrayPush(points, &point);
}
return TSDB_CODE_SUCCESS;
}
int taos_insert_telnet_lines(TAOS* taos, char* lines[], int numLines) {
int32_t code = 0;
SSmlLinesInfo* info = tcalloc(1, sizeof(SSmlLinesInfo));
info->id = genUID();
if (numLines <= 0 || numLines > 65536) {
tscError("OTD:0x%"PRIx64" taos_insert_telnet_lines numLines should be between 1 and 65536. numLines: %d", info->id, numLines);
tfree(info);
code = TSDB_CODE_TSC_APP_ERROR;
return code;
}
for (int i = 0; i < numLines; ++i) {
if (lines[i] == NULL) {
tscError("OTD:0x%"PRIx64" taos_insert_telnet_lines line %d is NULL", info->id, i);
tfree(info);
code = TSDB_CODE_TSC_APP_ERROR;
return code;
}
}
SArray* lpPoints = taosArrayInit(numLines, sizeof(TAOS_SML_DATA_POINT));
if (lpPoints == NULL) {
tscError("OTD:0x%"PRIx64" taos_insert_telnet_lines failed to allocate memory", info->id);
tfree(info);
return TSDB_CODE_TSC_OUT_OF_MEMORY;
}
tscDebug("OTD:0x%"PRIx64" taos_insert_telnet_lines begin inserting %d lines, first line: %s", info->id, numLines, lines[0]);
code = tscParseTelnetLines(lines, numLines, lpPoints, NULL, info);
size_t numPoints = taosArrayGetSize(lpPoints);
if (code != 0) {
goto cleanup;
}
TAOS_SML_DATA_POINT* points = TARRAY_GET_START(lpPoints);
code = tscSmlInsert(taos, points, (int)numPoints, info);
if (code != 0) {
tscError("OTD:0x%"PRIx64" taos_insert_telnet_lines error: %s", info->id, tstrerror((code)));
}
cleanup:
tscDebug("OTD:0x%"PRIx64" taos_insert_telnet_lines finish inserting %d lines. code: %d", info->id, numLines, code);
points = TARRAY_GET_START(lpPoints);
numPoints = taosArrayGetSize(lpPoints);
for (int i=0; i<numPoints; ++i) {
destroySmlDataPoint(points+i);
}
taosArrayDestroy(lpPoints);
tfree(info);
return code;
}
int taos_telnet_insert(TAOS* taos, TAOS_SML_DATA_POINT* points, int numPoint) {
SSmlLinesInfo* info = tcalloc(1, sizeof(SSmlLinesInfo));
info->id = genUID();
int code = tscSmlInsert(taos, points, numPoint, info);
tfree(info);
return code;
}
......@@ -827,6 +827,16 @@ def taos_insert_lines(connection, lines):
if errno != 0:
raise LinesError("insert lines error", errno)
def taos_insert_telnet_lines(connection, lines):
# type: (c_void_p, list[str] | tuple(str)) -> None
num_of_lines = len(lines)
lines = (c_char_p(line.encode("utf-8")) for line in lines)
lines_type = ctypes.c_char_p * num_of_lines
p_lines = lines_type(*lines)
errno = _libtaos.taos_insert_telnet_lines(connection, p_lines, num_of_lines)
if errno != 0:
raise LinesError("insert telnet lines error", errno)
class CTaosInterface(object):
def __init__(self, config=None):
......
......@@ -145,6 +145,15 @@ class TaosConnection(object):
"""
return taos_insert_lines(self._conn, lines)
def insert_telnet_lines(self, lines):
"""OpenTSDB telnet style API format support
## Example
cpu_load 1626056811855516532ns 2.0f32 id="tb1",host="host0",interface="eth0"
"""
return taos_insert_telnet_lines(self._conn, lines)
def cursor(self):
# type: () -> TaosCursor
"""Return a new Cursor object using the connection."""
......
......@@ -172,6 +172,8 @@ DLL_EXPORT int taos_load_table_info(TAOS *taos, const char* tableNameList);
DLL_EXPORT int taos_insert_lines(TAOS* taos, char* lines[], int numLines);
DLL_EXPORT int taos_insert_telnet_lines(TAOS* taos, char* lines[], int numLines);
#ifdef __cplusplus
}
#endif
......
......@@ -106,6 +106,7 @@ int32_t* taosGetErrno();
#define TSDB_CODE_TSC_DUP_COL_NAMES TAOS_DEF_ERROR_CODE(0, 0x021D) //"duplicated column names")
#define TSDB_CODE_TSC_INVALID_TAG_LENGTH TAOS_DEF_ERROR_CODE(0, 0x021E) //"Invalid tag length")
#define TSDB_CODE_TSC_INVALID_COLUMN_LENGTH TAOS_DEF_ERROR_CODE(0, 0x021F) //"Invalid column length")
#define TSDB_CODE_TSC_DUP_TAG_NAMES TAOS_DEF_ERROR_CODE(0, 0x0220) //"duplicated tag names")
// mnode
#define TSDB_CODE_MND_MSG_NOT_PROCESSED TAOS_DEF_ERROR_CODE(0, 0x0300) //"Message not processed")
......
......@@ -112,9 +112,10 @@ TAOS_DEFINE_ERROR(TSDB_CODE_TSC_EXCEED_SQL_LIMIT, "SQL statement too lon
TAOS_DEFINE_ERROR(TSDB_CODE_TSC_FILE_EMPTY, "File is empty")
TAOS_DEFINE_ERROR(TSDB_CODE_TSC_LINE_SYNTAX_ERROR, "Syntax error in Line")
TAOS_DEFINE_ERROR(TSDB_CODE_TSC_NO_META_CACHED, "No table meta cached")
TAOS_DEFINE_ERROR(TSDB_CODE_TSC_DUP_COL_NAMES, "duplicated column names")
TAOS_DEFINE_ERROR(TSDB_CODE_TSC_INVALID_TAG_LENGTH, "Invalid tag length")
TAOS_DEFINE_ERROR(TSDB_CODE_TSC_INVALID_COLUMN_LENGTH, "Invalid column length")
TAOS_DEFINE_ERROR(TSDB_CODE_TSC_DUP_COL_NAMES, "duplicated column names")
TAOS_DEFINE_ERROR(TSDB_CODE_TSC_INVALID_TAG_LENGTH, "Invalid tag length")
TAOS_DEFINE_ERROR(TSDB_CODE_TSC_INVALID_COLUMN_LENGTH, "Invalid column length")
TAOS_DEFINE_ERROR(TSDB_CODE_TSC_DUP_TAG_NAMES, "duplicated tag names")
// mnode
TAOS_DEFINE_ERROR(TSDB_CODE_MND_MSG_NOT_PROCESSED, "Message not processed")
......
// sample code to verify all TDengine API
// to compile: gcc -o apitest apitest.c -ltaos
#include "taoserror.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <taos.h>
#include <unistd.h>
static void prepare_data(TAOS* taos) {
TAOS_RES *result;
result = taos_query(taos, "drop database if exists test;");
......@@ -1014,6 +1017,186 @@ int32_t verify_schema_less(TAOS* taos) {
return (code);
}
void verify_telnet_insert(TAOS* taos) {
TAOS_RES *result;
result = taos_query(taos, "drop database if exists test;");
taos_free_result(result);
usleep(100000);
result = taos_query(taos, "create database db precision 'ms';");
taos_free_result(result);
usleep(100000);
(void)taos_select_db(taos, "db");
int32_t code = 0;
/* metric */
char* lines0[] = {
"stb0_0 1626006833639000000ns 4i8 host=\"host0\",interface=\"eth0\"",
"stb0_1 1626006833639000000ns 4i8 host=\"host0\",interface=\"eth0\"",
"stb0_2 1626006833639000000ns 4i8 host=\"host0\",interface=\"eth0\"",
};
code = taos_insert_telnet_lines(taos, lines0, 3);
if (code) {
printf("code: %d, %s.\n", code, tstrerror(code));
}
/* timestamp */
char* lines1[] = {
"stb1 1626006833s 1i8 host=\"host0\"",
"stb1 1626006833639000000ns 2i8 host=\"host0\"",
"stb1 1626006833640000us 3i8 host=\"host0\"",
"stb1 1626006833641123 4i8 host=\"host0\"",
"stb1 1626006833651ms 5i8 host=\"host0\"",
"stb1 0 6i8 host=\"host0\"",
};
code = taos_insert_telnet_lines(taos, lines1, 6);
if (code) {
printf("code: %d, %s.\n", code, tstrerror(code));
}
/* metric value */
//tinyin
char* lines2_0[] = {
"stb2_0 1626006833651ms -127i8 host=\"host0\"",
"stb2_0 1626006833652ms 127i8 host=\"host0\""
};
code = taos_insert_telnet_lines(taos, lines2_0, 2);
if (code) {
printf("code: %d, %s.\n", code, tstrerror(code));
}
//smallint
char* lines2_1[] = {
"stb2_1 1626006833651ms -32767i16 host=\"host0\"",
"stb2_1 1626006833652ms 32767i16 host=\"host0\""
};
code = taos_insert_telnet_lines(taos, lines2_1, 2);
if (code) {
printf("code: %d, %s.\n", code, tstrerror(code));
}
//int
char* lines2_2[] = {
"stb2_2 1626006833651ms -2147483647i32 host=\"host0\"",
"stb2_2 1626006833652ms 2147483647i32 host=\"host0\""
};
code = taos_insert_telnet_lines(taos, lines2_2, 2);
if (code) {
printf("code: %d, %s.\n", code, tstrerror(code));
}
//bigint
char* lines2_3[] = {
"stb2_3 1626006833651ms -9223372036854775807i64 host=\"host0\"",
"stb2_3 1626006833652ms 9223372036854775807i64 host=\"host0\""
};
code = taos_insert_telnet_lines(taos, lines2_3, 2);
if (code) {
printf("code: %d, %s.\n", code, tstrerror(code));
}
//float
char* lines2_4[] = {
"stb2_4 1626006833610ms 3f32 host=\"host0\"",
"stb2_4 1626006833620ms -3f32 host=\"host0\"",
"stb2_4 1626006833630ms 3.4f32 host=\"host0\"",
"stb2_4 1626006833640ms -3.4f32 host=\"host0\"",
"stb2_4 1626006833650ms 3.4E10f32 host=\"host0\"",
"stb2_4 1626006833660ms -3.4e10f32 host=\"host0\"",
"stb2_4 1626006833670ms 3.4E+2f32 host=\"host0\"",
"stb2_4 1626006833680ms -3.4e-2f32 host=\"host0\"",
"stb2_4 1626006833690ms 3.15 host=\"host0\"",
"stb2_4 1626006833700ms 3.4E38f32 host=\"host0\"",
"stb2_4 1626006833710ms -3.4E38f32 host=\"host0\""
};
code = taos_insert_telnet_lines(taos, lines2_4, 11);
if (code) {
printf("code: %d, %s.\n", code, tstrerror(code));
}
//double
char* lines2_5[] = {
"stb2_5 1626006833610ms 3f64 host=\"host0\"",
"stb2_5 1626006833620ms -3f64 host=\"host0\"",
"stb2_5 1626006833630ms 3.4f64 host=\"host0\"",
"stb2_5 1626006833640ms -3.4f64 host=\"host0\"",
"stb2_5 1626006833650ms 3.4E10f64 host=\"host0\"",
"stb2_5 1626006833660ms -3.4e10f64 host=\"host0\"",
"stb2_5 1626006833670ms 3.4E+2f64 host=\"host0\"",
"stb2_5 1626006833680ms -3.4e-2f64 host=\"host0\"",
"stb2_5 1626006833690ms 1.7E308f64 host=\"host0\"",
"stb2_5 1626006833700ms -1.7E308f64 host=\"host0\""
};
code = taos_insert_telnet_lines(taos, lines2_5, 10);
if (code) {
printf("code: %d, %s.\n", code, tstrerror(code));
}
//bool
char* lines2_6[] = {
"stb2_6 1626006833610ms t host=\"host0\"",
"stb2_6 1626006833620ms T host=\"host0\"",
"stb2_6 1626006833630ms true host=\"host0\"",
"stb2_6 1626006833640ms True host=\"host0\"",
"stb2_6 1626006833650ms TRUE host=\"host0\"",
"stb2_6 1626006833660ms f host=\"host0\"",
"stb2_6 1626006833670ms F host=\"host0\"",
"stb2_6 1626006833680ms false host=\"host0\"",
"stb2_6 1626006833690ms False host=\"host0\"",
"stb2_6 1626006833700ms FALSE host=\"host0\""
};
code = taos_insert_telnet_lines(taos, lines2_6, 10);
if (code) {
printf("code: %d, %s.\n", code, tstrerror(code));
}
//binary
char* lines2_7[] = {
"stb2_7 1626006833610ms \"binary_val.!@#$%^&*\" host=\"host0\"",
"stb2_7 1626006833620ms \"binary_val.:;,./?|+-=\" host=\"host0\"",
"stb2_7 1626006833630ms \"binary_val.()[]{}<>\" host=\"host0\""
};
code = taos_insert_telnet_lines(taos, lines2_7, 3);
if (code) {
printf("code: %d, %s.\n", code, tstrerror(code));
}
//nchar
char* lines2_8[] = {
"stb2_8 1626006833610ms L\"nchar_val数值一\" host=\"host0\"",
"stb2_8 1626006833620ms L\"nchar_val数值二\" host=\"host0\"",
};
code = taos_insert_telnet_lines(taos, lines2_8, 2);
if (code) {
printf("code: %d, %s.\n", code, tstrerror(code));
}
/* tags */
//tag value types
char* lines3_0[] = {
"stb3_0 1626006833610ms 1 t1=127i8,t2=32767i16,t3=2147483647i32,t4=9223372036854775807i64,t5=3.4E38f32,t6=1.7E308f64,t7=true,t8=\"binary_val_1\",t9=L\"标签值1\"",
"stb3_0 1626006833610ms 2 t1=-127i8,t2=-32767i16,t3=-2147483647i32,t4=-9223372036854775807i64,t5=-3.4E38f32,t6=-1.7E308f64,t7=false,t8=\"binary_val_2\",t9=L\"标签值2\""
};
code = taos_insert_telnet_lines(taos, lines3_0, 2);
if (code) {
printf("code: %d, %s.\n", code, tstrerror(code));
}
//tag ID as child table name
char* lines3_1[] = {
"stb3_1 1626006833610ms 1 id=\"child_table1\",host=\"host1\"",
"stb3_1 1626006833610ms 2 host=\"host2\",iD=\"child_table2\"",
"stb3_1 1626006833610ms 3 ID=\"child_table3\",host=\"host3\""
};
code = taos_insert_telnet_lines(taos, lines3_1, 3);
if (code) {
printf("code: %d, %s.\n", code, tstrerror(code));
}
return;
}
int main(int argc, char *argv[]) {
const char* host = "127.0.0.1";
const char* user = "root";
......@@ -1034,6 +1217,8 @@ int main(int argc, char *argv[]) {
printf("************ verify schema-less *************\n");
verify_schema_less(taos);
printf("************ verify telnet-insert *************\n");
verify_telnet_insert(taos);
printf("************ verify query *************\n");
verify_query(taos);
......@@ -1051,7 +1236,7 @@ int main(int argc, char *argv[]) {
verify_prepare2(taos);
printf("************ verify prepare3 *************\n");
verify_prepare3(taos);
printf("************ verify stream *************\n");
verify_stream(taos);
printf("done\n");
......
###################################################################
# Copyright (c) 2021 by TAOS Technologies, Inc.
# All rights reserved.
#
# This file is proprietary and confidential to TAOS Technologies.
# No part of this file may be reproduced, stored, transmitted,
# disclosed or used in any form or by any means other than as
# expressly provided by the written permission from Jianhui Tao
#
###################################################################
# -*- coding: utf-8 -*-
import sys
from util.log import *
from util.cases import *
from util.sql import *
class TDTestCase:
def init(self, conn, logSql):
tdLog.debug("start to execute %s" % __file__)
tdSql.init(conn.cursor(), logSql)
self._conn = conn
def run(self):
print("running {}".format(__file__))
tdSql.execute("drop database if exists test")
tdSql.execute("create database if not exists test precision 'us'")
tdSql.execute('use test')
### metric ###
print("============= step1 : test metric ================")
lines0 = [
"stb0_0 1626006833639000000ns 4i8 host=\"host0\",interface=\"eth0\"",
"stb0_1 1626006833639000000ns 4i8 host=\"host0\",interface=\"eth0\"",
"stb0_2 1626006833639000000ns 4i8 host=\"host0\",interface=\"eth0\"",
]
code = self._conn.insert_telnet_lines(lines0)
print("insert_telnet_lines result {}".format(code))
tdSql.query("show stables")
tdSql.checkRows(3)
tdSql.query("describe stb0_0")
tdSql.checkRows(4)
tdSql.query("describe stb0_1")
tdSql.checkRows(4)
tdSql.query("describe stb0_2")
tdSql.checkRows(4)
### timestamp ###
print("============= step2 : test timestamp ================")
lines1 = [
"stb1 1626006833s 1i8 host=\"host0\"",
"stb1 1626006833639000000ns 2i8 host=\"host0\"",
"stb1 1626006833640000us 3i8 host=\"host0\"",
"stb1 1626006833641123 4i8 host=\"host0\"",
"stb1 1626006833651ms 5i8 host=\"host0\"",
"stb1 0 6i8 host=\"host0\"",
]
code = self._conn.insert_telnet_lines(lines1)
print("insert_telnet_lines result {}".format(code))
tdSql.query("select * from stb1")
tdSql.checkRows(6)
### metric value ###
print("============= step3 : test metric value ================")
#tinyint
lines2_0 = [
"stb2_0 1626006833651ms -127i8 host=\"host0\"",
"stb2_0 1626006833652ms 127i8 host=\"host0\""
]
code = self._conn.insert_telnet_lines(lines2_0)
print("insert_telnet_lines result {}".format(code))
tdSql.query("select * from stb2_0")
tdSql.checkRows(2)
tdSql.query("describe stb2_0")
tdSql.checkRows(3)
tdSql.checkData(1, 1, "TINYINT")
#smallint
lines2_1 = [
"stb2_1 1626006833651ms -32767i16 host=\"host0\"",
"stb2_1 1626006833652ms 32767i16 host=\"host0\""
]
code = self._conn.insert_telnet_lines(lines2_1)
print("insert_telnet_lines result {}".format(code))
tdSql.query("select * from stb2_1")
tdSql.checkRows(2)
tdSql.query("describe stb2_1")
tdSql.checkRows(3)
tdSql.checkData(1, 1, "SMALLINT")
#int
lines2_2 = [
"stb2_2 1626006833651ms -2147483647i32 host=\"host0\"",
"stb2_2 1626006833652ms 2147483647i32 host=\"host0\""
]
code = self._conn.insert_telnet_lines(lines2_2)
print("insert_telnet_lines result {}".format(code))
tdSql.query("select * from stb2_2")
tdSql.checkRows(2)
tdSql.query("describe stb2_2")
tdSql.checkRows(3)
tdSql.checkData(1, 1, "INT")
#bigint
lines2_3 = [
"stb2_3 1626006833651ms -9223372036854775807i64 host=\"host0\"",
"stb2_3 1626006833652ms 9223372036854775807i64 host=\"host0\""
]
code = self._conn.insert_telnet_lines(lines2_3)
print("insert_telnet_lines result {}".format(code))
tdSql.query("select * from stb2_3")
tdSql.checkRows(2)
tdSql.query("describe stb2_3")
tdSql.checkRows(3)
tdSql.checkData(1, 1, "BIGINT")
#float
lines2_4 = [
"stb2_4 1626006833610ms 3f32 host=\"host0\"",
"stb2_4 1626006833620ms -3f32 host=\"host0\"",
"stb2_4 1626006833630ms 3.4f32 host=\"host0\"",
"stb2_4 1626006833640ms -3.4f32 host=\"host0\"",
"stb2_4 1626006833650ms 3.4E10f32 host=\"host0\"",
"stb2_4 1626006833660ms -3.4e10f32 host=\"host0\"",
"stb2_4 1626006833670ms 3.4E+2f32 host=\"host0\"",
"stb2_4 1626006833680ms -3.4e-2f32 host=\"host0\"",
"stb2_4 1626006833690ms 3.15 host=\"host0\"",
"stb2_4 1626006833700ms 3.4E38f32 host=\"host0\"",
"stb2_4 1626006833710ms -3.4E38f32 host=\"host0\""
]
code = self._conn.insert_telnet_lines(lines2_4)
print("insert_telnet_lines result {}".format(code))
tdSql.query("select * from stb2_4")
tdSql.checkRows(11)
tdSql.query("describe stb2_4")
tdSql.checkRows(3)
tdSql.checkData(1, 1, "FLOAT")
#double
lines2_5 = [
"stb2_5 1626006833610ms 3f64 host=\"host0\"",
"stb2_5 1626006833620ms -3f64 host=\"host0\"",
"stb2_5 1626006833630ms 3.4f64 host=\"host0\"",
"stb2_5 1626006833640ms -3.4f64 host=\"host0\"",
"stb2_5 1626006833650ms 3.4E10f64 host=\"host0\"",
"stb2_5 1626006833660ms -3.4e10f64 host=\"host0\"",
"stb2_5 1626006833670ms 3.4E+2f64 host=\"host0\"",
"stb2_5 1626006833680ms -3.4e-2f64 host=\"host0\"",
"stb2_5 1626006833690ms 1.7E308f64 host=\"host0\"",
"stb2_5 1626006833700ms -1.7E308f64 host=\"host0\""
]
code = self._conn.insert_telnet_lines(lines2_5)
print("insert_telnet_lines result {}".format(code))
tdSql.query("select * from stb2_5")
tdSql.checkRows(10)
tdSql.query("describe stb2_5")
tdSql.checkRows(3)
tdSql.checkData(1, 1, "DOUBLE")
#bool
lines2_6 = [
"stb2_6 1626006833610ms t host=\"host0\"",
"stb2_6 1626006833620ms T host=\"host0\"",
"stb2_6 1626006833630ms true host=\"host0\"",
"stb2_6 1626006833640ms True host=\"host0\"",
"stb2_6 1626006833650ms TRUE host=\"host0\"",
"stb2_6 1626006833660ms f host=\"host0\"",
"stb2_6 1626006833670ms F host=\"host0\"",
"stb2_6 1626006833680ms false host=\"host0\"",
"stb2_6 1626006833690ms False host=\"host0\"",
"stb2_6 1626006833700ms FALSE host=\"host0\""
]
code = self._conn.insert_telnet_lines(lines2_6)
print("insert_telnet_lines result {}".format(code))
tdSql.query("select * from stb2_6")
tdSql.checkRows(10)
tdSql.query("describe stb2_6")
tdSql.checkRows(3)
tdSql.checkData(1, 1, "BOOL")
#binary
lines2_7 = [
"stb2_7 1626006833610ms \"binary_val.!@#$%^&*\" host=\"host0\"",
"stb2_7 1626006833620ms \"binary_val.:;,./?|+-=\" host=\"host0\"",
"stb2_7 1626006833630ms \"binary_val.()[]{}<>\" host=\"host0\""
]
code = self._conn.insert_telnet_lines(lines2_7)
print("insert_telnet_lines result {}".format(code))
tdSql.query("select * from stb2_7")
tdSql.checkRows(3)
tdSql.query("describe stb2_7")
tdSql.checkRows(3)
tdSql.checkData(1, 1, "BINARY")
#nchar
lines2_8 = [
"stb2_8 1626006833610ms L\"nchar_val数值一\" host=\"host0\"",
"stb2_8 1626006833620ms L\"nchar_val数值二\" host=\"host0\""
]
code = self._conn.insert_telnet_lines(lines2_8)
print("insert_telnet_lines result {}".format(code))
tdSql.query("select * from stb2_8")
tdSql.checkRows(2)
tdSql.query("describe stb2_8")
tdSql.checkRows(3)
tdSql.checkData(1, 1, "NCHAR")
### tags ###
print("============= step3 : test tags ================")
#tag value types
lines3_0 = [
"stb3_0 1626006833610ms 1 t1=127i8,t2=32767i16,t3=2147483647i32,t4=9223372036854775807i64,t5=3.4E38f32,t6=1.7E308f64,t7=true,t8=\"binary_val_1\",t9=L\"标签值1\"",
"stb3_0 1626006833610ms 2 t1=-127i8,t2=-32767i16,t3=-2147483647i32,t4=-9223372036854775807i64,t5=-3.4E38f32,t6=-1.7E308f64,t7=false,t8=\"binary_val_2\",t9=L\"标签值2\""
]
code = self._conn.insert_telnet_lines(lines3_0)
print("insert_telnet_lines result {}".format(code))
tdSql.query("select * from stb3_0")
tdSql.checkRows(2)
tdSql.query("describe stb3_0")
tdSql.checkRows(11)
tdSql.checkData(2, 1, "TINYINT")
tdSql.checkData(2, 3, "TAG")
tdSql.checkData(3, 1, "SMALLINT")
tdSql.checkData(3, 3, "TAG")
tdSql.checkData(4, 1, "INT")
tdSql.checkData(4, 3, "TAG")
tdSql.checkData(5, 1, "BIGINT")
tdSql.checkData(5, 3, "TAG")
tdSql.checkData(6, 1, "FLOAT")
tdSql.checkData(6, 3, "TAG")
tdSql.checkData(7, 1, "DOUBLE")
tdSql.checkData(7, 3, "TAG")
tdSql.checkData(8, 1, "BOOL")
tdSql.checkData(8, 3, "TAG")
tdSql.checkData(9, 1, "BINARY")
tdSql.checkData(9, 3, "TAG")
tdSql.checkData(10, 1, "NCHAR")
tdSql.checkData(10, 3, "TAG")
#tag ID as child table name
lines3_1 = [
"stb3_1 1626006833610ms 1 id=\"child_table1\",host=\"host1\"",
"stb3_1 1626006833610ms 2 host=\"host2\",iD=\"child_table2\"",
"stb3_1 1626006833610ms 3 ID=\"child_table3\",host=\"host3\""
]
code = self._conn.insert_telnet_lines(lines3_1)
print("insert_telnet_lines result {}".format(code))
tdSql.query("select * from stb3_1")
tdSql.checkRows(3)
tdSql.query("show tables like \"child%\"")
tdSql.checkRows(3)
tdSql.checkData(0, 0, "child_table1")
def stop(self):
tdSql.close()
tdLog.success("%s successfully executed" % __file__)
tdCases.addWindows(__file__, TDTestCase())
tdCases.addLinux(__file__, TDTestCase())
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册