CORAL [RSSS94] ist ein deduktives Datenbanksystem, daßeine deklarative Sprache und eine Schnittstelle zu C++ beinhaltet. Ein Ziel der Entwickler ist, die deklarative Fähigkeiten von CORAL mit denen einer imperativen Sprache zu verbinden, da so für die Teilaufgaben die jeweils effizienteste Sprache ausgewählt werden kann. Die Programmierschnittstelle für C++ ist eine bidirektionale Schnittstelle: sie ermöglicht sowohl dem Benutzer in einem um deklarative CORAL-Elemente erweitertem C++ zu programmieren als auch in CORAL C++-Konstrukte zu verwenden. Das CORAL System ist selbst in C++ implementiert und kann deshalb auch durch benutzerdefinierte C++-Klassen und Funktionen erweitert werden. Die Objekte der benutzerdefinierten C++-Klassen können nicht durch die deklarative Anfragesprache geändert werden.
Die Syntax der deklarative Anfragesprache von CORAL ist ähnlich wie die von ProLog oder Datalog. In CORAL können auch Module mit Export/Import-Schnittstellen benutzt werden, um Namenskonflikte bei Regeln zuverhindern. Es gibt verschiedene Auswertungsstrategien für Regeln, die entweder vom System automatisch ausgewählt werden oder vom Benutzer bestimmt werden können.
CORAL stellt folgende vordefinierte C++-Klassen zur Verfügung:
CORAL kann in C++ auf zwei verschiedene Arten benutzt werden. Einerseits ist es möglich mit den oben beschriebenen Klassen CORAL-Relationen zu benutzen. Die C++-Funktion im folgenden Beispiel benutzt diesen Weg. Andererseits können CORAL-Befehle auch direkt in den C++-Code eingebettet werden. Dieser C++-Code mußjedoch zuerst von einem CORAL-Preprocessor behandelt werden und kann erst dann mit einem C++-Compiler übersetzt werden.
Diese C++-Funktion summiert die ersten Argumente einer beliebigen CORAL-Relation.
int sum_first_arg(char* rel_name, int rel_arity) {
Relation* rel=find_relation(rel_name,rel_arity);
C_ScanDesc *scan=new C_ScanDesc(rel);
Tuple* tuple;
int sum=0;
/* Iteriere \"uber alle Tupel der Relation */
for(tuple=scan->next_tuple();
!(scan->no_match());
tuple=scan->next_tuple()) {
if (!is_int((*tuple)[0])) {
/* Fehlermeldung, wenn erstes Feld kein Integer ist */
error("non-integer first field");
exit(1);
}
/* Summiere Elemente */
sum+=make_int((*tuple)[0]);
}
return sum;
}
Zunächst wird mit der Funktion find_relation eine Relation berechnet,
die sowohl eine Basisrelation als auch eine abgeleitete Relation sein kann.
Das Programm erzeugt dann einen Cursor (scan) für diese Relation,
und bearbeitet dann sukzessive alle Tupel der Relation. In der Schleife wird
von jedem Tupel das erste Argument ausgewertet (die Zählung beginnt bei 0)
und dann summiert, wenn es ein ganzzahliger Wert ist.
Neue externe Prädikate für das CORAL-System können in C++ mit Hilfe der _coral_export-Anweisung definiert werden. Der zugehörige C++-Code mußauch mit einem Preprocessor behandelt werden bevor er compiliert werden kann. Das Compilat kann zur Laufzeit zu CORAL hinzugeladen werden. Allerdings dürfen solche Funktionen nur die CORAL-Basistypen beinhalten, komplexe benutzerdefinierte Typen sind nicht erlaubt.
Die Erweiterbarkeit des CORAL-Systems mit benutzerdefinierten C++-Klassen ist genauer in [SRSS93] beschrieben. Die Autoren bezeichnen das erweiterte CORAL-System mit CORAL++.
Jede Klasse mußbestimmte Methoden wie z.B. equals und print beinhalten, damit das CORAL++-Basissystem nicht verändert werden muß. Außerdem sollten alle benutzerdefinierten Typen eine Unterklasse von (Coral-)Arg sein, damit während der Regelauswertung keine Typkonversionen vorgenommen werden müssen.
Die Methoden der benutzerdefinierten Objekte können auch im deklarativen Teil
von CORAL++ aufgerufen werden, also innerhalb von Regeln.
Das Literal C(X) bindet eine Variable X an ein Element der Klasse C. Methoden
werden durch einen Ausdruck der Form
aufgerufen. Dabei muß
die Variable X vorher an eine entsprechende Klasse gebunden worden sein.
Für die Auswertung mußein CORAL++-Programm zunächst von einem Preprocessor behandelt
werden.
Ein Überblick über die einzelnen Schritte
für die Erstellung eines erweiterten CORAL++-Systems ist in Abbildung 3.5
gezeigt.
Abbildung 3.5: Erstellung eines erweiterten CORAL++-Systems
Der Benutzer definiert seine eigene C++-Klassen und deren Methoden. Diese werden von einen C++-Compiler übersetzt und ergeben zusammen mit dem CORAL++-Basissystem das erweiterte CORAL++-System. Des weiteren kann der Benutzer ein deklaratives CORAL++-Programm erstellen, daßdie programmspezifischen Regeln enthält. Der Preprocessor generiert für jeden Methodenaufruf in diesem Programm ein externes CORAL-Prädikat. Alle externen CORAL-Prädikate können dann wie oben beschrieben zum erweiterten CORAL++-System hinzugeladen werden. In dem CORAL++-Programm werden dementsprechend alle Methodenaufrufe durch die externen Prädikate ersetzt. Das transformierte Programm kann dann vom CORAL-Interpreter ausgewertet werden.
Christoph Quix