From d2fdfd900d6804218c29ad2ee645a1e97e69eb9b Mon Sep 17 00:00:00 2001 From: Haolin Wang Date: Mon, 16 Dec 2024 15:50:54 +0800 Subject: [PATCH] morefix: not allow duplicate table names in stmt2 bind with interlace mode --- source/client/src/clientMain.c | 30 +++++++++++++++++++++++++ tests/script/api/stmt2-insert-dupkeys.c | 27 ++++++++++++++++++++-- 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/source/client/src/clientMain.c b/source/client/src/clientMain.c index 3d22c26fa7cf..f377f830e162 100644 --- a/source/client/src/clientMain.c +++ b/source/client/src/clientMain.c @@ -2166,9 +2166,37 @@ int taos_stmt2_bind_param(TAOS_STMT2 *stmt, TAOS_STMT2_BINDV *bindv, int32_t col pStmt->semWaited = true; } + /* + * Insert with interlace mode doesn't allow duplicate table names per bind, + * so initialize a tbnames hash table for duplication check. + * + * Note, STMT doesn't have such issue as it's unable to bind multiple tables. + */ + SSHashObj *hashTbnames = tSimpleHashInit(100, taosGetDefaultHashFunction(TSDB_DATA_TYPE_VARCHAR)); + if (NULL == hashTbnames) { + tscError("stmt2 bind failed: out of memory"); + terrno = TSDB_CODE_OUT_OF_MEMORY; + return terrno; + } + int32_t code = 0; for (int i = 0; i < bindv->count; ++i) { if (bindv->tbnames && bindv->tbnames[i]) { + if (pStmt->sql.stbInterlaceMode) { + if (tSimpleHashGet(hashTbnames, bindv->tbnames[i], strlen(bindv->tbnames[i])) != NULL) { + tSimpleHashCleanup(hashTbnames); + tscError("stmt2 bind failed: duplicate table name %s is not allowed in interlace mode.", bindv->tbnames[i]); + terrno = TSDB_CODE_PAR_TBNAME_DUPLICATED; + return terrno; + } + + code = tSimpleHashPut(hashTbnames, bindv->tbnames[i], strlen(bindv->tbnames[i]), NULL, 0); + if (TSDB_CODE_SUCCESS != code) { + tSimpleHashCleanup(hashTbnames); + return code; + } + } + code = stmtSetTbName2(stmt, bindv->tbnames[i]); if (code) { return code; @@ -2206,6 +2234,8 @@ int taos_stmt2_bind_param(TAOS_STMT2 *stmt, TAOS_STMT2_BINDV *bindv, int32_t col } } + tSimpleHashCleanup(hashTbnames); + return TSDB_CODE_SUCCESS; } diff --git a/tests/script/api/stmt2-insert-dupkeys.c b/tests/script/api/stmt2-insert-dupkeys.c index c056e1bcb040..adab3ddf396e 100644 --- a/tests/script/api/stmt2-insert-dupkeys.c +++ b/tests/script/api/stmt2-insert-dupkeys.c @@ -145,7 +145,7 @@ void insert_dist(TAOS* taos, const char *sql) { UINIT(tbs, ts, ts_len, b, b_len, tags, paramv); } -void insert_dup(TAOS* taos, const char *sql) { +void insert_dup_rows(TAOS* taos, const char *sql) { char **tbs, **b; int64_t **ts; int *ts_len, *b_len; @@ -169,6 +169,27 @@ void insert_dup(TAOS* taos, const char *sql) { UINIT(tbs, ts, ts_len, b, b_len, tags, paramv); } +void insert_dup_tables(TAOS* taos, const char *sql) { + char **tbs, **b; + int64_t **ts; + int *ts_len, *b_len; + TAOS_STMT2_BIND **paramv, **tags; + + INIT(tbs, ts, ts_len, b, b_len, tags, paramv); + + for (int i = 0; i < CTB_NUMS; i++) { + sprintf(tbs[i], "ctb_%d", i % 2); + } + + for (int i = 0; i < CTB_NUMS; i++) { + paramv[i][0] = (TAOS_STMT2_BIND){TSDB_DATA_TYPE_TIMESTAMP, &ts[i][0], &ts_len[0], NULL, ROW_NUMS}; + paramv[i][1] = (TAOS_STMT2_BIND){TSDB_DATA_TYPE_BINARY, &b[i][0], &b_len[0], NULL, ROW_NUMS}; + } + insert(taos, tbs, tags, paramv, sql); + + UINIT(tbs, ts, ts_len, b, b_len, tags, paramv); +} + int main() { TAOS* taos = taos_connect("localhost", "root", "taosdata", "", 0); if (!taos) { @@ -180,7 +201,9 @@ int main() { // insert distinct rows insert_dist(taos, "insert into db.? using db.stb tags(?,?)values(?,?)"); // insert duplicate rows - insert_dup(taos, "insert into db.? values(?,?)"); + insert_dup_rows(taos, "insert into db.? values(?,?)"); + // insert duplicate tables + insert_dup_tables(taos, "insert into db.? values(?,?)"); taos_close(taos); taos_cleanup();