From 5dcb75d43c6548d286d8cdb365870668cf22dfa5 Mon Sep 17 00:00:00 2001 From: "pengrongkun94@qq.com" Date: Thu, 2 Jan 2025 20:07:58 +0800 Subject: [PATCH] fix TD-33417 --- source/client/test/stmt2Test.cpp | 145 +++++++++++++++++-------- source/libs/parser/inc/parInsertUtil.h | 1 + source/libs/parser/src/parInsertSql.c | 71 +++++++++--- 3 files changed, 153 insertions(+), 64 deletions(-) diff --git a/source/client/test/stmt2Test.cpp b/source/client/test/stmt2Test.cpp index ee6fa7a9e1..e4dc9c3005 100644 --- a/source/client/test/stmt2Test.cpp +++ b/source/client/test/stmt2Test.cpp @@ -371,11 +371,11 @@ TEST(stmt2Case, insert_stb_get_fields_Test) { // not support case printf("not support case \n"); - // case 5 : add in main TD-33353 + // case 1 : add in main TD-33353 { const char* sql = "insert into db.stb(t1,t2,ts,b,tbname) values(1,?,?,'abc',?)"; - printf("case 2 : %s\n", sql); - getFieldsError(taos, sql, TSDB_CODE_TSC_INVALID_OPERATION); + printf("case 1dif : %s\n", sql); + getFieldsError(taos, sql, TSDB_CODE_PAR_INVALID_COLUMNS_NUM); } // case 2 : no pk @@ -431,7 +431,7 @@ TEST(stmt2Case, insert_stb_get_fields_Test) { { const char* sql = "insert into db.stb(t1,t2,ts,b,tbname) values(*,*,*,*,*)"; printf("case 9 : %s\n", sql); - getFieldsError(taos, sql, TSDB_CODE_TSC_INVALID_OPERATION); + getFieldsError(taos, sql, TSDB_CODE_PAR_INVALID_COLUMNS_NUM); } taos_close(taos); @@ -830,57 +830,108 @@ TEST(stmt2Case, stmt2_stb_insert) { taos_close(taos); } -// TEST(stmt2Case, stmt2_insert_all_types) { -// TAOS* taos = taos_connect("localhost", "root", "taosdata", "", 0); -// ASSERT_NE(taos, nullptr); -// do_query(taos, "drop database if exists example_all_type_stmt1"); -// do_query(taos, "create database example_all_type_stmt1"); -// do_query(taos, -// "create table example_all_type_stmt1.stb (ts timestamp, int_col int,long_col bigint,double_col " -// "double,bool_col bool,binary_col binary(20),nchar_col nchar(20),varbinary_col varbinary(20),geometry_col " -// "geometry(200)) tags(int_tag int,long_tag bigint,double_tag double,bool_tag bool,binary_tag " -// "binary(20),nchar_tag nchar(20),varbinary_tag varbinary(20),geometry_tag geometry(200));"); +// TD-33417 +TEST(stmt2Case, stmt2_insert_non_statndard) { + TAOS* taos = taos_connect("localhost", "root", "taosdata", "", 0); + ASSERT_NE(taos, nullptr); + do_query(taos, "drop database if exists example_all_type_stmt1"); + do_query(taos, "create database example_all_type_stmt1"); + do_query(taos, + "create table example_all_type_stmt1.stb1 (ts timestamp, int_col int,long_col bigint,double_col " + "double,bool_col bool,binary_col binary(20),nchar_col nchar(20),varbinary_col varbinary(20),geometry_col " + "geometry(200)) tags(int_tag int,long_tag bigint,double_tag double,bool_tag bool,binary_tag " + "binary(20),nchar_tag nchar(20),varbinary_tag varbinary(20),geometry_tag geometry(200));"); -// TAOS_STMT2_OPTION option = {0, false, false, NULL, NULL}; + TAOS_STMT2_OPTION option = {0, false, false, NULL, NULL}; -// TAOS_STMT2* stmt = taos_stmt2_init(taos, &option); -// ASSERT_NE(stmt, nullptr); + // less cols and tags + { + TAOS_STMT2* stmt = taos_stmt2_init(taos, &option); + ASSERT_NE(stmt, nullptr); + const char* sql = "INSERT INTO example_all_type_stmt1.stb1 (ts,int_tag,tbname) VALUES (?,?,?)"; + int code = taos_stmt2_prepare(stmt, sql, 0); + ASSERT_EQ(code, 0); -// const char* sql = -// "INSERT INTO `example_all_type_stmt1`.`stb1` " -// "(ts,int_col,long_col,double_col,bool_col,binary_col,nchar_col,varbinary_col,geometry_col,int_tag,long_tag," -// "double_tag,bool_tag,binary_tag,nchar_tag,varbinary_tag ,geometry_tag,tbname) VALUES " -// "(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"; -// int code = taos_stmt2_prepare(stmt, sql, 0); -// ASSERT_EQ(code, 0); + int t64_len[2] = {sizeof(int64_t), sizeof(int64_t)}; + int tag_i = 0; + int tag_l = sizeof(int); + int64_t ts[2] = {1591060628000, 1591060628100}; + for (int i = 0; i < 3; i++) { + ts[0] += 1000; + ts[1] += 1000; -// int t64_len[1] = {sizeof(int64_t)}; -// int b_len[1] = {3}; -// int64_t ts = 1591060628000; -// TAOS_STMT2_BIND params[18] = {{TSDB_DATA_TYPE_TIMESTAMP, &ts, t64_len, NULL, 1}}; -// TAOS_STMT2_BIND* paramv = ¶ms[0]; -// char* tbname = "tb1"; -// TAOS_STMT2_BINDV bindv = {1, &tbname, NULL, ¶mv}; -// code = taos_stmt2_bind_param(stmt, &bindv, -1); -// ASSERT_EQ(code, 0); + TAOS_STMT2_BIND tags1 = {TSDB_DATA_TYPE_INT, &tag_i, &tag_l, NULL, 1}; + TAOS_STMT2_BIND tags2 = {TSDB_DATA_TYPE_INT, &tag_i, &tag_l, NULL, 1}; + TAOS_STMT2_BIND params1 = {TSDB_DATA_TYPE_TIMESTAMP, &ts, &t64_len[0], NULL, 2}; + TAOS_STMT2_BIND params2 = {TSDB_DATA_TYPE_TIMESTAMP, &ts, &t64_len[0], NULL, 2}; -// taos_stmt2_exec(stmt, NULL); -// ASSERT_EQ(code, 0); + TAOS_STMT2_BIND* tagv[2] = {&tags1, &tags2}; + TAOS_STMT2_BIND* paramv[2] = {¶ms1, ¶ms2}; + char* tbname[2] = {"tb1", "tb2"}; + TAOS_STMT2_BINDV bindv = {2, &tbname[0], &tagv[0], ¶mv[0]}; + code = taos_stmt2_bind_param(stmt, &bindv, -1); + ASSERT_EQ(code, 0); -// TAOS_RES* pRes = taos_stmt2_result(stmt); -// ASSERT_NE(pRes, nullptr); + int affected_rows; + taos_stmt2_exec(stmt, &affected_rows); + ASSERT_EQ(code, 0); + } -// int getRecordCounts = 0; -// TAOS_ROW row; -// while ((row = taos_fetch_row(pRes))) { -// getRecordCounts++; -// } -// ASSERT_EQ(getRecordCounts, 1); -// taos_free_result(pRes); + checkRows(taos, "select * from example_all_type_stmt1.tb1", 6); + checkRows(taos, "select * from example_all_type_stmt1.tb2", 6); + checkRows(taos, "select * from example_all_type_stmt1.stb1", 12); + taos_stmt2_close(stmt); + } -// taos_stmt2_close(stmt); -// taos_close(taos); -// } + // disorder cols and tags + { + TAOS_STMT2* stmt = taos_stmt2_init(taos, &option); + ASSERT_NE(stmt, nullptr); + const char* sql = + "INSERT INTO example_all_type_stmt1.stb1 (binary_tag,int_col,tbname,ts,int_tag) VALUES (?,?,?,?,?)"; + int code = taos_stmt2_prepare(stmt, sql, 0); + ASSERT_EQ(code, 0); + + int tag_i = 0; + int tag_l = sizeof(int); + int tag_bl = 3; + int64_t ts[2] = {1591060628000, 1591060628100}; + int t64_len[2] = {sizeof(int64_t), sizeof(int64_t)}; + int coli[2] = {1, 2}; + int ilen[2] = {sizeof(int), sizeof(int)}; + for (int i = 0; i < 3; i++) { + ts[0] += 1000; + ts[1] += 1000; + + TAOS_STMT2_BIND tags1[2] = {{TSDB_DATA_TYPE_BINARY, (void*)"abc", &tag_bl, NULL, 1}, + {TSDB_DATA_TYPE_INT, &tag_i, &tag_l, NULL, 1}}; + TAOS_STMT2_BIND tags2[2] = {{TSDB_DATA_TYPE_BINARY, (void*)"abc", &tag_bl, NULL, 1}, + {TSDB_DATA_TYPE_INT, &tag_i, &tag_l, NULL, 1}}; + TAOS_STMT2_BIND params1[2] = {{TSDB_DATA_TYPE_INT, &coli, &ilen[0], NULL, 2}, + {TSDB_DATA_TYPE_TIMESTAMP, &ts, &t64_len[0], NULL, 2}}; + TAOS_STMT2_BIND params2[2] = {{TSDB_DATA_TYPE_INT, &coli, &ilen[0], NULL, 2}, + {TSDB_DATA_TYPE_TIMESTAMP, &ts, &t64_len[0], NULL, 2}}; + + TAOS_STMT2_BIND* tagv[2] = {&tags1[0], &tags2[0]}; + TAOS_STMT2_BIND* paramv[2] = {¶ms1[0], ¶ms2[0]}; + char* tbname[2] = {"tb3", "tb4"}; + TAOS_STMT2_BINDV bindv = {2, &tbname[0], &tagv[0], ¶mv[0]}; + code = taos_stmt2_bind_param(stmt, &bindv, -1); + ASSERT_EQ(code, 0); + + int affected_rows; + taos_stmt2_exec(stmt, &affected_rows); + ASSERT_EQ(code, 0); + } + + checkRows(taos, "select * from example_all_type_stmt1.tb3", 6); + checkRows(taos, "select * from example_all_type_stmt1.tb4", 6); + checkRows(taos, "select * from example_all_type_stmt1.stb1", 24); + taos_stmt2_close(stmt); + } + + taos_close(taos); +} TEST(stmt2Case, stmt2_query) { TAOS* taos = taos_connect("localhost", "root", "taosdata", "", 0); diff --git a/source/libs/parser/inc/parInsertUtil.h b/source/libs/parser/inc/parInsertUtil.h index c5cce55d9a..b2a585d881 100644 --- a/source/libs/parser/inc/parInsertUtil.h +++ b/source/libs/parser/inc/parInsertUtil.h @@ -50,6 +50,7 @@ int32_t insInitColValues(STableMeta *pTableMeta, SArray *aColValues); void insCheckTableDataOrder(STableDataCxt *pTableCxt, SRowKey *rowKey); int32_t insGetTableDataCxt(SHashObj *pHash, void *id, int32_t idLen, STableMeta *pTableMeta, SVCreateTbReq **pCreateTbReq, STableDataCxt **pTableCxt, bool colMode, bool ignoreColVals); +int32_t initTableColSubmitDataWithBoundInfo(STableDataCxt *pTableCxt, SBoundColInfo pBoundColsInfo); int32_t initTableColSubmitData(STableDataCxt *pTableCxt); int32_t insMergeTableDataCxt(SHashObj *pTableHash, SArray **pVgDataBlocks, bool isRebuild); //int32_t insMergeStmtTableDataCxt(STableDataCxt* pTableCxt, SArray* pTableList, SArray** pVgDataBlocks, bool isRebuild, int32_t tbNum); diff --git a/source/libs/parser/src/parInsertSql.c b/source/libs/parser/src/parInsertSql.c index 128fb50b8f..e39a885529 100644 --- a/source/libs/parser/src/parInsertSql.c +++ b/source/libs/parser/src/parInsertSql.c @@ -1446,6 +1446,27 @@ int32_t initTableColSubmitData(STableDataCxt* pTableCxt) { return TSDB_CODE_SUCCESS; } +int32_t initTableColSubmitDataWithBoundInfo(STableDataCxt* pTableCxt, SBoundColInfo pBoundColsInfo) { + insDestroyBoundColInfo(&(pTableCxt->boundColsInfo)); + pTableCxt->boundColsInfo = pBoundColsInfo; + pTableCxt->boundColsInfo.pColIndex = taosMemoryCalloc(pBoundColsInfo.numOfBound - 1, sizeof(int16_t)); + if (NULL == pTableCxt->boundColsInfo.pColIndex) { + return terrno; + } + (void)memcpy(pTableCxt->boundColsInfo.pColIndex, pBoundColsInfo.pColIndex, + sizeof(int16_t) * pBoundColsInfo.numOfBound - 1); + for (int32_t i = 0; i < pBoundColsInfo.numOfBound; ++i) { + SSchema* pSchema = &pTableCxt->pMeta->schema[pTableCxt->boundColsInfo.pColIndex[i]]; + SColData* pCol = taosArrayReserve(pTableCxt->pData->aCol, 1); + if (NULL == pCol) { + return terrno; + } + tColDataInit(pCol, pSchema->colId, pSchema->type, pSchema->flags); + } + + return TSDB_CODE_SUCCESS; +} + // input pStmt->pSql: // 1. [(tag1_name, ...)] ... // 2. VALUES ... | FILE ... @@ -1815,7 +1836,7 @@ static int32_t processCtbTagsAfterCtbName(SInsertParseContext* pCxt, SVnodeModif static int32_t doGetStbRowValues(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, const char** ppSql, SStbRowsDataContext* pStbRowsCxt, SToken* pToken, const SBoundColInfo* pCols, const SSchema* pSchemas, SToken* tagTokens, SSchema** tagSchemas, int* pNumOfTagTokens, - bool* bFoundTbName) { + bool* bFoundTbName, bool* setCtbName, SBoundColInfo* ctbCols) { int32_t code = TSDB_CODE_SUCCESS; SArray* pTagNames = pStbRowsCxt->aTagNames; SArray* pTagVals = pStbRowsCxt->aTagVals; @@ -1824,7 +1845,8 @@ static int32_t doGetStbRowValues(SInsertParseContext* pCxt, SVnodeModifyOpStmt* int32_t numOfTags = getNumOfTags(pStbRowsCxt->pStbMeta); int32_t tbnameIdx = getTbnameSchemaIndex(pStbRowsCxt->pStbMeta); uint8_t precision = getTableInfo(pStbRowsCxt->pStbMeta).precision; - int idx = 0; + int tag_index = 0; + int col_index = 0; for (int i = 0; i < pCols->numOfBound && (code) == TSDB_CODE_SUCCESS; ++i) { const char* pTmpSql = *ppSql; bool ignoreComma = false; @@ -1847,6 +1869,7 @@ static int32_t doGetStbRowValues(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pCxt->isStmtBind = true; pStmt->usingTableProcessing = true; if (pCols->pColIndex[i] == tbnameIdx) { + *bFoundTbName = true; char* tbName = NULL; if ((*pCxt->pComCxt->pStmtCb->getTbNameFn)(pCxt->pComCxt->pStmtCb->pStmt, &tbName) == TSDB_CODE_SUCCESS) { tstrncpy(pStbRowsCxt->ctbName.tname, tbName, sizeof(pStbRowsCxt->ctbName.tname)); @@ -1855,10 +1878,20 @@ static int32_t doGetStbRowValues(SInsertParseContext* pCxt, SVnodeModifyOpStmt* tstrncpy(pStmt->usingTableName.dbname, pStmt->targetTableName.dbname, sizeof(pStmt->usingTableName.dbname)); pStmt->usingTableName.type = 1; pStmt->pTableMeta->tableType = TSDB_CHILD_TABLE; // set the table type to child table for parse cache - *bFoundTbName = true; + *setCtbName = true; } } else if (pCols->pColIndex[i] < numOfCols) { // bind column + if (ctbCols->pColIndex == NULL) { + ctbCols->pColIndex = taosMemoryCalloc(numOfCols, sizeof(int16_t)); + if (NULL == ctbCols->pColIndex) { + return terrno; + } + } + ctbCols->pColIndex[col_index++] = pCols->pColIndex[i]; + ctbCols->numOfBound++; + ctbCols->numOfCols++; + } else if (pCols->pColIndex[i] < tbnameIdx) { if (pCxt->tags.pColIndex == NULL) { pCxt->tags.pColIndex = taosMemoryCalloc(numOfTags, sizeof(int16_t)); @@ -1866,10 +1899,10 @@ static int32_t doGetStbRowValues(SInsertParseContext* pCxt, SVnodeModifyOpStmt* return terrno; } } - if (!(idx < numOfTags)) { + if (!(tag_index < numOfTags)) { return buildInvalidOperationMsg(&pCxt->msg, "not expected numOfTags"); } - pCxt->tags.pColIndex[idx++] = pCols->pColIndex[i] - numOfCols; + pCxt->tags.pColIndex[tag_index++] = pCols->pColIndex[i] - numOfCols; pCxt->tags.mixTagsCols = true; pCxt->tags.numOfBound++; pCxt->tags.numOfCols++; @@ -1927,7 +1960,8 @@ static int32_t doGetStbRowValues(SInsertParseContext* pCxt, SVnodeModifyOpStmt* } static int32_t getStbRowValues(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, const char** ppSql, - SStbRowsDataContext* pStbRowsCxt, bool* pGotRow, SToken* pToken, bool* pCtbFirst) { + SStbRowsDataContext* pStbRowsCxt, bool* pGotRow, SToken* pToken, bool* pCtbFirst, + bool* setCtbName, SBoundColInfo* ctbCols) { SBoundColInfo* pCols = &pStbRowsCxt->boundColsInfo; SSchema* pSchemas = getTableColumnSchema(pStbRowsCxt->pStbMeta); @@ -1940,19 +1974,14 @@ static int32_t getStbRowValues(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pS int numOfTagTokens = 0; code = doGetStbRowValues(pCxt, pStmt, ppSql, pStbRowsCxt, pToken, pCols, pSchemas, tagTokens, tagSchemas, - &numOfTagTokens, &bFoundTbName); + &numOfTagTokens, &bFoundTbName, setCtbName, ctbCols); if (code != TSDB_CODE_SUCCESS) { return code; } if (!bFoundTbName) { - if (!pCxt->isStmtBind) { - code = buildSyntaxErrMsg(&pCxt->msg, "tbname value expected", pOrigSql); - } else { - *pGotRow = true; - return TSDB_CODE_TSC_STMT_TBNAME_ERROR; - } + code = buildSyntaxErrMsg(&pCxt->msg, "tbname value expected", pOrigSql); } bool ctbFirst = true; @@ -2079,9 +2108,11 @@ static int32_t parseOneStbRow(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pSt SStbRowsDataContext* pStbRowsCxt, bool* pGotRow, SToken* pToken, STableDataCxt** ppTableDataCxt) { bool bFirstTable = false; - int32_t code = getStbRowValues(pCxt, pStmt, ppSql, pStbRowsCxt, pGotRow, pToken, &bFirstTable); + bool setCtbName = false; + SBoundColInfo ctbCols = {0}; + int32_t code = getStbRowValues(pCxt, pStmt, ppSql, pStbRowsCxt, pGotRow, pToken, &bFirstTable, &setCtbName, &ctbCols); - if (code == TSDB_CODE_TSC_STMT_TBNAME_ERROR && *pGotRow) { + if (!setCtbName && pCxt->isStmtBind) { return parseStbBoundInfo(pStmt, pStbRowsCxt, ppTableDataCxt); } @@ -2108,7 +2139,13 @@ static int32_t parseOneStbRow(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pSt } } if (code == TSDB_CODE_SUCCESS) { - code = initTableColSubmitData(*ppTableDataCxt); + if (pCxt->isStmtBind) { + int32_t tbnameIdx = getTbnameSchemaIndex(pStbRowsCxt->pStbMeta); + code = initTableColSubmitDataWithBoundInfo(*ppTableDataCxt, ctbCols); + insDestroyBoundColInfo(&ctbCols); + } else { + code = initTableColSubmitData(*ppTableDataCxt); + } } if (code == TSDB_CODE_SUCCESS && !pCxt->isStmtBind) { SRow** pRow = taosArrayReserve((*ppTableDataCxt)->pData->aRowP, 1); @@ -3177,7 +3214,7 @@ int32_t parseInsertSql(SParseContext* pCxt, SQuery** pQuery, SCatalogReq* pCatal .forceUpdate = (NULL != pCatalogReq ? pCatalogReq->forceUpdate : false), .isStmtBind = pCxt->isStmtBind}; - int32_t code = initInsertQuery(&context, pCatalogReq, pMetaData, pQuery); + int32_t code = initInsertQuery(&context, pCatalogReq, pMetaData, pQuery); if (TSDB_CODE_SUCCESS == code) { code = parseInsertSqlImpl(&context, (SVnodeModifyOpStmt*)((*pQuery)->pRoot)); }