我使用一个包含字符字符串键和一个整数值单个表做一些实验中使用SQLite用一个简单的测试工具。以下是我正在使用的实验测试工具的源代码片段。为了显示表的创建以及我用来使用SQLite的回调函数从选择SQL语句创建记录集的功能,我将这些部分拉出来。在各个地方有printf()
语句和fprintf()
语句,以便我可以看到操作的结果,因为这是测试工具的简单控制台类型应用程序。
注意,有些时候你不需要回调参数,因此SQLite的允许您指定表示不与呼叫懒得回NULL指针。
而当你阅读源代码时,请记住这是一个实验性的黑客!
的函数来创建表如下所示:
int CreateSetupTable (sqlite3 *db)
{
char *zErrMsg = 0;
int rc;
char *aszSqlCreate = "create table tbl1(one varchar(10), two smallint)";
char *aszSqlCreateIndex01 = "create unique index index1 on tbl1 (one)";
do {
rc = sqlite3_exec(db, aszSqlCreate, 0, 0, &zErrMsg);
if(rc!=SQLITE_OK){
fprintf(stderr, "SQL error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
break;
}
rc = sqlite3_exec(db, aszSqlCreateIndex01, 0, 0, &zErrMsg);
if(rc!=SQLITE_OK){
fprintf(stderr, "SQL error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
break;
}
} while (0); // loop only once to allow breaks on errors
return rc;
}
我插入一些记录到这个表,然后让我打电话使用select SQL语句来从表中的一个或多个记录的功能。 select函数检索记录并使用回调将每个返回的记录转换为C结构。 C结构如下所示:
typedef struct {
char cKey[20];
int iValue;
} Tbl1Record;
用于记录集的回调使用包含记录选择管理数据的结构。我的意思是,回调函数将第一个参数作为指向结构体的指针,该结构体指向将转换后的数据以及关于存储区大小的一些信息的位置。由于select可能会根据where子句返回多个记录,因此回调函数使用回调结构来知道可以将多少个转换记录放入内存区域以及索引,以便在放入记录时,它可以通过内存区域索引以返回多个转换记录。
回叫管理结构是这样的:
typedef struct _RecordProcessor {
void *pRecordSet;
int nRecordSetMax;
int nRecordSetActual;
} RecordProcessor;
select函数看起来像:
int SelectRecord (sqlite3 *db, char *cSelect, char *cKey)
{
char *zErrMsg = 0;
int rc;
char aszSqlSelect[128];
Tbl1Record myRec[20];
RecordProcessor myProcessor;
myProcessor.pRecordSet = myRec;
myProcessor.nRecordSetActual = 0;
myProcessor.nRecordSetMax = 20;
if (cKey) {
sprintf (aszSqlSelect, "select %s from tbl1 where one='%s'", cSelect, cKey);
} else {
sprintf (aszSqlSelect, "select %s from tbl1", cSelect);
}
rc = sqlite3_exec(db, aszSqlSelect, MyRecordProcessor, &myProcessor, &zErrMsg);
if(rc!=SQLITE_OK){
fprintf(stderr, "SQL error SelectRecord: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
} else {
int i;
for (i = 0; i < myProcessor.nRecordSetActual; i++) {
printf ("ReC#%d cKey = %s iValue = %d\n", i+1, myRec[i].cKey, myRec[i].iValue);
}
}
return rc;
}
处理由选择这个样子的返回每条记录的回电:
static int MyRecordProcessor (void *callBackArg, int argc, char **argv, char **azColName)
{
int iRetStatus = 0;
char *colNameTable[] = {
"one",
"two"
};
Tbl1Record *pTbl1Record = (Tbl1Record *)((RecordProcessor *)callBackArg)->pRecordSet;
if (((RecordProcessor *)callBackArg)->nRecordSetActual < ((RecordProcessor *)callBackArg)->nRecordSetMax) {
int i, j;
int iIndex = ((RecordProcessor *)callBackArg)->nRecordSetActual;
memset (pTbl1Record + iIndex, 0, sizeof(Tbl1Record));
((RecordProcessor *)callBackArg)->nRecordSetActual++;
for (i = 0; i < argc; i++){
int j;
for (j = 0; j < sizeof (colNameTable)/sizeof(colNameTable[0]); j++) {
if (strcmp (azColName[i], colNameTable[j]) == 0) {
switch (j) {
case 0:
strncpy (pTbl1Record[iIndex].cKey, (argv[i] ? argv[i] : "NULL"), 19);
break;
case 1:
pTbl1Record[iIndex].iValue = atoi (argv[i] ? argv[i] : "0");
break;
default:
break;
}
break;
}
}
}
}
return iRetStatus;
}
定义回调以根据需要格式化并打印它不是一个选项吗? – 2009-11-27 01:38:13