Closed damaon closed 8 years ago
I'm running into something similar while attempting to update to Rails 4.2.4 (from 4.1.6), and using MySQL. It's not a polymorphic relation, but it looks like a similar parsing error is happening. Here's a really contrived example:
# person.rb
class Person < ActiveRecord::Base
has_many :active_emails, -> { where active: true }, class_name: 'Email'
has_many :twitters
end
Say we want to find all people with active emails starting with "johndoe".
Person.joins(:active_emails).where('address like ?', 'johndoe%')
yields
SELECT `people`.* FROM `people` INNER JOIN `emails` ON `emails`.`person_id` = `people`.`id` AND `emails`.`active` = 1 WHERE (address like 'johndoe%')
So far, so good. Now let's say we want to find all people with either an active email starting with "johndoe" or a Twitter handle starting with "johndoe".
Person.joins(:active_emails).where('address like ?', 'johndoe%').union(Person.joins(:twitters).where('handle like ?', 'johndoe%'))
yields
SELECT `people`.* FROM ( (SELECT `people`.* FROM `people` INNER JOIN `emails` ON `emails`.`person_id` = `people`.`id` AND `emails`.`active` = WHERE (address like 'johndoe%')) UNION (SELECT `people`.* FROM `people` INNER JOIN `twitters` ON `twitters`.`person_id` = `people`.`id` WHERE (handle like 'johndoe%')) ) people
Note that where it used to say, "AND emails
.active
= 1 WHERE...", the "1" has now mysteriously vanished, and this is no longer valid SQL.
This does not happen with sqlite3, presumably because the original syntax is different:
-- sqlite3 sanitizes out the parameter in the scope block
SELECT "people".* FROM "people" INNER JOIN "emails" ON "emails"."person_id" = "people"."id" AND "emails"."active" = ? WHERE (address like 'johndoe%') [["active", "t"]]
I can reproduce on SQLite…
class User < ActiveRecord::Base
has_many :posts
has_many :drafts, -> { where draft: true }, class_name: "Post"
end
class Post < ActiveRecord::Base
belongs_to :user
end
User.joins(:drafts).union(User.where(id: 11)).to_sql
SELECT "users".* FROM (
SELECT "users".*
FROM "users"
INNER JOIN "posts" ON "posts"."user_id" = "users"."id" AND "posts"."draft" = 11
UNION
SELECT "users".* FROM "users"
WHERE "users"."id" =
) "users"
Thanks for the bug report with the examples. You've been credited in the README.
v1.1.1 is live on RubyGems with the fix in #7.
Let me know if you have any more problems.
Check out this code:
=> "SELECT \"questions\".\"id\", \"questions\".\"title\", \"questions\".\"meta\", \"questions\".\"content\", \"questions\".\"updated_at\", \"questions\".\"user_id\", 'Question' AS \"type\" FROM \"questions\" INNER JOIN \"taggings\" ON \"taggings\".\"tagged_id\" = \"questions\".\"id\" AND \"taggings\".\"tagged_type\" = 'Question' INNER JOIN \"tags\" ON \"tags\".\"id\" = \"taggings\".\"tag_id\" WHERE \"questions\".\"deleted_at\" IS NULL AND (1=0)"
=> "SELECT \"findings\".\"id\", \"findings\".\"title\", \"findings\".\"meta\", \"findings\".\"content\", \"findings\".\"updated_at\", \"findings\".\"user_id\", 'Finding' AS \"type\" FROM \"findings\" INNER JOIN \"taggings\" ON \"taggings\".\"tagged_id\" = \"findings\".\"id\" AND \"taggings\".\"tagged_type\" = 'Finding' INNER JOIN \"tags\" ON \"tags\".\"id\" = \"taggings\".\"tag_id\" WHERE \"findings\".\"deleted_at\" IS NULL AND (1=0)"
=> "SELECT \"questions\".* FROM ( (SELECT \"questions\".\"id\", \"questions\".\"title\", \"questions\".\"meta\", \"questions\".\"content\", \"questions\".\"updated_at\", \"questions\".\"user_id\", 'Question' AS \"type\" FROM \"questions\" INNER JOIN \"taggings\" ON \"taggings\".\"tagged_id\" = \"questions\".\"id\" AND \"taggings\".\"tagged_type\" = INNER JOIN \"tags\" ON \"tags\".\"id\" = \"taggings\".\"tag_id\" WHERE \"questions\".\"deleted_at\" IS NULL AND (1=0)) UNION ALL (SELECT \"findings\".\"id\", \"findings\".\"title\", \"findings\".\"meta\", \"findings\".\"content\", \"findings\".\"updated_at\", \"findings\".\"user_id\", 'Finding' AS \"type\" FROM \"findings\" INNER JOIN \"taggings\" ON \"taggings\".\"tagged_id\" = \"findings\".\"id\" AND \"taggings\".\"tagged_type\" = INNER JOIN \"tags\" ON \"tags\".\"id\" = \"taggings\".\"tag_id\" WHERE \"findings\".\"deleted_at\" IS NULL AND (1=0)) ) questions"
AND \"taggings\".\"tagged_type\" = INNER JOIN
<- error spotted?This gem somehow misses these two bindings and when I try to execute query I get error that 2 bindings are missing.