Zum Inhalt

GraphQL Entwickler-Doku (2)

Gen. 24 Enterprise


Sie befinden sich auf der Seite: GraphQL Entwickler-Doku (2).

Weitere Seiten in diesem Bereich:


10. Erweiterte GraphQL-Kernfunktionalitäten

Neben den in den vorherigen Kapiteln beschriebenen Funktionen bietet das microtech GraphQL-Schema zwei weitere Kernfunktionalitäten:

System-Felder (_...) sind Hilfsfunktionen für Typkonvertierung, bedingte Ausführung und Berechnungen. Diese Felder sind in allen Objektkontexten verfügbar – auf Operationsebene, in Tabellen, innerhalb von Datensätzen, und allen anderen Objekten. Sie ermöglichen die Durchführung von Berechnungen, Transformationen und die dynamische Steuerung der Abfragelogik direkt innerhalb der GraphQL-Abfrage.

Erweiterte Schema-Metadaten erweitern die Standard-GraphQL-Introspection um zusätzliche Metadaten über die Datenbankstruktur und Konfiguration. Diese Erweiterungen ermöglichen programmatischen Zugriff auf microtech-spezifische Schema-Informationen.

10.1 System-Felder

10.1.1 Übersicht der System-Felder

System-Felder sind in vier Kategorien unterteilt:

Typisierte Konvertierung und Ausdrucksauswertung: Konvertierung von Werten und Auswertung von Ausdrücken mit definiertem Zieltyp: * _int * _float * _string * _boolean * _bigInt * _any * _guid * _localDate * _localTime * _localDateTime

Kontrollfluss: * _if - Bedingte Objektrückgabe * _ifThenElse - Bedingte Wertrückgabe

Fehlerbehandlung: * _raise - Explizites Auslösen von Exceptions

Metadaten-Abfrage: * _type - Gibt den __Type des aktuellen Kontexts zurück

Die folgende Tabelle zeigt alle verfügbaren System-Felder im Detail:

GraphQL-Feld Rückgabetyp Beschreibung
_int Int Konvertiert einen Wert in eine 32-Bit-Ganzzahl
_float Float Konvertiert einen Wert in eine Fließkommazahl
_string String Konvertiert einen Wert in einen String
_boolean Boolean Konvertiert einen Wert in einen booleschen Wert oder wertet einen booleschen Ausdruck aus
_bigInt BigInt Konvertiert einen Wert in eine Ganzzahl mit bis zu 64 Stellen
_any Any Gibt den Wert unverändert zurück oder wertet einen Ausdruck aus
_guid Guid Konvertiert einen Wert in eine GUID
_localDate LocalDate Konvertiert einen Wert in ein lokales Datum
_localTime LocalTime Konvertiert einen Wert in eine lokale Zeit
_localDateTime LocalDateTime Konvertiert einen Wert in ein lokales Datum mit Zeit
_if Kontext-Objekt oder null Gibt das aktuelle Objekt oder null zurück, abhängig von einer Bedingung
_ifThenElse Any Gibt einen von zwei Werten zurück, abhängig von einer Bedingung
_raise Void Löst eine Exception mit optionaler Nachricht aus
_type __Type Gibt die Typ-Informationen des aktuellen Objektkontexts zurück

10.1.2 Verwendungszweck und Zusammenspiel mit Variablen

System-Felder ermöglichen es, mit dynamischen Werten zu arbeiten, die während der Abfrageausführung in Variablen gespeichert wurden (siehe Kapitel 9.2 zur @store-Direktive). Dies erlaubt:

  • Dynamische Typkonvertierung: Variablen können je nach Kontext in den benötigten Typ konvertiert werden
  • Berechnungen zur Laufzeit: Komplexe Ausdrücke mit Zugriff auf Datenfeldwerte
  • Bedingte Abfragelogik: Teile der Abfrage können basierend auf Laufzeitwerten ein- oder ausgeblendet werden

Performance-Hinweis: Die Ausdrucksauswertung erfolgt anwendungsserverseitig. Obwohl dies Rechenzeit kostet, ist es in der Regel effizienter als mehrere Client-Server-Anfragen für bedingte Logik.

10.1.3 Typkonvertierung und Ausdrucksauswertung

Alle Typkonvertierungsfelder (_int, _float, _string, etc.) folgen einem einheitlichen Muster:

  • Sie akzeptieren entweder value oder expr als Parameter (nie beide gleichzeitig)
  • Bei Verwendung im Kontext eines Row-Objekts haben Ausdrücke automatisch Zugriff auf die Datenfelder dieses Datensatzes
  • Sie konvertieren das Ergebnis in den durch den Feldnamen spezifizierten Typ
10.1.3.1 Gemeinsame Parameter
  • value: Ein beliebiger Wert (meist eine Variable), der in den Zieltyp konvertiert werden soll
  • expr: Ein Ausdruck, der ausgewertet und dessen Ergebnis in den Zieltyp konvertiert werden soll
  • Für _boolean muss dies ein Ausdruck vom Typ SlowBooleanExpression sein (siehe Kapitel 5.4)
  • Für alle anderen Felder muss dies ein Ausdruck vom Typ SlowAnyExpression sein (siehe Kapitel 5.5)
10.1.3.2 Beispiele

Wertausgabe via _any direkt auf Operationsebene:

query (
  $variable: Any = 42
) {
  # Direkte Verwendung auf Operationsebene
  variableWert: _any(value: $variable)

  # Weiterhin normaler Zugriff auf Tabellen
  tblProducts {
    rowsRead {
      fldArtNr
    }
  }
}

Berechneter Ausdruck mit Datenfeldnutzung (expr):

query {
  tblProducts {
    rowsRead {
      fldArtNr
      fldSuchBeg
      fldLagMge
      fldStdPreis

      # Berechnung eines abgeleiteten Wertes aus Standardpreis und Lagermenge
      gesamtwert: _float(expr: {
        mul: [
          { field: fldLagMge },
          { field: fldStdPreis }
        ]
      })

      # Prüfen, ob Lagerbestand vorhanden ist
      hatBestand: _boolean(expr: {
        gt: [
          { field: fldLagMge },
          { value: 0 }
        ]
      })
    }
  }
}
10.1.3.3 Unterschied zur direkten Feldabfrage

Während Datenfelder direkt über fld...-Felder abgefragt werden können, bieten System-Felder zusätzliche Möglichkeiten:

  • Komplexe Berechnungen: System-Felder mit expr erlauben Berechnungen mit mehreren Datenfeldern und konstanten Werten
  • Typkonvertierung: System-Felder erzwingen einen bestimmten Rückgabetyp, unabhängig vom Quelldatentyp
  • Bedingte Logik: In Kombination mit _if und _ifThenElse ermöglichen sie dynamische Abfragen

10.1.3.4 Fehlerbehandlung bei Typkonvertierung

Null-Behandlung: Alle System-Felder folgen dem Prinzip "null in → null out". Wenn der value-Parameter oder das Ergebnis eines expr-Ausdrucks null ist, gibt das System-Feld ebenfalls null zurück.

Konvertierungsfehler: Ungültige Typkonvertierungen (z.B. String "abc" zu Int) lösen Laufzeitfehler aus, die nach Standard-GraphQL-Regeln behandelt werden.

10.1.4 Bedingte Ausführung mit _if und _ifThenElse

10.1.4.1 Das _if-Feld

Das _if-Feld prüft eine Bedingung und gibt basierend auf dem Ergebnis das aktuelle Objekt oder null zurück.

Parameter: * value: (Optional) Ein boolescher Wert (meist eine Variable) * expr: (Optional) Ein SlowBooleanExpression-Ausdruck

Hinweis: Es muss genau ein Parameter, entweder value oder expr, angegeben werden.

Rückgabe: * Wenn die Bedingung true ist: das aktuelle Objekt (der Kontext, auf dem _if aufgerufen wurde) * Wenn die Bedingung false oder null ist: null

Beispiel:

query {
  tblProducts {
    rowsRead {
      fldArtNr
      fldSuchBeg
      fldLagMge

      # Nur wenn Lagermenge > 0, Details anzeigen
      details: _if(expr: { 
        gt: [{ field: fldLagMge }, { value: 0 }] 
      }) {
        fldStdPreis
        fldLagMge
      }
    }
  }
}

In diesem Beispiel wird das details-Objekt nur für Artikel mit fldLagMge > 0 zurückgegeben, andernfalls ist es null.

10.1.4.2 Das _ifThenElse-Feld (If-Then-Else)

Das _ifThenElse-Feld ermöglicht eine bedingte Auswahl zwischen zwei Werten, ähnlich dem ternären Operator in vielen Programmiersprachen.

Parameter: * value: (Optional) Ein boolescher Wert (meist eine Variable) * expr: (Optional) Ein SlowBooleanExpression-Ausdruck * then: (Optional) Der Wert, der zurückgegeben wird, wenn die Bedingung true ist (standardmäßig null) * else: (Optional) Der Wert, der zurückgegeben wird, wenn die Bedingung false oder null ist (standardmäßig null)

Hinweis: Es muss genau ein Parameter für die Bedingung, entweder value oder expr, angegeben werden.

Beispiel:

query {
  tblProducts {
    rowsRead {
      fldArtNr
      fldSuchBeg
      fldLagMge

      # Statustext je nach Lagermenge
      lagerStatus: _ifThenElse(
        expr: { gt: [{ field: fldLagMge }, { value: 0 }] },
        then: "Verfügbar",
        else: "Nicht auf Lager"
      )
    }
  }
}

In diesem Beispiel wird für jeden Artikel abhängig von der Lagermenge ein entsprechender Statustext zurückgegeben.

Wichtiger Hinweis: Das _ifThenElse-Feld kann nicht innerhalb eines Ausdrucks (expr) verwendet werden.

10.1.5 Fehlerbehandlung mit _raise

Das _raise-Feld ermöglicht das explizite Auslösen einer Exception mit einer optionalen Fehlermeldung.

Parameter: * message: (Optional) Ein String mit der Fehlermeldung

Rückgabetyp: Void (der Aufruf kehrt nie normal zurück)

Anwendungsfälle: * Validierung von Eingabedaten * Abbruch der Abfrage bei unerwünschten Zuständen * Erzwingen von Fehlern für Testzwecke

Beispiel:

query {
  tblProducts {
    rowsRead {
      fldArtNr
      fldLagMge

      # Fehler auslösen, wenn Lagermenge negativ ist
      _if(expr: { lt: [{ field: fldLagMge }, { value: 0 }] }) {
        _raise(message: "Negative Lagermenge gefunden!")
      }
    }
  }
}

In diesem Beispiel wird ein Fehler mit der Nachricht "Negative Lagermenge gefunden!" ausgelöst, wenn ein Artikel mit einer negativen Lagermenge gefunden wird.

10.1.6 Realisierung komplexer Logik (durch Kombination mit Direktiven)

System-Felder können mit den in Kapitel 9 beschriebenen Direktiven kombiniert werden, insbesondere mit @store (Kapitel 9.2) und @onNull (Kapitel 9.3), um komplexe Logik zu realisieren.

10.1.6.1 Beispiel: Bedingte Anzeige mit dynamischen Variablen
query ($hatBestand: Boolean = false) {
  tblProducts {
    rowsRead {
      fldArtNr
      fldSuchBeg

      # Prüfen, ob Artikel einen Lagerbestand hat
      _boolean(expr: {
        gt: [{ field: fldLagMge }, { value: 0 }]
      }) @store(in: $hatBestand)

      # Details nur anzeigen, wenn Lagerbestand vorhanden
      details: _if(value: $hatBestand) {
        fldLagMge
        fldStdPreis
      }
    }
  }
}

In diesem Beispiel wird die Variable $hatBestand dynamisch aufgrund des Lagerbestands jedes Artikels aktualisiert und zur Steuerung der Anzeige weiterer Details verwendet.

10.1.6.2 Beispiel: Komplexe Bedingungslogik
query {
  tblProducts {
    rowsRead {
      fldArtNr
      fldGspKz
      fldLagMge

      # Bedingter Wert basierend auf Artikel-Status
      lieferStatus: _ifThenElse(
        expr: {
          and: [
            # Artikel ist nicht gesperrt
            { not: { field: fldGspKz } },
            # Lagermenge > 0
            { gt: [{ field: fldLagMge }, { value: 0 }] }
          ]
        },
        then: "Lieferbar",
        else: "Nicht lieferbar"
      )
    }
  }
}

Dieses Beispiel zeigt, wie komplexe Bedingungslogik mit verschachtelten Ausdrücken und mehreren Datenfeldern realisiert werden kann.

10.1.7 Praktische Einsatzbeispiele

10.1.7.1 Formatierung und Anreicherung von Daten
query {
  tblProducts {
    rowsRead {
      fldArtNr
      fldSuchBeg

      # Artikelnummer und Suchbegriff kombinieren
      artikelText: _string(expr: {
        add: [
          { field: fldArtNr },
          { value: " - " },
          { field: fldSuchBeg }
        ]
      })
    }
  }
}
10.1.7.2 Dynamische Filterung innerhalb eines Objekts
query {
  tblProducts {
    rowsRead {
      fldArtNr
      fldSuchBeg
      fldGspKz

      # Nur nicht gesperrte Artikel mit Warengruppe anzeigen
      warengruppe: _if(expr: {
        not: { field: fldGspKz }
      }) {
        rowWgrNr {
          fldWgrNr
          fldBez
        }
      }
    }
  }
}
10.1.7.3 Bedingte Darstellung mit Datumsverarbeitungen
query {
  tblTransactions {
    rowsRead {
      fldBelegNr
      fldDat

      # Datumsverarbeitung: Aktuelles Datum
      aktuellesDatum: _localDate(expr: { fnGetAktDate: [] })

      # Datum ein Jahr zurück (12 Monate)
      jahresVergleich: _localDate(expr: { 
        fnIncDate: [
          { fnGetAktDate: [] }, 
          { value: 0 }, 
          { value: -12 }
        ] 
      })

      # Prüfen ob Beleg älter als ein Jahr ist
      istAlt: _boolean(expr: {
        lt: [
          { field: fldDat },
          { fnIncDate: [
            { fnGetAktDate: [] }, 
            { value: 0 }, 
            { value: -12 }
          ]}
        ]
      })
    }
  }
}

Mit dieser umfassenden Palette an System-Feldern bietet die microtech GraphQL-Schnittstelle äußerst flexible Möglichkeiten, komplexe Datenabfragen und -manipulationen direkt in der Abfrage zu definieren und so die Effizienz und Lesbarkeit Ihrer Anwendungen zu verbessern.

10.1.8 Metadaten-Abfrage mit _type

Das _type-Feld ermöglicht den direkten Zugriff auf die Typ-Informationen des aktuellen Objektkontexts. Es gibt ein __Type-Objekt zurück, das alle Schema-Informationen einschließlich der microtech-spezifischen Extensions enthält.

10.1.8.1 Funktionsweise

_type benötigt keine Parameter und gibt immer den __Type des Objekts zurück, auf dem es aufgerufen wird. Dies funktioniert in allen Kontexten – auf Operationsebene, in Tabellen, in Datensätzen und allen anderen Objekttypen.

10.1.8.2 Anwendungsfälle
  • Schema-Exploration: Erkunden der verfügbaren Felder und deren Typen im aktuellen Kontext
  • Dynamische Metadaten-Abfrage: Zugriff auf microtech-spezifische Extensions ohne den Typ-Namen zu kennen
  • Debugging: Überprüfung der tatsächlichen Typ-Struktur zur Laufzeit
  • Generische Abfragen: Erstellen von Abfragen, die mit verschiedenen Objekttypen funktionieren
10.1.8.3 Beispiele

Grundlegende Verwendung:

query {
  # Typ-Informationen der Query-Operation
  _type {
    name  # "Query"
    kind  # "OBJECT"
  }

  tblProducts {
    # Typ-Informationen der Tabelle
    _type {
      name  # z.B. "ProductsTableQueryRead"
      mapExtensions  # Tabellen-spezifische Metadaten
    }

    rowsRead {
      # Typ-Informationen des Row-Objekts
      _type {
        name  # z.B. "ProductRowQueryRead"
        fields(excludeSystem: true) {
          name
          typeName
        }
      }
    }
  }
}

Zugriff auf erweiterte Metadaten:

query {
  tblProducts {
    _type {
      # Direkt auf Extensions zugreifen
      mapExtensions  # Alle Extensions als Map
      anyExtensionValue(name: "flags")  # Spezifische Extension

      # Strukturierte Extension-Informationen
      extensions {
        name
        value
      }
    }
  }
}

Kombination mit anderen System-Feldern:

query ($showDebugInfo: Boolean = false) {
  tblProducts {
    rowsRead {
      fldArtNr

      # Bedingte Debug-Informationen
      debugInfo: _if(value: $showDebugInfo) {
        _type {
          name
          fields {
            name
            typeName
            isDeprecated
          }
        }
      }
    }
  }
}

Das _type-Feld ist besonders nützlich für die Entwicklung generischer Tools und für das Debugging komplexer GraphQL-Abfragen.

10.2 Erweiterte Schema-Metadaten

Das microtech GraphQL-Schema erweitert die Standard-Introspection um zusätzliche Metadaten. Diese Erweiterungen ermöglichen programmatischen Zugriff auf erweiterte Schema-Informationen wie Datenbankstruktur, Tabellenbeziehungen und Konfigurationsdetails.

10.2.1 Erweiterte Introspection-Objekte

Alle Standard-GraphQL-Introspection-Objekte (__Schema, __Type, __Field, __InputValue, __EnumValue, __Directive) wurden um zusätzliche Extension-Felder erweitert.

Hinweis zur Verwendung in Entwicklungsumgebungen: Die meisten GraphQL-IDEs und interaktiven Oberflächen verwenden ihre eigene Definition der Introspection-Typen basierend auf der Standard-GraphQL-Spezifikation. Diese Tools erkennen die microtech-spezifischen Erweiterungen nicht und zeigen möglicherweise Fehler oder Warnungen an, wenn Sie Extension-Felder wie mapExtensions, anyExtensionValue oder typeName verwenden.

Diese Warnungen können ignoriert werden – die Abfragen werden trotzdem korrekt ausgeführt. Es handelt sich um ein reines Anzeigeproblem der Entwicklungsumgebung, nicht um einen tatsächlichen Fehler. Dieses Verhalten ist vergleichbar mit der in Kapitel 6.1.2 beschriebenen Situation beim Variable-Typ.

10.2.2 Extension-Zugriff

10.2.2.1 Das mapExtensions-Feld (empfohlen)

Das mapExtensions-Feld (Rückgabetyp: Any) stellt alle Extension-Werte in einem Map-Format zur Verfügung und ist der effizienteste Weg für den Zugriff auf Extension-Daten:

Syntax:

mapExtensions  # Gibt alle Extensions als Key-Value-Map zurück (Any)

Dieses Format sollte bevorzugt verwendet werden, wenn nur die Extension-Werte benötigt werden.

10.2.2.2 Das extensions-Feld

Das extensions-Feld gibt eine Liste von Extension-Objekten mit strukturierten Metadaten zurück:

Syntax:

extensions {
  name        # String: Name der Extension
  typeName    # String: GraphQL-Typ der Extension 
  description # String: Beschreibung der Extension
  value       # Any: Der eigentliche Wert der Extension
}

Verwenden Sie dieses Format nur, wenn Sie zusätzlich zu den Werten auch Typ-Informationen und Beschreibungen benötigen.

10.2.2.3 Das anyExtensionValue-Feld

Das anyExtensionValue(name: String!)-Feld (Rückgabetyp: Any) ermöglicht den direkten Zugriff auf den Wert einer spezifischen Extension:

Syntax:

anyExtensionValue(name: "extensionName")  # String! parameter ist erforderlich

10.2.3 Zusätzliche microtech-spezifische Felder

10.2.3.1 Das typeName-Feld

Die Introspection-Objekte __Field und __InputValue wurden um ein typeName-Feld erweitert, das eine String-Repräsentation des GraphQL-Typs liefert. Im Gegensatz zur Standard-Introspection wird die Typ-Information direkt als String bereitgestellt, einschließlich Non-Null- und List-Modifikatoren. Das typeName-Feld kann Werte wie "Int", "Int!", "[Type]", "[Type!]", "[Type]!" oder "[Type!]!" enthalten.

Beispiel aus dem Schema:

{
  "name": "aceByTaxCode",
  "description": "",
  "args": [
    {
      "name": "taxCode",
      "description": "",
      "typeName": "Int"
    }
  ],
  "typeName": "AmountCompositionEntryQuery",
  "isDeprecated": false
},
{
  "name": "aces",
  "description": "",
  "args": [],
  "typeName": "[AmountCompositionEntryQuery]",
  "isDeprecated": false
}

Das typeName-Feld zeigt direkt "[AmountCompositionEntryQuery]" für Listen und "Int" für einfache Typen, anstatt die bis zu 4-fach verschachtelte ofType-Struktur der Standard-Introspection zu verwenden.

10.2.3.2 Der excludeSystem-Parameter

Das fields-Feld von __Type unterstützt einen zusätzlichen excludeSystem-Parameter:

Syntax:

fields(includeDeprecated: true, excludeSystem: true)

Wenn excludeSystem: true gesetzt ist, werden die System-Felder (_...) aus der Rückgabe ausgeschlossen.

10.2.3.3 Einzelzugriffs-Felder

Alle Introspection-Objekte wurden um direkte Zugriffsmethoden für ihre Listen-Felder erweitert. Diese Felder ermöglichen den effizienten Zugriff auf einzelne Elemente ohne das Abrufen kompletter Listen.

Verfügbare Einzelzugriffs-Felder:

Introspection-Objekt Feld Alternative zu
__Schema type(name: String!) types-Liste
__Schema directive(name: String!) directives-Liste
__Type field(name: String!) fields-Liste
__Type inputField(name: String!) inputFields-Liste
__Type enumValue(name: String!) enumValues-Liste
__Field, __Directive arg(name: String!) args-Liste

Wichtig: Alle Felder geben null zurück, wenn das gesuchte Element nicht existiert.

Beispiel:

query {
  __schema {
    # Direkter Zugriff auf einen Typ
    type(name: "SetBooleanFieldInput") {
      # Direkter Zugriff auf ein Input-Feld
      inputField(name: "text") {
        name
        typeName
      }
    }

    # Direkter Zugriff auf eine Direktive
    directive(name: "onNull") {
      name
      # Direkter Zugriff auf ein Argument der Direktive
      arg(name: "do") {
        name
        typeName
      }
    }
  }

  tblClient {
    rowRead {
      _type {
        # Direkter Zugriff auf ein Feld  
        field(name: "fldID") {
          name
          # Direkter Zugriff auf ein Argument des Feldes
          arg(name: "as") {
            name
            type {
              # Direkter Zugriff auf einen Enum-Wert
              enumValue(name: "TEXT") {
                name
              }
            }
          }
        }
      }
    }
  }
}

Diese Erweiterungen reduzieren den Datenübertragungsaufwand erheblich, wenn nur spezifische Schema-Elemente benötigt werden.

10.2.4 Praktische Beispiele

10.2.4.1 Tabellen-Informationen abfragen

Abfrage:

query {
  __type(name: "PostalCodesTableQueryRead") {
    name
    kind
    extensions {
      name
      typeName
      description
      value
    }
    mapExtensions
    anyExtensionValue(name:"flags")
  }
}

Antwort:

{
  "data": {
    "__type": {
      "name": "PostalCodesTableQueryRead",
      "kind": "OBJECT",
      "extensions": [
        {
          "name": "type",
          "typeName": "DBStrukturKzEnum",
          "description": "",
          "value": "dbsPLZ"
        },
        {
          "name": "dbAlias",
          "typeName": "DbAliasEnum",
          "description": "",
          "value": "dbaGlobal"
        },
        {
          "name": "shortName",
          "typeName": "String!",
          "description": "",
          "value": "Plz"
        },
        {
          "name": "name",
          "typeName": "String!",
          "description": "",
          "value": "Postleitzahlen"
        },
        {
          "name": "shortDescription",
          "typeName": "String!",
          "description": "",
          "value": "Postleitzahlen"
        },
        {
          "name": "description",
          "typeName": "String!",
          "description": "",
          "value": "Postleitzahlen"
        },
        {
          "name": "flags",
          "typeName": "[DBSFlagEnum!]!",
          "description": "",
          "value": [
            "dbsfSetVgbIndex",
            "dbsfSelFelder",
            "dbsfSelSortierungen",
            "dbsfNeedRecreate",
            "dbsfFilterDef",
            "dbsfAllowIndexSuche",
            "dbsfCreated",
            "dbsfInternalAutoIncStruktur",
            "dbsfTableExists",
            "dbsfHatBereichLoeschenCommand",
            "dbsfVerzMehrfachSuche",
            "dbsfCommandDesigner",
            "dbsfUnicodeUnterstuetzung",
            "dbsfAllowClientCaching",
            "dbsfInternalClientCaching",
            "dbsfInternalLz4RecordCompression",
            "dbsfInternalKeylessIndices",
            "dbsfInfoGraphQLRecordType",
            "dbsfInfoGraphQLRootTable"
          ]
        }
      ],
      "mapExtensions": {
        "type": "dbsPLZ",
        "dbAlias": "dbaGlobal",
        "shortName": "Plz",
        "name": "Postleitzahlen",
        "shortDescription": "Postleitzahlen",
        "description": "Postleitzahlen",
        "flags": [
          "dbsfSetVgbIndex",
          "dbsfSelFelder",
          "dbsfSelSortierungen",
          "dbsfNeedRecreate",
          "dbsfFilterDef",
          "dbsfAllowIndexSuche",
          "dbsfCreated",
          "dbsfInternalAutoIncStruktur",
          "dbsfTableExists",
          "dbsfHatBereichLoeschenCommand",
          "dbsfVerzMehrfachSuche",
          "dbsfCommandDesigner",
          "dbsfUnicodeUnterstuetzung",
          "dbsfAllowClientCaching",
          "dbsfInternalClientCaching",
          "dbsfInternalLz4RecordCompression",
          "dbsfInternalKeylessIndices",
          "dbsfInfoGraphQLRecordType",
          "dbsfInfoGraphQLRootTable"
        ]
      },
      "anyExtensionValue": [
        "dbsfSetVgbIndex",
        "dbsfSelFelder",
        "dbsfSelSortierungen",
        "dbsfNeedRecreate",
        "dbsfFilterDef",
        "dbsfAllowIndexSuche",
        "dbsfCreated",
        "dbsfInternalAutoIncStruktur",
        "dbsfTableExists",
        "dbsfHatBereichLoeschenCommand",
        "dbsfVerzMehrfachSuche",
        "dbsfCommandDesigner",
        "dbsfUnicodeUnterstuetzung",
        "dbsfAllowClientCaching",
        "dbsfInternalClientCaching",
        "dbsfInternalLz4RecordCompression",
        "dbsfInternalKeylessIndices",
        "dbsfInfoGraphQLRecordType",
        "dbsfInfoGraphQLRootTable"
      ]
    }
  }
}

10.2.4.2 Vollständige Schema-Introspection

Für umfassende Schema-Analyse kann die folgende Abfrage verwendet werden:

query IntrospectionQuery {
  __schema {
    queryType @onNull(returnValue:skip) { name }
    mutationType @onNull(returnValue:skip) { name }
    subscriptionType @onNull(returnValue:skip) { name }
    types { ...FullType }
    directives { ...Directive }
  }
} 

fragment FullType on __Type {
  kind
  name @onNull(returnValue:skip)
  description @onNull(returnValue:skip)
  fields(includeDeprecated: true excludeSystem: true) @onNull(returnValue:skip) { ...Field }
  inputFields @onNull(returnValue:skip) { ...InputValue }
  interfaces @onNull(returnValue:skip) { ...TypeRef }
  enumValues(includeDeprecated: true) @onNull(returnValue:skip) { ...EnumValue }
  possibleTypes @onNull(returnValue:skip) { ...TypeRef }
  extensions: mapExtensions @onNull(returnValue:skip)
}

fragment InputValue on __InputValue {
  name
  description
  typeName
  defaultValue @onNull(returnValue:skip)
  extensions: mapExtensions @onNull(returnValue:skip)
}

fragment TypeRef on __Type {
  kind
  name @onNull(returnValue:skip)
  ofType @onNull(returnValue:skip) {
    kind
    name @onNull(returnValue:skip)
    ofType @onNull(returnValue:skip) {
      kind
      name @onNull(returnValue:skip)
      ofType @onNull(returnValue:skip) {
        kind
        name @onNull(returnValue:skip)
      }
    }
  }
}

fragment Directive on __Directive {
  name
  description
  locations
  args { ...InputValue }
  extensions: mapExtensions @onNull(returnValue:skip)   
}

fragment Field on __Field {
  name
  description
  args @onNull(returnValue:skip) { ...InputValue }
  typeName
  isDeprecated
  deprecationReason @onNull(returnValue:skip)
  extensions: mapExtensions @onNull(returnValue:skip)
}

fragment EnumValue on __EnumValue {
  name
  description @onNull(returnValue:skip)
  isDeprecated
  deprecationReason @onNull(returnValue:skip)
  extensions: mapExtensions @onNull(returnValue:skip)
}

Diese Abfrage nutzt die @onNull-Direktive (siehe Kapitel 9.3) um null-Werte zu handhaben und die Ausgabe zu bereinigen.

10.2.5 Anwendungsfälle

Die erweiterten Metadaten ermöglichen:

  • Automatische Tool-Generierung: Basierend auf Schema-Metadaten
  • Schema-Exploration: Programmatischer Zugriff auf erweiterte Schema-Informationen
  • Entwicklungsunterstützung: Besseres Verständnis der zugrundeliegenden Strukturen

10.2.6 Bewährte Verfahren

10.2.6.1 Effiziente Abfragen
  • Bevorzugen Sie mapExtensions: Für den Zugriff auf Extension-Werte
  • Verwenden Sie anyExtensionValue: Für einzelne, bekannte Extensions
  • Nutzen Sie excludeSystem: true: Um System-Felder bei der Schema-Analyse auszuschließen
  • Kombinieren Sie mit @onNull: Für saubere JSON-Ausgaben
10.2.6.2 Tool-Entwicklung
  • Schema-Caching: Die erweiterten Metadaten ändern sich selten und können aggressiv gecacht werden
  • Robuste Fehlerbehandlung: Tools sollten auch funktionieren, wenn spezifische Extensions fehlen
  • Typname-Nutzung: Verwenden Sie typeName für einfachere Typ-Verarbeitung

Hinweis: Die verfügbaren Extension-Namen und -Werte können sich je nach microtech Software-Version und Konfiguration unterscheiden. Tools sollten flexibel auf verfügbare Extensions reagieren.

Mutationen mit GraphQL

Im nächsten Kapitel stellen wir Ihnen das Mutationen-Konzept vor.


Weitere Informationen in diesem Bereich: