Drizzle join in a subquery results in ambiguous columns
This fails with
id ambiguous
error, since the orderedQuestions.survey_question.id
reference in the field selection of the second query generates the sql as 'id'
rather than 'survey_question'.'id'
as it should.
Generates the following ambiguous sql:
11 Replies
This is basically a self join, you need to create an alias to be able to create a self join like this
I’ll also copy from #general - That does mirror SQL behavior - you can’t
select *
from two joined tables that have a shared ID. You have to select with aliases in the select tied to that joinof course - I was expecting drizzle to be smart and use the mapped field names from my subquery in order to select them from the second query
see my follow-up comment:
leads to:
in this case, there is no way in drizzle to disambiguate the id field - since both
orderedQuestions.id
and orderedQuestions.sectionId
both generate "id"
in the select clause
I ended up doing it with
which feels extra silly to drop down to raw sql just to rename a column....
for the first example, if orderedQuestions.survey_question.id
generated "survey_question"."id"
rather than "id"
, it would work fine - this isn't a "select *" problem, this is an ambiguous sql generation problem, I think
for the second example, if the specific field selection generated aliases for the fields, it would work (or if the column reference tracked the table name it came from)What is the result if you delete the
.as("orderedQuestions")
from your follow up comment?doesn't work
you are required to have an
.as()
expression in order to use a query as a selection source
causes an error in the .from(orderedQuestions)
call:
Argument of type 'PgSelect<"survey_question", { id: PgColumn<{ name: "id"; tableName: "survey_question"; dataType: "string"; columnType: "PgUUID"; data: string; driverParam: string; notNull: true; hasDefault: true; enumValues: undefined; baseColumn: never; }, {}, {}>; sectionId: PgColumn<...>; }, "partial", Record<...> & { ...; }>' is not assignable to parameter of type 'SQL<unknown> | PgTable<TableConfig> | Subquery<string, unknown> | PgViewBase<string, boolean, ColumnsSelection>'.
Type 'PgSelect<"survey_question", { id: PgColumn<{ name: "id"; tableName: "survey_question"; dataType: "string"; columnType: "PgUUID"; data: string; driverParam: string; notNull: true; hasDefault: true; enumValues: undefined; baseColumn: never; }, {}, {}>; sectionId: PgColumn<...>; }, "partial", Record<...> & { ...; }>' is missing the following properties from type 'SQL<unknown>': queryChunks, shouldInlineParams, append, toQuery, and 4 more.
I think these are two separate issues - in the first case (the first question I posed), the orderedQuestions.survey_question.id
field should generate "survey_question"."id"
. In the second case, either the field should be renamed as an alias in the subquery itself, or the orderedQuestions.sectionId
field should retain the reference to the source table in the subquery in order to generate "survey_section"."id"
I was expecting drizzle to be smart and use the mapped field names from my subquery in order to select them from the second queryTo be clear: the keys provided to the object passed to select are not used as aliases in SQL, just when the result is mapped back to JS. Though I don't disagree it could be helpful to let drizzle handle more of that itself Though it gets a bit more complicated given the contents of the query are constructed pretty directly from the objects you use, so implicitly aliasing could cause a number of issues
How about like this?
that's what I ended up doing - it just seems silly that drizzle has no automatic handling when using a join as a subquery
(or even that you can't call
.as
on a column, but have to drop down to raw sql first)cc @bloberenober @alexblokh
we need to consider this
@francis4629 @luxaritas @angelelz thanks for suggestions, we will try to improve this part
+ 1
my use case here is joining tables a and b which both have id field, and flatten the results in one table but not the other (so result is something like {id, field1FromA, field2fromA, b: {id, field1fromB}}). if i just execute that query, it correctly creates an object with that shape. But if I create a subquery called c, and then try to use c in a join (using c.id i.e. a.id), then it says ambiguous column because the underlying select selects it twice. This is probably some sort of nice runtime magic to nest objects but ends up messing up the sql downstream.