Mittwoch, 23. Mai 2012


Artikel

Juli 2009 | Artikel

Datenbanken elegant in Embedded-Systeme integrieren Fortsetzung, Teil 3

Teil 1   Teil 2   Teil 3   Teil 4   

Die dargestellten SQL-Kommandos erstellen die Tabelle tb_books (SQL-Kommando 1) und fügen der Tabelle zwei Datensätze hinzu (SQL-Kommando 2 und 3). Die Kommandos können direkt auf der SQLite-Konsole eingegeben oder als SQL-Skript abgespeichert und mit dem Kommandozeileninterface ausgeführt werden. Für Letzteres stellt die SQLite-Konsole das .read-Kommando bereit. Die Abbildung 1 stellt den kompletten Ablauf nochmals dar.

Im Screenshot wird SQLite mit der nicht vorhandenen Datenbank test.db gestartet. Das angegebene Skript newdb.sql erstellt die gewünschte Datenbank. Es wird überprüft, ob das Skript korrekt ausgeführt wurde. Das allgemeine Kommando .tables listet alle Tabellen der Datenbank auf. Um das Schema einer Tabelle anzuzeigen, stellt die SQLite-Konsole das allgemeine Kommando .schema zur Verfügung, während das SQL-Kommando describe nicht unterstützt wird. Der komplette Inhalt der Tabelle tb_books wird mit dem SQL-Kommando select * from tb_books auf der Konsole ausgegeben.

Datenbankfunktionalität in C/C++-Programme integrieren

Da die SQLite Library in C entwickelt wurde, stellt das API Strukturen und Funktionen für den Zugriff auf die Datenbank bereit. Die Major-Version 3 ist in den Funktionsnamen enthalten, die stets mit dem Präfix sqlite3 beginnen. Das Programm accessdb.cpp (Listing 1) öffnet die zuvor angelegte Datenbank, führt ein SELECT-Statement aus und schließt die Datenbank.

  1. Listing 1:
  2. accessdb.cpp
  3. #include <iostream>
  4. #include "sqlite3.h"
  5. using namespace std;
  6. static int callbackFkt(void* unused, int colCount, char** colValue, char** colName) {
  7. for(int i=0; i<colCount; i++)
  8. cout << colName[i] << " " << (colValue[i] ? colValue[i] : "NULL") << endl;
  9. return 0;
  10. }
  11. int main() {
  12. sqlite3* db;
  13. char* error = 0;
  14. int result = sqlite3_open("test.db", &db);
  15. if(result != SQLITE_OK) {
  16. cout << "Can not open database: " << sqlite3_errmsg(db) << endl;
  17. sqlite3_close(db);
  18. exit(1);
  19. }
  20. result = sqlite3_exec(db, "SELECT author, title FROM tb_books",
  21. callbackFkt, 0, &error);
  22. if(result != SQLITE_OK) {
  23. cout << "SQL error: " << error << endl;
  24. if(error)
  25. free(error);
  26. }
  27. sqlite3_close(db);
  28. return 0;
  29. }

Mehr zum Thema

Hat Ihnen dieser Artikel gefallen? Dies und mehr ist alles Teil der Ausgabe 3.09 unseres Entwickler Magazins. Mehr zu diesen und anderen Themen bekommen Sie alle zwei Monate frisch am Kiosk! Zur jeweils aktuellen Ausgabe geht es hier.

Für das Öffnen der Datenbank wird die Funktion sqlite3_open aufgerufen, die als Parameter den Dateinamen und eine Referenz auf den Doppelzeiger auf die Struktur sqlite3, die die Datenbank repräsentiert, erwartet. Ist der Ergebniscode SQLITE_OK, dann wird mit sqlite3_exec ein Select-Statement ausgeführt. Andernfalls wird das Programm beendet. Die Funktion sqlite3_exec erwartet den Doppelzeiger auf die sqlite3-Struktur, das Select-Statement die Adresse der Callback-Funktion, das erste Argument der Callback-Funktion und eine Referenz auf einen String für eine eventuelle Fehlermeldung. Die Callback-Funktion wird dann für jeden Datensatz, der sich in der Ergebnismenge des Select-Statements befindet, aufgerufen.

Im Beispiel aus Listing 1 gibt die Callback-Funktion die Spaltennamen und die Werte der zugehörigen Datensätze aus. Die Datenbank wird mit der Funktion sqlite3_close wieder geschlossen. Das Beispielprogramm lässt sich direkt auf der Kommandozeile übersetzen. Der angegebene Compileraufruf erzeugt eine ausführbare Datei accessdb, die dynamisch an die Library libsqlite3.so gebunden ist:

> g++ -o accessdb accessdb.cpp -Wall -W -O2 -ldl -Wl,-R/usr/local/lib -lsqlite3

Es besteht allerdings auch die Möglichkeit, den Sourcecode von SQLite3 direkt mit dem Quellcode des Programms zu übersetzen. Das folgende Beispiel zeigt die Cross-Compileraufrufe für ARM-Linux:

> arm-linux-gcc -c sqlite3.c
> arm-linux-g++ -c accessdb.cpp
> arm-linux-g++ -o accessdb-arm sqlite3.o accessdb.o -ldl -pthread

Während die ersten beiden Compileraufrufe die Objektdateien sqlite3.o und accessdb.o erzeugen, werden in Zeile 3 die Objektdateien zusammengelinkt. Die ausführbare Datei accessdb-arm enthält nun die komplette Datenbankfunktionalität.

Teil 1   Teil 2   Teil 3   Teil 4   

Kommentare