如何构建可求值的Ruby SQL模板?解决Postgres转义字符问题
问题描述
我的应用允许管理员定义SQL模板脚本,供用户应用于数据结构。模板存储在Postgres数据库的文本字段中,会与数据结构元数据合并。
预期的模板语句:
CREATE TABLE #{@target.code} ( #{@target.getColList('ORACLE', 'typed')} )
求值后应得到目标SQL:
CREATE TABLE DSD_TEST ( AHVN13_1 number, ALTER_MT_ERFUELLT_1 number, CANTONS_2_1 varchar2(32), POPULATION_TYPE_1 varchar2(32) )
但实际从Postgres文本字段取出的模板语句为:
"CREATE TABLE \#{@target.code} ( \r\n\#{@target.getColList('ORACLE', 'typed')} \r\n)"
已通过 task.statement.gsub("\r\n", '') 去除换行,但无法去除转义字符\,请问如何构建该模板以实现正确求值?
解决方法
1. 清理取出的模板内容
取出的字符串带有前后双引号和转义的\,可以一次性处理:
# 移除前后双引号,再将转义的\#替换为# cleaned_statement = task.statement.gsub(/^"|"$/, '').gsub('\#', '#') # 按需处理换行(保留换行可让生成的SQL更易读) cleaned_statement = cleaned_statement.gsub("\r\n", "\n")
处理后模板里的\#{...}会还原为#{...},符合模板引擎的语法要求。
2. 修正模板存储时的转义问题
出现\#的核心原因是存储时模板被自动转义,需从源头解决:
- 用ORM(比如ActiveRecord)存储时,关闭自动转义特殊字符的配置;
- 管理员通过表单输入模板时,确保表单提交逻辑不对
#做转义处理; - 直接在Postgres中插入模板时,用单引号包裹内容,避免转义:
INSERT INTO your_table (statement) VALUES ('CREATE TABLE #{@target.code} ( #{@target.getColList('ORACLE', 'typed')} )');
3. 确保模板引擎正确解析
从#{}语法判断大概率用的是Ruby ERB,清理后的模板需正确传入上下文求值:
require 'erb' template = ERB.new(cleaned_statement) # 确保binding中包含@target对象 generated_sql = template.result(binding)
内容的提问来源于stack exchange,提问作者user1185081
相关产品推荐
相关产品推荐

