Специальные запросы к базе данных Rails для Heroku - PullRequest
0 голосов
/ 05 апреля 2011

Я недавно развернул некоторые приложения в Heroku. Я запускаю MySQL на своей локальной машине разработчика и потратил немного времени на обновление некоторых моих областей для работы в PostgreSQL. Однако один, на котором я получил ошибку, трудно изменить.

В настоящее время в моей модели есть конкретный регистр дел. Я понимаю, почему возникает ошибка, связанная с функциями даты в MySQL, но я не уверен, является ли это наиболее эффективным решением. У кого-нибудь есть лучший способ реализовать исправление, которое будет работать как с MySQL, так и с PostgreSQL?

  case ActiveRecord::Base.connection.adapter_name
  when 'PostgreSQL'
    named_scope :by_year, lambda { |*args| {:conditions => ["published = ? AND (date_part('year', created_at) = ?)", true, (args.first)], :order => "created_at DESC"} }
    named_scope :by_month, lambda { |*args| {:conditions => ["published = ? AND (date_part('month', created_at) = ?)", true, (args.first)], :order => "created_at DESC"} }
    named_scope :by_day, lambda { |*args| {:conditions => ["published = ? AND (date_part('day', created_at) = ?)", true, (args.first)], :order => "created_at DESC"} }
  else
    named_scope :by_year, lambda { |*args| {:conditions => ["published = ? AND (YEAR(created_at) = ?)", true, (args.first)], :order => "created_at DESC"} }
    named_scope :by_month, lambda { |*args| {:conditions => ["published = ? AND (MONTH(created_at) = ?)", true, (args.first)], :order => "created_at DESC"} }
    named_scope :by_day, lambda { |*args| {:conditions => ["published = ? AND (DAY(created_at) = ?)", true, (args.first)], :order => "created_at DESC"} }
  end

К вашему сведению, это ошибка PostgreSQL, которую я получаю:

PGError: ERROR: function month(timestamp without time zone) does not exist LINE 1: ...T * FROM "articles" WHERE (((published = 't' AND (MONTH(crea... ^ HINT: No function matches the given name and argument types. You might need to add explicit type casts. : SELECT * FROM "articles" WHERE (((published = 't' AND (MONTH(created_at) = '11')) AND (published = 't' AND (YEAR(created_at) = '2010'))) AND ("articles"."published" = 't')) ORDER BY created_at DESC LIMIT 5 OFFSET 0

Заранее спасибо за любой вклад, который есть у каждого.

Ответы [ 3 ]

4 голосов
/ 06 апреля 2011

Вы должны использовать стандартную функцию EXTRACT:

named_scope :by_year, lambda { |*args| {:conditions => ["published = ? AND (extract(year from created_at) = ?)", true, (args.first)], :order => "created_at DESC"} }

Оба PostgresSQL и MySQL поддерживают его.

2 голосов
/ 05 апреля 2011

К сожалению, это часто случается, но у вас есть общее правильное представление.

Ваш первый метод атаки - посмотреть, существует ли функция, существующая как в MySQL, так и в Postres, однако это невозможно вэтот случай.

Одно из предложений, которое я хотел бы сделать, заключается в том, что в этом решении много дублирования кода.Учитывая, что оператор условия является единственной совместимой проблемой здесь, я бы исключил проверку совместимости только для условия:

Пример (код Полу-Псюэдо):

named_scope :by_year, lambda { |*args| {:conditions => ["published = ? AND (#{by_year_condition} = ?)", true, (args.first)], :order => "created_at DESC"} }


#...code...

def by_year_condition
  if postgres
     "date_part('year', created_at)"
  else
     "YEAR(created_at)"
end
1 голос
/ 06 апреля 2011

Другой вариант - создать вычисляемые столбцы для каждой части даты (day, month и year) и выполнить запрос непосредственно к ним.Вы можете обновлять их с помощью кода модели или триггеров.Вы также получите возможность индексировать различные комбинации по столбцам year, month и day.Общеизвестно, что базы данных плохо работают с индексами, когда вы используете функцию в предложении where, особенно когда эта функция извлекает часть данных из середины столбца.

Преимущество наличия трех отдельных столбцовчто ваш запрос больше не будет зависеть от реализаций SQL любого поставщика.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...