From b444e18d901ce1b01769affabef64fe9bbc3272b Mon Sep 17 00:00:00 2001 From: xjzhou Date: Tue, 25 Jun 2024 16:16:32 +0800 Subject: [PATCH 1/2] enh: stmt supports 'insert into db.?' --- include/libs/parser/parser.h | 1 + source/client/inc/clientStmt.h | 1 + source/client/src/clientStmt.c | 22 ++++++++++++++ source/libs/parser/src/parInsertSql.c | 14 +++++++++ source/libs/parser/src/parTokenizer.c | 5 ++-- source/libs/parser/src/parser.c | 41 +++++++++++++++++++++++++++ 6 files changed, 82 insertions(+), 2 deletions(-) diff --git a/include/libs/parser/parser.h b/include/libs/parser/parser.h index 4c4505544b..ad41b9a542 100644 --- a/include/libs/parser/parser.h +++ b/include/libs/parser/parser.h @@ -101,6 +101,7 @@ typedef struct SParseContext { int32_t qParseSql(SParseContext* pCxt, SQuery** pQuery); bool qIsInsertValuesSql(const char* pStr, size_t length); +bool qParseDbName(const char* pStr, size_t length, char** pDbName); // for async mode int32_t qParseSqlSyntax(SParseContext* pCxt, SQuery** pQuery, struct SCatalogReq* pCatalogReq); diff --git a/source/client/inc/clientStmt.h b/source/client/inc/clientStmt.h index 64b2acf732..68765ee47a 100644 --- a/source/client/inc/clientStmt.h +++ b/source/client/inc/clientStmt.h @@ -219,6 +219,7 @@ const char *stmtErrstr(TAOS_STMT *stmt); int stmtAffectedRows(TAOS_STMT *stmt); int stmtAffectedRowsOnce(TAOS_STMT *stmt); int stmtPrepare(TAOS_STMT *stmt, const char *sql, unsigned long length); +int stmtSetDbName(TAOS_STMT* stmt, const char* dbName); int stmtSetTbName(TAOS_STMT *stmt, const char *tbName); int stmtSetTbTags(TAOS_STMT *stmt, TAOS_MULTI_BIND *tags); int stmtGetTagFields(TAOS_STMT *stmt, int *nums, TAOS_FIELD_E **fields); diff --git a/source/client/src/clientStmt.c b/source/client/src/clientStmt.c index 32d31585ea..baf2750ac8 100644 --- a/source/client/src/clientStmt.c +++ b/source/client/src/clientStmt.c @@ -900,6 +900,12 @@ int stmtPrepare(TAOS_STMT* stmt, const char* sql, unsigned long length) { pStmt->sql.sqlLen = length; pStmt->sql.stbInterlaceMode = pStmt->stbInterlaceMode; + char* dbName = NULL; + if (qParseDbName(sql, length, &dbName)) { + stmtSetDbName(stmt, dbName); + taosMemoryFreeClear(dbName); + } + return TSDB_CODE_SUCCESS; } @@ -929,6 +935,22 @@ int32_t stmtInitStbInterlaceTableInfo(STscStmt* pStmt) { return TSDB_CODE_SUCCESS; } +int stmtSetDbName(TAOS_STMT* stmt, const char* dbName) { + STscStmt *pStmt = (STscStmt *) stmt; + + STMT_DLOG("start to set dbName: %s", dbName); + + STMT_ERR_RET(stmtCreateRequest(pStmt)); + + // The SQL statement specifies a database name, overriding the previously specified database + taosMemoryFreeClear(pStmt->exec.pRequest->pDb); + pStmt->exec.pRequest->pDb = taosStrdup(dbName); + if (pStmt->exec.pRequest->pDb == NULL) { + return TSDB_CODE_OUT_OF_MEMORY; + } + return TSDB_CODE_SUCCESS; +} + int stmtSetTbName(TAOS_STMT* stmt, const char* tbName) { STscStmt* pStmt = (STscStmt*)stmt; diff --git a/source/libs/parser/src/parInsertSql.c b/source/libs/parser/src/parInsertSql.c index 53b9805267..2c142da259 100644 --- a/source/libs/parser/src/parInsertSql.c +++ b/source/libs/parser/src/parInsertSql.c @@ -2427,6 +2427,20 @@ static int32_t checkTableClauseFirstToken(SInsertParseContext* pCxt, SVnodeModif return buildSyntaxErrMsg(&pCxt->msg, "table_name is expected", pTbName->z); } + // db.? situation,ensure that the only thing following the '.' mark is '?' + char *tbNameAfterDbName = strchr(pTbName->z, '.'); + if ((tbNameAfterDbName != NULL) && (tbNameAfterDbName + 1 - pTbName->z == pTbName->n - 1) && + (*(tbNameAfterDbName + 1) == '?')) { + char *tbName = NULL; + int32_t code = (*pCxt->pComCxt->pStmtCb->getTbNameFn)(pCxt->pComCxt->pStmtCb->pStmt, &tbName); + if (TSDB_CODE_SUCCESS == code) { + pTbName->z = tbName; + pTbName->n = strlen(tbName); + } else { + return code; + } + } + *pHasData = true; return TSDB_CODE_SUCCESS; } diff --git a/source/libs/parser/src/parTokenizer.c b/source/libs/parser/src/parTokenizer.c index ff48f81fc1..53ea19f416 100644 --- a/source/libs/parser/src/parTokenizer.c +++ b/source/libs/parser/src/parTokenizer.c @@ -781,8 +781,9 @@ SToken tStrGetToken(const char* str, int32_t* i, bool isPrevOptr, bool* pIgnoreC if ('.' == str[*i + t0.n]) { len = tGetToken(&str[*i + t0.n + 1], &type); - // only id and string are valid - if (((TK_NK_STRING != t0.type) && (TK_NK_ID != t0.type)) || ((TK_NK_STRING != type) && (TK_NK_ID != type))) { + // only id、string and ? are valid + if (((TK_NK_STRING != t0.type) && (TK_NK_ID != t0.type)) || + ((TK_NK_STRING != type) && (TK_NK_ID != type) && (TK_NK_QUESTION != type))) { t0.type = TK_NK_ILLEGAL; t0.n = 0; diff --git a/source/libs/parser/src/parser.c b/source/libs/parser/src/parser.c index bdeccafa36..c0c834a97b 100644 --- a/source/libs/parser/src/parser.c +++ b/source/libs/parser/src/parser.c @@ -48,6 +48,47 @@ bool qIsInsertValuesSql(const char* pStr, size_t length) { return false; } +bool qParseDbName(const char* pStr, size_t length, char** pDbName) { + (void)length; + int32_t index = 0; + SToken t; + + if (NULL == pStr) { + *pDbName = NULL; + return false; + } + + t = tStrGetToken((char *)pStr, &index, false, NULL); + if (TK_INSERT != t.type && TK_IMPORT != t.type) { + *pDbName = NULL; + return false; + } + + t = tStrGetToken((char *)pStr, &index, false, NULL); + if (TK_INTO != t.type) { + *pDbName = NULL; + return false; + } + + t = tStrGetToken((char *)pStr, &index, false, NULL); + if (t.n == 0 || t.z == NULL) { + *pDbName = NULL; + return false; + } + char *dotPos = strchr(t.z, '.'); + if (dotPos != NULL) { + int dbNameLen = dotPos - t.z; + *pDbName = taosMemoryMalloc(dbNameLen + 1); + if (NULL == *pDbName) { + return false; + } + strncpy(*pDbName, t.z, dbNameLen); + (*pDbName)[dbNameLen] = '\0'; + return true; + } + return false; +} + static int32_t analyseSemantic(SParseContext* pCxt, SQuery* pQuery, SParseMetaCache* pMetaCache) { int32_t code = authenticate(pCxt, pQuery, pMetaCache); From 42361fcd458ba145054c441ab967109f97f2a30a Mon Sep 17 00:00:00 2001 From: xjzhou Date: Wed, 26 Jun 2024 16:38:21 +0800 Subject: [PATCH 2/2] fix: failed to identify dbName when only ? exists --- source/libs/parser/src/parser.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/source/libs/parser/src/parser.c b/source/libs/parser/src/parser.c index c0c834a97b..a5cbe90598 100644 --- a/source/libs/parser/src/parser.c +++ b/source/libs/parser/src/parser.c @@ -49,7 +49,7 @@ bool qIsInsertValuesSql(const char* pStr, size_t length) { } bool qParseDbName(const char* pStr, size_t length, char** pDbName) { - (void)length; + (void) length; int32_t index = 0; SToken t; @@ -58,28 +58,28 @@ bool qParseDbName(const char* pStr, size_t length, char** pDbName) { return false; } - t = tStrGetToken((char *)pStr, &index, false, NULL); + t = tStrGetToken((char *) pStr, &index, false, NULL); if (TK_INSERT != t.type && TK_IMPORT != t.type) { *pDbName = NULL; return false; } - t = tStrGetToken((char *)pStr, &index, false, NULL); + t = tStrGetToken((char *) pStr, &index, false, NULL); if (TK_INTO != t.type) { *pDbName = NULL; return false; } - t = tStrGetToken((char *)pStr, &index, false, NULL); + t = tStrGetToken((char *) pStr, &index, false, NULL); if (t.n == 0 || t.z == NULL) { *pDbName = NULL; return false; } - char *dotPos = strchr(t.z, '.'); + char *dotPos = strnchr(t.z, '.', t.n, true); if (dotPos != NULL) { int dbNameLen = dotPos - t.z; *pDbName = taosMemoryMalloc(dbNameLen + 1); - if (NULL == *pDbName) { + if (*pDbName == NULL) { return false; } strncpy(*pDbName, t.z, dbNameLen);