Специальные запросы к базе данных Rails для Heroku

0

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

В настоящее время у меня есть спецификация case в базе данных в моей модели. Я понимаю, почему возникает ошибка в отношении функций даты 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

FYI, это ошибка 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

Заранее благодарим за любой вклад.

Теги:
database
heroku

3 ответа

4
Лучший ответ

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

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

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

  • 0
    Как раз то решение, которое я искал, спасибо!
2

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

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

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

Пример (Semi-Psuedo Code):

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
  • 0
    Да, дублирование кода - это то, что действительно спровоцировало мой вопрос, это было то, без чего я хотел попробовать. Ваше предложение, безусловно, хорошее, спасибо.
1

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

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню