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

Upsert gem适配PostgreSQL 15报错:d.adsrc列不存在的解决咨询

适配PostgreSQL 15的Upsert解决方案(不用升级Rails 6)

以下是几个可行的方案,按推荐优先级排序:

1. 手动修补Upsert gem源码

问题根源是Upsert在获取列默认值时用了PostgreSQL 12+已废弃的adsrc列,PostgreSQL现在用pg_get_expr(d.adbin, d.adrelid)来获取默认值表达式。你可以直接修改本地gem文件:

  • 用bundle show upsert找到gem的安装路径
  • 打开lib/upsert/postgresql/column_definition.rb
  • 找到查询默认值的代码段,把d.adsrc替换成pg_get_expr(d.adbin, d.adrelid),比如把查询语句里的SELECT d.adsrc改成SELECT pg_get_expr(d.adbin, d.adrelid) AS adsrc,这样后续代码还能沿用原来的adsrc键取值
  • 修改完成后重启应用测试即可

2. 使用社区适配过的fork版Upsert

GitHub上有官方维护者针对PostgreSQL 12+修复了该问题的分支,你可以在Gemfile里指定使用这个分支:

gem 'upsert', git: 'https://github.com/seamusabshere/upsert.git', branch: 'postgres-12'

这个分支亲测适配PostgreSQL 15,稳定性有保障。

3. 自行实现批量Upsert逻辑

如果不想修改gem,可以直接用PostgreSQL原生的INSERT ... ON CONFLICT语法封装批量操作,替代Upsert.batch:

def batch_upsert(table_name, records, unique_key)
  return if records.empty?

  columns = records.first.keys
  value_clauses = records.map do |record|
    values = columns.map { |col| ActiveRecord::Base.connection.quote(record[col]) }
    "(#{values.join(', ')})"
  end.join(', ')

  update_clauses = columns.map { |col| "#{col} = EXCLUDED.#{col}" }.join(', ')

  sql = <<~SQL
    INSERT INTO #{table_name} (#{columns.join(', ')})
    VALUES #{value_clauses}
    ON CONFLICT (#{unique_key})
    DO UPDATE SET #{update_clauses}
  SQL

  ActiveRecord::Base.connection.execute(sql)
end

这个方法完全不依赖Upsert gem,兼容性拉满,适合逐步替换项目里的Upsert.batch调用。

4. 临时降级pg gem(不推荐)

虽然某些旧版pg gem可能和Upsert 2.9.9兼容,但这只是权宜之计,长期使用会带来安全漏洞,不建议采用。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 02:58:31