Zum Inhalt springen

Einführung in sqllogictest

Zum Testen von reinem SQL verwenden wir eine erweiterte Version der SQL-Logic-Testsuite, übernommen von SQLite. Jeder Test ist eine einzelne in sich geschlossene Datei im Verzeichnis test/sql. Um Tests außerhalb des Standardverzeichnisses test auszuführen, geben Sie --test-dir <root_directory> an und stellen Sie sicher, dass die angegebenen Testdateipfade relativ zu diesem Wurzelverzeichnis sind.

Der Test beschreibt eine Reihe von SQL-Anweisungen zusammen mit entweder dem erwarteten Ergebnis, einem Indikator statement ok oder einem Indikator statement error. Ein Beispiel für eine Testdatei sieht wie folgt aus:

test/sql/projection/test_simple_projection.test
# group [projection]
# enable query verification
statement ok
PRAGMA enable_verification
# create table
statement ok
CREATE TABLE a (i INTEGER, j INTEGER);
# insertion: 1 affected row
statement ok
INSERT INTO a VALUES (42, 84);
query II
SELECT * FROM a;
----
42 84

In diesem Beispiel werden drei Anweisungen ausgeführt. Die ersten Anweisungen sollen erfolgreich sein (gekennzeichnet durch statement ok). Die dritte Anweisung soll eine einzelne Zeile mit zwei Spalten zurückgeben (angezeigt durch query II). Die Werte der Zeile sollen 42 und 84 sein (getrennt durch ein Tabulatorzeichen). Weitere Informationen zur Prüfung von Abfrageergebnissen finden Sie im Abschnitt zur Ergebnisprüfung.

Oben in jeder Datei sollte ein Kommentar stehen, der Name und Gruppe des Tests beschreibt. Der Name des Tests ist immer der relative Dateipfad der Datei. Die Gruppe ist der Ordner, in dem die Datei liegt. Name und Gruppe des Tests sind relevant, weil sie verwendet werden können, um nur diesen Test in der unittest-Gruppe auszuführen. Wenn wir zum Beispiel nur den obigen Test ausführen wollten, würden wir den Befehl unittest test/sql/projection/test_simple_projection.test ausführen. Wenn wir alle Tests in einem bestimmten Verzeichnis ausführen wollten, würden wir den Befehl unittest "[projection]" ausführen.

Alle Tests, die im Verzeichnis test abgelegt werden, werden automatisch zur Testsuite hinzugefügt. Beachten Sie, dass die Erweiterung des Tests maßgeblich ist. Die sqllogictests sollten entweder die Erweiterung .test oder die Erweiterung .test_slow verwenden. Die Erweiterung .test_slow zeigt an, dass der Test länger dauert und nur ausgeführt wird, wenn alle Tests explizit mit unittest * gestartet werden. Tests mit der Erweiterung .test gehören zur schnellen Testmenge.

Abfrageprüfung

Viele einfache Tests beginnen damit, die Abfrageprüfung zu aktivieren. Das geschieht über die folgende PRAGMA-Anweisung:

statement ok
PRAGMA enable_verification

Die Abfrageprüfung führt zusätzliche Validierung aus, um sicherzustellen, dass der zugrunde liegende Code korrekt läuft. Der wichtigste Teil davon ist, dass sie prüft, ob Optimierer keine Fehler in der Abfrage verursachen. Dazu wird sowohl eine unoptimierte als auch eine optimierte Version der Abfrage ausgeführt und geprüft, dass die Ergebnisse dieser Abfragen identisch sind.

Die Abfrageprüfung ist sehr nützlich, weil sie nicht nur Fehler in Optimierern findet, sondern auch Fehler z. B. in Join-Implementierungen. Das liegt daran, dass die unoptimierte Version typischerweise mit Kreuzprodukten arbeitet. Deshalb kann die Abfrageprüfung bei größeren Datensätzen sehr langsam sein. Es wird daher empfohlen, die Abfrageprüfung für alle Unit-Tests einzuschalten, außer für solche mit größeren Datensätzen (mehr als etwa 10–100 Zeilen).

Editoren und Syntaxhervorhebung

Die sqllogictests sind kein Branchenstandard, aber mehrere andere Systeme haben sie ebenfalls übernommen. Das Parsen von sqllogictests ist bewusst einfach. Alle Anweisungen müssen durch Leerzeilen getrennt sein. Deshalb ist das Schreiben eines Syntax-Highlighters nicht besonders schwierig.

Einen Syntax-Highlighter gibt es für Visual Studio Code. Wir haben außerdem einen Fork erstellt, der den DuckDB-Dialekt der sqllogictests unterstützt. Sie können den Fork nutzen, indem Sie das Original installieren und anschließend syntaxes/sqllogictest.tmLanguage.json in die installierte Erweiterung kopieren (unter macOS liegt sie in ~/.vscode/extensions/benesch.sqllogictest-0.1.1).

Einen Syntax-Highlighter gibt es auch für CLion. Er lässt sich direkt in der IDE installieren, indem Sie im Marketplace nach SQLTest suchen. Ein GitHub-Repository ist ebenfalls vorhanden; Erweiterungen und Fehlerberichte sind willkommen.

Temporäre Dateien

Für einige Tests (z. B. Tests zu CSV-/Parquet-Dateiformaten) ist es nötig, temporäre Dateien anzulegen. Alle temporären Dateien sollten im temporären Testverzeichnis erstellt werden. Dieses Verzeichnis können Sie nutzen, indem Sie die Zeichenkette __TEST_DIR__ in eine Abfrage schreiben. Diese Zeichenkette wird durch den Pfad des temporären Testverzeichnisses ersetzt.

statement ok
COPY csv_data TO '__TEST_DIR__/output_file.csv.gz' (COMPRESSION gzip);

Require und Erweiterungen

Um den Kern des Systems schlank zu halten, ist bestimmte Funktionalität von DuckDB nur als Erweiterung verfügbar. Tests für diese Erweiterungen können Sie bauen, indem Sie ein Feld require in den Test aufnehmen. Ist die Erweiterung nicht geladen, werden alle Anweisungen nach dem Require-Feld übersprungen. Beispiele dafür sind require parquet oder require icu.

Eine weitere Verwendung ist, einen Test auf eine bestimmte Vektorgröße zu beschränken. Wenn Sie beispielsweise require vector_size 512 zu einem Test hinzufügen, wird der Test nur ausgeführt, wenn die Vektorgröße größer oder gleich 512 ist. Das ist nützlich, weil bestimmte Funktionalität bei kleinen Vektorgrößen nicht unterstützt wird, wir in der CI aber Tests mit einer Vektorgröße von 2 ausführen.