PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Как мога да получа достъп до стойността по подразбиране на колона на Postgres с помощта на ActiveRecord?

Когато 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 call в горната заявка е мястото, откъдето идва стойността по подразбиране на колоната.

Резултатите от тази заявка отиват, повече или по-малко, направо в 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 конструктор ще използва extract_value_from_default за Ruby-ify по подразбиране; края на превключвателя в 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 (като before_create ).

IMO би било много по-добре, ако AR остави стойностите по подразбиране до базата данни, ако не ги разбира:оставянето им извън INSERT или използването на DEFAULT в VALUES би дало много по-добри резултати; AR, разбира се, ще трябва да презареди новосъздадени обекти от базата данни, за да получи всички правилни настройки по подразбиране, но ще имате нужда от презареждане само ако има настройки по подразбиране, които AR не разбира. Ако друго в extract_value_from_default използва специален флаг „Не знам какво означава това“ вместо nil тогава условието „Трябва да презаредя този обект след първото записване“ ще бъде тривиално за откриване и ще презаредите само когато е необходимо.

Горното е специфично за PostgreSQL, но процесът трябва да е подобен за други бази данни; обаче не давам гаранции.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. SQL Брои дни до първо число на месеца

  2. Как да се справим с грешката на Ruby on Rails:Моля, инсталирайте Postgresql адаптера:`gem install activerecord-postgresql-adapter'

  3. Какъв е максималният размер на пакета JDBC?

  4. SQL, Postgres OID, какви са те и защо са полезни?

  5. Как да регистрирам промяна на данните в postgresql?