drizzle-team / drizzle-team/drizzle-orm

[FEATURE]: Auto-Alias Columns in Subqueries

Open
#2,772 6 comments 45 reactions 0 assignees View on GitHub
improvement qb/crud
Dominant language
TypeScript
Stars
35.8k
Forks
1.6k
Avg merge
2d 7h
Merged PRs (30d)
4

Description

### Describe what you want

### Feature Request: Automatically Alias Columns in Subqueries to Avoid Ambiguity

**Issue**:
When using a custom select in a query that involves joins, and the query is used as a subquery with `.select()` (select all), an error like `column reference "column_name" is ambiguous` occurs. This is evident when inspecting the generated query via `.toSQL()`.

**Example**:
Consider the following TypeScript code:

```ts
const tableOneDefaultSelect = {
created_at: tableOne.createdAt,
updated_at: tableOne.updatedAt,
deleted_at: tableOne.deletedAt,
created_by: tableOne.createdBy,
updated_by: tableOne.updatedBy,
deleted_by: tableOne.deletedBy,
id: tableOne.id,
key: tableOne.key,
// ...
};
const tableTwoDefaultSelect = { id: tableTwo.id, title: tableTwo.title };
const tableThreeDefaultSelect = { /* similar structure */ };
const tableFourDefaultSelect = { /* similar structure */ };

const baseCriteria = and(
isNull(tableOne.deletedAt),
eq(tableFour.key, "published"),
// ...
);
const aliasTableThree = alias(tableThree, "table_boo");
const baseQuery = db
.select({
...tableOneDefaultSelect,
table_two: tableTwoDefaultSelect,
table_three: {
...tableThreeDefaultSelect,
name: tableThree.title,
},
table_four: tableFourDefaultSelect,
})
.from(tableOne)
.leftJoin(tableTwo, eq(tableTwo.id, tableOne.tableTwoId))
.leftJoin(tableThree, eq(tableThree.id, tableOne.tableThreeId))
.leftJoin(tableFour, eq(tableFour.id, tableOne.tableFourId))
.leftJoin(tableOneTableAce, eq(tableOneTableAce.tableOneId, tableOne.id)) // Junction table
.leftJoin(tableAce, eq(tableAce.id, tableOneTableAce.tableAceId))
.leftJoin(tableOneTableBoo, eq(tableOneTableBoo.tableOneId, tableOne.id)) // Junction table
.leftJoin(aliasTableThree, eq(aliasTableThree.id, tableOneTableBoo.tableThreeId))
.orderBy(desc(tableOne.updatedAt))
.where(baseCriteria);

const finalQuery = await db
.select()
.from(baseQuery)
.where(...);
```

The generated SQL query from `db.select().from(baseQuery).where(...).toSQL()` shows the following (formatted for readability):

```sql
select
"created_at", "updated_at", "deleted_at", "id", "key", /* ... */,
"id", "key", "title", "id", "title", "type", "is_active", "id", "key", "title"
from
(
select
"table_one"."created_at", "table_one"."updated_at", "table_one"."id", "table_one"."key", /* ... */,
"table_two"."id", "table_two"."key", "table_two"."title",
"table_three"."id", "table_three"."title", "table_three"."type", "table_three"."is_active",
"table_four"."id", "table_four"."key", "table_four"."title"
from
"table_one"
left join "table_two" on "table_two"."id" = "table_one"."table_two_id"
left join "table_three" on "table_three"."id" = "table_one"."table_three_id"
left join "table_four" on "table_four"."id" = "table_one"."table_four_id"
/* ... */
where
"table_one"."deleted_at" is null
and "table_four"."key" = $1
/* ... */
order by
"table_one"."updated_at" desc
) "documents"
where
/* ... */
```

The resulting SQL contains multiple ambiguous column names (`id`, `key`, `title`), leading to the error.

**Proposed Solution**:
If possible, enhance the query builder to automatically alias columns in subqueries when using `.select()` to avoid ambiguity. The alias could follow a pattern like `"table_name.column_name"` or `"table_name$column_name"`, so the result types remain correctly mapped in TypeScript by drizzle.

**Expected SQL Output**:
The inner query would automatically alias columns as follows:

```sql
select
"table_one.created_at", "table_one.updated_at", /* ... */,
"table_two.id", "table_two.title",
"table_three.id", "table_three.title",
/* ... */
from
(
select
"table_one"."created_at" as "table_one.created_at",
"table_one"."updated_at" as "table_one.updated_at",
/* ... */
"table_two"."id" as "table_two.id",
"table_two"."title" as "table_two.title",
/* ... */
from
"table_one"
left join "table_two" on "table_two"."id" = "table_one"."table_two_id"
left join "table_three" on "table_three"."id" = "table_one"."table_three_id"
/* ... */
) "documents"
where
/* ... */
```

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.