You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rails7迁移后schema.rb生成无效索引,导致db:test:prepare执行失败

Rails 7 中 JSON 字段自定义索引导致 schema.rb 语法错误的解决方案

问题场景

  • 在 Rails 7 环境下,通过自定义 SQL 迁移为 JSON 字段添加函数索引后,自动生成的 schema.rb 索引语句存在语法错误
  • 执行命令 RAILS_ENV=test rake db:test:prepare 时触发 ActiveRecord::StatementInvalid 错误
  • 手动修改 schema.rb 可临时修复,但后续执行迁移后问题会再次出现

相关代码与错误信息

自定义迁移代码

class AddSavedSearchAPIKeyIndex < ActiveRecord::Migration[7.0]
  def change
    execute <<~SQL
      ALTER TABLE saved_searches
      ADD INDEX ecomm_analyze_api_key ((
        CAST(configuration->>"$.ecomm_analyze_api_key" as CHAR(255)) COLLATE utf8mb4_bin
      )) USING BTREE;
    SQL
  end
end

schema.rb 生成的错误索引语句

t.index "(cast(json_unquote(json_extract(`configuration`,_utf8mb4\\'$.ecomm_analyze_api_key\\')) as char(255) charset utf8mb4) collate utf8mb4_bin)", name: "ecomm_analyze_api_key"

触发的错误信息

ActiveRecord::StatementInvalid: Mysql2::Error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use

解决方案

推荐方案:改用 structure.sql 替代 schema.rb

Rails 的 schema.rb 基于 Ruby DSL,无法完全兼容所有数据库原生 SQL 语法,对于复杂的函数索引支持不足。改用 structure.sql 直接保存数据库原生结构,能准确保留自定义索引的语法:

  1. 修改 config/application.rb,设置 schema 格式为 SQL:
    config.active_record.schema_format = :sql
    
  2. 执行命令生成 db/structure.sql:
    rails db:structure:dump
    
  3. 后续测试环境准备使用以下命令替代 db:test:prepare:
    RAILS_ENV=test rake db:structure:load
    

临时方案(不推荐):手动修正 schema.rb

如果暂时无法切换到 structure.sql,可以手动将 schema.rb 中的错误索引语句替换为原生 SQL 执行:

# 替换自动生成的 t.index 语句
execute <<~SQL
  CREATE INDEX ecomm_analyze_api_key ON saved_searches ((CAST(configuration->>"$.ecomm_analyze_api_key" as CHAR(255)) COLLATE utf8mb4_bin)) USING BTREE;
SQL

注意:每次执行迁移后都需要重新修改,无法长期解决问题。

问题原因

Rails 的 Schema Dumper 在解析 MySQL 的 JSON 运算符 ->> 时,会将其转换为 json_unquote(json_extract(...)),但转义处理逻辑出错,导致生成的语句中出现多余的转义符(\\')和错误的语法结构,最终触发 MySQL 语法错误。

内容的提问来源于stack exchange,提问作者Overload119

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 17:15:42