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對我多麼希望我的數據庫工作太有限開始。

  • 相關問題