Ich mache einige Experimente mit SQLite mit einem einfachen Test-Harnisch eine einzelne Tabelle verwenden, die ein char String-Schlüssel und ein einzelner Integer-Wert enthält. Das Folgende sind Teile der Quelle aus dem experimentellen Test Kabelbaum, den ich verwende. Ich habe diese Teile gezogen, um die Erstellung der Tabelle zusammen mit der Funktion zu zeigen, die ich benutze, um eine Datensatzmenge aus einer SELECT-SQL-Anweisung mit der Rückruffunktion von SQLite zu erstellen. Es gibt printf()
Anweisungen und fprintf()
Anweisungen an verschiedenen Stellen, so dass ich die Ergebnisse von Aktionen sehen kann, da dies eine einfache Konsolanwendung für den Testkabelbaum ist.
Beachten Sie, dass es Zeiten gibt, in denen Sie das Argument Rückruf nicht benötigen, so dass SQLite Ihnen ermöglicht, einen Nullzeiger anzugeben, der angibt, dass der Rückruf nicht gestört wird.
Und wie Sie über die Quelle lesen, denken Sie daran, dies ist ein experimenteller Hack!
Die Funktion zum Erstellen der Tabelle wie folgt aussieht:
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;
}
ich einige Datensätze in diese Tabelle einfügen und dann eine Funktion, die ich eine oder mehr Datensätze aus der Tabelle eine ausgewählte SQL-Anweisung erhalten rufen. Die Auswahlfunktion ruft die Datensätze ab und verwendet einen Rückruf, um jeden zurückgegebenen Datensatz in eine C-Struktur umzuwandeln. Die C-Struktur wie folgt aussehen:
typedef struct {
char cKey[20];
int iValue;
} Tbl1Record;
Der Aufruf für den Datensatz verwendet zurück verwendet eine Struktur, die Aufzeichnung wählen Sie Verwaltungsdaten enthält. Damit meine ich, dass der Rückruf als erstes Argument einen Zeiger auf eine Struktur verwendet, die wiederum auf die Stelle verweist, an der die transformierten Daten zusammen mit einigen Informationen über die Größe des Speicherbereichs abgelegt werden. Da eine Auswahl abhängig von der where-Klausel mehr als einen Datensatz zurückgeben kann, verwendet die Rückruffunktion die Rückrufstruktur, um zu ermitteln, wie viele transformierte Datensätze in den Speicherbereich eingefügt werden können, sowie einen Index, so dass beim Erstellen von Datensätzen Es kann durch den Speicherbereich indizieren, um mehrere transformierte Datensätze zurückzugeben.
Der Rückruf sieht Management-Struktur wie folgt aus:
typedef struct _RecordProcessor {
void *pRecordSet;
int nRecordSetMax;
int nRecordSetActual;
} RecordProcessor;
Die select-Funktion wie folgt aussieht:
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;
}
Der Rückruf, die jeden Datensatz durch die Auswahl sieht wie folgt zurück verarbeitet:
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;
}
Definieren eines Rückrufs zum Formatieren und Ausdrucken wie gewünscht ist keine Option? –