创建安装脚本

本主题介绍在运行 CREATE APPLICATION 命令时如何使用安装脚本,在应用程序对象中创建对象。

本主题还描述了应用程序角色以及它们在安装脚本中的使用方式。

关于安装脚本

安装脚本包含在如下上下文之一中运行 CREATE APPLICATION 命令时所运行的 SQL 语句:

  • 使用者安装或升级 Snowflake Native App。

  • 提供商在测试应用程序包时创建或升级应用程序对象。

备注

安装脚本仅支持使用 SQL 命令。不支持其他语言。

安装脚本中的 SQL 语句会在应用程序所需的对象中创建对象。这包括数据库对象、存储过程、视图、应用程序角色 等。

应用程序包需要安装脚本。manifest.yml 文件指定安装脚本的文件名和相对路径。在创建应用程序包时,manifest.yml 文件和安装脚本都必须存在于命名暂存区中。

安装脚本的限制

在安装脚本中无法执行以下操作:

  • USE DATABASE

  • USE SCHEMA

  • USE ROLE

  • USE SECONDARY ROLES

  • 使用 ALTER <object> 命令设置 LOG_LEVEL 或 TRACE_LEVEL 属性。

  • 创建或调用 EXECUTE AS CALLER 过程。

  • 创建 Snowpark 用户定义的函数 (UDFs) 或在命名暂存区中使用 IMPORT 包含文件的过程。

  • 调用引用应用程序包中未包含的代码的过程、函数或匿名代码块。

  • 使用 CREATE FUNCTION 命令时从命名暂存区导入代码文件。

  • 使用 CALL 调用作为 EXECUTE AS CALLER 运行的过程。

在带有版本控制的架构中创建的对象还存在其他限制。

安装脚本中创建的对象的可见性

安装脚本可创建大多数类型的数据库级对象。安装脚本创建的数据库对象是应用程序的内部对象。默认情况下,在使用者安装应用程序时,这些对象不可见,并且使用者账户不能直接访问这些对象。

备注

提供商可在测试应用程序包时使用开发模式,访问由安装脚本创建的对象。有关更多信息,请参阅 关于开发模式

提供商可使用应用程序角色,使这些对象对使用者可见。安装脚本中创建的应用程序角色将自动授予拥有应用程序对象的角色。安装脚本授予的应用程序角色不能撤销。

随后,如果用户具有拥有应用程序对象的角色,则可将应用程序角色授予其组织内的其他角色。例如,安装脚本可以定义应用程序角色(例如 APP_ADMIN),向其授予访问应用程序内对象的权限。获授拥有应用程序对象的角色的用户可向其他角色授予这些对象的应用程序角色。

设置安装脚本输出的消息的日志级别

提供商可为安装脚本运行时生成的消息指定日志级别。有关更多信息,请参阅 Snowflake Scripting 中的日志记录消息

要配置安装脚本的日志级别,请使用以下系统函数之一:

例如,要配置安装脚本以在日志中记录错误消息,请在安装脚本的开头添加以下命令:

SYSTEM$LOG('error', 'Error message');
Copy

创建模块化安装脚本

典型应用程序的安装脚本可能庞大而复杂。为了使安装脚本更加模块化且更易于维护,提供商可创建一个主安装脚本,并使该脚本调用多个辅助安装脚本。

例如,提供商可以创建不同的安装脚本来处理不同类型的任务,如创建对象、创建视图、创建存储过程等。

CREATE APPLICATION 命令运行时,它将运行 manifest.yml 中指定的主安装脚本。要从主安装脚本运行其他安装脚本,请使用 EXECUTE IMMEDIATE FROM 命令。

主安装脚本中包含的安装脚本将按照遇到它们的顺序运行。这些辅助安装脚本还可以包含 EXECUTE IMMEDIATE FROM 命令。

向应用程序添加多个安装脚本

要向应用程序添加多个安装脚本,请执行以下操作:

  1. 将主安装脚本的位置添加到 manifest.yml

    artifacts:
      ...
      setup_script: scripts/setup.sql
      ...
    
    Copy
  2. 创建主安装脚本。

    以下示例显示了一个应用程序的典型目录结构:

    @test.schema1.stage1:
    └── /
        ├── manifest.yml
        ├── readme.md
        ├── scripts/setup_script.sql
    
    Copy

    其中 setup_script.sql 是主安装脚本。

  3. 创建辅助安装脚本。

    以下示例显示了一个包含多个安装脚本的应用程序的典型目录结构:

    @test.schema1.stage1:
    └── /
        ├── manifest.yml
        ├── readme.md
        ├── scripts/setup_script.sql
        ├── scripts/secondary_script.sql
        ├── scripts/procs/setup_procs.sql
        ├── scripts/views/setup_views.sql
        ├── scripts/data/setup_data.sql
    
    Copy
  4. 在主安装脚本中,使用 EXECUTE IMMEDIATE FROM 命令指定每个辅助安装脚本的相对路径:

    ...
    EXECUTE IMMEDIATE FROM 'secondary_script.sql'
    EXECUTE IMMEDIATE FROM './procs/setup_procs.sql'
    EXECUTE IMMEDIATE FROM './views/setup_views.sql'
    EXECUTE IMMEDIATE FROM './data/setup_data.sql'
    ...
    
    Copy

提供给 EXECUTE IMMEDIATE FROM 命令的路径是相对于主安装脚本的位置。

在安装脚本中使用 EXECUTE IMMEDIATE FROM 时的限制

在安装脚本内使用 EXECUTE IMMEDIATE FROM 时,以下限制适用:

  • 使用 EXECUTE IMMEDIATE FROM 调用的安装脚本内不支持事件日志记录。

  • 仅在安装脚本内支持 EXECUTE IMMEDIATE FROM。不支持在安装脚本以外的其他上下文中使用此命令。

  • 不支持访问在使用者账户以外的加密外部暂存区上存储的文件。

创建安装脚本时遵循的最佳实践

Snowflake 建议在为应用程序创建安装脚本时遵循以下最佳实践:

使用 CREATE 语句的幂等形式

使用 CREATE 命令在安装脚本中创建对象时,Snowflake 建议使用这些命令的以下版本:

  • CREATE OR REPLACE

  • CREATE IF NOT EXISTS

在安装和升级过程中,可多次运行安装脚本。如果出错,这些对象可能已经存在,尤其是在受到版本控制的架构中创建这些对象时。

在创建对象时包含目标架构

CREATE SCHEMA 命令不会更改会话上下文。创建对象时必须使用目标架构限定对象。例如,要在安装脚本中创建架构,请使用以下命令:

CREATE SCHEMA IF NOT EXISTS app_config;
CREATE TABLE IF NOT EXISTS app_config.params(...);
Copy

不要在应用程序对象外部引用应用程序对象内的对象

不要在应用程序对象外部创建对象来引用应用程序对象内的对象。虽然 Snowflake Native App Framework 并不禁止创建这些对象,但在使用者安装 Snowflake Native App 时,这可能会造成问题。

例如,考虑安装脚本在应用程序对象外部创建数据库、架构和视图的上下文,视图会引用应用程序对象内的表。在这种情况下,如果使用者获得了数据库所有权并删除了应用程序对象,数据库内的视图将被破坏。

此最佳实践适用于通过安装脚本创建的表、存储过程、用户定义的函数和引用。

使用受版本控制或不受版本控制的架构时,考虑可能出现的故障

受版本控制的架构中的对象可引用不受版本控制的架构中的对象,反之亦然。安装脚本必须考虑到在安装或升级过程中发生故障时可能出现的情况。例如,如果初始运行失败,若安装脚本自动再次运行,提供商必须考虑会发生什么情况。

例如,考虑使用以下方法创建对象:

CREATE OR REPLACE PROCEDURE app_state.proc()...;
GRANT USAGE ON PROCEDURE app_state.proc()
  TO APPLICATION ROLE app_user;
Copy

在此示例中,CREATE OR REPLACE 语句会替换现有过程,该过程隐式删除以前授予该过程的权限。尽管稍后可能会在脚本中恢复授权,但如果脚本在运行时失败,使用者可能无法访问该过程。

如果安装脚本因重试无法解决的问题(例如语法错误)而失败,则在将应用程序升级到新版本或补丁并恢复授权之前,使用者将无法访问该过程。

小心

本节中的指导不适用于 Snowflake Native App Framework 上下文以外的 标签掩码策略行访问策略

标签和策略分配不会传播到受版本控制的架构的增量版本。以下场景会触发错误消息(以标签为例):

  • 在版本化架构中创建标签,并将标签分配给不同架构中的对象。

  • 在非版本化架构中创建标签,并将标签分配给版本化架构中的对象。

  • 在版本化架构中创建表或视图,并在非版本化架构中存在标签时为表或视图分配标签。

  • 在非版本化的架构中创建表或视图,并在版本化的架构中存在标签时为表或视图分配标签。

错误消息是:

A TAG in a versioned schema can only be assigned to the objects in the same schema. An object in a versioned schema can only have a TAG assigned that is defined in the same schema.

如果策略分配触发了错误消息,则错误消息指定 POLICY 而非 TAG

要防止出现错误消息,请执行以下操作:

  • Snowflake Native App 提供商应更新设置脚本,确保在受版本控制的架构包含标签或设置了标签的对象时,在与标签相同的架构内的对象上设置标签(或策略)。如果非版本化架构包含标签或为其设置标签的对象,则无需更新设置脚本。

  • 如果 Snowflake Native App 使用者在安装应用程序时看到此错误消息,使用者应要求提供商更新其安装脚本。此外,使用者不应将受版本控制的架构中存在的任何标签分配给其账户中的任何对象(例如仓库),不应将受版本控制的架构中存在的策略分配给表或列,也不应将策略或标签分配给存在于 Snowflake Native App 内受版本控制的架构中的对象。如果执行了这些操作,Snowflake 将返回相同的错误消息。

在受版本控制的架构中定义视图

始终在受版本控制的架构中定义共享内容的视图。这确保了升级期间访问视图的任何代码都将使用一致的视图,即使添加或移除了新列或其他属性也是如此。

确保耗时的操作的兼容性

如果安装脚本必须执行非常长时间运行的操作,例如升级大型状态表,请确保这些更新与以前版本的现有运行代码兼容。

关于应用程序角色

默认情况下,使用者对应用程序内创建的对象没有任何权限。即便是 ACCOUNTADMIN 角色也无法查看应用程序 的对象。应用程序在其外部创建的对象(例如数据库)仅对使用者账户的 ACCOUNTADMIN 角色可见。

应用程序角色与数据库角色类似,但应用程序角色只能在应用程序内创建。与数据库角色不同,应用程序角色可以被授予对应用程序外部存在的对象的权限。

应用程序角色应在安装应用程序时由安装脚本创建,并被自动授予应用程序所有者角色,然后应用程序所有者角色可以将相应的应用程序角色授予使用者账户中的其他角色。

备注

应用程序角色是唯一可以在应用程序内创建的角色类型。例如,应用程序内不允许存在数据库角色。

同样,应用程序角色只能在应用程序中创建,而不能在普通数据库中创建,也不能在账户级别创建。

向应用程序角色授予的任何权限都将传递给应用程序所有者(即用于安装应用程序的角色)。所有者可以进一步将应用程序角色委派给使用者账户内的其他角色。

安装脚本还可以定义应用程序角色(例如 USER)。使用此角色,使用者被授予使用应用程序提供的功能的访问权限。安装脚本可以定义应用程序角色(例如 READ_ONLY),以提供对应用程序中选定数据区域的受限访问权限。

与数据库角色不同,还可以向应用程序角色授予对已安装应用程序外部的对象的权限。因此,应用程序角色可用于授予对应用程序外部对象的权限。但是,应用程序角色本身必须在应用程序内创建。

支持与应用程序角色结合使用的 SQL 命令

Snowflake Native App Framework 提供以下与应用程序角色结合使用的 SQL 命令:

在安装脚本中使用应用程序角色

安装脚本中定义的应用程序角色会自动被授予拥有应用程序实例的角色。当安装应用程序时,用于已安装应用程序的角色是应用程序的所有者。但是,应用程序所有者可以向使用者账户中的其他账户角色授予权限。

应用程序角色允许向使用者授予对应用程序内对象的权限。例如:

CREATE APPLICATION ROLE admin;
CREATE APPLICATION ROLE user;
GRANT APPLICATION ROLE user TO APPLICATION ROLE admin;

CREATE OR ALTER VERSIONED SCHEMA app_code;
GRANT USAGE ON SCHEMA app_code TO APPLICATION ROLE admin;
GRANT USAGE ON SCHEMA app_code TO APPLICATION ROLE user;
CREATE OR REPLACE PROCEDURE app_code.config_app(...)
GRANT USAGE ON PROCEDURE app_code.config_app(..)
  TO APPLICATION ROLE admin;

CREATE OR REPLACE FUNCTION app_code.add(x INT, y INT)
GRANT USAGE ON FUNCTION app_code.add(INT, INT)
  TO APPLICATION ROLE admin;
GRANT USAGE ON FUNCTION app_code.add(INT, INT)
  TO APPLICATION ROLE user;
Copy

在此示例中,安装脚本创建了名为 adminuser 的应用程序角色。然后,安装脚本向两个应用程序角色授予了对包含应用程序代码的架构的访问权限。安装脚本还授予了对架构内 add 函数的访问权限。admin 还被授予了对 config_app 过程的访问权限。

应用程序角色和版本

应用程序角色没有版本控制。这意味着,删除应用程序角色或撤消不在带有版本控制的架构中的对象的权限可能会影响应用程序的当前版本或正在升级的版本。仅当您删除了使用应用程序角色的应用程序的所有版本后,才可以安全地删除这些角色。

备注

不能向应用程序角色授予对象的所有权。这意味着安装脚本中定义的应用程序角色应该只用于允许使用者访问已安装的 Snowflake Native App 内的对象。

语言: 中文