Snowpark Python存储过程调用JavaScript存储过程执行DDL时报错
问题解答
原因分析
这确实是Snowpark Python存储过程的设计特性导致的:
- Snowpark Python存储过程运行在隔离的沙箱会话中,该会话与外层调用会话相互独立,且Snowpark的
Session对象维护着自身的状态上下文。 - 当从Snowpark Python存储过程调用JavaScript存储过程时,被调用的JS过程若尝试执行
USE SCHEMA、ALTER SESSION SET ...这类修改会话上下文属性的语句,会被沙箱的限制拦截,返回“不支持”错误。 - 而
USE ROLE属于权限身份切换操作,不属于会话上下文属性修改范畴,因此不在限制范围内,可正常执行。
解决方法
1. 在Snowpark Python存储过程中提前设置会话上下文
将JS过程中需要的会话设置逻辑移到Python存储过程中执行,再调用JS过程:
create or replace procedure utility.procedure.Test_Python() returns string language PYTHON RUNTIME_VERSION = '3.10' handler = 'main' PACKAGES = ('snowflake-snowpark-python') as $$ import snowflake.snowpark as snowpark def main(session): # 提前设置会话上下文 session.use_role("REPORT_ANALYST") session.use_warehouse("REPORT_WH_XS") session.use_schema("END_USER_INPUT.REPORT_ANALYST") session.sql("ALTER SESSION SET QUERY_TAG = 'something'").collect() # 调用JS存储过程 session.call("UTILITY.END_USER_INPUT_PROCEDURE.Test_Javascript") $$
同时简化JavaScript存储过程,移除会话设置语句:
create or replace procedure utility.procedure.Test_Javascript() returns VARCHAR language javascript execute as caller as $$ # 仅保留业务逻辑,无需再设置会话 return "执行完成"; $$
2. 将会话设置移到调用链最外层
如果业务允许,可在调用Python存储过程之前,直接在客户端或外层会话中执行会话设置语句,后续所有存储过程调用都会继承该上下文:
USE ROLE REPORT_ANALYST; USE WAREHOUSE REPORT_WH_XS; USE SCHEMA END_USER_INPUT.REPORT_ANALYST; ALTER SESSION SET QUERY_TAG = 'something'; -- 调用Python存储过程 CALL utility.procedure.Test_Python();
3. 调整JavaScript存储过程的执行模式(慎用)
若业务必须在JS过程中执行会话设置,可尝试将JS存储过程的EXECUTE AS改为OWNER,但这会改变存储过程的权限执行上下文,可能带来安全风险,仅在确认权限安全的情况下使用:
create or replace procedure utility.procedure.Test_Javascript() returns VARCHAR language javascript execute as owner as -- 修改执行模式为所有者 $$ snowflake.execute({sqlText: 'use role REPORT_ANALYST;'}) snowflake.execute({sqlText: 'use warehouse REPORT_WH_XS;'}) snowflake.execute({sqlText: 'USE SCHEMA END_USER_INPUT.REPORT_ANALYST;'}) $$
内容的提问来源于stack exchange,提问作者Brandon Coleman
相关产品推荐
相关产品推荐

