Home Up PDF Prof. Dr. Ingo Claßen
P6

JSON aus GraphQL-Abfragen erzeugen

Einleitung

In dieser Aufgabe sollen sie aus vereinfachten GraphQL-Abfragen Postgres-SQL-Code erzeugen, der JSON-Strukturen als Antwort zurückliefert.

Grundlage für die Erzeugung sind Tabellen, die durch Fremdschlüssel miteinander verbunden sind, wie im folgenden Beispiel. GraphQL ermöglicht einen einfachen Zugriff auf solche Strukturen und liefert JSON zurück, das dann in Anwendungsprogrammen direkt weiterverwendet werden kann.

Konkret besteht ihr Aufgabe darin, in Python folgende Funktion zu implementieren:

def gql_to_jon(gql: AST) -> str

Die Abfragen werden als Abstract Syntax Trees (AST) bereitgestellt:

@dataclass
class Cond():
    l: str
    r: str

@dataclass
class AST():
    name: str
    attr: list[str]
    cond: Optional[Cond] = None
    sub: Optional['AST'] = None

Abfrage AST
t1 {
      a
}
AST(name='t1', attr=['a'], cond=None, sub=None)

Notebook Preview

Notebook

Beispielabfragen

Im Folgenden finden sie eine Reihe von Beispielabfragen, die für ihren Code als Test dienen sollen.

Abfrage Bedeutung
Beispiel 01
t1 {
    a
}
Alle Objekte aus Tabelle "t1". Es soll nur Spalte "a" ausgegeben werden.
Beispiel 02
t1 (a: 'a1') {
    a
    b
}
Wie Beispiel 01. Es sollen aber nur Objekte ausgegeben werden, bei denen die Spalte "a" den Wert 'a1' hat.
Beispiel 03
t1 (a: 'a1') {
    a
    b
    t2 {
        c
        d
    }
}
Wie Beispiel 02. Es sollen zusätzlich alle "t2"-Objekte ausgegeben werden, die mit den "t1"-Objekten verbunden sind.
Beispiel 04
t1 (a: 'a1') {
    a
    b
    t2 (d: 'd12') {
        c
        d
    }
}
Wie Beispiel 03. Die verbundenen Objekte sollen gefiltert werden, die Spalte "d" soll den Wert 'd12' haben.
Beispiel 05
t1 (a: 'a1') {
    a
    b
    t2 (d: 'd12') {
        c
        d
        t3 {
            e
            f
        }
    }
}
Wie Beispiel 04. Es soll eine weitere Ebene mit den verbundenen "t3"-Objekten ausgegeben werden
Beispiel 06
t1 (a: 'a1') {
    a
    b
    t2 (d: 'd12') {
        c
        d
        t3 (f: 'f103') {
            e
            f
        }
    }
}
Wie Beispiel 05. Die verbundenen "t3"-Objekte sollen gefiltert werden, die Spalte "f" soll den Wert 'f103' haben.

Tabellen

Zum Testen werde folgenden Beispieldaten bereitgestellt.

t1 t2 t3

Auswertungsbeispiele

Hier werden die Ergebnisse angegeben, die ihr Code bei der jeweiligen Abfrage liefern soll.

Abfrage Erwartetes JSON-Ergebnis
Beispiel 01
t1 {
    a
}
[
      {
          "a": "a1"
      },
      {
          "a": "a2"
      }
]
Beispiel 02
t1 (a: 'a1') {
    a
    b
}
[
    {
        "a": "a1",
        "b": "b1"
    }
]
Beispiel 03
t1 (a: 'a1') {
    a
    b
    t2 {
        c
        d
    }
}
[
    {
        "a": "a1",
        "b": "b1",
        "t2": [
            {
                "c": "c11",
                "d": "d11"
            },
            {
                "c": "c12",
                "d": "d12"
            }
        ]
    }
]
Beispiel 04
t1 (a: 'a1') {
    a
    b
    t2 (d: 'd12') {
        c
        d
    }
}
[
    {
        "a": "a1",
        "b": "b1",
        "t2": [
            {
                "c": "c12",
                "d": "d12"
            }
        ]
    }
]
Beispiel 05
t1 (a: 'a1') {
    a
    b
    t2 (d: 'd12') {
        c
        d
        t3 {
            e
            f
        }
    }
}
[
    {
        "a": "a1",
        "b": "b1",
        "t2": [
            {
                "c": "c12",
                "d": "d12",
                "t3": [
                    {
                        "e": "e103",
                        "f": "f103"
                    },
                    {
                        "e": "e104",
                        "f": "f104"
                    }
                ]
            }
        ]
    }
]
Beispiel 06
t1 (a: 'a1') {
    a
    b
    t2 (d: 'd12') {
        c
        d
        t3 (f: 'f103') {
            e
            f
        }
    }
}
[
    {
        "a": "a1",
        "b": "b1",
        "t2": [
            {
                "c": "c12",
                "d": "d12",
                "t3": [
                    {
                        "e": "e103",
                        "f": "f103"
                    }
                ]
            }
        ]
    }
]

Hinweise zur Lösung

Gehen sie bei der Implementierung wie folgt vor:

  • AST traversieren und eine Postgres-Query erzeugen
  • Diese Query muss geeignete JSON-Erzeugungsfunktionen verwenden
  • Query an die Datenbank senden und Ergebnis ausgeben
  • Beachten sie, dass sie die Namen der Tabellen und Spalten aus der GraphQL-Query entnehmen und nicht hart kodieren
  • Um verbundene Objekte auszugeben, müssen sie Datenbank-Joins erzeugen
  • Die dazu notwendigen Fremd- und Primärschlüssel müssen sie über die Datenbank-Metadaten ermitteln