Ajout d’une logique d’application à un paquet d’application

Cette rubrique décrit comment ajouter une logique d’application au script d’installation à un paquet d’application. Elle décrit également comment utiliser des fichiers de code externe dans un paquet d’application.

Consultez Ajouter une expérience front-end à une application en utilisant Streamlit pour obtenir des informations sur l’inclusion d’une application Streamlit dans un paquet d’application.

Considérations relatives à l’utilisation de procédures stockées et de fonctions

Le Snowflake Native App Framework vous permet d’inclure des procédures stockées, des fonctions définies par l’utilisateur (UDFs) et des fonctions externes dans un paquet d’application. Ces éléments peuvent être écrits dans l’un des langages que Snowflake prend en charge.

Ajouter le code d’application de manière sécurisée

Toutes les procédures stockées et les UDFs au sein d’une Snowflake Native App s’exécutent comme l’application et ont accès à tous les objets de l”Snowflake Native App installée. Cela peut conduire à des attaques par injection SQL.

Lorsque vous développez des procédures et des fonctions à utiliser dans une Snowflake Native App, Snowflake recommande que toutes les commandes SQL nécessitant une entrée de la part des utilisateurs soient exécutées à l’aide de paramètres liés. Cela inclut les fournisseurs de données par le biais d’arguments de procédure.

Voir Création d’une procédure stockée pour plus d’informations.

À propos des droits de l’appelant et des droits du propriétaire

Toutes les procédures créées par le script d’installation ou exécutées au sein de la Snowflake Native App installée doivent être exécutées avec les droits du propriétaire (EXECUTE AS OWNER).

Cette restriction existe parce que si l”Snowflake Native App était exécutée avec les droits de l’appelant (EXECUTE AS CALLER) dans une procédure dont la Snowflake Native App n’est pas propriétaire, la procédure s’exécuterait en tant que Snowflake Native App elle-même et permettrait à un consommateur de créer du code pour voir ou modifier le contenu de l”Snowflake Native App et le contenu des données partagées.

Voir Understanding Caller’s Rights and Owner’s Rights Stored Procedures pour plus d’informations.

Limitations lors de l’appel de fonctions contextuelles à partir du script d’installation

Les fonctions de contexte fournissent des informations sur le contexte dans lequel une instruction est exécutée. Dans le contexte du Snowflake Native App Framework, certaines fonctions contextuelles ne sont pas disponibles. Les fonctions contextuelles qui ne sont pas disponibles sont soit bloquées et renvoient une erreur, soit renvoient toujours une valeur nulle.

En général, vous devez faire preuve de prudence lorsque vous utilisez des fonctions contextuelles dans des politiques appliquées à du contenu de données partagées au sein d’une Snowflake Native App. Certaines fonctions, par exemple CURRENT_IP_ADDRESS, se comportent différemment dans le contexte d’une Snowflake Native App.

Notez que lorsque vous utilisez des fonctions contextuelles qui dépendent de l’espace de noms au sein de l’organisation cliente, il peut y avoir des conflits avec des fonctions dans d’autres espaces de noms. Par exemple, une politique d’accès aux lignes utilisant CURRENT_USER doit tenir compte du fait qu’un même nom d’utilisateur peut exister dans plusieurs comptes.

Le tableau suivant répertorie les fonctions contextuelles qui ne sont pas prises en charge par le Snowflake Native App Framework :

Fonction contextuelle

Bloquée dans le contenu partagé (renvoie null)

Bloquée dans les scripts d’installation, les procédures stockées et les UDFs appartenant à l”Snowflake Native App (lève une exception).

CURRENT_ROLE

CURRENT_ROLE_TYPE

CURRENT_USER

IS_ROLE_IN_SESSION

CURRENT_IP_ADDRESS

CURRENT_AVAILABLE_ROLES

CURRENT_SECONDARY_ROLES

ALL_USER_NAMES

GET_USERS_FOR_COLLABORATION

CURRENT_WAREHOUSE

SYSTEM$ALLOWLIST

Utiliser des fonctions et procédures Snowpark dans un paquet d’application

Le Snowflake Native App Framework prend en charge les bibliothèques Snowpark pour la création de procédures stockées en Java, Scala et Python.

Référencer des fichiers de code externes

Il existe deux types de fichiers de code que vous pouvez inclure dans un paquet d’application :

  • Fichiers référencés : comprennent les fichiers binaires, les bibliothèques et d’autres fichiers de code. Ces fichiers sont spécifiques à une version définie dans un paquet d’application. Ces fichiers doivent se trouver dans le répertoire racine de la zone de préparation lors de la création d’un paquet d’application.

    Les fichiers référencés sont différents des fonctions définies par l’utilisateur et des procédures stockées, car ils ne sont pas définis dans le script d’installation d’un paquet d’application. Ces fichiers sont référencés par les instructions d’importation dans les procédures stockées et les UDFs qui dont définies dans le script d’installation.

  • Fichiers de ressources : comprennent les données semi-structurées, les données structurées et les binaires, comme un modèle de machine learning. Ces fichiers doivent être chargés dans une zone de préparation nommée accessible au paquet d’application.

Une procédure stockée, une fonction définie par l’utilisateur ou une fonction externe qui fait référence à ces types de fichiers de code doit être créée dans un schéma versionné dans le script d’installation. Lorsque vous créez des procédures stockées ou des fonctions dans un schéma versionné, vous devez faire référence à un fichier de code relatif au répertoire racine de la zone de préparation nommée.

Par exemple, si le répertoire racine de votre zone de préparation est /app_files/dev, ce répertoire contiendra les fichiers et répertoires suivants :

  • Un fichier manifest.yml.

  • Un répertoire contenant le script d’installation, par exemple scripts/setup_version.sql.

  • Fichiers référencés qui sont importés lors de la création d’une procédure stockée, d’une UDF ou d’une fonction externe dans le script d’installation, par exemple :

    • libraries/jars/lookup.jar

    • libraries/jars/log4j.jar

    • libraries/python/evaluate.py

Dans ce scénario, la structure du répertoire serait la suivante :

@DEV_DB.DEV_SCHEMA.DEV_STAGE/V1:
└── app_files/
    └── dev
        ├── manifest.yml
        └── scripts/
            ├── setup_script.sql
            └── libraries/
                └── jars/
                    ├── lookup.jar
                    └── log4j.jar
            └── python
                └── evaluation.py
Copy

Pour accéder aux fichiers JAR dans cette structure de répertoire, une procédure stockée définie dans le script d’installation fait référence à ces fichiers, comme le montre l’exemple suivant :

CREATE PROCEDURE PROGRAMS.LOOKUP(...)
 RETURNS STRING
 LANGUAGE JAVA
 PACKAGES = ('com.snowflake:snowpark:latest')
 IMPORTS = ('/scripts/libraries/jar/lookup.jar',
            '/scripts/libraries/jar/log4j.jar')
 HANDLER = 'com.acme.programs.Lookup';
Copy

Dans cet exemple, l’instruction IMPORTS a un chemin relatif vers le répertoire racine utilisé pour créer la version, par exemple, l’emplacement du fichier manifest.yml.

Inclure du code Java et Scala dans un paquet d’application

Le Snowflake Native App Framework permet d’utiliser Java et Scala dans des procédures stockées et dans des fichiers de code externes.

Créer des UDFs en ligne Java et Scala

Le Snowflake Native App Framework permet de créer des procédures stockées contenant du Java et du Scala. Le code qui définit la procédure stockée doit être ajouté au script d’installation.

L’exemple suivant montre une procédure stockée contenant une fonction Java :

CREATE OR ALTER VERSIONED SCHEMA app_code;
CREATE STAGE app_code.app_jars;

CREATE FUNCTION app_code.add(x INT, y INT)
 RETURNS INTEGER
 LANGUAGE JAVA
 HANDLER = 'TestAddFunc.add'
 TARGET_PATH = '@app_code.app_jars/TestAddFunc.jar'
 AS
 $$
   class TestAddFunc {
       public static int add(int x, int y) {
           Return x + y;
       }
   }
 $$;
Copy

Importer des UDFs Java et Scala externes

La syntaxe de création d’UDFs précompilées exige que les JARs importés soit inclus dans un ensemble d’artefacts versionnés. Pour faire référence à des JARs précompilés, utilisez le chemin relatif plutôt que de spécifier la zone de préparation complète dans la clause IMPORT.

Le chemin doit être relatif au répertoire racine contenant la version et commencer par une simple barre oblique, par exemple IMPORTS = ('/path/to/JARs/from/version/root'). Reportez-vous à Référencer des fichiers de code externes pour plus d’informations sur les chemins relatifs.

Vous trouverez ci-dessous un exemple de structure de répertoire pour les fichiers de code.

@DEV_DB.DEV_SCHEMA.DEV_STAGE/V1:
└── V1/
 ├── manifest.yml
 ├── setup_script.sql
 └── JARs/
     ├── Java/
     │   └── TestAddFunc.jar
     └── Scala/
         └── TestMulFunc.jar
Copy

L’exemple suivant montre comment créer une fonction Java à l’aide d’un fichier JAR :

CREATE FUNCTION app_code.add(x INTEGER, y INTEGER)
  RETURNS INTEGER
  LANGUAGE JAVA
  HANDLER = 'TestAddFunc.add'
  IMPORTS = ('/JARs/Java/TestAddFunc.jar');
Copy

Restrictions concernant les UDFs Java et Scala

Le Snowflake Native App Framework impose les restrictions suivantes lors de l’utilisation de Java et de Scala :

  • Les importations ne sont autorisées que pour les UDFs créées dans un schéma versionné.

  • Les importations ne peuvent accéder aux artefacts de version qu’en utilisant un chemin relatif.

  • Les UDFs créées en dehors des schémas versionnés ne peuvent être créées qu’en ligne.

  • Les chemins relatifs ne sont pas pris en charge pour TARGET_PATH.

Ajouter du code Python à un paquet d’application

Le Snowflake Native App Framework prend en charge l’utilisation de Python dans les procédures stockées et dans les fichiers de code externes.

Définir une fonction Python dans le script d’installation

Le Snowflake Native App Framework permet de créer des procédures stockées en Python.

L’exemple suivant montre une procédure stockée contenant une fonction Python :

CREATE FUNCTION app_code.py_echo_func(str STRING)
RETURNS STRING
LANGUAGE PYTHON
HANDLER = 'echo'
AS
$$
  def echo(str):
    return "ECHO: " + str
$$;
Copy

Utiliser des fichiers Python externes

L’exemple suivant montre comment inclure un fichier Python externe dans un paquet d’application :

CREATE FUNCTION PY_PROCESS_DATA_FUNC()
  RETURNS STRING
  LANGUAGE PYTHON
  HANDLER = 'TestPythonFunc.process'
  IMPORTS = ('/python_modules/TestPythonFunc.py',
    '/python_modules/data.csv')
Copy

Consultez Référencer des fichiers de code externes pour plus d’informations sur les chemins relatifs.

Restrictions concernant les UDFs Python

le Snowflake Native App Framework impose les restrictions suivantes aux UDFs Python :

  • Les importations ne sont autorisées que pour les UDFs créées dans un schéma versionné.

  • Les importations ne peuvent accéder aux artefacts de version qu’en utilisant un chemin relatif.

  • Les UDFs créées en dehors des schémas versionnés ne peuvent être créées qu’en ligne.

Ajouter des fonctions et des procédures JavaScript à un paquet d’application

Le Snowflake Native App Framework prend en charge l’utilisation de JavaScript dans les procédures stockées et les fonctions définies par l’utilisateur à l’aide de l’API JavaScript.

Traiter les erreurs JavaScript

Lorsque vous utilisez JavaScript au sein d’un paquet d’application, Snowflake vous recommande de détecter et de gérer les erreurs. Dans le cas contraire, le message d’erreur et le traçage de la pile renvoyée par l’erreur sont visibles par le consommateur. Pour garantir la confidentialité du contenu des données et de la logique d’application, utilisez des blocs try/catch dans les situations où des objets ou des données sensibles sont accessibles.

L’exemple suivant montre une procédure stockée JavaScript qui détecte une erreur et renvoie un message :

CREATE OR REPLACE PROCEDURE APP_SCHEMA.ERROR_CATCH()
  RETURNS STRING
  LANGUAGE JAVASCRIPT
  EXECUTE AS OWNER
  AS $$
     try {
      let x = y.length;
     }
     catch(err){
        return "There is an error.";
     }
     return "Done";
  $$;
Copy

Cet exemple crée une procédure stockée JavaScript qui contient une bloc try/catch. Si la procédure stockée rencontre une erreur lors de l’exécution de l’instruction dans le bloc try elle renvoie le message « Il y a une erreur » qui est visible par le consommateur.

Sans le bloc try/catch, la procédure stockée renverrait le message d’erreur d’origine et le traçage complet de la pile, qui serait visible pour le consommateur.

Note

Les autres langues prises en charge par le Snowflake Native App Framework renvoient les messages d’erreur qui se produisent dans une Snowflake Native App.

Ajouter des fonctions externes à un paquet d’application

Les fonctions externes permettent à une Snowflake Native App de faire des appels au code de l’application qui est stocké en dehors de Snowflake. Les fonctions externes nécessitent la création d’un objet d’intégration API.

Comme les intégrations API permettent une connectivité en dehors de l’environnement du consommateur, ce dernier doit fournir la méthode d’intégration à l”Snowflake Native App.

L’exemple suivant montre une procédure stockée créée par le script d’installation qui accepte l’intégration et crée une fonction externe. L’exemple suivant montre comment créer une fonction externe dans le script d’installation du paquet d’application :

CREATE OR REPLACE PROCEDURE calculator.create_external_function(integration_name STRING)
RETURNS STRING
LANGUAGE SQL
EXECUTE AS OWNER
AS
DECLARE
  CREATE_STATEMENT VARCHAR;
BEGIN
  CREATE_STATEMENT := 'CREATE OR REPLACE EXTERNAL FUNCTION EXTERNAL_ADD(NUM1 FLOAT, NUM2 FLOAT)
        RETURNS FLOAT API_INTEGRATION = ? AS ''https://xyz.execute-api.us-west-2.amazonaws.com/production/sum'';' ;
  EXECUTE IMMEDIATE :CREATE_STATEMENT USING (INTEGRATION_NAME);
  RETURN 'EXTERNAL FUNCTION CREATED';
END;

GRANT USAGE ON PROCEDURE calculator.create_external_function(string) TO APPLICATION ROLE app_public;
Copy

Cet exemple définit une procédure stockée, écrite en SQL et crée une fonction externe qui fait référence à une application hébergée sur un système extérieur à Snowflake. La fonction externe renvoie une intégration d’API.

Cet exemple accorde également USAGE sur la procédure stockée à un rôle d’application. Le consommateur doit accorder ce privilège à l”Snowflake Native App avant d’invoquer cette procédure dans le script d’installation.