diff --git a/source/libs/parser/inc/parInsertUtil.h b/source/libs/parser/inc/parInsertUtil.h index 5cc72f86923762454c8cae66ef9bbc7828b9ef05..9dd4daec3b3905740aa8ee2d25bcbd7751279aec 100644 --- a/source/libs/parser/inc/parInsertUtil.h +++ b/source/libs/parser/inc/parInsertUtil.h @@ -22,11 +22,11 @@ struct SToken; #define IS_DATA_COL_ORDERED(spd) ((spd->orderStatus) == (int8_t)ORDER_STATUS_ORDERED) -#define NEXT_TOKEN(pSql, sToken) \ - do { \ - int32_t index = 0; \ - sToken = tStrGetToken(pSql, &index, false); \ - pSql += index; \ +#define NEXT_TOKEN(pSql, sToken) \ + do { \ + int32_t index = 0; \ + sToken = tStrGetToken(pSql, &index, false, NULL); \ + pSql += index; \ } while (0) #define CHECK_CODE(expr) \ diff --git a/source/libs/parser/inc/parToken.h b/source/libs/parser/inc/parToken.h index fb4b46aa35094fd3ac65171c5499c038eb92d233..d539e8b37bfbab8cd0995f2f77c8228809b07f7e 100644 --- a/source/libs/parser/inc/parToken.h +++ b/source/libs/parser/inc/parToken.h @@ -55,7 +55,7 @@ uint32_t tGetToken(const char *z, uint32_t *tokenType); * @param isPrevOptr * @return */ -SToken tStrGetToken(const char *str, int32_t *i, bool isPrevOptr); +SToken tStrGetToken(const char *str, int32_t *i, bool isPrevOptr, bool *pIgnoreComma); /** * check if it is a keyword or not diff --git a/source/libs/parser/src/parInsertSql.c b/source/libs/parser/src/parInsertSql.c index 1e1821842fb39139d961fae78b9dfad6f294a5d4..2e6c3a5fb1822cb8034763be3dd893b04b9277b3 100644 --- a/source/libs/parser/src/parInsertSql.c +++ b/source/libs/parser/src/parInsertSql.c @@ -18,16 +18,23 @@ #include "tglobal.h" #include "ttime.h" -#define NEXT_TOKEN_WITH_PREV(pSql, token) \ - do { \ - int32_t index = 0; \ - token = tStrGetToken(pSql, &index, true); \ - pSql += index; \ +#define NEXT_TOKEN_WITH_PREV(pSql, token) \ + do { \ + int32_t index = 0; \ + token = tStrGetToken(pSql, &index, true, NULL); \ + pSql += index; \ } while (0) -#define NEXT_TOKEN_KEEP_SQL(pSql, token, index) \ - do { \ - token = tStrGetToken(pSql, &index, false); \ +#define NEXT_TOKEN_WITH_PREV_EXT(pSql, token, pIgnoreComma) \ + do { \ + int32_t index = 0; \ + token = tStrGetToken(pSql, &index, true, pIgnoreComma); \ + pSql += index; \ + } while (0) + +#define NEXT_TOKEN_KEEP_SQL(pSql, token, index) \ + do { \ + token = tStrGetToken(pSql, &index, false, NULL); \ } while (0) #define NEXT_VALID_TOKEN(pSql, token) \ @@ -302,12 +309,12 @@ static int parseTime(const char** end, SToken* pToken, int16_t timePrec, int64_t * e.g., now+12a, now-5h */ index = 0; - SToken token = tStrGetToken(pTokenEnd, &index, false); + SToken token = tStrGetToken(pTokenEnd, &index, false, NULL); pTokenEnd += index; if (token.type == TK_NK_MINUS || token.type == TK_NK_PLUS) { index = 0; - SToken valueToken = tStrGetToken(pTokenEnd, &index, false); + SToken valueToken = tStrGetToken(pTokenEnd, &index, false, NULL); pTokenEnd += index; if (valueToken.n < 2) { @@ -1240,10 +1247,14 @@ static int parseOneRow(SInsertParseContext* pCxt, const char** pSql, STableDataB int32_t code = tdSRowResetBuf(pBuilder, row); // 1. set the parsed value from sql string for (int i = 0; i < pCols->numOfBound && TSDB_CODE_SUCCESS == code; ++i) { - NEXT_TOKEN_WITH_PREV(*pSql, *pToken); - SSchema* pSchema = &pSchemas[pCols->boundColumns[i]]; + const char* pOrigSql = *pSql; + bool ignoreComma = false; + NEXT_TOKEN_WITH_PREV_EXT(*pSql, *pToken, &ignoreComma); + if (ignoreComma) { + code = buildSyntaxErrMsg(&pCxt->msg, "invalid data or symbol", pOrigSql); + } - if (pToken->type == TK_NK_QUESTION) { + if (TSDB_CODE_SUCCESS == code && pToken->type == TK_NK_QUESTION) { isParseBindParam = true; if (NULL == pCxt->pComCxt->pStmtCb) { code = buildSyntaxErrMsg(&pCxt->msg, "? only used in stmt", pToken->z); @@ -1260,10 +1271,10 @@ static int parseOneRow(SInsertParseContext* pCxt, const char** pSql, STableDataB } if (TSDB_CODE_SUCCESS == code) { - param.schema = pSchema; + param.schema = &pSchemas[pCols->boundColumns[i]]; insGetSTSRowAppendInfo(pBuilder->rowType, pCols, i, ¶m.toffset, ¶m.colIdx); - code = parseValueToken(pCxt, pSql, pToken, pSchema, getTableInfo(pDataBuf->pTableMeta).precision, insMemRowAppend, - ¶m); + code = parseValueToken(pCxt, pSql, pToken, param.schema, getTableInfo(pDataBuf->pTableMeta).precision, + insMemRowAppend, ¶m); } if (TSDB_CODE_SUCCESS == code && i < pCols->numOfBound - 1) { diff --git a/source/libs/parser/src/parTokenizer.c b/source/libs/parser/src/parTokenizer.c index e62b2f0f5ab2db843d41009bb21e68a60f19cd67..6a96ff9c504c957b86d91ea96075a98da76e4478 100644 --- a/source/libs/parser/src/parTokenizer.c +++ b/source/libs/parser/src/parTokenizer.c @@ -620,7 +620,7 @@ uint32_t tGetToken(const char* z, uint32_t* tokenId) { return 0; } -SToken tStrGetToken(const char* str, int32_t* i, bool isPrevOptr) { +SToken tStrGetToken(const char* str, int32_t* i, bool isPrevOptr, bool* pIgnoreComma) { SToken t0 = {0}; // here we reach the end of sql string, null-terminated string @@ -641,6 +641,10 @@ SToken tStrGetToken(const char* str, int32_t* i, bool isPrevOptr) { return t0; } + if (NULL != pIgnoreComma && t == ',') { + *pIgnoreComma = true; + } + t = str[++(*i)]; } diff --git a/source/libs/parser/src/parser.c b/source/libs/parser/src/parser.c index cf338d63ff43182330d2f1e229aa2a03070feb6a..47482db7400f98c839c112d93e503b20d25f8073 100644 --- a/source/libs/parser/src/parser.c +++ b/source/libs/parser/src/parser.c @@ -27,7 +27,7 @@ bool qIsInsertValuesSql(const char* pStr, size_t length) { const char* pSql = pStr; int32_t index = 0; - SToken t = tStrGetToken((char*)pStr, &index, false); + SToken t = tStrGetToken((char*)pStr, &index, false, NULL); if (TK_INSERT != t.type && TK_IMPORT != t.type) { return false; } @@ -35,7 +35,7 @@ bool qIsInsertValuesSql(const char* pStr, size_t length) { do { pStr += index; index = 0; - t = tStrGetToken((char*)pStr, &index, false); + t = tStrGetToken((char*)pStr, &index, false, NULL); if (TK_USING == t.type || TK_VALUES == t.type || TK_FILE == t.type) { return true; } else if (TK_SELECT == t.type) {