diff --git a/driver/class/ClientSidePreparedStatement.cpp b/driver/class/ClientSidePreparedStatement.cpp index 00f4ddee..0b4d3eff 100644 --- a/driver/class/ClientSidePreparedStatement.cpp +++ b/driver/class/ClientSidePreparedStatement.cpp @@ -236,7 +236,7 @@ namespace mariadb if (!metadata) { loadParametersData(); } - return metadata.get(); + return metadata.release(); } diff --git a/driver/ma_bulk.cpp b/driver/ma_bulk.cpp index 8be09f9b..1ae6ecde 100644 --- a/driver/ma_bulk.cpp +++ b/driver/ma_bulk.cpp @@ -473,7 +473,7 @@ SQLRETURN MADB_ExecuteBulk(MADB_Stmt *Stmt, unsigned int ParamOffset) if (Stmt->stmt->isServerSide() && !MADB_ServerSupports(Stmt->Connection, MADB_CAPABLE_PARAM_ARRAYS)) { - Stmt->stmt.reset(new ClientSidePreparedStatement(Stmt->Connection->guard.get(), STMT_STRING(Stmt), Stmt->Options.CursorType + MADB_CXX_RESET(Stmt->stmt, new ClientSidePreparedStatement(Stmt->Connection->guard.get(), STMT_STRING(Stmt), Stmt->Options.CursorType , Stmt->Query.NoBackslashEscape)); // So far useCallbacks= false; diff --git a/driver/ma_desc.cpp b/driver/ma_desc.cpp index b74900fe..a9b24655 100644 --- a/driver/ma_desc.cpp +++ b/driver/ma_desc.cpp @@ -356,6 +356,7 @@ MADB_DescSetIrdMetadata(MADB_Stmt *Stmt, const MYSQL_FIELD *Fields, unsigned int { return 1; } + Stmt->Ird->Header.Count= i + 1; } return 0; } @@ -638,32 +639,34 @@ void MADB_DescSetRecordDefaults(MADB_Desc *Desc, MADB_DescRecord *Record) } /* }}} */ -/* {{{ MADB_DescGetInternalRecord */ -MADB_DescRecord *MADB_DescGetInternalRecord(MADB_Desc *Desc, SQLSMALLINT RecordNumber, SQLSMALLINT Type) +/* {{{ MADB_DescGetInternalRecord + [in] ReorordNumber - 0 based record index */ +MADB_DescRecord* MADB_DescGetInternalRecord(MADB_Desc *Desc, SQLSMALLINT RecordNumber, SQLSMALLINT Type) { MADB_DescRecord *DescRecord; - if (RecordNumber > (SQLINTEGER)Desc->Records.elements && - Type == MADB_DESC_READ) + if (RecordNumber >= (SQLINTEGER)Desc->Records.elements) { - MADB_SetError(&Desc->Error, MADB_ERR_07009, nullptr, 0); - return nullptr; - } - - while (RecordNumber >= (SQLINTEGER)Desc->Records.elements) - { - if (!(DescRecord= (MADB_DescRecord *)MADB_AllocDynamic(&Desc->Records))) + if (Type == MADB_DESC_READ) { - MADB_SetError(&Desc->Error, MADB_ERR_HY001, nullptr, 0); + MADB_SetError(&Desc->Error, MADB_ERR_07009, nullptr, 0); return nullptr; } - - MADB_DescSetRecordDefaults(Desc, DescRecord); + + do { + if (!(DescRecord= (MADB_DescRecord *)MADB_AllocDynamic(&Desc->Records))) + { + MADB_SetError(&Desc->Error, MADB_ERR_HY001, nullptr, 0); + return nullptr; + } + + MADB_DescSetRecordDefaults(Desc, DescRecord); + } while (RecordNumber >= (SQLINTEGER)Desc->Records.elements); + + if (RecordNumber + 1 > Desc->Header.Count) + Desc->Header.Count= (SQLSMALLINT)(RecordNumber + 1); } - if (RecordNumber + 1 > Desc->Header.Count) - Desc->Header.Count= (SQLSMALLINT)(RecordNumber + 1); - DescRecord= ((MADB_DescRecord *)Desc->Records.buffer) + RecordNumber; return DescRecord; diff --git a/driver/ma_helper.cpp b/driver/ma_helper.cpp index d7b27f87..39ef6f45 100644 --- a/driver/ma_helper.cpp +++ b/driver/ma_helper.cpp @@ -257,9 +257,10 @@ MYSQL_RES *MADB_GetDefaultColumnValues(MADB_Stmt *Stmt, const MYSQL_FIELD *field for (i= 0; i < Stmt->metadata->getColumnCount(); i++) { + // TODO: Shouldn't it be really IRD here? MADB_DescRecord* Rec= MADB_DescGetInternalRecord(Stmt->Ard, i, MADB_DESC_READ); - if (!Rec->inUse || MADB_ColumnIgnoredInAllRows(Stmt->Ard, Rec) == TRUE) + if (!Rec || !Rec->inUse || MADB_ColumnIgnoredInAllRows(Stmt->Ard, Rec) == TRUE) { continue; } @@ -864,7 +865,7 @@ void* GetBindOffset(MADB_Header& Header, void* Ptr, SQLULEN RowNumber, std::size } /* Checking if column ignored in all bound rows. Should hel*/ -BOOL MADB_ColumnIgnoredInAllRows(MADB_Desc *Desc, MADB_DescRecord *Rec) +bool MADB_ColumnIgnoredInAllRows(MADB_Desc *Desc, MADB_DescRecord *Rec) { SQLULEN row; SQLLEN *IndicatorPtr; @@ -873,13 +874,13 @@ BOOL MADB_ColumnIgnoredInAllRows(MADB_Desc *Desc, MADB_DescRecord *Rec) { IndicatorPtr= (SQLLEN *)GetBindOffset(Desc->Header, Rec->IndicatorPtr, row, sizeof(SQLLEN)); - if (IndicatorPtr == NULL || *IndicatorPtr != SQL_COLUMN_IGNORE) + if (IndicatorPtr == nullptr || *IndicatorPtr != SQL_COLUMN_IGNORE) { - return FALSE; + return false; } } - return TRUE; + return true; } diff --git a/driver/ma_helper.h b/driver/ma_helper.h index 7889ab36..26869f15 100644 --- a/driver/ma_helper.h +++ b/driver/ma_helper.h @@ -53,7 +53,7 @@ const char * MADB_GetTypeName(const MYSQL_FIELD *Field); my_bool MADB_CheckPtrLength(SQLINTEGER MaxLength, char *Ptr, SQLINTEGER NameLen); std::size_t getArrayStep(MADB_Header& header, std::size_t pointedSize); void * GetBindOffset(MADB_Header& DescHeader, void *Ptr, SQLULEN RowNumber, size_t PtrSize); -BOOL MADB_ColumnIgnoredInAllRows(MADB_Desc *Desc, MADB_DescRecord *Rec); +bool MADB_ColumnIgnoredInAllRows(MADB_Desc *Desc, MADB_DescRecord *Rec); SQLRETURN MADB_DaeStmt(MADB_Stmt *Stmt, SQLUSMALLINT Operation); MYSQL_RES * MADB_GetDefaultColumnValues(MADB_Stmt *Stmt, const MYSQL_FIELD *fields); @@ -109,4 +109,7 @@ extern my_bool DummyError; #define MADB_FRACTIONAL_PART(_decimals) ((_decimals) > 0 ? (_decimals) + 1/*Decimal point*/ : 0) +#define MADB_DELETE(PTR) do {delete (PTR); (PTR)= nullptr;} while(false) +#define MADB_CXX_RESET(PTR,NEWPTR) do {delete (PTR); (PTR)= (NEWPTR);} while(false) + #endif diff --git a/driver/ma_info.cpp b/driver/ma_info.cpp index 50233770..4d07cc56 100644 --- a/driver/ma_info.cpp +++ b/driver/ma_info.cpp @@ -247,10 +247,10 @@ SQLRETURN MADB_GetTypeInfo(SQLHSTMT StatementHandle, std::vector> row; - Stmt->stmt.reset(); + MADB_DELETE(Stmt->stmt); if (DataType == SQL_ALL_TYPES) { - Stmt->rs.reset(ResultSet::createResultSet(TypeInfoColumnName, TypeInfoColumnType, *TypeInfo)); + MADB_CXX_RESET(Stmt->rs, ResultSet::createResultSet(TypeInfoColumnName, TypeInfoColumnType, *TypeInfo)); } else { @@ -262,7 +262,7 @@ SQLRETURN MADB_GetTypeInfo(SQLHSTMT StatementHandle, row.push_back(cit); } } - Stmt->rs.reset(ResultSet::createResultSet(TypeInfoColumnName, TypeInfoColumnType, row)); + MADB_CXX_RESET(Stmt->rs, ResultSet::createResultSet(TypeInfoColumnName, TypeInfoColumnType, row)); } Stmt->State= MADB_SS_EXECUTED; diff --git a/driver/ma_odbc.h b/driver/ma_odbc.h index df83399e..29bd56c2 100644 --- a/driver/ma_odbc.h +++ b/driver/ma_odbc.h @@ -291,9 +291,9 @@ struct MADB_Stmt long long AffectedRows= 0; MADB_Dbc *Connection; struct st_ma_stmt_methods *Methods; - Unique::ResultSet rs; - Unique::PreparedStatement stmt; - Unique::ResultSetMetaData metadata; + ResultSet* rs= nullptr; + PreparedStatement* stmt= nullptr; + mariadb::ResultSetMetaData* metadata= nullptr; Unique::MYSQL_RES DefaultsResult; MADB_DescRecord *PutDataRec= nullptr; MADB_Stmt *DaeStmt= nullptr; diff --git a/driver/ma_parse.cpp b/driver/ma_parse.cpp index d49bf41f..6c27856f 100644 --- a/driver/ma_parse.cpp +++ b/driver/ma_parse.cpp @@ -119,7 +119,7 @@ void MADB_QUERY::reset() Original.assign(""); RefinedText.assign(""); Tokens.clear(); - PoorManParsing= ReturnsResult= false; + PoorManParsing= false; } int MADB_ParseQuery(MADB_QUERY * Query) @@ -397,8 +397,6 @@ int ParseQuery(MADB_QUERY *Query) /* We are currently at 2nd token of statement, and getting previous token position from Tokens array*/ StmtType= MADB_GetQueryType(MADB_Token(Query, Query->Tokens.size() - 2), p); - Query->ReturnsResult= Query->ReturnsResult || !QUERY_DOESNT_RETURN_RESULT(StmtType); - /* If we on first statement, setting QueryType*/ if (Query->Tokens.size() == 2) { diff --git a/driver/ma_parse.h b/driver/ma_parse.h index ded7c1b6..14931752 100644 --- a/driver/ma_parse.h +++ b/driver/ma_parse.h @@ -61,8 +61,6 @@ typedef struct { SQLString RefinedText; enum enum_madb_query_type QueryType= MADB_QUERY_NO_RESULT; bool MultiStatement= false; - /* Keeping it so far */ - bool ReturnsResult= false; bool PoorManParsing= false; bool BatchAllowed= false; diff --git a/driver/ma_result.cpp b/driver/ma_result.cpp index 0777ec7e..a0ac9f5e 100644 --- a/driver/ma_result.cpp +++ b/driver/ma_result.cpp @@ -153,8 +153,8 @@ SQLRETURN MADB_StmtMoreResults(SQLHSTMT StatementHandle) /* We can't have it in MADB_StmtResetResultStructures, as it breaks dyn_cursor functionality. Thus we free-ing bind structs on move to new result only */ MADB_FREE(Stmt->result); - Stmt->metadata.reset(); - Stmt->rs.reset(); + MADB_DELETE(Stmt->metadata); + MADB_DELETE(Stmt->rs); try { // TODO: that's not right to mess here with Protocol's lock. Protocol should take care of that @@ -163,7 +163,7 @@ SQLRETURN MADB_StmtMoreResults(SQLHSTMT StatementHandle) { unsigned int ServerStatus; mariadb_get_infov(Stmt->Connection->mariadb, MARIADB_CONNECTION_SERVER_STATUS, (void*)&ServerStatus); - Stmt->rs.reset(Stmt->stmt->getResultSet()); + MADB_CXX_RESET(Stmt->rs, Stmt->stmt->getResultSet()); bool itsOutParams= ServerStatus & SERVER_PS_OUT_PARAMS; bool haveOutParams= HasOutParams(Stmt); @@ -198,7 +198,7 @@ SQLRETURN MADB_StmtMoreResults(SQLHSTMT StatementHandle) ret= MADB_FromException(Stmt->Error, e); } catch (int32_t /*rc*/) { - ret= MADB_SetNativeError(&Stmt->Error, SQL_HANDLE_STMT, Stmt->stmt.get()); + ret= MADB_SetNativeError(&Stmt->Error, SQL_HANDLE_STMT, Stmt->stmt); } MADB_StmtResetResultStructures(Stmt); diff --git a/driver/ma_statement.cpp b/driver/ma_statement.cpp index 0839219f..9a5275be 100644 --- a/driver/ma_statement.cpp +++ b/driver/ma_statement.cpp @@ -82,12 +82,12 @@ SQLRETURN MADB_StmtFree(MADB_Stmt *Stmt, SQLUSMALLINT Option) MADB_DescFree(Stmt->Ird, TRUE); if (Stmt->State > MADB_SS_PREPARED) { - MDBUG_C_PRINT(Stmt->Connection, "Closing resultset", Stmt->stmt.get()); + MDBUG_C_PRINT(Stmt->Connection, "Closing resultset", Stmt->stmt); try { // TODO: that's not right to mess here with Protocol's lock. Protocol should take care of that std::lock_guard localScopeLock(Stmt->Connection->guard->getLock()); - Stmt->rs.reset(); + MADB_DELETE(Stmt->rs); if (Stmt->stmt->hasMoreResults()) { Stmt->Connection->guard->skipAllResults(); } @@ -97,8 +97,7 @@ SQLRETURN MADB_StmtFree(MADB_Stmt *Stmt, SQLUSMALLINT Option) // eating errors } } - - Stmt->metadata.reset(); + MADB_DELETE(Stmt->metadata); MADB_FREE(Stmt->result); MADB_FREE(Stmt->CharOffset); @@ -127,7 +126,7 @@ SQLRETURN MADB_StmtFree(MADB_Stmt *Stmt, SQLUSMALLINT Option) MADB_FREE(Stmt->CatalogName); MADB_FREE(Stmt->TableName); MADB_FREE(Stmt->UniqueIndex); - //Stmt->metadata.reset(); + delete Stmt->metadata; /* For explicit descriptors we only remove reference to the stmt*/ if (Stmt->Apd->AppType) @@ -165,8 +164,8 @@ SQLRETURN MADB_StmtFree(MADB_Stmt *Stmt, SQLUSMALLINT Option) if (Stmt->stmt != nullptr) { - MDBUG_C_PRINT(Stmt->Connection, "-->closing %0x", Stmt->stmt.get()); - MADB_STMT_CLOSE_STMT(Stmt); + MDBUG_C_PRINT(Stmt->Connection, "-->closing %0x", Stmt->stmt); + MADB_DELETE(Stmt->stmt); } /* Query has to be deleted after multistmt handles are closed, since the depends on info in the Query */ std::lock_guard localScopeLock(Stmt->Connection->ListsCs); @@ -247,16 +246,17 @@ MADB_Stmt *MADB_FindCursor(MADB_Stmt *Stmt, const char *CursorName) /* {{{ FetchMetadata */ ResultSetMetaData* FetchMetadata(MADB_Stmt *Stmt, bool early) { + delete Stmt->metadata; /* TODO early probably is not needed here at all */ if (early) { - Stmt->metadata.reset(Stmt->stmt->getEarlyMetaData()); + Stmt->metadata= Stmt->stmt->getEarlyMetaData(); } else { - Stmt->metadata.reset(Stmt->rs->getMetaData()); + Stmt->metadata= Stmt->rs->getMetaData(); } - return Stmt->metadata.get(); + return Stmt->metadata; } /* }}} */ @@ -265,14 +265,14 @@ SQLRETURN MADB_StmtReset(MADB_Stmt* Stmt) { if (Stmt->State > MADB_SS_PREPARED) { - MDBUG_C_PRINT(Stmt->Connection, "mysql_stmt_free_result(%0x)", Stmt->rs.get()); - Stmt->rs.reset(); + MDBUG_C_PRINT(Stmt->Connection, "mysql_stmt_free_result(%0x)", Stmt->rs); + MADB_DELETE(Stmt->rs); } if (Stmt->State >= MADB_SS_PREPARED) { - MDBUG_C_PRINT(Stmt->Connection, "mysql_stmt_close(%0x)", Stmt->stmt.get()); - Stmt->stmt.reset(); + MDBUG_C_PRINT(Stmt->Connection, "mysql_stmt_close(%0x)", Stmt->stmt); + MADB_DELETE(Stmt->stmt); } switch (Stmt->State) @@ -286,8 +286,7 @@ SQLRETURN MADB_StmtReset(MADB_Stmt* Stmt) RESET_DAE_STATUS(Stmt); case MADB_SS_PREPARED: - Stmt->metadata.reset(); - + MADB_DELETE(Stmt->metadata); Stmt->PositionedCursor= nullptr; Stmt->Ird->Header.Count= 0; @@ -305,7 +304,7 @@ SQLRETURN MADB_StmtReset(MADB_Stmt* Stmt) /* {{{ MADB_CsPrepare - Method called if we do client side prepare */ SQLRETURN MADB_CsPrepare(MADB_Stmt *Stmt) { - Stmt->stmt.reset(new ClientSidePreparedStatement(Stmt->Connection->guard.get(), STMT_STRING(Stmt), Stmt->Options.CursorType + MADB_CXX_RESET(Stmt->stmt, new ClientSidePreparedStatement(Stmt->Connection->guard.get(), STMT_STRING(Stmt), Stmt->Options.CursorType , Stmt->Query.NoBackslashEscape)); if ((Stmt->ParamCount= static_cast(Stmt->stmt->getParamCount())/* + (MADB_POSITIONED_COMMAND(Stmt) ? MADB_POS_COMM_IDX_FIELD_COUNT(Stmt) : 0)*/) != 0) { @@ -324,8 +323,7 @@ SQLRETURN MADB_CsPrepare(MADB_Stmt *Stmt) void MADB_Stmt::AfterPrepare() { State= MADB_SS_PREPARED; - - metadata.reset(stmt->getEarlyMetaData()); + MADB_CXX_RESET(metadata, stmt->getEarlyMetaData()); /* If we have result returning query - fill descriptor records with metadata */ if (metadata && metadata->getColumnCount() > 0) { @@ -339,6 +337,8 @@ void MADB_Stmt::AfterPrepare() MADB_FREE(params); } params= (MYSQL_BIND *)MADB_CALLOC(sizeof(MYSQL_BIND) * ParamCount); + // Creating IPD records for all params + MADB_DescGetInternalRecord(Ipd, ParamCount - 1, MADB_DESC_WRITE); } } @@ -348,19 +348,19 @@ void MADB_Stmt::AfterPrepare() */ SQLRETURN MADB_RegularPrepare(MADB_Stmt *Stmt) { - MDBUG_C_PRINT(Stmt->Connection, "mysql_stmt_prepare(%0x,%s)", Stmt->stmt.get(), STMT_STRING(Stmt).c_str()); + MDBUG_C_PRINT(Stmt->Connection, "mysql_stmt_prepare(%0x,%s)", Stmt->stmt, STMT_STRING(Stmt).c_str()); try { ServerPrepareResult *pr= Stmt->Connection->guard->prepare(STMT_STRING(Stmt)); - Stmt->stmt.reset(new ServerSidePreparedStatement(Stmt->Connection->guard.get(), pr, Stmt->Options.CursorType)); + MADB_CXX_RESET(Stmt->stmt, new ServerSidePreparedStatement(Stmt->Connection->guard.get(), pr, Stmt->Options.CursorType)); } catch (SQLException& e) { // First condition is probably means we can a multistatement, that can't be prepared, 2nd - that the query is not preparable if ((e.getErrorCode() == 1064 && Stmt->Query.BatchAllowed) || e.getErrorCode() == 1295) { - Stmt->stmt.reset(new ClientSidePreparedStatement(Stmt->Connection->guard.get(), STMT_STRING(Stmt), + MADB_CXX_RESET(Stmt->stmt, new ClientSidePreparedStatement(Stmt->Connection->guard.get(), STMT_STRING(Stmt), Stmt->Options.CursorType, Stmt->Query.NoBackslashEscape)); } else @@ -368,16 +368,15 @@ SQLRETURN MADB_RegularPrepare(MADB_Stmt *Stmt) ///* Need to save error first */ MADB_FromException(Stmt->Error, e); ///* We need to close the stmt here, or it becomes unusable like in ODBC-21 */ - MDBUG_C_PRINT(Stmt->Connection, "mysql_stmt_close(%0x)", Stmt->stmt.get()); + MDBUG_C_PRINT(Stmt->Connection, "mysql_stmt_close(%0x)", Stmt->stmt); return Stmt->Error.ReturnValue; } } catch (int) { - Stmt->stmt.reset(new ClientSidePreparedStatement(Stmt->Connection->guard.get(), STMT_STRING(Stmt), + MADB_CXX_RESET(Stmt->stmt, new ClientSidePreparedStatement(Stmt->Connection->guard.get(), STMT_STRING(Stmt), Stmt->Options.CursorType, Stmt->Query.NoBackslashEscape)); } - Stmt->AfterPrepare(); return SQL_SUCCESS; } @@ -392,14 +391,14 @@ void SwitchToSsIfNeeded(MADB_Stmt* Stmt) if (!Stmt->metadata && Stmt->State < MADB_SS_EXECUTED && Stmt->Connection->Dsn->PrepareOnClient && !Stmt->stmt->isServerSide()) { // We need it for the case server side prepare fails, but MADB_RegularPrepare falls back to CS on its own, if SS goes wrong. - PreparedStatement *currenCs= Stmt->stmt.release(); + PreparedStatement *currentCs= Stmt->stmt; if (MADB_RegularPrepare(Stmt) == SQL_ERROR) { - Stmt->stmt.reset(currenCs); + Stmt->stmt= currentCs; } else { - delete currenCs; + delete currentCs; } } } @@ -445,12 +444,6 @@ SQLRETURN MADB_Stmt::Prepare(const char *StatementText, SQLINTEGER TextLength, b MADB_ResetParser(this, StatementText, TextLength); MADB_ParseQuery(&Query); - if ((Query.QueryType == MADB_QUERY_INSERT || Query.QueryType == MADB_QUERY_UPDATE || Query.QueryType == MADB_QUERY_DELETE) - && MADB_FindToken(&Query, "RETURNING")) - { - Query.ReturnsResult= '\1'; - } - if (Query.QueryType == MADB_QUERY_CALL) { ServerSide= true; @@ -700,7 +693,7 @@ SQLRETURN MADB_StmtPutData(MADB_Stmt *Stmt, SQLPOINTER DataPtr, SQLLEN StrLen_or buffer. This means we need to process Update and Insert statements row by row. */ if (MyStmt->stmt->sendLongData(Stmt->PutParam, static_cast(ConvertedDataPtr ? ConvertedDataPtr : DataPtr), Length)) { - MADB_SetNativeError(&Stmt->Error, SQL_HANDLE_STMT, MyStmt->stmt.get()); + MADB_SetNativeError(&Stmt->Error, SQL_HANDLE_STMT, MyStmt->stmt); } else { @@ -737,13 +730,14 @@ SQLRETURN MADB_ExecutePositionedUpdate(MADB_Stmt *Stmt, bool ExecDirect) MADB_InitDynamicArray(&DynData, sizeof(char *), 8, 8); - for (j= 1; j < MADB_STMT_COLUMN_COUNT(Stmt->PositionedCursor) + 1; ++j) + for (j= 0; j < MADB_STMT_COLUMN_COUNT(Stmt->PositionedCursor); ++j) { if (Stmt->PositionedCursor->UniqueIndex == nullptr || - (Stmt->PositionedCursor->UniqueIndex[0] != 0 && IndexIdx <= Stmt->PositionedCursor->UniqueIndex[0] && j == Stmt->PositionedCursor->UniqueIndex[IndexIdx] + 1)) + (Stmt->PositionedCursor->UniqueIndex[0] != 0 && IndexIdx <= Stmt->PositionedCursor->UniqueIndex[0] && j == Stmt->PositionedCursor->UniqueIndex[IndexIdx])) { SQLLEN Length; - MADB_DescRecord* Rec= MADB_DescGetInternalRecord(Stmt->PositionedCursor->Ard, j, MADB_DESC_READ); + MADB_DescRecord* Rec= MADB_DescGetInternalRecord(Stmt->PositionedCursor->Ard, j, MADB_DESC_WRITE/* Should be WRITE so it gets created + if it does not exist */); SQLUSMALLINT ParamNumber= 0; Length= Rec->OctetLength; @@ -755,19 +749,15 @@ SQLRETURN MADB_ExecutePositionedUpdate(MADB_Stmt *Stmt, bool ExecDirect) } else { - ParamNumber= /* Param ordnum in pos.cursor condition */ j + + ParamNumber= /* Param ordnum in pos.cursor condition */ j + 1 + /* Num of params in main stmt */(Stmt->ParamCount - MADB_STMT_COLUMN_COUNT(Stmt->PositionedCursor)); } - /* if (Rec->inUse) - MA_SQLBindParameter(Stmt, j+1, SQL_PARAM_INPUT, Rec->ConciseType, Rec->Type, Rec->DisplaySize, Rec->Scale, Rec->DataPtr, Length, Rec->OctetLengthPtr); - else */ - { - Stmt->Methods->GetData(Stmt->PositionedCursor, j, SQL_CHAR, nullptr, 0, &Length, true); - p= (char*)MADB_CALLOC(Length + 2); - MADB_InsertDynamic(&DynData, (char*)&p); - Stmt->Methods->GetData(Stmt->PositionedCursor, j, SQL_CHAR, p, Length + 1, nullptr, true); - Stmt->Methods->BindParam(Stmt, ParamNumber, SQL_PARAM_INPUT, SQL_CHAR, SQL_CHAR, 0, 0, p, Length, nullptr); - } + + Stmt->Methods->GetData(Stmt->PositionedCursor, j + 1, SQL_CHAR, nullptr, 0, &Length, true); + p= (char*)MADB_CALLOC(Length + 2); + MADB_InsertDynamic(&DynData, (char*)&p); + Stmt->Methods->GetData(Stmt->PositionedCursor, j + 1, SQL_CHAR, p, Length + 1, nullptr, true); + Stmt->Methods->BindParam(Stmt, ParamNumber, SQL_PARAM_INPUT, SQL_CHAR, SQL_CHAR, 0, 0, p, Length, nullptr); } } @@ -820,12 +810,12 @@ SQLRETURN MADB_Stmt::GetOutParams(int CurrentOffset) try { - metadata.reset(rs->getMetaData()); + MADB_CXX_RESET(metadata, rs->getMetaData()); columnCount= metadata->getColumnCount(); } catch(int) { - return MADB_SetNativeError(&Error, SQL_HANDLE_STMT, stmt.get()); + return MADB_SetNativeError(&Error, SQL_HANDLE_STMT, stmt); } MADB_FREE(result); @@ -894,17 +884,17 @@ SQLRETURN MADB_Stmt::DoExecuteBatch() try { const Longs &batchRes= stmt->executeBatch(); - rs.reset(); + MADB_DELETE(rs); } catch (int32_t /*rc*/) { MDBUG_C_PRINT(Connection, "execute:ERROR%s", ""); - if (stmt.get()->getErrno() == CR_ERR_STMT_PARAM_CALLBACK && Error.ReturnValue == SQL_ERROR) + if (stmt->getErrno() == CR_ERR_STMT_PARAM_CALLBACK && Error.ReturnValue == SQL_ERROR) { //Rerturning error set by callback return SQL_ERROR; } - return MADB_SetNativeError(&Error, SQL_HANDLE_STMT, stmt.get()); + return MADB_SetNativeError(&Error, SQL_HANDLE_STMT, stmt); } catch (SQLException &e) { @@ -937,18 +927,18 @@ SQLRETURN MADB_DoExecute(MADB_Stmt *Stmt) } if (Stmt->stmt->execute()) { - Stmt->rs.reset(Stmt->stmt->getResultSet()); + MADB_CXX_RESET(Stmt->rs, Stmt->stmt->getResultSet()); } else { - Stmt->rs.reset(); + MADB_DELETE(Stmt->rs); Stmt->AffectedRows+= Stmt->stmt->getUpdateCount(); } } catch (int32_t /*rc*/) { MDBUG_C_PRINT(Stmt->Connection, "execute:ERROR%s", ""); - return MADB_SetNativeError(&Stmt->Error, SQL_HANDLE_STMT, Stmt->stmt.get()); + return MADB_SetNativeError(&Stmt->Error, SQL_HANDLE_STMT, Stmt->stmt); } Stmt->State= MADB_SS_EXECUTED; @@ -1219,7 +1209,7 @@ SQLRETURN MADB_StmtExecute(MADB_Stmt *Stmt, bool ExecDirect) try { ServerSidePreparedStatement* ssps= new ServerSidePreparedStatement(Stmt->Connection->guard.get(), STMT_STRING(Stmt), Stmt->Options.CursorType); - Stmt->stmt.reset(ssps); + MADB_CXX_RESET(Stmt->stmt, ssps); } catch (int32_t) { // going further with csps @@ -1269,19 +1259,26 @@ SQLRETURN MADB_StmtBindCol(MADB_Stmt *Stmt, SQLUSMALLINT ColumnNumber, SQLSMALLI { int i; Record->inUse= 0; - /* Update counter */ - for (i= Ard->Records.elements; i > 0; i--) + /* Update counter if needed */ + if (Ard->Header.Count == ColumnNumber) { - MADB_DescRecord *Rec= MADB_DescGetInternalRecord(Ard, i-1, MADB_DESC_READ); - if (Rec && Rec->inUse) + for (i= ColumnNumber; i > 0; i--) { - Ard->Header.Count= i; - return SQL_SUCCESS; + MADB_DescRecord *Rec= MADB_DescGetInternalRecord(Ard, i - 1, MADB_DESC_READ); + if (Rec && Rec->inUse) + { + Ard->Header.Count= i; + return SQL_SUCCESS; + } } + Ard->Header.Count= 0; } - Ard->Header.Count= 0; return SQL_SUCCESS; } + else if (Ard->Header.Count < ColumnNumber) + { + Ard->Header.Count= ColumnNumber; + } if (!SQL_SUCCEEDED(MADB_DescSetField(Ard, ColumnNumber, SQL_DESC_TYPE, (SQLPOINTER)(SQLLEN)TargetType, SQL_IS_SMALLINT, 0)) || !SQL_SUCCEEDED(MADB_DescSetField(Ard, ColumnNumber, SQL_DESC_OCTET_LENGTH_PTR, (SQLPOINTER)StrLen_or_Ind, SQL_IS_POINTER, 0)) || @@ -2140,7 +2137,7 @@ SQLRETURN MADB_StmtFetch(MADB_Stmt *Stmt) { switch (rc) { case 1: - RowResult= MADB_SetNativeError(&Stmt->Error, SQL_HANDLE_STMT, Stmt->stmt.get()); + RowResult= MADB_SetNativeError(&Stmt->Error, SQL_HANDLE_STMT, Stmt->stmt); /* If mysql_stmt_fetch returned error, there is no sense to continue */ if (Stmt->Ird->Header.ArrayStatusPtr) { @@ -2550,14 +2547,14 @@ SQLRETURN MADB_GetBookmark(MADB_Stmt *Stmt, { if (Stmt->Options.UseBookmarks == SQL_UB_OFF) { - MADB_SetError(&Stmt->Error, MADB_ERR_07009, NULL, 0); + MADB_SetError(&Stmt->Error, MADB_ERR_07009, nullptr, 0); return Stmt->Error.ReturnValue; } if ((Stmt->Options.UseBookmarks == SQL_UB_VARIABLE && TargetType != SQL_C_VARBOOKMARK) || (Stmt->Options.UseBookmarks != SQL_UB_VARIABLE && TargetType == SQL_C_VARBOOKMARK)) { - MADB_SetError(&Stmt->Error, MADB_ERR_HY003, NULL, 0); + MADB_SetError(&Stmt->Error, MADB_ERR_HY003, nullptr, 0); return Stmt->Error.ReturnValue; } @@ -2621,7 +2618,7 @@ SQLRETURN MADB_StmtGetData(SQLHSTMT StatementHandle, IrdRec= MADB_DescGetInternalRecord(Stmt->Ird, Offset, MADB_DESC_READ); if (!IrdRec) { - MADB_SetError(&Stmt->Error, MADB_ERR_07009, NULL, 0); + MADB_SetError(&Stmt->Error, MADB_ERR_07009, nullptr, 0); return Stmt->Error.ReturnValue; } @@ -2632,7 +2629,7 @@ SQLRETURN MADB_StmtGetData(SQLHSTMT StatementHandle, if (!Ard) { - MADB_SetError(&Stmt->Error, MADB_ERR_07009, NULL, 0); + MADB_SetError(&Stmt->Error, MADB_ERR_07009, nullptr, 0); return Stmt->Error.ReturnValue; } OdbcType= Ard->ConciseType; @@ -2856,7 +2853,7 @@ SQLRETURN MADB_StmtGetData(SQLHSTMT StatementHandle, if (Stmt->rs->get(&Bind, Offset, CurrentOffset)) { - MADB_SetNativeError(&Stmt->Error, SQL_HANDLE_STMT, Stmt->stmt.get()); + MADB_SetNativeError(&Stmt->Error, SQL_HANDLE_STMT, Stmt->stmt); return Stmt->Error.ReturnValue; } /* Dirty temporary hack before we know what is going on. Yes, there is nothing more eternal, than temporary @@ -3001,7 +2998,7 @@ SQLRETURN MADB_StmtGetData(SQLHSTMT StatementHandle, return MADB_FromException(Stmt->Error, e); } catch (int32_t /*rc*/) { - return MADB_SetNativeError(&Stmt->Error, SQL_HANDLE_STMT, Stmt->stmt.get()); + return MADB_SetNativeError(&Stmt->Error, SQL_HANDLE_STMT, Stmt->stmt); } catch (std::invalid_argument &ia) { return MADB_SetError(&Stmt->Error, MADB_ERR_22018, ia.what(), 0); @@ -3107,13 +3104,13 @@ SQLRETURN MADB_StmtColAttr(MADB_Stmt *Stmt, SQLUSMALLINT ColumnNumber, SQLUSMALL SwitchToSsIfNeeded(Stmt); if (!Stmt->metadata || Stmt->metadata->getColumnCount() == 0) { - MADB_SetError(&Stmt->Error, MADB_ERR_07005, NULL, 0); + MADB_SetError(&Stmt->Error, MADB_ERR_07005, nullptr, 0); return Stmt->Error.ReturnValue; } if (ColumnNumber < 1 || ColumnNumber > Stmt->metadata->getColumnCount()) { - MADB_SetError(&Stmt->Error, MADB_ERR_07009, NULL, 0); + MADB_SetError(&Stmt->Error, MADB_ERR_07009, nullptr, 0); return Stmt->Error.ReturnValue; } @@ -3122,7 +3119,7 @@ SQLRETURN MADB_StmtColAttr(MADB_Stmt *Stmt, SQLUSMALLINT ColumnNumber, SQLUSMALL if (!(Record= MADB_DescGetInternalRecord(Stmt->Ird, ColumnNumber, MADB_DESC_READ))) { - MADB_SetError(&Stmt->Error, MADB_ERR_07009, NULL, 0); + MADB_SetError(&Stmt->Error, MADB_ERR_07009, nullptr, 0); return Stmt->Error.ReturnValue; } @@ -3521,7 +3518,7 @@ SQLRETURN MADB_StmtSetPos(MADB_Stmt* Stmt, SQLSETPOSIROW RowNumber, SQLUSMALLINT MADB_DescRecord *Rec= MADB_DescGetInternalRecord(Stmt->Ard, column, MADB_DESC_READ), *ApdRec= NULL; - if (Rec->inUse && MADB_ColumnIgnoredInAllRows(Stmt->Ard, Rec) == FALSE) + if (Rec && Rec->inUse && !MADB_ColumnIgnoredInAllRows(Stmt->Ard, Rec)) { Stmt->DaeStmt->Methods->BindParam(Stmt->DaeStmt, param + 1, SQL_PARAM_INPUT, Rec->ConciseType, Rec->Type, Rec->DisplaySize, Rec->Scale, Rec->DataPtr, Rec->OctetLength, Rec->OctetLengthPtr); @@ -3633,16 +3630,16 @@ SQLRETURN MADB_StmtSetPos(MADB_Stmt* Stmt, SQLSETPOSIROW RowNumber, SQLUSMALLINT for(column= 0; column < MADB_STMT_COLUMN_COUNT(Stmt); ++column) { SQLLEN *LengthPtr= NULL; - my_bool GetDefault= FALSE; + bool GetDefault= false; MADB_DescRecord *Rec= MADB_DescGetInternalRecord(Stmt->Ard, column, MADB_DESC_READ); /* TODO: shouldn't here be IndicatorPtr? */ - if (Rec->OctetLengthPtr) + if (Rec && Rec->OctetLengthPtr) LengthPtr= static_cast(GetBindOffset(Stmt->Ard->Header, Rec->OctetLengthPtr, Stmt->DaeRowNumber > 1 ? Stmt->DaeRowNumber - 1 : 0, sizeof(SQLLEN))); - if (!Rec->inUse || + if (!Rec || !Rec->inUse || (LengthPtr && *LengthPtr == SQL_COLUMN_IGNORE)) { - GetDefault= TRUE; + GetDefault= true; continue; } @@ -3982,7 +3979,7 @@ SQLRETURN MADB_StmtInit(MADB_Dbc *Connection, SQLHANDLE *pHStmt) *pHStmt= Stmt; Stmt->Connection= Connection; - Stmt->stmt.reset(); + MADB_DELETE(Stmt->stmt); if (!(Stmt->IApd= MADB_DescInit(Connection, MADB_DESC_APD, FALSE)) || !(Stmt->IArd= MADB_DescInit(Connection, MADB_DESC_ARD, FALSE)) || @@ -3992,7 +3989,7 @@ SQLRETURN MADB_StmtInit(MADB_Dbc *Connection, SQLHANDLE *pHStmt) goto error; } - MDBUG_C_PRINT(Stmt->Connection, "-->inited %0x", Stmt->stmt.get()); + MDBUG_C_PRINT(Stmt->Connection, "-->inited %0x", Stmt->stmt); Stmt->Methods= &MADB_StmtMethods; @@ -4019,7 +4016,7 @@ SQLRETURN MADB_StmtInit(MADB_Dbc *Connection, SQLHANDLE *pHStmt) error: if (Stmt && Stmt->stmt) { - MADB_STMT_CLOSE_STMT(Stmt); + MADB_DELETE(Stmt->stmt); } MADB_DescFree(Stmt->IApd, TRUE); MADB_DescFree(Stmt->IArd, TRUE); diff --git a/driver/ma_statement.h b/driver/ma_statement.h index 5ed3067a..b1698486 100644 --- a/driver/ma_statement.h +++ b/driver/ma_statement.h @@ -116,7 +116,6 @@ SQLRETURN MADB_DoExecute (MADB_Stmt *Stmt); #define MADB_POS_COMM_IDX_FIELD_COUNT(aStmt) (MADB_STMT_HAS_UNIQUE_IDX((aStmt)->PositionedCursor)?(aStmt)->PositionedCursor->UniqueIndex[0]:MADB_STMT_COLUMN_COUNT((aStmt)->PositionedCursor)) #define MADB_STMT_FORGET_NEXT_POS(aStmt) (aStmt)->Cursor.Next= -1 #define MADB_STMT_RESET_CURSOR(aStmt) (aStmt)->Cursor.Position= 0; MADB_STMT_FORGET_NEXT_POS(aStmt) -#define MADB_STMT_CLOSE_STMT(aStmt) (aStmt)->stmt.reset() #define MADB_STMT_SHOULD_STREAM(_a) (DSN_OPTION((_a)->Connection, MADB_OPT_FLAG_NO_CACHE) &&\ (_a)->Options.CursorType == SQL_CURSOR_FORWARD_ONLY) /* Checks if given Stmt handle is currently streaming (prev variant (MADB_STMT_SHOULD_STREAM(_a) && STMT_EXECUTED(_a) && MADB_STMT_COLUMN_COUNT(_a) > 0) */ diff --git a/driver/ma_string.cpp b/driver/ma_string.cpp index 5806a387..dc346749 100644 --- a/driver/ma_string.cpp +++ b/driver/ma_string.cpp @@ -124,10 +124,10 @@ bool MADB_DynStrUpdateSet(MADB_Stmt* Stmt, SQLString& DynString) { SQLLEN *IndicatorPtr= nullptr; Record= MADB_DescGetInternalRecord(Stmt->Ard, i, MADB_DESC_READ); - if (Record->IndicatorPtr) + if (Record && Record->IndicatorPtr) IndicatorPtr= (SQLLEN *)GetBindOffset(Stmt->Ard->Header, Record->IndicatorPtr, Stmt->DaeRowNumber > 1 ? Stmt->DaeRowNumber-1 : 0, sizeof(SQLLEN)/*Record->OctetLength*/); - if ((IndicatorPtr && *IndicatorPtr == SQL_COLUMN_IGNORE) || !Record->inUse) + if (!Record || (IndicatorPtr && *IndicatorPtr == SQL_COLUMN_IGNORE) || !Record->inUse) { ++IgnoredColumns; continue; @@ -167,8 +167,9 @@ my_bool MADB_DynStrInsertSet(MADB_Stmt *Stmt, MADB_DynString *DynString) TODO: we gave to use this column count in most, if not all, places, where it's got via API function */ for (i= 0; i < MADB_STMT_COLUMN_COUNT(Stmt); i++) { + // Shouldn't it be really IRD here? Record= MADB_DescGetInternalRecord(Stmt->Ard, i, MADB_DESC_READ); - if (!Record->inUse || MADB_ColumnIgnoredInAllRows(Stmt->Ard, Record) == TRUE) + if (!Record || !Record->inUse || MADB_ColumnIgnoredInAllRows(Stmt->Ard, Record) == TRUE) { continue; } @@ -244,7 +245,7 @@ bool MADB_DynStrGetWhere(MADB_Stmt *Stmt, SQLString &DynString, char *TableName, { for (i= 0; i < MADB_STMT_COLUMN_COUNT(Stmt); i++) { - const MYSQL_FIELD* field= FetchMetadata(Stmt)->getField(i); + const MYSQL_FIELD* field= Stmt->metadata->getField(i); if (field->flags & PRI_KEY_FLAG) { ++PrimaryCount; @@ -622,7 +623,7 @@ void StreamWstring(MADB_Stmt* Stmt, SQLUSMALLINT Offset, MADB_DescRecord* IrdRec /* Getting value's length to allocate the buffer */ if (Stmt->rs->get(&Bind, Offset, Stmt->CharOffset[Offset])) { - MADB_SetNativeError(&Stmt->Error, SQL_HANDLE_STMT, Stmt->stmt.get()); + MADB_SetNativeError(&Stmt->Error, SQL_HANDLE_STMT, Stmt->stmt); throw Stmt->Error; } /* Adding byte for terminating null */ @@ -639,7 +640,7 @@ void StreamWstring(MADB_Stmt* Stmt, SQLUSMALLINT Offset, MADB_DescRecord* IrdRec if (Stmt->rs->get(&Bind, Offset, Stmt->CharOffset[Offset])) { MADB_FREE(ClientValue); - MADB_SetNativeError(&Stmt->Error, SQL_HANDLE_STMT, Stmt->stmt.get()); + MADB_SetNativeError(&Stmt->Error, SQL_HANDLE_STMT, Stmt->stmt); throw Stmt->Error; } diff --git a/test/basic.c b/test/basic.c index e76e171b..f344c44f 100644 --- a/test/basic.c +++ b/test/basic.c @@ -1,6 +1,6 @@ /* Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. - 2013, 2023 MariaDB Corporation AB + 2013, 2024 MariaDB Corporation AB The MySQL Connector/ODBC is licensed under the terms of the GPLv2 , like most @@ -80,14 +80,14 @@ ODBC_TEST(simple_test) CHECK_STMT_RC(Stmt, SQLFreeStmt(Stmt, SQL_CLOSE)); OK_SIMPLE_STMTW(Stmt, CW("DROP TABLE IF EXISTS smpltest")); - OK_SIMPLE_STMTW(Stmt, CW("CREATE TABLE smpltest (a int, b varchar(25))")); + OK_SIMPLE_STMTW(Stmt, CW("CREATE TABLE smpltest (a INT, b VARCHAR(25))")); OK_SIMPLE_STMTW(Stmt, CW("INSERT INTO smpltest VALUES (1, 'Row no 1')")); OK_SIMPLE_STMTW(Stmt, CW("INSERT INTO smpltest VALUES (2, 'Row no 2')")); CHECK_STMT_RC(Stmt, SQLPrepareW(Stmt, CW("SELECT a, b FROM smpltest"), SQL_NTS)); CHECK_STMT_RC(Stmt, SQLExecute(Stmt)); - SQLFetch(Stmt); + CHECK_STMT_RC(Stmt, SQLFetch(Stmt)); SQLGetData(Stmt, 1, SQL_C_USHORT, &value, sizeof(value), 0); SQLGetData(Stmt, 2, SQL_C_WCHAR, Buffer, sizeof(Buffer), 0); is_num(value, 1); diff --git a/test/desc.c b/test/desc.c index 0ce20b1e..a221dedd 100644 --- a/test/desc.c +++ b/test/desc.c @@ -171,7 +171,7 @@ ODBC_TEST(t_sqlbindcol_count_reset) SQL_IS_INTEGER, NULL)); is_num(count, 0); - OK_SIMPLE_STMT(Stmt, "select 1,2,3,4,5"); + OK_SIMPLE_STMT(Stmt, "SELECT 1,2,3,4,5"); CHECK_DESC_RC(ard, SQLGetDescField(ard, 0, SQL_DESC_COUNT, &count, SQL_IS_INTEGER, NULL)); @@ -225,7 +225,7 @@ ODBC_TEST(t_desc_default_type) SQLHANDLE ard, apd; SQLINTEGER inval= 20, outval= 0; - CHECK_STMT_RC(Stmt, SQLPrepare(Stmt, (SQLCHAR *)"select ?", SQL_NTS)); + CHECK_STMT_RC(Stmt, SQLPrepare(Stmt, (SQLCHAR *)"SELECT ?", SQL_NTS)); CHECK_STMT_RC(Stmt, SQLGetStmtAttr(Stmt, SQL_ATTR_APP_PARAM_DESC, &apd, 0, NULL)); CHECK_STMT_RC(Stmt, SQLGetStmtAttr(Stmt, SQL_ATTR_APP_ROW_DESC, diff --git a/test/relative.c b/test/relative.c index 6f01d39f..a65df734 100644 --- a/test/relative.c +++ b/test/relative.c @@ -825,10 +825,58 @@ ODBC_TEST(bench1) } +ODBC_TEST(bench2) +{ + SQLINTEGER id= 0; + SQLRETURN rc= SQL_SUCCESS; + + /*SQLExecDirect(Stmt, (SQLCHAR*)"DROP TABLE test100", SQL_NTS); + SQLExecDirect(Stmt, (SQLCHAR*)"CREATE TABLE test100 (i1 int,i2 int,i3 int,i4 int,i5 int,i6 int,i7 int,i8 int,i9 int,i10 int,i11 int,i12 int,i13 int,i14 int,i15 int,i16 int," + "i17 int,i18 int,i19 int,i20 int,i21 int,i22 int,i23 int,i24 int,i25 int,i26 int,i27 int,i28 int,i29 int,i30 int,i31 int,i32 int,i33 int,i34 int,i35 int,i36 int,i37 int," + "i38 int,i39 int,i40 int,i41 int,i42 int,i43 int,i44 int,i45 int,i46 int,i47 int,i48 int,i49 int,i50 int,i51 int,i52 int,i53 int,i54 int,i55 int,i56 int,i57 int,i58 int," + "i59 int,i60 int,i61 int,i62 int,i63 int,i64 int,i65 int,i66 int,i67 int,i68 int,i69 int,i70 int,i71 int,i72 int,i73 int,i74 int,i75 int,i76 int,i77 int,i78 int,i79 int," + "i80 int,i81 int,i82 int,i83 int,i84 int,i85 int,i86 int,i87 int,i88 int,i89 int,i90 int,i91 int,i92 int,i93 int,i94 int,i95 int,i96 int,i97 int,i98 int,i99 int,i100 int)", SQL_NTS); + SQLExecDirect(Stmt, (SQLCHAR*)"INSERT INTO test100 value (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41," + "42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100)", SQL_NTS);*/ + for (auto j= 0; j < 20000; ++j) { + SQLExecDirect(Stmt, (SQLCHAR*)"SELECT * FROM test100", SQL_NTS); + + while ((rc= SQLFetch(Stmt)) != SQL_NO_DATA && SQL_SUCCEEDED(rc)) { + for (size_t i= 0; i < 100; ++i) { + SQLGetData(Stmt, (SQLUSMALLINT)(i + 1), SQL_INTEGER, &id, 0, NULL); + } + } + SQLFreeStmt(Stmt, SQL_CLOSE); + } + return OK; +} + + +ODBC_TEST(bench3) +{ + SQLINTEGER id= 0; + SQLRETURN rc= SQL_SUCCESS; + + SQLPrepare(Stmt, (SQLCHAR*)"SELECT * FROM test100", SQL_NTS); + for (auto j= 0; j < 50; ++j) { + SQLExecute(Stmt); + + while ((rc= SQLFetch(Stmt)) != SQL_NO_DATA && SQL_SUCCEEDED(rc)) { + for (size_t i= 0; i < 100; ++i) { + SQLGetData(Stmt, (SQLUSMALLINT)(i + 1), SQL_INTEGER, &id, 0, NULL); + } + } + SQLFreeStmt(Stmt, SQL_CLOSE); + } + return OK; +} + MA_ODBC_TESTS my_tests[]= { //{bench, "bench"}, //{bench1, "bench1"}, + //{bench2, "bench2"}, + //{bench3, "bench3"}, {t_relative, "t_relative"}, {t_relative1, "t_relative1"}, {t_relative2, "t_relative2"}, diff --git a/test/tap.h b/test/tap.h index 6df14d1d..844a1ec8 100644 --- a/test/tap.h +++ b/test/tap.h @@ -1020,7 +1020,7 @@ int ReadInfoOneTime(HDBC Connection, HSTMT Stmt) } CHECK_STMT_RC(Connection, SQLGetInfo(Connection, SQL_DRIVER_VER, DriverVersion, sizeof(DriverVersion), &len)); - OK_SIMPLE_STMT(Stmt, "SELECT 1 FROM dual where @@performance_schema=1"); + OK_SIMPLE_STMT(Stmt, "SELECT 1 FROM dual WHERE @@performance_schema=1"); if (SQL_SUCCEEDED(SQLFetch(Stmt))) { PerfSchema= TRUE;