Kommunikation zwischen Apps

Unter diesem Thema wird beschrieben, wie eine Snowflake Native App mit einer anderen Snowflake Native App mithilfe der Kommunikation zwischen Apps (Inter-app Communication, IAC) kommunizieren kann.

Kommunikation zwischen Apps: Überblick

Die Kommunikation zwischen Apps (IAC) ermöglicht einer Snowflake Native App, zusätzliche Funktionen für andere Snowflake Native Apps im selben Verbraucherkonto bereitzustellen, indem es Zugriff auf Funktionen und Prozeduren gewährt, die andere Apps aufrufen können.

Beispiel: Eine Snowflake Native App, die Kunden-IDs auflöst, kann anderen Snowflake Native Apps dabei helfen, Kundendaten durch Verknüpfen von Datensets verschiedener Anbietenden zu verbessern.

IAC bietet die Infrastruktur für zwei oder mehr unabhängige Apps, um miteinander zu kommunizieren und dabei ihre Anforderungen an Verwaltung und Sicherheit zu berücksichtigen. App-Entwicklerteams aktivieren IAC für ihre Apps, indem sie Folgendes tun:

  • Erstellen von Schnittstellen.

  • Verwenden von App-Rollen zur Steuerung des Zugriffs auf die Schnittstellen.

  • Auswahl der synchronen oder asynchronen Interaktion. Bei der synchronen Interaktion werden gespeicherte Prozeduren oder Funktionen verwendet, die andere Apps direkt aufrufen können, während die asynchrone Interaktion den Zugriff auf Anforderungsergebnisse ermöglicht, die in Tabellen oder Ansichten gespeichert sind, die andere Apps abfragen können, um die Ergebnisse zu prüfen.

Terminologie

IAC verwendet die folgenden Begriffe:

Client

Die App, die die Verbindungsanforderung initiiert und die Funktionen und Prozeduren der Server-App aufruft.

Server

Die App, die über App-Rollen Zugriff auf ihre Funktionen und Prozeduren bietet.

Verbraucher

Die benutzende Person, die die Client- und Server-Apps installiert.

Anwendungskonfiguration

Ein SQL-Objekt, das die Client-App verwendet, um den Namen der Server-App anzufordern. IAC verwendet eine Anwendungskonfiguration vom Typ``APPLICATION_NAME``, um den Namen der Server-App zu speichern.

Anwendungsspezifikation

Ein SQL-Objekt, das die Client-App erstellt, um eine Verbindung zur Server-App anzufordern. IAC verwendet eine Anwendungsspezifikation vom Typ CONNECTION. Weitere Informationen zu App-Spezifikationen finden Sie unter Überblick über App-Spezifikationen.

Workflow für die Kommunikation zwischen Apps

Das Herstellen und Verwenden einer Verbindung erfordert einen Handshake-Prozess zwischen der Client- und der Server-App.

  1. Abrufen der App-Rollennamen vom Anbieter der Server-App: Der Anbieter der Client-App stimmt sich mit dem Anbieter der Server-App außerhalb von Snowflake ab, um zu bestimmen, welche Server-App-Rollen in der Verbindungsspezifikation angefordert werden sollen.

  2. Identifizieren der Ziel-App: Die Client-App erstellt ein Konfigurationsdefinitionsobjekt, um den Namen der Server-App anzufordern. Der Verbrauchende erkennt eingehende Anforderungen und stellt der Client-App den Namen der Server-App über das Konfigurationsobjekt zur Verfügung.

  3. Anfordern und Genehmigen einer Verbindung: Die Client-App erstellt eine Anwendungsspezifikation, um eine Verbindung zur Server-App anzufordern, und der Verbrauchende genehmigt die Verbindungsanforderung.

  4. Kommunizieren mit der Server-App: Die Client-App ruft die Prozeduren oder Funktionen der Server-App auf.

Identifizieren der Ziel-App

Bevor eine Client-App mit einer Server-App kommunizieren kann, muss sie zunächst den genauen Namen der App ermitteln. Da der Verbrauchende während der Installation einen kundenspezifischen Namen für eine App wählen kann, muss die Client-App zunächst den genauen Namen der Server-App identifizieren.

Das Setup-Skript der Client-App erstellt ein CONFIGURATION DEFINITION-Objekt, um diese Informationen anzufordern.

Das folgende Beispiel zeigt, wie das Setup-Skript der Client-App ein CONFIGURATION DEFINITION-Objekt erstellt, um den Namen der Serveranwendung anzufordern:

ALTER APPLICATION
  SET CONFIGURATION DEFINITION my_server_app_name_configuration
    TYPE = APPLICATION_NAME
    LABEL = 'Server App'
    DESCRIPTION = 'Request for an app that will provide access to server procedures and functions. The server app version must be greater than or equal to 3.2.'
    APPLICATION_ROLES = (my_server_app_role);
Copy

Das folgende Beispiel zeigt, wie der Verbrauchende eingehende Anforderungen zur Konfigurationsdefinition überprüft.

SHOW CONFIGURATIONS IN APPLICATION my_server_app_name;
Copy

Der Befehl gibt Ergebnisse ähnlich den folgenden zurück:

name                             | created_on              | updated_on              | type               | ...
my_server_app_name_configuration | 2026-02-09 10:00:00.000 | 2026-02-09 10:00:00.000 | APPLICATION_NAME   | ...

Der Verbrauchende verwendet dann den folgenden Befehl, um den Namen der Server-App zur Verfügung zu stellen:

ALTER APPLICATION my_client_app_name
  SET CONFIGURATION my_server_app_name_configuration
  VALUE = MY_SERVER_APP_NAME;
Copy

Anfordern und Genehmigen einer Verbindung

Sobald die Client-App den Namen der Server-App hat, wird eine APPLICATION SPECIFICATION erstellt, um eine Verbindung zur Server-App anzufordern. Beachten Sie, dass die Namen der Anwendungsrollen über die Offline-Kommunikation außerhalb von Snowflake ermittelt werden.

Im folgenden Beispiel wird das Erstellen einer APPLICATION SPECIFICATION für eine Verbindung zur Server-App namens my_server_app_name veranschaulicht:

ALTER APPLICATION SET SPECIFICATION my_server_app_name_connection_specification
  TYPE = CONNECTION
  LABEL = 'Server App'
  DESCRIPTION = 'Request for an app that will provide access to server procedures and functions. The server app version must be greater than or equal to 3.2.'
  SERVER_APPLICATION = MY_SERVER_APP_NAME -- server name obtained from Step 1
  SERVER_APPLICATION_ROLES = (my_server_app_role);
Copy

Durch die Erstellung der Anwendungsspezifikation fordert die Client-App die Zuweisung der in der Spezifikation definierten Server-App-Rollen an.

Bemerkung

Die für LABEL und DESCRIPTION angegebenen Werte in der App-Spezifikation müssen mit den für LABEL und DESCRIPTION im CONFIGURATION DEFINITION-Objekt angegebenen Werten, das in Schritt 1 erstellt wurde, übereinstimmen. Wenn die Werte nicht übereinstimmen, wird die Verbindung in Snowsight nicht korrekt angezeigt.

Um einen effizienten Verbindungs-Workflow zu erstellen, empfehlen wir, dass die Client-App die Anwendungsspezifikation im synchronen Callback before_configuration_change erstellt. Dieser Callback wird ausgeführt, wenn der ALTER APPLICATION SET CONFIGURATION VALUE-Befehl absetzt wird. Weitere Informationen zu Callbacks finden Sie unter Callbacks. Ein beispielhaftes Setup-Skript, das die Anwendungsspezifikation im synchronen Callback before_configuration_change erstellt, finden Sie unter Beispiele.

Sobald die Client-App die App-Spezifikation erstellt hat, kann der Verbrauchende die Verbindungsanforderung überprüfen und genehmigen oder ablehnen.

Genehmigen der Verbindungsanforderung mit SQL

Das folgende Beispiel zeigt, wie der Verbrauchende die Verbindungsanforderung mit SQL genehmigt:

ALTER APPLICATION my_server_app_name
  APPROVE SPECIFICATION my_server_app_name_connection_specification
  SEQUENCE_NUMBER = 1;
Copy

Genehmigen der Verbindungsanforderung mit Snowsight

Zum Anzeigen und Genehmigen von Verbindungsforderungen in Snowsight gehen Sie wie folgt vor:

  1. Melden Sie sich bei Snowsight an.

  2. Wählen Sie die App aus. Ein Abschnitt mit dem Titel Application connections wird unter Configurations angezeigt. Für jede ausstehende Verbindung werden der Name oder die Bezeichnung der Verbindung, eine kurze Beschreibung der Verbindung und eine Schaltfläche:ui:Review angezeigt.

  3. Klicken Sie auf die Schaltfläche Review. Die Details der Verbindungsanforderung werden angezeigt.

  4. Wählen Sie die Ziel-App unter Select from your apps aus.

  5. Klicken Sie auf Next. Die folgenden Informationen werden angezeigt:

    • Ein Diagramm, das zeigt, wie sich die Client-App mit der Server-App verbindet und welche Rollen die Apps verwenden werden.

    • Die Details der Verbindung.

    • Eine Teilmenge der Serverberechtigungen, die der Client-App gewährt werden. Weitere Informationen zu Sicherheitshinweisen für IAC finden Sie unter Sicherheitshinweise.

    • Den Umschalter Approve Connection. Der Schalter ist auf On gesetzt.

  6. Um die Verbindung zu genehmigen, belassen Sie den Umschalter auf On und klicken Sie auf Save. Die aktualisierte Verbindungsliste wird mit dem Status der Verbindung angezeigt.

  7. Um die Verbindung abzulehnen, schalten Sie den Umschalter auf Off um.

  8. Um die Überprüfungsseite zu verlassen, ohne die Verbindung zu genehmigen oder abzulehnen, klicken Sie auf die Schaltfläche Cancel.

Nach der Genehmigung

Wenn der Verbrauchende die Verbindungsanforderung genehmigt, weist Snowflake Native App Framework der Client-App die angeforderten Server-App-Rollen zu. Die Genehmigung gewährt der Server-App zudem die USAGE-Berechtigung für die Client-App. Dadurch kann die Server-App erkennen, welche Client-Apps mit ihr verbunden sind.

Wenn der Verbrauchende die Verbindungsanforderung genehmigt, werden in den Client- bzw. Server-Apps die folgenden Callbacks ausgelöst:

Diese Callbacks ermöglichen es den Server- und Client-Apps, beim Herstellen der Verbindung zusätzliche Aktionen auszuführen.

Weitere Informationen zum Genehmigen von Anwendungsspezifikationen finden Sie unter den folgenden Themen:

Kommunizieren mit der Server-App

Sobald die Verbindung hergestellt ist und der Client-App die angeforderten Server-App-Rollen zugewiesen wurden, kann die Client-App mit der Server-App kommunizieren.

Bemerkung

Bevor Sie die Methoden der Server-App aufrufen, sollte die Client-App den Namen der Server-App zur Laufzeit aus der genehmigten Anwendungsspezifikation abrufen, um sicherzustellen, dass der korrekte Name verwendet wird, falls die Server-App umbenannt wird. Das folgende Beispiel zeigt, wie Sie den Namen der Server-App zur Laufzeit abrufen:

SHOW APPROVED SPECIFICATIONS ->>
  SELECT PARSE_JSON("definition"):"SERVER_APPLICATION"::STRING
  FROM $1
  WHERE "name" = 'MY_SERVER_APP_NAME_CONNECTION_SPECIFICATION';
Copy

Die Client-App kann mit der Server-App synchron oder asynchron kommunizieren.

  • Bei der synchronen Kommunikation werden die Prozeduren oder Funktionen der Server-App direkt aufgerufen.

  • Bei der asynchronen Kommunikation wird eine Warteschlange verwendet, die in einem Datenobjekt, z. B. einer Tabelle, gespeichert ist. Die Server-App kann beispielsweise eine Prozedur bereitstellen, um Datensätze als Anforderungen in eine Tabelle einzufügen, die die Server-App dann regelmäßig verarbeitet. Die Client-App kann dann eine andere vom Server bereitgestellte Prozedur verwenden, um die Tabelle auf Ergebnisse zu überprüfen.

Das folgende Beispiel für eine synchrone Operation zeigt, wie eine Client-App die Prozedur einer Server-App mit Python aufruft:

session.call("server_app_name.customer_schema.get_customer_data", customer_id);
Copy

Das folgende Beispiel für eine asynchrone Operation zeigt, wie eine Client-App die Prozedur einer Server-App mit Python aufruft. Die Client-App ruft die Prozedur der Server-App auf, die eine Anforderung in einer Tabelle erstellt, die die Server-App dann verarbeitet. Die Client-App kann die Tabelle abfragen, um nach aktualisierten Datensätzen für Ergebnisse zu suchen.

session.call("server_app_name.customer_schema.request_customer_data_async", customer_id);
Copy

Die Client-App kann dann die Tabelle abfragen, um nach aktualisierten Datensätzen für Ergebnisse zu suchen:

session.call("server_app_name.customer_schema.check_customer_data_requests_async", customer_id);
Copy

Verwalten von Verbindungen

Zum Anzeigen bestehender Verbindungen in |sf-web-interface|gehen Sie wie folgt vor:

  1. Melden Sie sich bei Snowsight an.

  2. Wählen Sie im Navigationsmenü die Option Catalog » Apps aus.

  3. Wählen Sie die App aus. Alle Verbindungen der App werden in einem Abschnitt mit der Bezeichnung Configurations angezeigt. Unterhalb dieses Abschnitts gibt es einen Unterabschnitt mit der Bezeichnung Application connections.

  4. Um eine Verbindung zu ändern, klicken Sie auf das Bleistiftsymbol für die Verbindung. Sie können Folgendes ändern:

    • Welche App mit der App verbunden ist

    • Der Genehmigungsstatus der Verbindung

  5. Um die verbundene App anzuzeigen, klicken Sie die Schaltfläche View app.

  6. Klicken Sie auf das Zahnrad-Symbol, um die Sicherheitseinstellungen für die Verbindung zu ändern.

Sicherheitshinweise

Bei der Genehmigung einer Spezifikationsanforderung sollten sich Verbrauchende darüber im Klaren sein, dass die Gewährung des Zugriffs einer Server-App auf eine Client-App die Berechtigungen der Client-App verbessern kann. Wenn beispielsweise eine Server-App über einen externen Zugriff verfügt, könnte die Client-App über die Server-App indirekten Zugriff auf das Internet oder auf andere externe Ressourcen erhalten. Wenn die Server-App eine Client-App einer anderen Server-App ist, kann die Client-App möglicherweise über die erste Server-App auf die Ressourcen der anderen Server-App zugreifen.

Verbrauchende sollten die Möglichkeiten und Berechtigungen der Server-App überprüfen, bevor sie eine Verbindung genehmigen. Verwenden Sie eine Admin-Rolle (z. B. ACCOUNTADMIN), um die Funktionen des Servers zu prüfen. Wenn Sie den Server mit einer Rolle mit niedrigeren Berechtigungen überprüfen, werden nicht alle Funktionen und Berechtigungen des Servers angezeigt. Verbrauchende sollten beachten, dass der Code der Server-App für den Verbrauchenden nicht sichtbar ist und dass die Berechtigungen und Funktionen der Server-App geändert werden können, nachdem der Verbrauchende die Verbindung genehmigt hat.

Beispielhafte SQL-Befehle zur Überprüfung der Fähigkeiten und Berechtigungen der Server-App umfassen unter anderem die folgenden:

  • SHOW GRANTS TO APPLICATION: Dieser Befehl listet auf, welche Berechtigungen für die Client-App der Server-App erteilt wurden.

  • SHOW PRIVILEGES IN APPLICATION: Dieser Befehl listet auf, welche potenziellen Berechtigungen auf Kontoebene der Client-App erteilt werden könnten.

  • SHOW REFERENCES IN APPLICATION: Dieser Befehl listet Referenzen auf, die die Client-App möglicherweise ohne Verwendung von Berechtigungen verwenden könnte.

  • SHOW SPECIFICATIONS IN APPLICATION: Dieser Befehl listet die Anwendungsspezifikationen auf, die der Verbrauchende genehmigt hat, einschließlich der Integrationen für den externen Zugriff (EAIs), Sicherheitsintegrationen, Freigaben, Freigabeangebote und Verbindungen.

SQL-Referenz

Die folgenden SQL-Befehle werden verwendet, um die Kommunikation zwischen Apps zu verwalten.

Callbacks

Das Snowflake Native App Framework bietet Lebenszyklus-Callbacks, um den Workflow für die Kommunikation zwischen Apps zu verwalten. Mit diesen Callbacks kann eine App auf Änderungen in Konfigurationen, Verbindungen und Spezifikationen reagieren. Um Callbacks zu verwenden, registrieren Sie diese im Abschnitt lifecycle_callbacks der Manifest-Datei der App.

Allgemeine Informationen zu Callbacks finden Sie unter Callbacks.

Konfigurations-Callbacks

Diese Callbacks werden ausgelöst, wenn ein Konfigurationswert festgelegt oder aufgehoben wird. Ein typischer Anwendungsfall ist die Verwendung des Callbacks before_configuration_change, um automatisch eine Verbindungsspezifikation zu erstellen, wenn der Verbrauchende den Namen der Server-App festlegt.

validate_configuration_change

Ein synchroner Callback, der als Teil des ALTER APPLICATION SET CONFIGURATION VALUE-Befehls aufgerufen wird. Ermöglicht der App eine kundenspezifische Validierung des angegebenen Wertes. Wenn der Callback einen Fehler zurückgibt, schlägt der Befehl fehl und der neue Wert wird nicht festgelegt.

before_configuration_change

Ein synchroner Callback, der als Teil des ALTER APPLICATION SET CONFIGURATION VALUE- und des ALTER APPLICATION UNSET CONFIGURATION-Befehls aufgerufen wird. Ermöglicht es der App, Vorgänge auf der Grundlage des Konfigurationswertes auszuführen, bevor dieser gespeichert wird.

after_configuration_change

Ein asynchroner Callback, der nach Abschluss des ALTER APPLICATION SET CONFIGURATION VALUE- oder ALTER APPLICATION UNSET CONFIGURATION-Befehls aufgerufen wird. Ermöglicht es der App, auf die Änderung zu reagieren, z. B. zur Benachrichtigung oder zur Nachverfolgung.

Verbindungs-Callbacks

Diese Callbacks werden ausgelöst, wenn sich der Status einer Verbindung ändert, z. B. wenn eine Verbindung hergestellt, abgelehnt oder gelöscht wird, oder wenn die verbundene App gelöscht wird.

after_server_connection_change

Ein asynchroner Callback, der in der Client-App durch einen beliebigen Vorgang ausgelöst wird, die sich auf den Verbindungsstatus auswirkt, einschließlich der Genehmigung, Ablehnung oder Löschung einer Spezifikation oder der Server-App.

after_client_connection_change

Ein asynchroner Callback, der in der Server-App durch einen beliebigen Vorgang ausgelöst wird, die sich auf den Verbindungsstatus auswirkt, einschließlich der Genehmigung, Ablehnung oder Löschung einer Spezifikation oder der Client-app.

after_server_version_change

Ein asynchroner Callback, der in der Client-App aufgerufen wird, nachdem sich die Version oder die Patch-Nummer der Server-App geändert hat. Damit kann die Client-App auf ein Upgrade oder Downgrade reagieren.

Beispiele

Die folgenden Beispiele zeigen, wie Sie eine App für die Kommunikation zwischen Apps konfigurieren.

Beispiel: Setup-Skript und Manifest-Dateien

Das folgende Beispiel zeigt das Setup-Skript einer Client-App (setup.sql):

CREATE OR ALTER VERSIONED SCHEMA app_schema;

-- create a callback that creates the connection request before the config value of the server name is saved
CREATE OR REPLACE PROCEDURE app_schema.before_config_change_callback(config_name STRING, config_value STRING)
RETURNS STRING
LANGUAGE SQL
AS
$$
DECLARE
    spec_name VARCHAR;
    existing_target VARCHAR;
BEGIN
    IF (config_value IS NOT NULL AND config_name = 'MY_SERVER_APP_NAME_CONFIGURATION') THEN
        SHOW SPECIFICATIONS;
        SELECT PARSE_JSON("definition"):SERVER_APPLICATION::STRING
            INTO existing_target
            FROM TABLE(RESULT_SCAN(LAST_QUERY_ID()));

        IF(existing_target IS NOT NULL AND UPPER(existing_target) != UPPER(config_value)) THEN
            EXECUTE IMMEDIATE 'ALTER APPLICATION DROP SPECIFICATION CONNECTION_' || UPPER(existing_target);
        END IF;

        spec_name := 'CONNECTION_' || UPPER(config_value);
        EXECUTE IMMEDIATE
        'ALTER APPLICATION SET SPECIFICATION ' || spec_name || '
            TYPE = CONNECTION
            LABEL = ''Server App''
            DESCRIPTION = ''Request for an app that will provide access to server procedures and functions. The server app version must be greater than or equal to 3.2.''
            SERVER_APPLICATION = ' || config_value || '
            SERVER_APPLICATION_ROLES = (my_server_app_role)';
    END IF;
RETURN 'success';
END;
$$;

CREATE APPLICATION ROLE IF NOT EXISTS client_app_user;
GRANT USAGE ON SCHEMA app_schema TO APPLICATION ROLE client_app_user;
ALTER APPLICATION SET CONFIGURATION DEFINITION my_server_app_name_configuration
    TYPE = APPLICATION_NAME
    LABEL = 'Server App'
    DESCRIPTION = 'Request for an application that will provide access to server procedures and functions. The server app version must be greater than or equal to 3.2'
    APPLICATION_ROLES = (client_app_user);
Copy

Das folgende Beispiel zeigt die Manifest-Datei einer Client-App (manifest.yml):

manifest_version: 2

artifacts:
  setup_script: setup.sql

lifecycle_callbacks:
    before_configuration_change: app_schema.before_config_change_callback
Copy

Beachten Sie zum vorangegangenen Codebeispiel Folgendes:

  • Im Callback before_configuration_change sucht die App nach einer vorhandenen Verbindungsspezifikation, die mit dem vorherigen Wert der Konfiguration übereinstimmt, und löscht diese, falls sie existiert. Der Callback erstellt dann eine neue Verbindungsspezifikation für den neu angegebenen Namen der Server-App. Wird eine neue Verbindung erstellt, wenn der Servername definiert ist, werden keine doppelten Verbindungsspezifikationen erstellt.

Beispiel: Asynchrone Kommunikation zwischen Apps

Das folgende Beispiel zeigt, wie Sie Prozeduren im Setup-Skript (setup.sql ) einer Server-App für die asynchrone Kommunikation erstellen. Die Server-App erstellt eine Verarbeitungswarteschlangentabelle und stellt Client-Apps über eine Anwendungsrolle zwei Prozeduren zur Verfügung: submit_request zum Hinzufügen einer Anforderung zur Warteschlange und fetch_response zum Abrufen des Ergebnisses einer abgeschlossenen Anforderung. Die Server-App verwendet regelmäßig die``process_requests``-Prozedur, um alle ausstehenden Anforderungen zu bearbeiten.

CREATE TABLE IF NOT EXISTS app_schema.processing_queue (
  request_id NUMBER AUTOINCREMENT,
  operation STRING,
  input STRING,
  status STRING DEFAULT 'PENDING',
  response STRING DEFAULT ''
);

CREATE OR REPLACE PROCEDURE app_schema.submit_request(operation STRING, input STRING)
RETURNS STRING
LANGUAGE SQL
EXECUTE AS OWNER
AS
$$
BEGIN
    INSERT INTO app_schema.processing_queue (operation, input) VALUES (:operation, :input);
    RETURN 'Request submitted successfully';
END;
$$;

CREATE OR REPLACE PROCEDURE app_schema.process_requests()
RETURNS STRING
LANGUAGE SQL
EXECUTE AS OWNER
AS
$$
DECLARE
    -- Cursor to find all PENDING requests
    c1 CURSOR FOR SELECT * FROM app_schema.processing_queue WHERE status = 'PENDING';
    result STRING;
BEGIN
    FOR request IN c1 DO

        IF (request.operation = 'OPERATION_X') THEN
            -- assuming there is a UDF func_x(input) to perform operation_x
            result := (SELECT func_x(:request.input));
        END IF;

        -- update the processing queue with the result
        LET stmt STRING :=
            'UPDATE app_schema.processing_queue SET status = 'DONE', response = ' ||
            result ||
            ' WHERE request_id = ' ||
            request.request_id;
        EXECUTE IMMEDIATE (:stmt);

    END FOR;

    RETURN 'Processed pending requests.';
END;
$$;

CREATE OR REPLACE PROCEDURE app_schema.fetch_response(operation STRING, input STRING)
RETURNS STRING
LANGUAGE SQL
EXECUTE AS OWNER
AS
$$
BEGIN
    LET res STRING := (SELECT response FROM app_schema.processing_queue WHERE operation = :operation AND input = :input);
    RETURN res;
END;
$$;

CREATE APPLICATION ROLE IF NOT EXISTS my_server_app_role;
GRANT USAGE ON SCHEMA app_schema TO APPLICATION ROLE my_server_app_role;
GRANT USAGE ON PROCEDURE app_schema.submit_request(string, string) TO APPLICATION ROLE my_server_app_role;
GRANT USAGE ON PROCEDURE app_schema.process_requests() TO APPLICATION ROLE my_server_app_role;
GRANT USAGE ON PROCEDURE app_schema.fetch_response(string, string) TO APPLICATION ROLE my_server_app_role;
Copy