sequelize: Incorrect SELECT query generation including "LIMIT" clause and "M:N" association with "where" clause returns unexpected results
Hello,
I’ve come across a bug with query generation which include limiting results with including belongsToMany
relation containing WHERE
clause.
I made executable script to demonstrate this behavior as they are cases when generated query might return expected result if query and data in database are in specific state.
if you investigate the file the following are queries generated for particular demonstration cases:
“Test 1”: Works
Student.findAndCount({
offset: 6,
order: [["id", "DESC"]],
include: [
{
model: Teacher,
as: 'teachers',
where: {
id: {$in: [3, 2]}
}
}
]
});
SELECT "student"."id", "student"."age", "student"."name",
"student"."created_at", "student"."updated_at", "teachers"."id" AS
"teachers.id", "teachers"."age" AS "teachers.age", "teachers"."name" AS
"teachers.name", "teachers"."created_at" AS "teachers.created_at",
"teachers"."updated_at" AS "teachers.updated_at",
"teachers.student_teacher"."id" AS "teachers.student_teacher.id",
"teachers.student_teacher"."teacher_id" AS
"teachers.student_teacher.teacher_id", "teachers.student_teacher"."student_id"
AS "teachers.student_teacher.student_id"
FROM "student" AS "student"
INNER JOIN (
"student_teacher" AS "teachers.student_teacher"
INNER JOIN "teacher" AS "teachers"
ON "teachers"."id" = "teachers.student_teacher"."teacher_id"
)
ON "student"."id" = "teachers.student_teacher"."student_id"
AND "teachers"."id" IN (3, 2)
ORDER BY "student"."id" DESC OFFSET 6;
“Test 2”: Bug - Wrong query generated… but this case returns expected result by “coincidence”
Student.findAndCount({
limit: 5,
offset: 6,
order: [["id", "DESC"]],
include: [
{
model: Teacher,
as: 'teachers',
where: {
id: {$in: [3, 2]}
}
}
]
});
SELECT "student".*, "teachers"."id" AS "teachers.id", "teachers"."age" AS
"teachers.age", "teachers"."name" AS "teachers.name", "teachers"."created_at"
AS "teachers.created_at", "teachers"."updated_at" AS "teachers.updated_at",
"teachers.student_teacher"."id" AS "teachers.student_teacher.id",
"teachers.student_teacher"."teacher_id" AS
"teachers.student_teacher.teacher_id", "teachers.student_teacher"."student_id"
AS "teachers.student_teacher.student_id"
FROM (
SELECT "student"."id", "student"."age", "student"."name",
"student"."created_at", "student"."updated_at"
FROM "student" AS "student"
WHERE (
SELECT "student_teacher"."id"
FROM "student_teacher" AS "student_teacher"
INNER JOIN "teacher" AS "teacher"
ON "student_teacher"."teacher_id" = "teacher"."id"
WHERE ("student"."id" = "student_teacher"."student_id")
LIMIT 1
) IS NOT NULL
ORDER BY "student"."id" DESC LIMIT 5 OFFSET 6
) AS "student"
INNER JOIN (
"student_teacher" AS "teachers.student_teacher"
INNER JOIN "teacher" AS "teachers"
ON "teachers"."id" = "teachers.student_teacher"."teacher_id"
)
ON "student"."id" = "teachers.student_teacher"."student_id"
AND "teachers"."id" IN (3, 2)
ORDER BY "student"."id" DESC;
“Test 3”: Bug - Wrong query - returns unexpected results
Student.findAndCount({
limit: 5,
offset: 6,
include: [
{
model: Teacher,
as: 'teachers',
where: {
id: {$in: [3, 2]}
}
}
]
});
SELECT "student".*, "teachers"."id" AS "teachers.id", "teachers"."age" AS
"teachers.age", "teachers"."name" AS "teachers.name", "teachers"."created_at"
AS "teachers.created_at", "teachers"."updated_at" AS "teachers.updated_at",
"teachers.student_teacher"."id" AS "teachers.student_teacher.id",
"teachers.student_teacher"."teacher_id" AS
"teachers.student_teacher.teacher_id", "teachers.student_teacher"."student_id"
AS "teachers.student_teacher.student_id"
FROM (
SELECT "student"."id", "student"."age", "student"."name",
"student"."created_at", "student"."updated_at"
FROM "student" AS "student"
WHERE (
SELECT "student_teacher"."id"
FROM "student_teacher" AS "student_teacher"
INNER JOIN "teacher" AS "teacher"
ON "student_teacher"."teacher_id" = "teacher"."id"
WHERE ("student"."id" = "student_teacher"."student_id")
LIMIT 1
) IS NOT NULL LIMIT 5 OFFSET 6
) AS "student"
INNER JOIN (
"student_teacher" AS "teachers.student_teacher"
INNER JOIN "teacher" AS "teachers"
ON "teachers"."id" = "teachers.student_teacher"."teacher_id"
)
ON "student"."id" = "teachers.student_teacher"."student_id"
AND "teachers"."id" IN (3, 2);
As I look at queries it seems it would be great if generated queries for test cases 2
and 3
would be the same as in 1
with LIMIT
included at the end of query, wouldn’t it?
Thank you for your work!
About this issue
- Original URL
- State: closed
- Created 9 years ago
- Reactions: 2
- Comments: 23 (13 by maintainers)
@janmeier my case is exactly the same as @fogine first post.
I have noticed that adding the option
subQuery: false
seems to produce the desired mysql query. Is there any downside of using this?Same issue here. Any progress or workaround?
Is there any reason for those subqueries being there?
Basically, my problem is that I have a where clause on the subquery (which is triggered by a limit), but it it isn’t working because it references a table that is joined outside the subquery. I’m not sure how much detail to provide for a SSCCE, but here goes: https://gist.github.com/markdboyd/cf19937dec07b1af2bd7
It also seems like #4737 is a related issue here.