含JS代码的Snowflake SQL脚本无法通过Liquibase执行求助
问题描述
使用Snowflake管理数据库,尝试将现有含JavaScript代码的SQL脚本适配Liquibase执行。以下是创建函数的SQL代码:
create or replace function GetTimeSeries (businessDate text) returns varchar language javascript as $$ var bDate = new Date(BUSINESSDATE); if(BUSINESSDATE == '' || bDate > new Date('2059-09-18')) { return 32767; } return Math.ceil(parseFloat((bDate-(new Date('01/01/1970')))/(24*3600*1000))); $$;
该代码在Snowflake工作表中手动执行正常,但通过Liquibase CLI执行以下命令时:
liquibase update --defaults-file=dev.liquibase.properties --default-schema-name=DEV "-Dschema=DEV"
出现报错:
Unexpected error running Liquibase: Migration failed for changeset ../changelogs/dev/.. Reason: liquibase.exception.DatabaseException: SQL compilation error: parse error line 6 at position 39 near '<EOF>'. syntax error line 5 at position 1 unexpected '$'. [Failed SQL: (1003) create or replace procedure GetTimeSeries (businessDate text) returns text language javascript as $$ var bDate = new Date(BUSINESSDATE);
已对SQL文件做适配修改:
--liquibase formatted sql -- changeset Bhushan:1 create or replace function ${schema}.GetTimeSeries (businessDate text) returns varchar language javascript as $$ var bDate = new Date(BUSINESSDATE); if(BUSINESSDATE == '' || bDate > new Date('2059-09-18')) { return 32767; } return Math.ceil(parseFloat((bDate-(new Date('01/01/1970')))/(24*3600*1000))); $$;
需要无需手动转换大量JS代码的解决方案。
解决方案
方法1:在Changeset中禁用语句拆分
Liquibase默认会按分号拆分SQL语句,且会错误解析Snowflake JS函数中的$$分界符,导致提前终止语句解析。只需在changeset中添加splitStatements=false配置,让Liquibase将整个函数定义作为单条完整SQL发送给Snowflake处理:
--liquibase formatted sql -- changeset Bhushan:1 splitStatements=false create or replace function ${schema}.GetTimeSeries (businessDate text) returns varchar language javascript as $$ var bDate = new Date(BUSINESSDATE); if(BUSINESSDATE == '' || bDate > new Date('2059-09-18')) { return 32767; } return Math.ceil(parseFloat((bDate-(new Date('01/01/1970')))/(24*3600*1000))); $$;
这种方式无需修改JS代码本身,适配所有含$$分界符的Snowflake JS函数/存储过程。
方法2:命令行全局禁用语句拆分
如果多个changeset都需要处理类似的JS代码,可以在执行Liquibase命令时添加--splitStatements=false参数:
liquibase update --defaults-file=dev.liquibase.properties --default-schema-name=DEV "-Dschema=DEV" --splitStatements=false
注意:该参数会对所有changeset生效,若存在需要拆分的普通SQL语句,建议优先使用方法1的局部配置。
方法3:使用XML格式Changelog(可选)
若切换到XML格式的changelog,可通过<sql>标签的splitStatements="false"属性实现同样效果:
<changeSet id="1" author="Bhushan"> <sql splitStatements="false"> create or replace function ${schema}.GetTimeSeries (businessDate text) returns varchar language javascript as $$ var bDate = new Date(BUSINESSDATE); if(BUSINESSDATE == '' || bDate > new Date('2059-09-18')) { return 32767; } return Math.ceil(parseFloat((bDate-(new Date('01/01/1970')))/(24*3600*1000))); $$; </sql> </changeSet>
内容的提问来源于stack exchange,提问作者Bhushan Goel
相关产品推荐
相关产品推荐

