Zum Inhalt springen

Ergebnisprüfung

Die Standardweise, Ergebnisse von Abfragen zu prüfen, ist die Anweisung query, gefolgt vom Buchstaben I so oft, wie Spalten im Ergebnis erwartet werden. Nach der Abfrage werden vier Bindestriche (----) erwartet, gefolgt von den Ergebniswerten, getrennt durch Tabulatoren. Zum Beispiel:

query II
SELECT 42, 84 UNION ALL SELECT 10, 20;
----
42 84
10 20

Aus historischen Gründen werden die Buchstaben R und T ebenfalls akzeptiert, um Spalten zu bezeichnen.

Deprecated DuckDB hat die Verwendung von Typen im sqllogictest als veraltet markiert. Der DuckDB-Test-Runner verwendet oder benötigt sie intern nicht – daher sollte nur I verwendet werden, um Spalten zu bezeichnen.

NULL-Werte und leere Zeichenketten

Leerzeilen haben für den SQLLogic-Test-Runner eine besondere Bedeutung: Sie kennzeichnen das Ende der aktuellen Anweisung oder Abfrage. Deshalb gibt es für leere Zeichenketten und NULL-Werte eine besondere Syntax, die bei der Ergebnisprüfung verwendet werden muss. NULL-Werte sollten die Zeichenkette NULL verwenden, leere Zeichenketten die Zeichenkette (empty), z. B.:

query II
SELECT NULL, ''
----
NULL
(empty)

Fehlerprüfung

Um anzuzeigen, dass ein Fehler erwartet wird, kann der Indikator statement error verwendet werden. statement error nimmt außerdem ein optionales erwartetes Ergebnis entgegen – das als erwartete Fehlermeldung interpretiert wird. Ähnlich wie bei query sollte der erwartete Fehler nach den vier Bindestrichen (----) hinter der Abfrage stehen. Der Test besteht, wenn die Fehlermeldung den Text unter statement error enthält – die gesamte Fehlermeldung muss nicht angegeben werden. Es wird empfohlen, nur einen Teil der Fehlermeldung zu verwenden, damit der Test nicht unnötig bricht, wenn die Formatierung von Fehlermeldungen geändert wird.

statement error
SELECT * FROM non_existent_table;
----
Table with name non_existent_table does not exist!

Regex

In bestimmten Fällen können Ergebniswerte sehr groß oder komplex sein, und uns interessiert nur, ob das Ergebnis einen Textausschnitt enthält. In diesem Fall können wir den Modifikator <REGEX>: gefolgt von einem bestimmten Regex verwenden. Wenn der Ergebniswert zum Regex passt, besteht der Test. Das wird vor allem für die Analyse von Abfrageplänen verwendet.

query II
EXPLAIN SELECT tbl.a FROM 'data/parquet-testing/arrow/alltypes_plain.parquet' tbl(a) WHERE a = 1 OR a = 2
----
physical_plan <REGEX>:.*PARQUET_SCAN.*Filters: a=1 OR a=2.*

Wenn wir stattdessen wollen, dass das Ergebnis einen Textausschnitt nicht enthält, können wir den Modifikator <!REGEX>: verwenden.

Datei

Da Ergebnisse sehr groß werden können und wir Ergebnisse über mehrere Dateien hinweg wiederverwenden möchten, ist es auch möglich, erwartete Ergebnisse mit dem Befehl <FILE> aus Dateien zu lesen. Das erwartete Ergebnis wird aus der angegebenen Datei gelesen. Konventionsgemäß sollte der Dateipfad relativ zur Wurzel des GitHub-Repositorys angegeben werden.

query I
PRAGMA tpch(1)
----
<FILE>:extension/tpch/dbgen/answers/sf1/q01.csv

Zeilenweise gegenüber wertweise Ergebnisreihenfolge

Die Ergebniswerte einer Abfrage können entweder in zeilenweiser Reihenfolge angegeben werden, wobei die einzelnen Werte durch Tabulatoren getrennt sind, oder in wertweiser Reihenfolge. In wertweiser Reihenfolge müssen die einzelnen Werte der Abfrage in Zeilen-Spalten-Reihenfolge jeweils in einer eigenen Zeile stehen. Betrachten Sie das folgende Beispiel in zeilenweiser und wertweiser Reihenfolge:

# row-wise
query II
SELECT 42, 84 UNION ALL SELECT 10, 20;
----
42 84
10 20
# value-wise
query II
SELECT 42, 84 UNION ALL SELECT 10, 20;
----
42
84
10
20

Hashes und Ausgabe von Werten

Neben der direkten Ergebnisprüfung hat die sqllogic-Testsuite auch die Option, MD5-Hashes für Wertvergleiche zu verwenden. Ein Test, der Hashes zur Ergebnisprüfung verwendet, sieht so aus:

query I
SELECT g, string_agg(x,',') FROM strings GROUP BY g
----
200 values hashing to b8126ea73f21372cdb3f2dc483106a12

Dieser Ansatz ist nützlich, um die Größe von Tests zu reduzieren, wenn Ergebnisse viele Ausgabezeilen haben. Er sollte jedoch sparsam verwendet werden, weil Hash-Werte die Tests schwieriger zu debuggen machen, wenn sie fehlschlagen.

Nachdem sichergestellt ist, dass das System das korrekte Ergebnis ausgibt, können Hashes der Abfragen in einer Testdatei berechnet werden, indem mode output_hash zur Testdatei hinzugefügt wird. Zum Beispiel:

mode output_hash
query II
SELECT 42, 84 UNION ALL SELECT 10, 20;
----
42 84
10 20

Die erwarteten Ausgabe-Hashes für jede Abfrage in der Testdatei werden dann auf dem Terminal ausgegeben, wie folgt:

================================================================================
SQL Query
SELECT 42, 84 UNION ALL SELECT 10, 20;
================================================================================
4 values hashing to 498c69da8f30c24da3bd5b322a2fd455
================================================================================

Auf ähnliche Weise kann mode output_result verwendet werden, um das Programm zu zwingen, das Ergebnis für jede in der Testdatei ausgeführte Abfrage auf dem Terminal auszugeben.

Ergebnis-Sortierung

Abfragen können ein optionales Feld haben, das angibt, dass das Ergebnis auf eine bestimmte Weise sortiert werden soll. Dieses Feld steht an derselben Stelle wie das Verbindungs-Label. Deshalb können Verbindungs-Labels und Ergebnis-Sortierung nicht gemischt werden.

Die möglichen Werte dieses Feldes sind nosort, rowsort und valuesort. Ein Beispiel, wie das verwendet werden kann, ist unten angegeben:

query I rowsort
SELECT 'world' UNION ALL SELECT 'hello'
----
hello
world

Im Allgemeinen bevorzugen wir, dieses Feld nicht zu verwenden und uns auf ORDER BY in der Abfrage zu stützen, um deterministische Abfrageantworten zu erzeugen. Bestehende sqllogictests verwenden dieses Feld jedoch umfangreich, daher ist es wichtig, von seiner Existenz zu wissen.

Query-Labels

Ein weiteres Feature, das zur Ergebnisprüfung verwendet werden kann, sind query labels. Damit kann geprüft werden, dass unterschiedliche Abfragen dasselbe Ergebnis liefern. Das ist nützlich, um Abfragen zu vergleichen, die logisch gleichwertig, aber unterschiedlich formuliert sind. Query-Labels werden nach dem Verbindungs-Label oder der Sortierangabe angegeben.

Abfragen mit einem Query-Label müssen kein Ergebnis angeben. Stattdessen werden die Ergebnisse aller Abfragen mit demselben Label miteinander verglichen. Das folgende Skript prüft beispielsweise, dass die Abfragen SELECT 42+1 und SELECT 44-1 dasselbe Ergebnis liefern:

query I nosort r43
SELECT 42+1;
----
query I nosort r43
SELECT 44-1;
----