简体   繁体   中英

C++ MySql Connector - results from query going out of scope

I'm having a scoping issue with the results of a C++ mysql connector query execution.

In the code below the ResultSet * result is passed from another function, initially NULL ; however, after performing the line result = statement->executeQuery( query ) , result is no longer NULL .

There are no errors printed from the table either.

The issue arises when returning from that function. The ResultSet * result goes from being not NULL to being equal to NULL .

Clearly, there is some form of scoping on sql query results. Perhaps their function is returning a reference to a local variable ( Really not sure otherwise )?

How do I get around this scoping issue, so that classes/functions calling this function may do with the results as they please and mitigate the need to write a bunch of specialized functions in this wrapper? Furthermore, copies should be minimized - hence the use of pointers.

bool MySQLConnector::ExecuteQuery( std::string query, sql::ResultSet * result )
{

   //connection is a member variable and has been initialized
   sql::Statement * statement = connection->createStatement();

   try
   {
       result = statement->executeQuery( query );
   }
   catch( sql::SQLException &e )
   {
      //handle errors
   }

   delete statement;

   if( result == NULL )
   {
       printf( "Result is null File: %s Line %i\n", __FILE__, __LINE__ );
       return false;
   }
   else
   {
        printf("Result is not null File: %s Line %i\n", __FILE__, __LINE__ );
   }

   return true;
}

If I have a function foo that calls the function above with correct parameters. The printf stating that result is not null will print, but in foo , right after the execution of ExecuteQuery , the pointer passed into the function becomes NULL .

There are a couple of issues:

1. result is passed by value

You pass result by value. Meaning that the function receives a copy of the pointer you pass when calling the method.

For example, if the code that calls ExecuteQuery look like this:

std::string query("SELECT ...");
sql::ResultSet *result = NULL;
ExecuteQuery(query, result);

Then ExecuteQuery cannot change the value of result , since it is COPIED into the method. If you wish to change its value, you should pass a reference to result. You can do that by changing ExecuteQuery to:

bool MySQLConnector::ExecuteQuery( std::string query, sql::ResultSet *& result )

Then, ExecuteQuery manipulates the original pointer, rather than a copy.

2. MySQL C++ API frees the ResultSet when the Statement is deleted

Just like @nos pointed out, when you call delete statement , you also free the resources that hold the information for your result .

result will still have a valid value because it won't be aware of the deallocated memory, but if you access it, it might cause a segmentation fault.

The right way to handle this is to either:

  • Copy the result
  • OR
  • Let the caller pass a statement object as well, and deallocate it after using the value from result.
bool MySQLConnector::ExecuteQuery( std::string query, sql::ResultSet * result )
                                                                     ^^^^^^^^

Here, result is much like a local variable within a function, and it contains a copy of the variable of the caller.

When you assign to it within ExecuteQuery, it'll only affect the variable within the function, not the variable of the caller.

You can instead make it a reference, so it'll reference the variable of the caller like so:

bool MySQLConnector::ExecuteQuery( std::string query, sql::ResultSet *&result )

Another approach is to pass in a pointer to the variable (and as the variable is itself a pointer, you'll deal with a pointer to a pointer). This lets you also modify the pointer of the caller :

 bool MySQLConnector::ExecuteQuery( std::string query, sql::ResultSet **result ) {
 ...
     *result = statement->executeQuery( query );

This also requires modification to the caller, so it passes in a pointer to its local variable, eg

sql::ResultSet *rs;
c->ExecuteQuery("select ...", &rs);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM