1

我在Rails项目中有一个默认表达式的遗留表。该表达式会随机选取一个四位数字并将其转换为字符串。在我的测试中,我一直在打字这个确切的语句转换成PSQL设置默认表情:当我做\d owners为什么Postgres在为列设置默认函数时双引用第一个函数标识符?

alter table owners alter column signing_code set default 
substring(to_char(((random() * ((10000 - 1))::double precision) + 
(1)::double precision), '0000'::text), '....$'::text); 

那么,什么是Postgres的决定是我实际的默认表情:

default "substring"(to_char(((random() * ((10000 - 1))::double 
precision) + (1)::double precision), '0000'::text), '....$'::text) 

公告围绕第一个函数标识符substring的双引号。这会导致两个问题的Rails架构转储/负载:

  1. 当倾倒架构DB/schema.rb,无效红宝石产生,因为双引号没有逃过
  2. 即使你正确地逃脱报价当将模式加载回数据库时,Rails错误地将整个表达式设置为默认的字符串值,而不是表达式(即它用单引号括起表达式)

有没有办法让Postgres不是在我的情况下双引号嵌套函数调用中的第一个函数?这将是一个很好的解决方法,否则我会向Rails项目提交一个错误。

回答

0

为什么substring函数被双引号并不重要,这两个表达式在功能上是等价的。 PostgreSQL将解析默认表达式,然后保存解析后的版本,在此过程中,substring标识符会被双引号引用。你可以看到,如果你添加一个CHECK约束类似的这样的事情发生:

check (c in (1, 2, 3)) 

在桌子上做一个\d与约束为您提供:

CHECK (c = ANY (ARRAY[1, 2, 3])) 

PostgreSQL的平移in表达为等效= ANY表达式,因为这就是它想要在内部工作。这两个表达式在功能上是等同的。

真正的问题是ActiveRecord不知道如何处理比单个文字值更复杂的默认表达式。 AR对于什么样的默认设置做出了一个无效的假设,然后盲目地沉溺于一团糟。

当您处理超出最简单的DDL SQL之外的任何事情时,最好的办法是使用db/structure.sql而不是db/schema.rbstructure.sql使用数据库的本地转储/恢复工具,因此它可以理解并保留数据库知道的所有信息。

切换到structure.sql很简单:使用db:structure:dump rake任务

config.active_record.schema_format = :sql 
  • 转储structure.sql

    1. 更新config/application.rb使用正确的格式。

    2. 从您的源代码树和版本控制中删除db/schema.rb

    3. db/structure.sql添加到修订控件。

    4. 重新训练你的手指使用不同的耙任务倾销和恢复模式:

      • db:structure:dump而不是db:schema:dump
      • db:structure:load而不是db:schema:load

    我总是structure.sqlschema.rb对我多么希望我的数据库工作太有限开始。

  • 相关问题