I do have a code structure where I read Oracle rows from database and I do assign then to a common model that represents its data (called commonmodel::Model
). I´m using VS2012 on Windows 7.
My issue is with this piece of code below, where I do execute some statement like SELECT ...
I´m running for test and the tables are empty, so no data is returned from SELECT...
.from database, thus the piece of code inside while (resultSet->next())
is not being called.
My program compiles, but it crashes at runtime on returnin data (return retData
). I have no idea what´s causing this behaviour and I would like help to solve it.
BTW: I choose to create std::unique_ptr´s
for Oracle pointers so that I can leave to the compiler to free these pointers when not needed any mode. In that wat I don´t need to delete them at the end of the operation.
std::vector<std::unique_ptr<commonmodel::Model>> OracleDatabase::ExecuteStmtReturningData(std::string sql, int& totalRecords, commonmodel::Model &modelTemplate)
{
std::unique_ptr<oracle::occi::Statement> stmt(connection->createStatement());
stmt->setAutoCommit(TRUE);
std::unique_ptr<oracle::occi::ResultSet> res(stmt->executeQuery(sql));
std::vector<std::unique_ptr<commonmodel::Model>> ret = getModelsFromResultSet(res, modelTemplate);
return ret;
}
std::vector<std::unique_ptr<commonmodel::Model>> OracleDatabase::getModelsFromResultSet(std::unique_ptr<oracle::occi::ResultSet>& resultSet, commonmodel::Model &modelTemplate)
{
std::vector<std::unique_ptr<commonmodel::Model>> retData;
std::vector<oracle::occi::MetaData> resultMeta = resultSet->getColumnListMetaData();
while (resultSet->next())
{
std::unique_ptr<commonmodel::Model> model = modelTemplate.clone();
for (unsigned int i = 1; i <= resultMeta.size(); i++) // ResultSet starts with one, not zero
{
std::string label = resultMeta.at(i).getString(oracle::occi::MetaData::ATTR_NAME);
setPropertyFromResultSet(resultSet, label, i, *model);
}
retData.push_back(std::move(model)); // unique_ptr can only be copied or moved.
}
return retData; <<<==== CRASH ON RETURN....
}
You can't use 'stock' unique_ptr
to deal with OCCI objects and pointers. OCCI doesn't want to you to delete
those pointers (this is what unique_ptr
is going to do), instead, they want you to free them using OCCI-provided mechanisms.
In particular, to free Statement
object you should use Connection::terminateStatement
. Same for ResultSet*
, and any other OCCI pointer for this matter.
Now, you can supply custom deleter into unique_ptr object, but the issue there is that you'd need to use a pointer to already existing 'parent' object for this - and it is hard to manage lifetime of independent pointers in such a way.
On a side note, I strongly advise against using OCCI. It is a very badly designed, not properly documented library. OCI provides a much better choice.