我使用一個包含字符字符串鍵和一個整數值單個表做一些實驗中使用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