From f76f30ba6b4f45d515fea6a64c413822755d71ac Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Wed, 29 Dec 2021 11:42:39 +0800 Subject: [PATCH] [td-11818] refactor create child table procedure. --- include/libs/parser/parser.h | 2 +- source/client/src/clientImpl.c | 34 +- source/client/test/clientTests.cpp | 1 - source/libs/parser/inc/parserUtil.h | 13 +- source/libs/parser/src/dCDAstProcess.c | 19 +- source/libs/parser/src/insertParser.c | 466 +++++++++++----------- source/libs/parser/src/parserUtil.c | 514 +++++++++++++------------ 7 files changed, 502 insertions(+), 547 deletions(-) diff --git a/include/libs/parser/parser.h b/include/libs/parser/parser.h index 3cd5e3a379..dd3d92866f 100644 --- a/include/libs/parser/parser.h +++ b/include/libs/parser/parser.h @@ -27,7 +27,7 @@ typedef struct SParseContext { int8_t schemaAttached; // denote if submit block is built with table schema or not const char *pSql; // sql string size_t sqlLen; // length of the sql string - char *pMsg; // extended error message if exists to help avoid the problem in sql statement. + char *pMsg; // extended error message if exists to help identifying the problem in sql statement. int32_t msgLen; // max length of the msg } SParseContext; diff --git a/source/client/src/clientImpl.c b/source/client/src/clientImpl.c index 5885d10454..6ecd9a59f7 100644 --- a/source/client/src/clientImpl.c +++ b/source/client/src/clientImpl.c @@ -181,43 +181,13 @@ int32_t execDdlQuery(SRequestObj* pRequest, SQueryNode* pQuery) { pRequest->body.requestMsg = (SDataBuf){.pData = pDcl->pMsg, .len = pDcl->msgLen}; STscObj* pTscObj = pRequest->pTscObj; - - SMsgSendInfo* pSendMsg = buildSendMsgInfoImpl(pRequest); - SEpSet* pEpSet = &pTscObj->pAppInfo->mgmtEp.epSet; + int64_t transporterId = 0; if (pDcl->msgType == TDMT_VND_CREATE_TABLE) { -// struct SCatalog* pCatalog = NULL; -// -// char buf[18] = {0}; -// sprintf(buf, "%" PRId64, pRequest->pTscObj->pAppInfo->clusterId); -// int32_t code = catalogGetHandle(buf, &pCatalog); -// if (code != TSDB_CODE_SUCCESS) { -// return code; -// } -// -// SCreateTableMsg* pMsg = pSendMsg->msgInfo.pData; -// -// SName t = {0}; -// tNameFromString(&t, pMsg->name, T_NAME_ACCT|T_NAME_DB|T_NAME_TABLE); -// -// char db[TSDB_DB_NAME_LEN + TSDB_NAME_DELIMITER_LEN + TSDB_ACCT_ID_LEN] = {0}; -// tNameGetFullDbName(&t, db); -// -// SVgroupInfo info = {0}; -// catalogGetTableHashVgroup(pCatalog, pRequest->pTscObj->pTransporter, pEpSet, db, tNameGetTableName(&t), &info); -// - int64_t transporterId = 0; -// SEpSet ep = {0}; -// ep.inUse = info.inUse; -// ep.numOfEps = info.numOfEps; -// for(int32_t i = 0; i < ep.numOfEps; ++i) { -// ep.port[i] = info.epAddr[i].port; -// tstrncpy(ep.fqdn[i], info.epAddr[i].fqdn, tListLen(ep.fqdn[i])); -// } asyncSendMsgToServer(pTscObj->pTransporter, &pDcl->epSet, &transporterId, pSendMsg); } else { - int64_t transporterId = 0; + SEpSet* pEpSet = &pTscObj->pAppInfo->mgmtEp.epSet; asyncSendMsgToServer(pTscObj->pTransporter, pEpSet, &transporterId, pSendMsg); } diff --git a/source/client/test/clientTests.cpp b/source/client/test/clientTests.cpp index 0a4519eabc..9616166e21 100644 --- a/source/client/test/clientTests.cpp +++ b/source/client/test/clientTests.cpp @@ -433,7 +433,6 @@ TEST(testCase, create_topic_Test) { taos_close(pConn); } - //TEST(testCase, show_table_Test) { // TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0); // assert(pConn != NULL); diff --git a/source/libs/parser/inc/parserUtil.h b/source/libs/parser/inc/parserUtil.h index 3d8729e72d..b7c9f967c1 100644 --- a/source/libs/parser/inc/parserUtil.h +++ b/source/libs/parser/inc/parserUtil.h @@ -62,7 +62,7 @@ void cleanupTagCond(STagCond* pTagCond); void cleanupColumnCond(SArray** pCond); uint32_t convertRelationalOperator(SToken *pToken); -int32_t getExprFunctionId(SExprInfo *pExprInfo); +int32_t getExprFunctionId(SExprInfo *pExprInfo); STableMeta* tableMetaDup(const STableMeta* pTableMeta); @@ -70,6 +70,17 @@ bool isDclSqlStatement(SSqlInfo* pSqlInfo); bool isDdlSqlStatement(SSqlInfo* pSqlInfo); bool isDqlSqlStatement(SSqlInfo* pSqlInfo); +typedef struct SKvParam { + SKVRowBuilder *builder; + SSchema *schema; + char buf[TSDB_MAX_TAGS_LEN]; +} SKvParam; + +int32_t KvRowAppend(const void *value, int32_t len, void *param); + +typedef int32_t (*_row_append_fn_t)(const void *value, int32_t len, void *param); +int32_t parseValueToken(char** end, SToken* pToken, SSchema* pSchema, int16_t timePrec, char* tmpTokenBuf, _row_append_fn_t func, void* param, SMsgBuf* pMsgBuf); + #ifdef __cplusplus } #endif diff --git a/source/libs/parser/src/dCDAstProcess.c b/source/libs/parser/src/dCDAstProcess.c index f01338e051..51d4e14a2a 100644 --- a/source/libs/parser/src/dCDAstProcess.c +++ b/source/libs/parser/src/dCDAstProcess.c @@ -429,7 +429,6 @@ int32_t doCheckForCreateCTable(SSqlInfo* pInfo, SParseBasicCtx *pCtx, SMsgBuf* p SSchema *pSchema = &pTagSchema[i]; SToken* pItem = taosArrayGet(pValList, i); - char tagVal[TSDB_MAX_TAGS_LEN]; if (pSchema->type == TSDB_DATA_TYPE_BINARY || pSchema->type == TSDB_DATA_TYPE_NCHAR) { if (pItem->n > pSchema->bytes) { tdDestroyKVRowBuilder(&kvRowBuilder); @@ -446,26 +445,16 @@ int32_t doCheckForCreateCTable(SSqlInfo* pInfo, SParseBasicCtx *pCtx, SMsgBuf* p // } } - char* endPtr = NULL; - int64_t v = strtoll(pItem->z, &endPtr, 10); - *(int32_t*) tagVal = v; -// code = taosVariantDump(&(pItem->pVar), tagVal, pSchema->type, true); + char tmpTokenBuf[TSDB_MAX_TAGS_LEN] = {0}; + SKvParam param = {.builder = &kvRowBuilder, .schema = pSchema}; - // check again after the convert since it may be converted from binary to nchar. - if (pSchema->type == TSDB_DATA_TYPE_BINARY || pSchema->type == TSDB_DATA_TYPE_NCHAR) { - int16_t len = varDataTLen(tagVal); - if (len > pSchema->bytes) { - tdDestroyKVRowBuilder(&kvRowBuilder); - return buildInvalidOperationMsg(pMsgBuf, msg3); - } - } + char* endPtr = NULL; + code = parseValueToken(&endPtr, pItem, pSchema, tinfo.precision, tmpTokenBuf, KvRowAppend, ¶m, pMsgBuf); if (code != TSDB_CODE_SUCCESS) { tdDestroyKVRowBuilder(&kvRowBuilder); return buildInvalidOperationMsg(pMsgBuf, msg4); } - - tdAddColToKVRow(&kvRowBuilder, pSchema->colId, pSchema->type, tagVal); } } diff --git a/source/libs/parser/src/insertParser.c b/source/libs/parser/src/insertParser.c index d6bdf5dbca..5574c7316c 100644 --- a/source/libs/parser/src/insertParser.c +++ b/source/libs/parser/src/insertParser.c @@ -51,8 +51,8 @@ enum { typedef struct SInsertParseContext { SParseContext* pComCxt; // input - const char* pSql; // input - SMsgBuf msg; // input + char *pSql; // input + SMsgBuf msg; // input STableMeta* pTableMeta; // each table SParsedDataColInfo tags; // each table SKVRowBuilder tagsBuilder; // each table @@ -64,22 +64,6 @@ typedef struct SInsertParseContext { SInsertStmtInfo* pOutput; } SInsertParseContext; -typedef int32_t (*FRowAppend)(const void *value, int32_t len, void *param); - -typedef struct SKvParam { - char buf[TSDB_MAX_TAGS_LEN]; - SKVRowBuilder* builder; - SSchema* schema; -} SKvParam; - -static uint8_t TRUE_VALUE = (uint8_t)TSDB_TRUE; -static uint8_t FALSE_VALUE = (uint8_t)TSDB_FALSE; - -static bool isNullStr(SToken *pToken) { - return (pToken->type == TK_NULL) || ((pToken->type == TK_STRING) && (pToken->n != 0) && - (strncasecmp(TSDB_DATA_NULL_STR_L, pToken->z, pToken->n) == 0)); -} - static FORCE_INLINE int32_t toDouble(SToken *pToken, double *value, char **endPtr) { errno = 0; *value = strtold(pToken->z, endPtr); @@ -263,23 +247,21 @@ static int32_t checkTimestamp(STableDataBlocks *pDataBlocks, const char *start) return TSDB_CODE_SUCCESS; } -static int parseTime(SInsertParseContext* pCxt, SToken *pToken, int16_t timePrec, int64_t *time) { +static int parseTime(char **end, SToken *pToken, int16_t timePrec, int64_t *time, SMsgBuf* pMsgBuf) { int32_t index = 0; - SToken sToken; + SToken sToken; int64_t interval; - int64_t useconds = 0; - const char* pTokenEnd = pCxt->pSql; + int64_t ts = 0; + char* pTokenEnd = *end; if (pToken->type == TK_NOW) { - useconds = taosGetTimestamp(timePrec); - } else if (strncmp(pToken->z, "0", 1) == 0 && pToken->n == 1) { - // do nothing + ts = taosGetTimestamp(timePrec); } else if (pToken->type == TK_INTEGER) { - useconds = taosStr2int64(pToken->z); - } else { - // strptime("2001-11-12 18:31:01", "%Y-%m-%d %H:%M:%S", &tm); + bool isSigned = false; + toInteger(pToken->z, pToken->n, 10, &ts, &isSigned); + } else { // parse the RFC-3339/ISO-8601 timestamp format string if (taosParseTime(pToken->z, time, pToken->n, timePrec, tsDaylight) != TSDB_CODE_SUCCESS) { - return buildSyntaxErrMsg(&pCxt->msg, "invalid timestamp format", pToken->z); + return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp format", pToken->z); } return TSDB_CODE_SUCCESS; @@ -288,8 +270,8 @@ static int parseTime(SInsertParseContext* pCxt, SToken *pToken, int16_t timePrec for (int k = pToken->n; pToken->z[k] != '\0'; k++) { if (pToken->z[k] == ' ' || pToken->z[k] == '\t') continue; if (pToken->z[k] == ',') { - pCxt->pSql = pTokenEnd; - *time = useconds; + *end = pTokenEnd; + *time = ts; return 0; } @@ -311,7 +293,7 @@ static int parseTime(SInsertParseContext* pCxt, SToken *pToken, int16_t timePrec pTokenEnd += index; if (valueToken.n < 2) { - return buildSyntaxErrMsg(&pCxt->msg, "value expected in timestamp", sToken.z); + return buildSyntaxErrMsg(pMsgBuf, "value expected in timestamp", sToken.z); } char unit = 0; @@ -320,34 +302,15 @@ static int parseTime(SInsertParseContext* pCxt, SToken *pToken, int16_t timePrec } if (sToken.type == TK_PLUS) { - useconds += interval; + ts += interval; } else { - useconds = useconds - interval; + ts = ts - interval; } - pCxt->pSql = pTokenEnd; + *end = pTokenEnd; } - *time = useconds; - return TSDB_CODE_SUCCESS; -} - -static FORCE_INLINE int32_t KvRowAppend(const void *value, int32_t len, void *param) { - SKvParam* pa = (SKvParam*)param; - if (TSDB_DATA_TYPE_BINARY == pa->schema->type) { - STR_WITH_SIZE_TO_VARSTR(pa->buf, value, len); - tdAddColToKVRow(pa->builder, pa->schema->colId, pa->schema->type, pa->buf); - } else if (TSDB_DATA_TYPE_NCHAR == pa->schema->type) { - // if the converted output len is over than pColumnModel->bytes, return error: 'Argument list too long' - int32_t output = 0; - if (!taosMbsToUcs4(value, len, varDataVal(pa->buf), pa->schema->bytes - VARSTR_HEADER_SIZE, &output)) { - return TSDB_CODE_TSC_SQL_SYNTAX_ERROR; - } - varDataSetLen(pa->buf, output); - tdAddColToKVRow(pa->builder, pa->schema->colId, pa->schema->type, pa->buf); - } else { - tdAddColToKVRow(pa->builder, pa->schema->colId, pa->schema->type, value); - } + *time = ts; return TSDB_CODE_SUCCESS; } @@ -381,193 +344,206 @@ static FORCE_INLINE int32_t MemRowAppend(const void *value, int32_t len, void *p return TSDB_CODE_SUCCESS; } -static FORCE_INLINE int32_t checkAndTrimValue(SInsertParseContext* pCxt, SToken* pToken, SSchema* pSchema, char* tmpTokenBuf) { - int16_t type = pToken->type; - if ((type != TK_NOW && type != TK_INTEGER && type != TK_STRING && type != TK_FLOAT && type != TK_BOOL && - type != TK_NULL && type != TK_HEX && type != TK_OCT && type != TK_BIN) || - (pToken->n == 0) || (type == TK_RP)) { - return buildSyntaxErrMsg(&pCxt->msg, "invalid data or symbol", pToken->z); - } - - if (IS_NUMERIC_TYPE(pSchema->type) && pToken->n == 0) { - return buildSyntaxErrMsg(&pCxt->msg, "invalid numeric data", pToken->z); - } - - // Remove quotation marks - if (TK_STRING == type) { - if (pToken->n >= TSDB_MAX_BYTES_PER_ROW) { - return buildSyntaxErrMsg(&pCxt->msg, "too long string", pToken->z); - } - // delete escape character: \\, \', \" - char delim = pToken->z[0]; - int32_t cnt = 0; - int32_t j = 0; - for (uint32_t k = 1; k < pToken->n - 1; ++k) { - if (pToken->z[k] == '\\' || (pToken->z[k] == delim && pToken->z[k + 1] == delim)) { - tmpTokenBuf[j] = pToken->z[k + 1]; - cnt++; - j++; - k++; - continue; - } - tmpTokenBuf[j] = pToken->z[k]; - j++; - } - tmpTokenBuf[j] = 0; - pToken->z = tmpTokenBuf; - pToken->n -= 2 + cnt; - } - - return TSDB_CODE_SUCCESS; -} - -static FORCE_INLINE int32_t parseOneValue(SInsertParseContext* pCxt, SToken* pToken, SSchema* pSchema, int16_t timePrec, char* tmpTokenBuf, FRowAppend func, void* param) { - int64_t iv; - int32_t ret; - char * endptr = NULL; - - CHECK_CODE(checkAndTrimValue(pCxt, pToken, pSchema, tmpTokenBuf)); - - if (isNullStr(pToken)) { - if (TSDB_DATA_TYPE_TIMESTAMP == pSchema->type && PRIMARYKEY_TIMESTAMP_COL_ID == pSchema->colId) { - int64_t tmpVal = 0; - return func(&tmpVal, pSchema->bytes, param); - } - return func(getNullValue(pSchema->type), 0, param); - } - - switch (pSchema->type) { - case TSDB_DATA_TYPE_BOOL: { - if ((pToken->type == TK_BOOL || pToken->type == TK_STRING) && (pToken->n != 0)) { - if (strncmp(pToken->z, "true", pToken->n) == 0) { - return func(&TRUE_VALUE, pSchema->bytes, param); - } else if (strncmp(pToken->z, "false", pToken->n) == 0) { - return func(&FALSE_VALUE, pSchema->bytes, param); - } else { - return buildSyntaxErrMsg(&pCxt->msg, "invalid bool data", pToken->z); - } - } else if (pToken->type == TK_INTEGER) { - return func(((strtoll(pToken->z, NULL, 10) == 0) ? &FALSE_VALUE : &TRUE_VALUE), pSchema->bytes, param); - } else if (pToken->type == TK_FLOAT) { - return func(((strtod(pToken->z, NULL) == 0) ? &FALSE_VALUE : &TRUE_VALUE), pSchema->bytes, param); - } else { - return buildSyntaxErrMsg(&pCxt->msg, "invalid bool data", pToken->z); - } - break; - } - case TSDB_DATA_TYPE_TINYINT: { - if (TSDB_CODE_SUCCESS != toInt64(pToken->z, pToken->type, pToken->n, &iv, true)) { - return buildSyntaxErrMsg(&pCxt->msg, "invalid tinyint data", pToken->z); - } else if (!IS_VALID_TINYINT(iv)) { - return buildSyntaxErrMsg(&pCxt->msg, "data overflow", pToken->z); - } - uint8_t tmpVal = (uint8_t)iv; - return func(&tmpVal, pSchema->bytes, param); - } - case TSDB_DATA_TYPE_UTINYINT:{ - if (TSDB_CODE_SUCCESS != toInt64(pToken->z, pToken->type, pToken->n, &iv, false)) { - return buildSyntaxErrMsg(&pCxt->msg, "invalid unsigned tinyint data", pToken->z); - } else if (!IS_VALID_UTINYINT(iv)) { - return buildSyntaxErrMsg(&pCxt->msg, "unsigned tinyint data overflow", pToken->z); - } - uint8_t tmpVal = (uint8_t)iv; - return func(&tmpVal, pSchema->bytes, param); - } - case TSDB_DATA_TYPE_SMALLINT: { - if (TSDB_CODE_SUCCESS != toInt64(pToken->z, pToken->type, pToken->n, &iv, true)) { - return buildSyntaxErrMsg(&pCxt->msg, "invalid smallint data", pToken->z); - } else if (!IS_VALID_SMALLINT(iv)) { - return buildSyntaxErrMsg(&pCxt->msg, "smallint data overflow", pToken->z); - } - int16_t tmpVal = (int16_t)iv; - return func(&tmpVal, pSchema->bytes, param); - } - case TSDB_DATA_TYPE_USMALLINT: { - if (TSDB_CODE_SUCCESS != toInt64(pToken->z, pToken->type, pToken->n, &iv, false)) { - return buildSyntaxErrMsg(&pCxt->msg, "invalid unsigned smallint data", pToken->z); - } else if (!IS_VALID_USMALLINT(iv)) { - return buildSyntaxErrMsg(&pCxt->msg, "unsigned smallint data overflow", pToken->z); - } - uint16_t tmpVal = (uint16_t)iv; - return func(&tmpVal, pSchema->bytes, param); - } - case TSDB_DATA_TYPE_INT: { - if (TSDB_CODE_SUCCESS != toInt64(pToken->z, pToken->type, pToken->n, &iv, true)) { - return buildSyntaxErrMsg(&pCxt->msg, "invalid int data", pToken->z); - } else if (!IS_VALID_INT(iv)) { - return buildSyntaxErrMsg(&pCxt->msg, "int data overflow", pToken->z); - } - int32_t tmpVal = (int32_t)iv; - return func(&tmpVal, pSchema->bytes, param); - } - case TSDB_DATA_TYPE_UINT: { - if (TSDB_CODE_SUCCESS != toInt64(pToken->z, pToken->type, pToken->n, &iv, false)) { - return buildSyntaxErrMsg(&pCxt->msg, "invalid unsigned int data", pToken->z); - } else if (!IS_VALID_UINT(iv)) { - return buildSyntaxErrMsg(&pCxt->msg, "unsigned int data overflow", pToken->z); - } - uint32_t tmpVal = (uint32_t)iv; - return func(&tmpVal, pSchema->bytes, param); - } - case TSDB_DATA_TYPE_BIGINT: { - if (TSDB_CODE_SUCCESS != toInt64(pToken->z, pToken->type, pToken->n, &iv, true)) { - return buildSyntaxErrMsg(&pCxt->msg, "invalid bigint data", pToken->z); - } else if (!IS_VALID_BIGINT(iv)) { - return buildSyntaxErrMsg(&pCxt->msg, "bigint data overflow", pToken->z); - } - return func(&iv, pSchema->bytes, param); - } - case TSDB_DATA_TYPE_UBIGINT: { - if (TSDB_CODE_SUCCESS != toInt64(pToken->z, pToken->type, pToken->n, &iv, false)) { - return buildSyntaxErrMsg(&pCxt->msg, "invalid unsigned bigint data", pToken->z); - } else if (!IS_VALID_UBIGINT((uint64_t)iv)) { - return buildSyntaxErrMsg(&pCxt->msg, "unsigned bigint data overflow", pToken->z); - } - uint64_t tmpVal = (uint64_t)iv; - return func(&tmpVal, pSchema->bytes, param); - } - case TSDB_DATA_TYPE_FLOAT: { - double dv; - if (TK_ILLEGAL == toDouble(pToken, &dv, &endptr)) { - return buildSyntaxErrMsg(&pCxt->msg, "illegal float data", pToken->z); - } - if (((dv == HUGE_VAL || dv == -HUGE_VAL) && errno == ERANGE) || dv > FLT_MAX || dv < -FLT_MAX || isinf(dv) || isnan(dv)) { - return buildSyntaxErrMsg(&pCxt->msg, "illegal float data", pToken->z); - } - float tmpVal = (float)dv; - return func(&tmpVal, pSchema->bytes, param); - } - case TSDB_DATA_TYPE_DOUBLE: { - double dv; - if (TK_ILLEGAL == toDouble(pToken, &dv, &endptr)) { - return buildSyntaxErrMsg(&pCxt->msg, "illegal double data", pToken->z); - } - if (((dv == HUGE_VAL || dv == -HUGE_VAL) && errno == ERANGE) || isinf(dv) || isnan(dv)) { - return buildSyntaxErrMsg(&pCxt->msg, "illegal double data", pToken->z); - } - return func(&dv, pSchema->bytes, param); - } - case TSDB_DATA_TYPE_BINARY: { - // too long values will return invalid sql, not be truncated automatically - if (pToken->n + VARSTR_HEADER_SIZE > pSchema->bytes) { - return buildSyntaxErrMsg(&pCxt->msg, "string data overflow", pToken->z); - } - return func(pToken->z, pToken->n, param); - } - case TSDB_DATA_TYPE_NCHAR: { - return func(pToken->z, pToken->n, param); - } - case TSDB_DATA_TYPE_TIMESTAMP: { - int64_t tmpVal; - if (parseTime(pCxt, pToken, timePrec, &tmpVal) != TSDB_CODE_SUCCESS) { - return buildSyntaxErrMsg(&pCxt->msg, "invalid timestamp", pToken->z); - } - return func(&tmpVal, pSchema->bytes, param); - } - } - - return TSDB_CODE_FAILED; -} +//static FORCE_INLINE int32_t checkAndTrimValue(SToken* pToken, uint32_t type, char* tmpTokenBuf, SMsgBuf* pMsgBuf) { +// if ((type != TK_NOW && type != TK_INTEGER && type != TK_STRING && type != TK_FLOAT && type != TK_BOOL && +// type != TK_NULL && type != TK_HEX && type != TK_OCT && type != TK_BIN) || +// (pToken->n == 0) || (type == TK_RP)) { +// return buildSyntaxErrMsg(pMsgBuf, "invalid data or symbol", pToken->z); +// } +// +// if (IS_NUMERIC_TYPE(type) && pToken->n == 0) { +// return buildSyntaxErrMsg(pMsgBuf, "invalid numeric data", pToken->z); +// } +// +// // Remove quotation marks +// if (TK_STRING == type) { +// if (pToken->n >= TSDB_MAX_BYTES_PER_ROW) { +// return buildSyntaxErrMsg(pMsgBuf, "too long string", pToken->z); +// } +// +// // delete escape character: \\, \', \" +// char delim = pToken->z[0]; +// int32_t cnt = 0; +// int32_t j = 0; +// for (uint32_t k = 1; k < pToken->n - 1; ++k) { +// if (pToken->z[k] == '\\' || (pToken->z[k] == delim && pToken->z[k + 1] == delim)) { +// tmpTokenBuf[j] = pToken->z[k + 1]; +// cnt++; +// j++; +// k++; +// continue; +// } +// tmpTokenBuf[j] = pToken->z[k]; +// j++; +// } +// +// tmpTokenBuf[j] = 0; +// pToken->z = tmpTokenBuf; +// pToken->n -= 2 + cnt; +// } +// +// return TSDB_CODE_SUCCESS; +//} + +//static FORCE_INLINE int32_t parseValueToken(char** end, SToken* pToken, SSchema* pSchema, int16_t timePrec, char* tmpTokenBuf, _row_append_fn_t func, void* param, SMsgBuf* pMsgBuf) { +// int64_t iv; +// char *endptr = NULL; +// bool isSigned = false; +// +// CHECK_CODE(checkAndTrimValue(pToken, pSchema->type, tmpTokenBuf, pMsgBuf)); +// +// if (isNullStr(pToken)) { +// if (TSDB_DATA_TYPE_TIMESTAMP == pSchema->type && PRIMARYKEY_TIMESTAMP_COL_ID == pSchema->colId) { +// int64_t tmpVal = 0; +// return func(&tmpVal, pSchema->bytes, param); +// } +// +// return func(getNullValue(pSchema->type), 0, param); +// } +// +// switch (pSchema->type) { +// case TSDB_DATA_TYPE_BOOL: { +// if ((pToken->type == TK_BOOL || pToken->type == TK_STRING) && (pToken->n != 0)) { +// if (strncmp(pToken->z, "true", pToken->n) == 0) { +// return func(&TRUE_VALUE, pSchema->bytes, param); +// } else if (strncmp(pToken->z, "false", pToken->n) == 0) { +// return func(&FALSE_VALUE, pSchema->bytes, param); +// } else { +// return buildSyntaxErrMsg(pMsgBuf, "invalid bool data", pToken->z); +// } +// } else if (pToken->type == TK_INTEGER) { +// return func(((strtoll(pToken->z, NULL, 10) == 0) ? &FALSE_VALUE : &TRUE_VALUE), pSchema->bytes, param); +// } else if (pToken->type == TK_FLOAT) { +// return func(((strtod(pToken->z, NULL) == 0) ? &FALSE_VALUE : &TRUE_VALUE), pSchema->bytes, param); +// } else { +// return buildSyntaxErrMsg(pMsgBuf, "invalid bool data", pToken->z); +// } +// } +// +// case TSDB_DATA_TYPE_TINYINT: { +// if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, pToken->type, &iv, &isSigned)) { +// return buildSyntaxErrMsg(pMsgBuf, "invalid tinyint data", pToken->z); +// } else if (!IS_VALID_TINYINT(iv)) { +// return buildSyntaxErrMsg(pMsgBuf, "tinyint data overflow", pToken->z); +// } +// +// uint8_t tmpVal = (uint8_t)iv; +// return func(&tmpVal, pSchema->bytes, param); +// } +// +// case TSDB_DATA_TYPE_UTINYINT:{ +// if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, pToken->type, &iv, &isSigned)) { +// return buildSyntaxErrMsg(pMsgBuf, "invalid unsigned tinyint data", pToken->z); +// } else if (!IS_VALID_UTINYINT(iv)) { +// return buildSyntaxErrMsg(pMsgBuf, "unsigned tinyint data overflow", pToken->z); +// } +// uint8_t tmpVal = (uint8_t)iv; +// return func(&tmpVal, pSchema->bytes, param); +// } +// +// case TSDB_DATA_TYPE_SMALLINT: { +// if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, pToken->type, &iv, &isSigned)) { +// return buildSyntaxErrMsg(pMsgBuf, "invalid smallint data", pToken->z); +// } else if (!IS_VALID_SMALLINT(iv)) { +// return buildSyntaxErrMsg(pMsgBuf, "smallint data overflow", pToken->z); +// } +// int16_t tmpVal = (int16_t)iv; +// return func(&tmpVal, pSchema->bytes, param); +// } +// +// case TSDB_DATA_TYPE_USMALLINT: { +// if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, pToken->type, &iv, &isSigned)) { +// return buildSyntaxErrMsg(pMsgBuf, "invalid unsigned smallint data", pToken->z); +// } else if (!IS_VALID_USMALLINT(iv)) { +// return buildSyntaxErrMsg(pMsgBuf, "unsigned smallint data overflow", pToken->z); +// } +// uint16_t tmpVal = (uint16_t)iv; +// return func(&tmpVal, pSchema->bytes, param); +// } +// +// case TSDB_DATA_TYPE_INT: { +// if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, pToken->type, &iv, &isSigned)) { +// return buildSyntaxErrMsg(pMsgBuf, "invalid int data", pToken->z); +// } else if (!IS_VALID_INT(iv)) { +// return buildSyntaxErrMsg(pMsgBuf, "int data overflow", pToken->z); +// } +// int32_t tmpVal = (int32_t)iv; +// return func(&tmpVal, pSchema->bytes, param); +// } +// +// case TSDB_DATA_TYPE_UINT: { +// if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, pToken->type, &iv, &isSigned)) { +// return buildSyntaxErrMsg(pMsgBuf, "invalid unsigned int data", pToken->z); +// } else if (!IS_VALID_UINT(iv)) { +// return buildSyntaxErrMsg(pMsgBuf, "unsigned int data overflow", pToken->z); +// } +// uint32_t tmpVal = (uint32_t)iv; +// return func(&tmpVal, pSchema->bytes, param); +// } +// +// case TSDB_DATA_TYPE_BIGINT: { +// if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, pToken->type, &iv, &isSigned)) { +// return buildSyntaxErrMsg(pMsgBuf, "invalid bigint data", pToken->z); +// } else if (!IS_VALID_BIGINT(iv)) { +// return buildSyntaxErrMsg(pMsgBuf, "bigint data overflow", pToken->z); +// } +// return func(&iv, pSchema->bytes, param); +// } +// +// case TSDB_DATA_TYPE_UBIGINT: { +// if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, pToken->type, &iv, &isSigned)) { +// return buildSyntaxErrMsg(pMsgBuf, "invalid unsigned bigint data", pToken->z); +// } else if (!IS_VALID_UBIGINT((uint64_t)iv)) { +// return buildSyntaxErrMsg(pMsgBuf, "unsigned bigint data overflow", pToken->z); +// } +// uint64_t tmpVal = (uint64_t)iv; +// return func(&tmpVal, pSchema->bytes, param); +// } +// +// case TSDB_DATA_TYPE_FLOAT: { +// double dv; +// if (TK_ILLEGAL == toDouble(pToken, &dv, &endptr)) { +// return buildSyntaxErrMsg(pMsgBuf, "illegal float data", pToken->z); +// } +// if (((dv == HUGE_VAL || dv == -HUGE_VAL) && errno == ERANGE) || dv > FLT_MAX || dv < -FLT_MAX || isinf(dv) || isnan(dv)) { +// return buildSyntaxErrMsg(pMsgBuf, "illegal float data", pToken->z); +// } +// float tmpVal = (float)dv; +// return func(&tmpVal, pSchema->bytes, param); +// } +// +// case TSDB_DATA_TYPE_DOUBLE: { +// double dv; +// if (TK_ILLEGAL == toDouble(pToken, &dv, &endptr)) { +// return buildSyntaxErrMsg(pMsgBuf, "illegal double data", pToken->z); +// } +// if (((dv == HUGE_VAL || dv == -HUGE_VAL) && errno == ERANGE) || isinf(dv) || isnan(dv)) { +// return buildSyntaxErrMsg(pMsgBuf, "illegal double data", pToken->z); +// } +// return func(&dv, pSchema->bytes, param); +// } +// +// case TSDB_DATA_TYPE_BINARY: { +// // too long values will return invalid sql, not be truncated automatically +// if (pToken->n + VARSTR_HEADER_SIZE > pSchema->bytes) { +// return buildSyntaxErrMsg(pMsgBuf, "string data overflow", pToken->z); +// } +// return func(pToken->z, pToken->n, param); +// } +// case TSDB_DATA_TYPE_NCHAR: { +// return func(pToken->z, pToken->n, param); +// } +// case TSDB_DATA_TYPE_TIMESTAMP: { +// int64_t tmpVal; +// if (parseTime(end, pToken, timePrec, &tmpVal, pMsgBuf) != TSDB_CODE_SUCCESS) { +// return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp", pToken->z); +// } +// return func(&tmpVal, pSchema->bytes, param); +// } +// } +// +// return TSDB_CODE_FAILED; +//} // pSql -> tag1_name, ...) static int32_t parseBoundColumns(SInsertParseContext* pCxt, SParsedDataColInfo* pColList, SSchema* pSchema) { @@ -644,7 +620,7 @@ static int32_t parseTagsClause(SInsertParseContext* pCxt, SSchema* pTagsSchema, NEXT_TOKEN(pCxt->pSql, sToken); SSchema* pSchema = &pTagsSchema[pCxt->tags.boundedColumns[i]]; param.schema = pSchema; - CHECK_CODE(parseOneValue(pCxt, &sToken, pSchema, precision, tmpTokenBuf, KvRowAppend, ¶m)); + CHECK_CODE(parseValueToken(&pCxt->pSql, &sToken, pSchema, precision, tmpTokenBuf, KvRowAppend, ¶m, &pCxt->msg)); } SKVRow row = tdGetKVRowFromBuilder(&pCxt->tagsBuilder); @@ -709,7 +685,7 @@ static int parseOneRow(SInsertParseContext* pCxt, STableDataBlocks* pDataBlocks, param.schema = pSchema; param.compareStat = pBuilder->compareStat; getMemRowAppendInfo(schema, pBuilder->memRowType, spd, i, ¶m.toffset); - CHECK_CODE(parseOneValue(pCxt, &sToken, pSchema, timePrec, tmpTokenBuf, MemRowAppend, ¶m)); + CHECK_CODE(parseValueToken(&pCxt->pSql, &sToken, pSchema, timePrec, tmpTokenBuf, MemRowAppend, ¶m, &pCxt->msg)); if (PRIMARYKEY_TIMESTAMP_COL_ID == pSchema->colId) { TSKEY tsKey = memRowKey(row); @@ -894,7 +870,7 @@ static int32_t parseInsertBody(SInsertParseContext* pCxt) { int32_t parseInsertSql(SParseContext* pContext, SInsertStmtInfo** pInfo) { SInsertParseContext context = { .pComCxt = pContext, - .pSql = pContext->pSql, + .pSql = (char*) pContext->pSql, .msg = {.buf = pContext->pMsg, .len = pContext->msgLen}, .pTableMeta = NULL, .pVgroupsHashObj = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, false), diff --git a/source/libs/parser/src/parserUtil.c b/source/libs/parser/src/parserUtil.c index 39223b7754..6e814038a7 100644 --- a/source/libs/parser/src/parserUtil.c +++ b/source/libs/parser/src/parserUtil.c @@ -13,19 +13,20 @@ * along with this program. If not, see . */ - -#include "tmsg.h" +#include "parserUtil.h" +#include +#include +#include "function.h" #include "parser.h" +#include "parserInt.h" +#include "queryInfoUtil.h" #include "taoserror.h" -#include "tutil.h" -#include "ttypes.h" -#include "thash.h" #include "tbuffer.h" -#include "parserInt.h" -#include "parserUtil.h" +#include "thash.h" +#include "tmsg.h" #include "tmsgtype.h" -#include "queryInfoUtil.h" -#include "function.h" +#include "ttypes.h" +#include "tutil.h" typedef struct STableFilterCond { uint64_t uid; @@ -1627,313 +1628,322 @@ bool isDqlSqlStatement(SSqlInfo* pSqlInfo) { return pSqlInfo->type == TSDB_SQL_SELECT; } -#if 0 -int32_t tscCreateQueryFromQueryInfo(SQueryStmtInfo* pQueryInfo, SQueryAttr* pQueryAttr, void* addr) { - memset(pQueryAttr, 0, sizeof(SQueryAttr)); - - int16_t numOfCols = (int16_t) taosArrayGetSize(pQueryInfo->colList); - int16_t numOfOutput = (int16_t) getNumOfExprs(pQueryInfo); - - pQueryAttr->topBotQuery = tscIsTopBotQuery(pQueryInfo); - pQueryAttr->hasTagResults = hasTagValOutput(pQueryInfo); - pQueryAttr->stabledev = isStabledev(pQueryInfo); - pQueryAttr->tsCompQuery = isTsCompQuery(pQueryInfo); - pQueryAttr->diffQuery = tscIsDiffDerivQuery(pQueryInfo); - pQueryAttr->simpleAgg = isSimpleAggregateRv(pQueryInfo); - pQueryAttr->needReverseScan = tscNeedReverseScan(pQueryInfo); - pQueryAttr->stableQuery = QUERY_IS_STABLE_QUERY(pQueryInfo->type); - pQueryAttr->groupbyColumn = (!pQueryInfo->stateWindow) && tscGroupbyColumn(pQueryInfo); - pQueryAttr->queryBlockDist = isBlockDistQuery(pQueryInfo); - pQueryAttr->pointInterpQuery = tscIsPointInterpQuery(pQueryInfo); - pQueryAttr->timeWindowInterpo = timeWindowInterpoRequired(pQueryInfo); - pQueryAttr->distinct = pQueryInfo->distinct; - pQueryAttr->sw = pQueryInfo->sessionWindow; - pQueryAttr->stateWindow = pQueryInfo->stateWindow; - pQueryAttr->multigroupResult = pQueryInfo->multigroupResult; - - pQueryAttr->numOfCols = numOfCols; - pQueryAttr->numOfOutput = numOfOutput; - pQueryAttr->limit = pQueryInfo->limit; - pQueryAttr->slimit = pQueryInfo->slimit; - pQueryAttr->order = pQueryInfo->order; - pQueryAttr->fillType = pQueryInfo->fillType; - pQueryAttr->havingNum = pQueryInfo->havingFieldNum; - pQueryAttr->pUdfInfo = pQueryInfo->pUdfInfo; - - if (pQueryInfo->order.order == TSDB_ORDER_ASC) { // TODO refactor - pQueryAttr->window = pQueryInfo->window; - } else { - pQueryAttr->window.skey = pQueryInfo->window.ekey; - pQueryAttr->window.ekey = pQueryInfo->window.skey; - } - - memcpy(&pQueryAttr->interval, &pQueryInfo->interval, sizeof(pQueryAttr->interval)); +static uint8_t TRUE_VALUE = (uint8_t)TSDB_TRUE; +static uint8_t FALSE_VALUE = (uint8_t)TSDB_FALSE; - STableMetaInfo* pTableMetaInfo = pQueryInfo->pTableMetaInfo[0]; +static FORCE_INLINE int32_t toDouble(SToken *pToken, double *value, char **endPtr) { + errno = 0; + *value = strtold(pToken->z, endPtr); - if (pQueryInfo->groupbyExpr.numOfGroupCols > 0) { - pQueryAttr->pGroupbyExpr = calloc(1, sizeof(SGroupbyExpr)); - *(pQueryAttr->pGroupbyExpr) = pQueryInfo->groupbyExpr; - pQueryAttr->pGroupbyExpr->columnInfo = taosArrayDup(pQueryInfo->groupbyExpr.columnInfo); - } else { - assert(pQueryInfo->groupbyExpr.columnInfo == NULL); + // not a valid integer number, return error + if ((*endPtr - pToken->z) != pToken->n) { + return TK_ILLEGAL; } - pQueryAttr->pExpr1 = calloc(pQueryAttr->numOfOutput, sizeof(SExprInfo)); - for(int32_t i = 0; i < pQueryAttr->numOfOutput; ++i) { - SExprInfo* pExpr = getExprInfo(pQueryInfo, i); - ExprInfoCopy(&pQueryAttr->pExpr1[i], pExpr); - - if (pQueryAttr->pExpr1[i].base.functionId == FUNCTION_ARITHM) { - for (int32_t j = 0; j < pQueryAttr->pExpr1[i].base.numOfParams; ++j) { - buildArithmeticExprFromMsg(&pQueryAttr->pExpr1[i], NULL); - } - } - } + return pToken->type; +} - pQueryAttr->tableCols = calloc(numOfCols, sizeof(SColumnInfo)); - for(int32_t i = 0; i < numOfCols; ++i) { - SColumn* pCol = taosArrayGetP(pQueryInfo->colList, i); - if (!isValidDataType(pCol->info.type) || pCol->info.type == TSDB_DATA_TYPE_NULL) { - assert(0); - } +static bool isNullStr(SToken *pToken) { + return (pToken->type == TK_NULL) || ((pToken->type == TK_STRING) && (pToken->n != 0) && + (strncasecmp(TSDB_DATA_NULL_STR_L, pToken->z, pToken->n) == 0)); +} - pQueryAttr->tableCols[i] = pCol->info; - pQueryAttr->tableCols[i].flist.filterInfo = tFilterInfoDup(pCol->info.flist.filterInfo, pQueryAttr->tableCols[i].flist.numOfFilters); +static FORCE_INLINE int32_t checkAndTrimValue(SToken* pToken, uint32_t type, char* tmpTokenBuf, SMsgBuf* pMsgBuf) { + if ((type != TK_NOW && type != TK_INTEGER && type != TK_STRING && type != TK_FLOAT && type != TK_BOOL && + type != TK_NULL && type != TK_HEX && type != TK_OCT && type != TK_BIN) || + (pToken->n == 0) || (type == TK_RP)) { + return buildSyntaxErrMsg(pMsgBuf, "invalid data or symbol", pToken->z); } - // global aggregate query - if (pQueryAttr->stableQuery && (pQueryAttr->simpleAgg || pQueryAttr->interval.interval > 0) && tscIsTwoStageSTableQuery(pQueryInfo, 0)) { - createGlobalAggregateExpr(pQueryAttr, pQueryInfo); + if (IS_NUMERIC_TYPE(type) && pToken->n == 0) { + return buildSyntaxErrMsg(pMsgBuf, "invalid numeric data", pToken->z); } - // for simple table, not for super table - if (pQueryInfo->arithmeticOnAgg) { - pQueryAttr->numOfExpr2 = (int32_t) taosArrayGetSize(pQueryInfo->exprList1); - pQueryAttr->pExpr2 = calloc(pQueryAttr->numOfExpr2, sizeof(SExprInfo)); - for(int32_t i = 0; i < pQueryAttr->numOfExpr2; ++i) { - SExprInfo* p = taosArrayGetP(pQueryInfo->exprList1, i); - ExprInfoCopy(&pQueryAttr->pExpr2[i], p); + // Remove quotation marks + if (TK_STRING == type) { + if (pToken->n >= TSDB_MAX_BYTES_PER_ROW) { + return buildSyntaxErrMsg(pMsgBuf, "too long string", pToken->z); } - } - // tag column info - int32_t code = createTagColumnInfo(pQueryAttr, pQueryInfo, pTableMetaInfo); - if (code != TSDB_CODE_SUCCESS) { - return code; - } - - if (pQueryAttr->fillType != TSDB_FILL_NONE) { - pQueryAttr->fillVal = calloc(pQueryAttr->numOfOutput, sizeof(int64_t)); - memcpy(pQueryAttr->fillVal, pQueryInfo->fillVal, pQueryInfo->numOfFillVal * sizeof(int64_t)); - } - - pQueryAttr->srcRowSize = 0; - pQueryAttr->maxTableColumnWidth = 0; - for (int16_t i = 0; i < numOfCols; ++i) { - pQueryAttr->srcRowSize += pQueryAttr->tableCols[i].bytes; - if (pQueryAttr->maxTableColumnWidth < pQueryAttr->tableCols[i].bytes) { - pQueryAttr->maxTableColumnWidth = pQueryAttr->tableCols[i].bytes; + // delete escape character: \\, \', \" + char delim = pToken->z[0]; + int32_t cnt = 0; + int32_t j = 0; + for (uint32_t k = 1; k < pToken->n - 1; ++k) { + if (pToken->z[k] == '\\' || (pToken->z[k] == delim && pToken->z[k + 1] == delim)) { + tmpTokenBuf[j] = pToken->z[k + 1]; + cnt++; + j++; + k++; + continue; + } + tmpTokenBuf[j] = pToken->z[k]; + j++; } + + tmpTokenBuf[j] = 0; + pToken->z = tmpTokenBuf; + pToken->n -= 2 + cnt; } - pQueryAttr->interBufSize = getOutputInterResultBufSize(pQueryAttr); + return TSDB_CODE_SUCCESS; +} - if (pQueryAttr->numOfCols <= 0 && !tscQueryTags(pQueryInfo) && !pQueryAttr->queryBlockDist) { - tscError("%p illegal value of numOfCols in query msg: %" PRIu64 ", table cols:%d", addr, - (uint64_t)pQueryAttr->numOfCols, numOfCols); +static int parseTime(char **end, SToken *pToken, int16_t timePrec, int64_t *time, SMsgBuf* pMsgBuf) { + int32_t index = 0; + SToken sToken; + int64_t interval; + int64_t ts = 0; + char* pTokenEnd = *end; + + if (pToken->type == TK_NOW) { + ts = taosGetTimestamp(timePrec); + } else if (pToken->type == TK_INTEGER) { + bool isSigned = false; + toInteger(pToken->z, pToken->n, 10, &ts, &isSigned); + } else { // parse the RFC-3339/ISO-8601 timestamp format string + if (taosParseTime(pToken->z, time, pToken->n, timePrec, tsDaylight) != TSDB_CODE_SUCCESS) { + return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp format", pToken->z); + } - return TSDB_CODE_TSC_INVALID_OPERATION; + return TSDB_CODE_SUCCESS; } - if (pQueryAttr->interval.interval < 0) { - tscError("%p illegal value of aggregation time interval in query msg: %" PRId64, addr, - (int64_t)pQueryInfo->interval.interval); - return TSDB_CODE_TSC_INVALID_OPERATION; - } + for (int k = pToken->n; pToken->z[k] != '\0'; k++) { + if (pToken->z[k] == ' ' || pToken->z[k] == '\t') continue; + if (pToken->z[k] == ',') { + *end = pTokenEnd; + *time = ts; + return 0; + } - if (pQueryAttr->pGroupbyExpr != NULL && pQueryAttr->pGroupbyExpr->numOfGroupCols < 0) { - tscError("%p illegal value of numOfGroupCols in query msg: %d", addr, pQueryInfo->groupbyExpr.numOfGroupCols); - return TSDB_CODE_TSC_INVALID_OPERATION; + break; } - return TSDB_CODE_SUCCESS; -} + /* + * time expression: + * e.g., now+12a, now-5h + */ + SToken valueToken; + index = 0; + sToken = tStrGetToken(pTokenEnd, &index, false); + pTokenEnd += index; -static int32_t doAddTableName(char* nextStr, char** str, SArray* pNameArray, SSqlObj* pSql) { - int32_t code = TSDB_CODE_SUCCESS; - SSqlCmd* pCmd = &pSql->cmd; + if (sToken.type == TK_MINUS || sToken.type == TK_PLUS) { + index = 0; + valueToken = tStrGetToken(pTokenEnd, &index, false); + pTokenEnd += index; - char tablename[TSDB_TABLE_FNAME_LEN] = {0}; - int32_t len = 0; + if (valueToken.n < 2) { + return buildSyntaxErrMsg(pMsgBuf, "value expected in timestamp", sToken.z); + } - if (nextStr == NULL) { - tstrncpy(tablename, *str, TSDB_TABLE_FNAME_LEN); - len = (int32_t) strlen(tablename); - } else { - len = (int32_t)(nextStr - (*str)); - if (len >= TSDB_TABLE_NAME_LEN) { - sprintf(pCmd->payload, "table name too long"); + char unit = 0; + if (parseAbsoluteDuration(valueToken.z, valueToken.n, &interval, &unit, timePrec) != TSDB_CODE_SUCCESS) { return TSDB_CODE_TSC_INVALID_OPERATION; } - memcpy(tablename, *str, nextStr - (*str)); - tablename[len] = '\0'; + if (sToken.type == TK_PLUS) { + ts += interval; + } else { + ts = ts - interval; + } + + *end = pTokenEnd; } - (*str) = nextStr + 1; - len = (int32_t)strtrim(tablename); + *time = ts; + return TSDB_CODE_SUCCESS; +} - SToken sToken = {.n = len, .type = TK_ID, .z = tablename}; - tGetToken(tablename, &sToken.type); +int32_t parseValueToken(char** end, SToken* pToken, SSchema* pSchema, int16_t timePrec, char* tmpTokenBuf, _row_append_fn_t func, void* param, SMsgBuf* pMsgBuf) { + int64_t iv; + char *endptr = NULL; + bool isSigned = false; - // Check if the table name available or not - if (tscValidateName(&sToken) != TSDB_CODE_SUCCESS) { - sprintf(pCmd->payload, "table name is invalid"); - return TSDB_CODE_TSC_INVALID_TABLE_ID_LENGTH; - } - - SName name = {0}; - if ((code = tscSetTableFullName(&name, &sToken, pSql)) != TSDB_CODE_SUCCESS) { + int32_t code = checkAndTrimValue(pToken, pSchema->type, tmpTokenBuf, pMsgBuf); + if (code != TSDB_CODE_SUCCESS) { return code; } - memset(tablename, 0, tListLen(tablename)); - tNameExtractFullName(&name, tablename); - - char* p = strdup(tablename); - taosArrayPush(pNameArray, &p); - return TSDB_CODE_SUCCESS; -} + if (isNullStr(pToken)) { + if (TSDB_DATA_TYPE_TIMESTAMP == pSchema->type && PRIMARYKEY_TIMESTAMP_COL_ID == pSchema->colId) { + int64_t tmpVal = 0; + return func(&tmpVal, pSchema->bytes, param); + } -int32_t nameComparFn(const void* n1, const void* n2) { - int32_t ret = strcmp(*(char**)n1, *(char**)n2); - if (ret == 0) { - return 0; - } else { - return ret > 0? 1:-1; + return func(getNullValue(pSchema->type), 0, param); } -} -static void freeContent(void* p) { - char* ptr = *(char**)p; - tfree(ptr); -} + switch (pSchema->type) { + case TSDB_DATA_TYPE_BOOL: { + if ((pToken->type == TK_BOOL || pToken->type == TK_STRING) && (pToken->n != 0)) { + if (strncmp(pToken->z, "true", pToken->n) == 0) { + return func(&TRUE_VALUE, pSchema->bytes, param); + } else if (strncmp(pToken->z, "false", pToken->n) == 0) { + return func(&FALSE_VALUE, pSchema->bytes, param); + } else { + return buildSyntaxErrMsg(pMsgBuf, "invalid bool data", pToken->z); + } + } else if (pToken->type == TK_INTEGER) { + return func(((strtoll(pToken->z, NULL, 10) == 0) ? &FALSE_VALUE : &TRUE_VALUE), pSchema->bytes, param); + } else if (pToken->type == TK_FLOAT) { + return func(((strtod(pToken->z, NULL) == 0) ? &FALSE_VALUE : &TRUE_VALUE), pSchema->bytes, param); + } else { + return buildSyntaxErrMsg(pMsgBuf, "invalid bool data", pToken->z); + } + } + case TSDB_DATA_TYPE_TINYINT: { + if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, pToken->type, &iv, &isSigned)) { + return buildSyntaxErrMsg(pMsgBuf, "invalid tinyint data", pToken->z); + } else if (!IS_VALID_TINYINT(iv)) { + return buildSyntaxErrMsg(pMsgBuf, "tinyint data overflow", pToken->z); + } -int tscTransferTableNameList(SSqlObj *pSql, const char *pNameList, int32_t length, SArray* pNameArray) { - SSqlCmd *pCmd = &pSql->cmd; + uint8_t tmpVal = (uint8_t)iv; + return func(&tmpVal, pSchema->bytes, param); + } - pCmd->command = TSDB_SQL_MULTI_META; - pCmd->msgType = TDMT_VND_TABLES_META; + case TSDB_DATA_TYPE_UTINYINT:{ + if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, pToken->type, &iv, &isSigned)) { + return buildSyntaxErrMsg(pMsgBuf, "invalid unsigned tinyint data", pToken->z); + } else if (!IS_VALID_UTINYINT(iv)) { + return buildSyntaxErrMsg(pMsgBuf, "unsigned tinyint data overflow", pToken->z); + } + uint8_t tmpVal = (uint8_t)iv; + return func(&tmpVal, pSchema->bytes, param); + } - int code = TSDB_CODE_TSC_INVALID_TABLE_ID_LENGTH; - char *str = (char *)pNameList; + case TSDB_DATA_TYPE_SMALLINT: { + if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, pToken->type, &iv, &isSigned)) { + return buildSyntaxErrMsg(pMsgBuf, "invalid smallint data", pToken->z); + } else if (!IS_VALID_SMALLINT(iv)) { + return buildSyntaxErrMsg(pMsgBuf, "smallint data overflow", pToken->z); + } + int16_t tmpVal = (int16_t)iv; + return func(&tmpVal, pSchema->bytes, param); + } - SQueryStmtInfo *pQueryInfo = tscGetQueryInfoS(pCmd); - if (pQueryInfo == NULL) { - pSql->res.code = terrno; - return terrno; - } + case TSDB_DATA_TYPE_USMALLINT: { + if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, pToken->type, &iv, &isSigned)) { + return buildSyntaxErrMsg(pMsgBuf, "invalid unsigned smallint data", pToken->z); + } else if (!IS_VALID_USMALLINT(iv)) { + return buildSyntaxErrMsg(pMsgBuf, "unsigned smallint data overflow", pToken->z); + } + uint16_t tmpVal = (uint16_t)iv; + return func(&tmpVal, pSchema->bytes, param); + } - char *nextStr; - while (1) { - nextStr = strchr(str, ','); - if (nextStr == NULL) { - code = doAddTableName(nextStr, &str, pNameArray, pSql); - break; + case TSDB_DATA_TYPE_INT: { + if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, pToken->type, &iv, &isSigned)) { + return buildSyntaxErrMsg(pMsgBuf, "invalid int data", pToken->z); + } else if (!IS_VALID_INT(iv)) { + return buildSyntaxErrMsg(pMsgBuf, "int data overflow", pToken->z); + } + int32_t tmpVal = (int32_t)iv; + return func(&tmpVal, pSchema->bytes, param); } - code = doAddTableName(nextStr, &str, pNameArray, pSql); - if (code != TSDB_CODE_SUCCESS) { - return code; + case TSDB_DATA_TYPE_UINT: { + if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, pToken->type, &iv, &isSigned)) { + return buildSyntaxErrMsg(pMsgBuf, "invalid unsigned int data", pToken->z); + } else if (!IS_VALID_UINT(iv)) { + return buildSyntaxErrMsg(pMsgBuf, "unsigned int data overflow", pToken->z); + } + uint32_t tmpVal = (uint32_t)iv; + return func(&tmpVal, pSchema->bytes, param); } - if (taosArrayGetSize(pNameArray) > TSDB_MULTI_TABLEMETA_MAX_NUM) { - code = TSDB_CODE_TSC_INVALID_TABLE_ID_LENGTH; - sprintf(pCmd->payload, "tables over the max number"); - return code; + case TSDB_DATA_TYPE_BIGINT: { + if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, pToken->type, &iv, &isSigned)) { + return buildSyntaxErrMsg(pMsgBuf, "invalid bigint data", pToken->z); + } else if (!IS_VALID_BIGINT(iv)) { + return buildSyntaxErrMsg(pMsgBuf, "bigint data overflow", pToken->z); + } + return func(&iv, pSchema->bytes, param); } - } - size_t len = taosArrayGetSize(pNameArray); - if (len == 1) { - return TSDB_CODE_SUCCESS; - } + case TSDB_DATA_TYPE_UBIGINT: { + if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, pToken->type, &iv, &isSigned)) { + return buildSyntaxErrMsg(pMsgBuf, "invalid unsigned bigint data", pToken->z); + } else if (!IS_VALID_UBIGINT((uint64_t)iv)) { + return buildSyntaxErrMsg(pMsgBuf, "unsigned bigint data overflow", pToken->z); + } + uint64_t tmpVal = (uint64_t)iv; + return func(&tmpVal, pSchema->bytes, param); + } - if (len > TSDB_MULTI_TABLEMETA_MAX_NUM) { - code = TSDB_CODE_TSC_INVALID_TABLE_ID_LENGTH; - sprintf(pCmd->payload, "tables over the max number"); - return code; - } + case TSDB_DATA_TYPE_FLOAT: { + double dv; + if (TK_ILLEGAL == toDouble(pToken, &dv, &endptr)) { + return buildSyntaxErrMsg(pMsgBuf, "illegal float data", pToken->z); + } + if (((dv == HUGE_VAL || dv == -HUGE_VAL) && errno == ERANGE) || dv > FLT_MAX || dv < -FLT_MAX || isinf(dv) || isnan(dv)) { + return buildSyntaxErrMsg(pMsgBuf, "illegal float data", pToken->z); + } + float tmpVal = (float)dv; + return func(&tmpVal, pSchema->bytes, param); + } - taosArraySort(pNameArray, nameComparFn); - taosArrayRemoveDuplicate(pNameArray, nameComparFn, freeContent); - return TSDB_CODE_SUCCESS; -} + case TSDB_DATA_TYPE_DOUBLE: { + double dv; + if (TK_ILLEGAL == toDouble(pToken, &dv, &endptr)) { + return buildSyntaxErrMsg(pMsgBuf, "illegal double data", pToken->z); + } + if (((dv == HUGE_VAL || dv == -HUGE_VAL) && errno == ERANGE) || isinf(dv) || isnan(dv)) { + return buildSyntaxErrMsg(pMsgBuf, "illegal double data", pToken->z); + } + return func(&dv, pSchema->bytes, param); + } -bool vgroupInfoIdentical(SNewVgroupInfo *pExisted, SVgroupMsg* src) { - assert(pExisted != NULL && src != NULL); - if (pExisted->numOfEps != src->numOfEps) { - return false; - } + case TSDB_DATA_TYPE_BINARY: { + // Too long values will raise the invalid sql error message + if (pToken->n + VARSTR_HEADER_SIZE > pSchema->bytes) { + return buildSyntaxErrMsg(pMsgBuf, "string data overflow", pToken->z); + } - for(int32_t i = 0; i < pExisted->numOfEps; ++i) { - if (pExisted->ep[i].port != src->epAddr[i].port) { - return false; + return func(pToken->z, pToken->n, param); } - if (strncmp(pExisted->ep[i].fqdn, src->epAddr[i].fqdn, tListLen(pExisted->ep[i].fqdn)) != 0) { - return false; + case TSDB_DATA_TYPE_NCHAR: { + return func(pToken->z, pToken->n, param); } - } - - return true; -} - -SNewVgroupInfo createNewVgroupInfo(SVgroupMsg *pVgroupMsg) { - assert(pVgroupMsg != NULL); - SNewVgroupInfo info = {0}; - info.numOfEps = pVgroupMsg->numOfEps; - info.vgId = pVgroupMsg->vgId; - info.inUse = 0; // 0 is the default value of inUse in case of multiple replica + case TSDB_DATA_TYPE_TIMESTAMP: { + int64_t tmpVal; + if (parseTime(end, pToken, timePrec, &tmpVal, pMsgBuf) != TSDB_CODE_SUCCESS) { + return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp", pToken->z); + } - assert(info.numOfEps >= 1 && info.vgId >= 1); - for(int32_t i = 0; i < pVgroupMsg->numOfEps; ++i) { - tstrncpy(info.ep[i].fqdn, pVgroupMsg->epAddr[i].fqdn, TSDB_FQDN_LEN); - info.ep[i].port = pVgroupMsg->epAddr[i].port; + return func(&tmpVal, pSchema->bytes, param); + } } - return info; + return TSDB_CODE_FAILED; } -char* cloneCurrentDBName(SSqlObj* pSql) { - char *p = NULL; - HttpContext *pCtx = NULL; +int32_t KvRowAppend(const void *value, int32_t len, void *param) { + SKvParam* pa = (SKvParam*) param; - pthread_mutex_lock(&pSql->pTscObj->mutex); - STscObj *pTscObj = pSql->pTscObj; - switch (pTscObj->from) { - case TAOS_REQ_FROM_HTTP: - pCtx = pSql->param; - if (pCtx && pCtx->db[0] != '\0') { - char db[TSDB_DB_FNAME_LEN] = {0}; - int32_t len = sprintf(db, "%s%s%s", pTscObj->acctId, TS_PATH_DELIMITER, pCtx->db); - assert(len <= sizeof(db)); + int32_t type = pa->schema->type; + int32_t colId = pa->schema->colId; - p = strdup(db); - } - break; - default: - break; - } - if (p == NULL) { - p = strdup(pSql->pTscObj->db); - } - pthread_mutex_unlock(&pSql->pTscObj->mutex); + if (TSDB_DATA_TYPE_BINARY == type) { + STR_WITH_SIZE_TO_VARSTR(pa->buf, value, len); + tdAddColToKVRow(pa->builder, colId, type, pa->buf); + } else if (TSDB_DATA_TYPE_NCHAR == type) { + // if the converted output len is over than pColumnModel->bytes, return error: 'Argument list too long' + int32_t output = 0; + if (!taosMbsToUcs4(value, len, varDataVal(pa->buf), pa->schema->bytes - VARSTR_HEADER_SIZE, &output)) { + return TSDB_CODE_TSC_SQL_SYNTAX_ERROR; + } - return p; -} + varDataSetLen(pa->buf, output); + tdAddColToKVRow(pa->builder, colId, type, pa->buf); + } else { + tdAddColToKVRow(pa->builder, colId, type, value); + } -#endif \ No newline at end of file + return TSDB_CODE_SUCCESS; +} \ No newline at end of file -- GitLab