drizzle-team / drizzle-team/drizzle-orm

[BUG]: Avoid unnecessary nesting in the query builder

Open
#3,701 0 comments 0 reactions 0 assignees View on GitHub
improvement rqb
Dominant language
TypeScript
Stars
35.8k
Forks
1.6k
Avg merge
2d 7h
Merged PRs (30d)
4

Description

### Report hasn't been filed before.

- [X] I have verified that the bug I'm about to report hasn't been filed before.

### What version of `drizzle-orm` are you using?

0.37.0

### What version of `drizzle-kit` are you using?

0.29.1

### Other packages

better-sqlite3@11.6.0

### Describe the Bug

tl:dr; Remove unnecessary nesting if the relation depth ends in 1.

---

This query:

```js
db.query.userTable.findFirst({
columns: { id: true },
where: eq(userTable.id, ''),
with: { profile: { columns: { userId: true } } }
});

relations(profileTable, ({ one }) => ({
user: one(userTable, {
fields: [profileTable.userId], // this is a primary-key, which can be used as an index
references: [userTable.id]
})
}));

```

generates this nested SQL:

```sql
select
"id",
(
select
json_array ("user_id") as "data"
from
(
select
*
from
"profile" "userTable_profile"
where
"userTable_profile"."user_id" = "userTable"."id"
limit
?
) "userTable_profile"
) as "profile"
from
"user" "userTable"
where
"userTable"."id" = ?
limit
?

-- 1,,1
```

which causes a full-table scan (index 4):

```
┌─────────┬────┬────────┬─────────┬───────────────────────────────────────────────────────────────────────────────┐
│ (index) │ id │ parent │ notused │ detail │
├─────────┼────┼────────┼─────────┼───────────────────────────────────────────────────────────────────────────────┤
│ 0 │ 5 │ 0 │ 39 │ 'SEARCH userTable USING COVERING INDEX sqlite_autoindex_user_1 (id=?)' │
│ 1 │ 13 │ 0 │ 0 │ 'CORRELATED SCALAR SUBQUERY 2' │
│ 2 │ 16 │ 13 │ 0 │ 'CO-ROUTINE userTable_profile' │
│ 3 │ 22 │ 16 │ 39 │ 'SEARCH userTable_profile USING INDEX sqlite_autoindex_profile_1 (user_id=?)' │
│ 4 │ 36 │ 13 │ 17 │ 'SCAN userTable_profile' │
└─────────┴────┴────────┴─────────┴───────────────────────────────────────────────────────────────────────────────┘
```

---

Removing the nesting:

```sql
SELECT
"id",
(
SELECT
json_array ("user_id") AS "data"
FROM
"profile" AS "userTable_profile"
WHERE
"userTable_profile"."user_id" = "userTable"."id"
LIMIT
1
) AS "profile"
FROM
"user" AS "userTable"
WHERE
"userTable"."id" = ?
LIMIT
1;
```

removes the full-table scan:

```
┌─────────┬────┬────────┬─────────┬────────────────────────────────────────────────────────────────────────────────────────┐
│ (index) │ id │ parent │ notused │ detail │
├─────────┼────┼────────┼─────────┼────────────────────────────────────────────────────────────────────────────────────────┤
│ 0 │ 3 │ 0 │ 39 │ 'SEARCH userTable USING COVERING INDEX sqlite_autoindex_user_1 (id=?)' │
│ 1 │ 9 │ 0 │ 0 │ 'CORRELATED SCALAR SUBQUERY 1' │
│ 2 │ 17 │ 9 │ 39 │ 'SEARCH userTable_profile USING COVERING INDEX sqlite_autoindex_profile_1 (user_id=?)' │
└─────────┴────┴────────┴─────────┴────────────────────────────────────────────────────────────────────────────────────────┘
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.