sql >> データベース >  >> RDS >> PostgreSQL

ActiveRecordを使用してPostgres列のデフォルト値にアクセスするにはどうすればよいですか?

    ActiveRecordがテーブルについて知る必要がある場合、 information_schemaと同様のクエリを実行します。 クエリを実行しますが、ARはPostgreSQL固有のシステムテーブル 代わりに:

      SELECT a.attname, format_type(a.atttypid, a.atttypmod),
             pg_get_expr(d.adbin, d.adrelid), a.attnotnull, a.atttypid, a.atttypmod
        FROM pg_attribute a LEFT JOIN pg_attrdef d
          ON a.attrelid = d.adrelid AND a.attnum = d.adnum
       WHERE a.attrelid = '#{quote_table_name(table_name)}'::regclass
         AND a.attnum > 0 AND NOT a.attisdropped
    ORDER BY a.attnum
    

    PostgreSQLアダプターソースを検索します 「regclass」の場合、ARがテーブルの構造を理解するために使用する他のクエリがいくつか表示されます。

    pg_get_expr 上記のクエリでの呼び出しは、列のデフォルト値の取得元です。

    そのクエリの結果は、多かれ少なかれ、 PostgreSQLColumn.newに直接アクセスします

    def columns(table_name, name = nil)
      # Limit, precision, and scale are all handled by the superclass.
      column_definitions(table_name).collect do |column_name, type, default, notnull|
        PostgreSQLColumn.new(column_name, default, type, notnull == 'f')
      end
    end
    

    PostgreSQLColumn コンストラクター <を使用しますcode> extract_value_from_default デフォルトをRuby化する。 スイッチ extract_value_from_defaultで ここで興味深いです:

    else
      # Anything else is blank, some user type, or some function
      # and we can't know the value of that, so return nil.
      nil
    

    したがって、デフォルト値がシーケンスにバインドされている場合( id PostgreSQLの列は)になり、デフォルトは次のような関数呼び出しとしてデータベースから出力されます:

    nextval('models_id_seq'::regclass)
    

    それは上記のelseになります ブランチとcolumn.default.nil? 本当になります。

    idの場合 列これは問題ではありません。ARはデータベースがidの値を提供することを期待しています。 列なので、デフォルト値は関係ありません。

    列のデフォルトがARが理解できないものである場合、これは大きな問題です。 md5(random()::text)として 。問題は、ARがすべての属性をデフォルト値に初期化することです– Model.columns Model.new と言うと、データベースが認識するのではなく、それらが表示されます。 。たとえば、コンソールには次のようなものが表示されます。

     > Model.new
    => #<Model id: nil, def_is_function: nil, def_is_zero: 0>
    

    したがって、 def_is_function 実際にはデフォルト値として関数呼び出しを使用しますが、ARはそれを無視し、その列の値としてNULLを挿入しようとします。そのNULLは、デフォルト値が使用されるのを防ぎ、混乱を招く混乱を招きます。ただし、ARが理解できるデフォルト(文字列や数値など)は問題なく機能します。

    その結果、ActiveRecordで重要なデフォルトの列値を実際に使用することはできません。重要な値が必要な場合は、RubyでActiveRecordコールバックの1つ( before_create > 。

    IMOがデフォルト値を理解していない場合、ARがデフォルト値をデータベースに任せた方がはるかに良いでしょう。それらをINSERTから除外するか、VALUESでDEFAULTを使用すると、はるかに良い結果が得られます。もちろん、ARは、すべての適切なデフォルトを取得するために、データベースから新しく作成されたオブジェクトをリロードする必要がありますが、ARが理解できないデフォルトがあった場合にのみ、リロードが必要になります。 else の場合 extract_value_from_default nil の代わりに、特別な「これが何を意味するのかわからない」フラグを使用しました その場合、「最初の保存後にこのオブジェクトをリロードする必要があります」という条件を検出するのは簡単で、必要な場合にのみリロードします。

    上記はPostgreSQL固有ですが、プロセスは他のデータベースでも同様である必要があります。ただし、保証はいたしません。




    1. パラメータを使用したnodejsmssql挿入

    2. 日付はOracleにどのように保存されますか?

    3. レーキが中止されました!初期化されていない定数Mysql2

    4. MySQLで3つのパックで行を表示する方法