Zum Inhalt

Frictionless-zu-Parquet-Typmapping

Beim CSV-Upload erzeugt das odi-staging-backend aus der validierten CSV-Datei mehrere Repräsentationen, darunter eine Apache-Parquet-Datei. Damit die Parquet-Spalten exakt den im Frictionless-Schema deklarierten Typen entsprechen und nicht von der automatischen Typ-Inferenz von Apache Arrow abhängen, wird ein explizites Mapping verwendet.

Wo wird das Mapping genutzt?

Die zentrale Typ-Map liegt im odi-staging-backend unter src/upload/parquet/frictionless-to-parquet-type.map.ts.

Vor der Parquet-Erzeugung werden die CSV-Zeilen vom CsvJsonService in die passenden JavaScript-Werte konvertiert. Anschließend baut der ParquetService daraus ein Arrow-Schema mit expliziten Datentypen und schreibt es über parquet-wasm als Parquet.

Logische und physische Parquet-Typen

Parquet unterscheidet zwischen zwei Ebenen:

  • Physischer Typ: Beschreibt, wie die Rohbytes in der Datei abgelegt werden (z. B. BYTE_ARRAY, INT32, INT64, DOUBLE). Er ist werkzeugunabhängig und Teil des Parquet-Formats.
  • Logischer Typ: Gibt die semantische Bedeutung der physischen Daten an (z. B. UTF8, DATE, TIMESTAMP). Viele Werkzeuge zeigen den logischen Typ an, verwenden aber eigene Namen dafür.

Darum kann ein und dieselbe Spalte je nach Betrachter unterschiedlich beschriftet sein: Parquet selbst und Apache Arrow sprechen von UTF8, während Datenbank-Werkzeuge und einige Parquet-Viewer den logischen Typ häufig als VARCHAR oder STRING anzeigen. UTF8, VARCHAR und STRING bedeuten hier dasselbe: eine variable Zeichenkette.

Mapping-Tabelle

Frictionless-Typ Parquet-Typ (logisch) Parquet-Typ (physisch) Beschreibung
string UTF8 (VARCHAR) BYTE_ARRAY Beliebiger Text.
number DOUBLE DOUBLE Gleitkommazahlen (IEEE 754 doppelte Genauigkeit).
integer INT64 (BIGINT) INT64 Ganze Zahlen mit Vorzeichen (64 Bit).
boolean BOOLEAN BOOLEAN Wahrheitswerte.
date DATE INT32 Kalenderdatum ohne Uhrzeit.
datetime TIMESTAMP(MILLIS, UTC) (TIMESTAMP) INT64 Zeitstempel mit Millisekundengenauigkeit.
time TIME(MILLIS) (TIME) INT32 Tageszeit in Millisekunden seit Mitternacht.
year INT64 (BIGINT) INT64 Jahreszahl als Ganzzahl.
yearmonth UTF8 (VARCHAR) BYTE_ARRAY Jahr-Monat-Kombination, als ISO-Text belassen.
duration UTF8 (VARCHAR) BYTE_ARRAY Dauer als ISO-8601-Text belassen.
geopoint UTF8 (VARCHAR) BYTE_ARRAY Geografischer Punkt als Text belassen.
geojson UTF8 (VARCHAR) BYTE_ARRAY GeoJSON-Geometrie als Text belassen.
any UTF8 (VARCHAR) BYTE_ARRAY Fallback auf UTF8 für den generischen Typ any.

Besondere Verhaltensweisen

Leere Zellen

Leere CSV-Zellen werden für typisierte Spalten als null geschrieben. Alle Spalten werden daher im Arrow-Schema als nullable deklariert.

Unbekannte Frictionless-Typen

Ist ein Feld im Schema mit einem noch nicht unterstützten Typ deklariert, fällt das Mapping auf string (UTF8) zurück. Dadurch bleibt die Parquet-Erzeugung stabil, auch wenn Schemas neue Typen enthalten, bevor die Map erweitert wird.

Boolean-Spalten mit ausschließlich null

In Apache Arrow erzeugt ein Bool-Vektor, der nur null-Werte enthält, kein Validity-Bitmap. Das führt beim Schreiben durch parquet-wasm zu einem Fehler. In diesem Edge-Case fällt das Staging-Backend daher für diese Spalte auf UTF8 zurück, sodass die Werte weiterhin als null erhalten bleiben.

Weiterführend