#sql #ruby-on-rails #ruby #activerecord
#sql #ruby-on-rails #ruby #activerecord
Вопрос:
Давайте рассмотрим две модели ActiveRecord Product
и Promotion
Построение запроса с использованием внешнего соединения и псевдонима для столбца объединенной таблицы приводит к следующему недопустимому SQL:
Product.distinct.includes(:promotion).select('promotions.advertised as featured').
references(:promotion).order('featured').limit(10).to_sql
SELECT DISTINCT "products"."id", featured AS alias_0 FROM "products"
^^^^^^^^^^^^^^^^^^^
LEFT OUTER JOIN "promotions" ON "promotions"."product_id" = "products"."id" ORDER BY featured LIMIT 10
Результатом выполнения является ошибка базы данных: ActiveRecord::StatementInvalid: PG::UndefinedColumn: ERROR: column "featured" does not exist
. Как и ожидалось, потому что featured является псевдонимом для столбца promotions.advertised, не определенного в таблице products.
Как вы можете видеть, ActiveRecord вводит недопустимое "featured AS alias_0"
выражение в select. Кроме того, все столбцы products
таблицы, за исключением id
, опущены.
Вышеуказанное неправильное поведение связано с одновременным использованием методов order
И limit
. Когда какой-либо из них опущен, созданный SQL становится правильным. Например, простое удаление limit приводит к правильному запросу:
Product.distinct.includes(:promotion).select('promotions.advertised as featured').
references(:promotion).order('featured').to_sql
SELECT DISTINCT promotions.advertised as featured, "products"."id" AS t0_r0, "products"."name" AS t0_r1, … FROM "products"
LEFT OUTER JOIN "promotions" ON "promotions"."product_id" = "products"."id" ORDER BY featured
Кто-нибудь может объяснить это поведение?
Кандидат на сообщение об ошибке или я что-то упускаю?
протестировано с ActiveRecord версии 4.2.7.1
Комментарии:
1.
distinct
это не проблема. Не влияет на исправление неверного запроса, если он пропущен. Я пытался упростить гораздо более сложную проблему, но основная идея сохранена. Я не совсем понимаю, что вы подразумеваете под «борьбой» с вышеуказанными методами, почему их не следует использовать вместе.2. Под «борьбой» я подразумеваю, что
distinct
,includes
иselect
все пытаются что-то сделать с предложением SELECT, и, похоже, в конечном итоге они все портят.3. Я все еще не вижу никакой двусмысленности или неправильного использования этих методов. Что меня беспокоит, и, вероятно, должно беспокоить других, он молча возвращает явно неправильный результат, просто добавляя совершенно несвязанный
limit
метод.