title: Proper use of callback function of sqlite3 in C++
body: <p>I have the following C++ code for testing purposes in conjunction with SQLite3.
  It's a class called <code>customer</code> with a callback function declared. This callback function is called whenever <code>sqlite3_exec()</code> returns results (records) from the SQLite database.</p>
  
  <p>What I don't like about this construction is that source code to process the results is located in a call back function outside of the class rather than the results being processed by the class method from which <code>sqlite3_exec()</code> is called.</p>
  
  <p>I could use global variables that will be used in the class method after the callback function has finished extracting the values from the SQL query results. But what if there is more than one record and the call back function is called several times. Then I need to work with arrays unless I make sure that I will only have single results.</p>
  
  <p>Do I need to forget about the callback function and go into deeper calls of the SQLite API?</p>
  
  <p>Or do I need to go to  a C++ wrapper, I suppose that there is no call back mechanism there and the results being passed back to the class method itself?</p>
  
  <pre><code>// customer
  #include "Customer\customer.h"
  //## begin module%50E6CCB50119.additionalDeclarations preserve=yes
  static int callback(void *NotUsed, int argc, char **argv, char **azColName)
  {
    int i;
    char* columnName;
    char* columnValueString;
    short int columnValueShortInt = 0;
    int columnValueInt = 0;
  
    cout &lt;&lt; "begin of callback function\n";
  
    for(i=0; i&lt;argc; i++)
    {
      columnName = azColName[i];
      if (strcmp(columnName, "FirstName")==0 || strcmp(columnName, "LastName")==0)
      {
        columnValueString = argv[i];
        cout &lt;&lt; "columnName = " &lt;&lt; columnName &lt;&lt; "; value = " &lt;&lt; columnValueString &lt;&lt;"\n";
      }
      else
      {
        if(strcmp(columnName, "Age")==0)
        {
          stringstream(argv[i]) &gt;&gt; columnValueShortInt;
          cout &lt;&lt; "columnName = " &lt;&lt; columnName &lt;&lt; "; value = " &lt;&lt; columnValueShortInt &lt;&lt;"\n";
        }
        else // strcmp(columnName, "Id")==0)
        {
          stringstream(argv[i]) &gt;&gt; columnValueInt;
          cout &lt;&lt; "columnName = " &lt;&lt; columnName &lt;&lt; "; value = " &lt;&lt; columnValueInt &lt;&lt;"\n";
        }
      }
    }
    cout &lt;&lt; "end of call back function \n";
    return 0;
  }
  
  //## end module%50E6CCB50119.additionalDeclarations
  
  
  // Class customer
  
  customer::customer ()
    //## begin customer::customer%50F969EE01E4.hasinit preserve=no
    //## end customer::customer%50F969EE01E4.hasinit
    //## begin customer::customer%50F969EE01E4.initialization preserve=yes
    //## end customer::customer%50F969EE01E4.initialization
  {
    //## begin customer::customer%50F969EE01E4.body preserve=yes
    customerId = 0;
    zErrMsg = 0;
  
    customerDataBaseRc = sqlite3_open("customerdb", &amp;customerDataBase);
    if(customerDataBaseRc)
    {
      fprintf(stderr, "Can't open database %s\n", sqlite3_errmsg(customerDataBase));
      sqlite3_close(customerDataBase);
    }
  
    const char * pSQL[6];
    const char * sqlStatement;
  
    pSQL[0] = "create table customerTable (Id int, FirstName varchar(30), LastName varchar(30), Age smallint)";
  
    // execute all the sql statements
    for(int i = 0; i &lt; 1; i++)
    {
      customerDataBaseRc = sqlite3_exec(customerDataBase, pSQL[i], callback, 0, &amp;zErrMsg);
  
      if( customerDataBaseRc !=SQLITE_OK )
      {
        fprintf(stderr, "SQL error: %s\n", zErrMsg);
        sqlite3_free(zErrMsg);
        break; // break the loop if error occur
      }
    }
    //## end customer::customer%50F969EE01E4.body
  }
  
  
  customer::~customer ()
  {
    //## begin customer::~customer%50F93279003E.body preserve=yes
    const char *pSQL[6];
  
    // Remove all data in customerTable
    pSQL[0] = "delete from customerTable";
  
    // Drop the table from database
    pSQL[1] = "drop table customerTable";
  
    // execute all the sql statements
    for(int i = 0; i &lt; 2; i++)
    {
      customerDataBaseRc = sqlite3_exec(customerDataBase, pSQL[i], callback, 0, &amp;zErrMsg);
      if( customerDataBaseRc !=SQLITE_OK )
      {
        fprintf(stderr, "SQL error: %s\n", zErrMsg);
        sqlite3_free(zErrMsg);
        break; // break the loop if error occur
      }
    }
    cout &lt;&lt; "destructor";
    //## end customer::~customer%50F93279003E.body
  }
  
  
  
  //## Other Operations (implementation)
  unsigned int customer::createCustomer (char  iCustomerFirstName[20], char  iCustomerLastName[20], unsigned short iCustomerAge)
  {
    //## begin customer::createCustomer%50EBFFA3036B.body preserve=yes
    const char *sqlStatement;
  
    string result;          // string which will contain the result
  
    ostringstream convert;   // stream used for the conversion
  
    convert &lt;&lt; "insert into customerTable (Id, FirstName, LastName, Age) values (" &lt;&lt; customerId &lt;&lt; ", '" &lt;&lt; iCustomerFirstName &lt;&lt; "', '" &lt;&lt; iCustomerLastName &lt;&lt; "', " &lt;&lt; iCustomerAge &lt;&lt; ")";
    result = convert.str(); // set 'Result' to the contents of the stream
  
    sqlStatement = result.c_str();
  
    // Execute sql statement
    customerDataBaseRc = sqlite3_exec(customerDataBase, sqlStatement, callback, 0, &amp;zErrMsg);
    // Check for errors
    if(customerDataBaseRc !=SQLITE_OK )
    {
      fprintf(stderr, "SQL error: %s\n", zErrMsg);
      sqlite3_free(zErrMsg);
    }
  
    return customerId++;
    //## end customer::createCustomer%50EBFFA3036B.body
  }
  
  char * customer::getCustomer (unsigned int iCustomerId)
  {
    //## begin customer::getCustomer%50ED3D700186.body preserve=yes
    const char *sqlStatement;
  
    char *tmp ="blabla";
  
    string result;          // string which will contain the result
  
    ostringstream convert;   // stream used for the conversion
  
    convert &lt;&lt; "select * from customerTable where Id = " &lt;&lt; iCustomerId;
    result = convert.str(); // set 'Result' to the contents of the stream
  
    sqlStatement = result.c_str();
  
    // Execute the sql statement
    customerDataBaseRc = sqlite3_exec(customerDataBase, sqlStatement, callback, 0, &amp;zErrMsg);
    // Check for errors
    if(customerDataBaseRc !=SQLITE_OK )
    {
      fprintf(stderr, "SQL error: %s\n", zErrMsg);
      sqlite3_free(zErrMsg);
    }
  
    return tmp;
    //## end customer::getCustomer%50ED3D700186.body
  }
  
  // Additional Declarations
    //## begin customer%50E6CCB50119.declarations preserve=yes
    //## end customer%50E6CCB50119.declarations
  
  //## begin module%50E6CCB50119.epilog preserve=yes
  //## end module%50E6CCB50119.epilog
  </code></pre>