Postgres 提取多态列

Postgres extracting a polymorphic column

我有以下 table 称为 feeds

 from_type | from_id 
-----------+---------
 user      |       1
 project   |       1
 user      |       2
 program   |       1
 program   |       2
 project   |       1
 challenge |       1
 project   |       3
 community |       1

我想将其转换为:

 from_type | user_id | project_id | program_id | challenge_id | community_id
-----------+---------+------------+------------+--------------+-------------
 user      |       1 |            |            |              |         
 project   |         |          1 |            |              |         
 user      |       2 |            |            |              |         
 program   |         |            |          1 |              |         
 program   |         |            |          2 |              |         
 project   |         |          1 |            |              |         
 challenge |         |            |            |            1 |         
 project   |         |          3 |            |              |         
 community |         |            |            |              |           1

我这样做的原因是,如果我们需要回滚,可以进行反向迁移。我设法用 coalesce + update statement 将底部版本转换为顶部版本,但我不太确定如何执行反向操作。

这是向上迁移,向下迁移应该是什么样的?

class PolymorphicFeedTable < ActiveRecord::Migration[5.2]
  def up
    execute <<-SQL
      UPDATE feeds SET
        from_id = coalesce(user_id, project_id, community_id, challenge_id, program_id, need_id);
    SQL
  end

  def down
    execute <<-SQL
      ?
    SQL
  end
end

如果展开 up 方法:

def up
  %w[challenge community need program project user].each do |type|
    execute("update feeds set from_id = #{type}_id where from_type = '#{type}'")
  end
end

然后就可以看到回去的路了,把赋值倒过来就好了:

def down
  %w[challenge community need program project user].each do |type|
    execute("update feeds set #{type}_id = from_id where from_type = '#{type}'")
    # ------------------------^^^^^^^^^^^^^^^^^^^^
  end
end

假设您的 table 数据没有损坏(即您的 from_type 值与 X_id 列匹配)。


您可以 connection.quote(type) 而不是简单地手动将 #{type} 括在单引号中,但您知道这些类型事先是安全的,因此没有必要这样做。 connection.quote_column_name#{type}_id 插值也是如此。