SQLite3 と組み合わせてテストする目的で、次の C++ コードがあります。customer
コールバック関数を宣言して呼び出すクラスです。このコールバック関数はsqlite3_exec()
、SQLite データベースから結果 (レコード) が返されるたびに呼び出されます。
この構造について私が気に入らないのは、結果を処理するソース コードが、呼び出されたクラス メソッドによって処理される結果ではなく、クラス外のコールバック関数にあることsqlite3_exec()
です。
コールバック関数が SQL クエリの結果から値を抽出し終わった後に、クラス メソッドで使用されるグローバル変数を使用できます。しかし、複数のレコードがあり、コールバック関数が数回呼び出された場合はどうなるでしょうか。次に、単一の結果しか得られないことを確認しない限り、配列を操作する必要があります。
コールバック関数のことは忘れて、SQLite API のより深い呼び出しに入る必要がありますか?
または、C++ ラッパーに移動する必要がありますか?そこにはコールバック メカニズムがなく、結果がクラス メソッド自体に返されると思いますか?
// 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 << "begin of callback function\n";
for(i=0; i<argc; i++)
{
columnName = azColName[i];
if (strcmp(columnName, "FirstName")==0 || strcmp(columnName, "LastName")==0)
{
columnValueString = argv[i];
cout << "columnName = " << columnName << "; value = " << columnValueString <<"\n";
}
else
{
if(strcmp(columnName, "Age")==0)
{
stringstream(argv[i]) >> columnValueShortInt;
cout << "columnName = " << columnName << "; value = " << columnValueShortInt <<"\n";
}
else // strcmp(columnName, "Id")==0)
{
stringstream(argv[i]) >> columnValueInt;
cout << "columnName = " << columnName << "; value = " << columnValueInt <<"\n";
}
}
}
cout << "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", &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 < 1; i++)
{
customerDataBaseRc = sqlite3_exec(customerDataBase, pSQL[i], callback, 0, &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 < 2; i++)
{
customerDataBaseRc = sqlite3_exec(customerDataBase, pSQL[i], callback, 0, &zErrMsg);
if( customerDataBaseRc !=SQLITE_OK )
{
fprintf(stderr, "SQL error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
break; // break the loop if error occur
}
}
cout << "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 << "insert into customerTable (Id, FirstName, LastName, Age) values (" << customerId << ", '" << iCustomerFirstName << "', '" << iCustomerLastName << "', " << iCustomerAge << ")";
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, &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 << "select * from customerTable where Id = " << 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, &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