question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Joining more than once on the same table produces invalid SQL

See original GitHub issue

First of all - super awesome library!

Just running into a problem relating to joining on the same table more than once in a query. For example, given the following postgresql schema:

CREATE TABLE public.user
(
    user_pk uuid NOT NULL DEFAULT gen_random_uuid(),
    username character varying NOT NULL,
    PRIMARY KEY (user_pk)
);

CREATE TABLE public.message
(
    message_pk uuid NOT NULL DEFAULT gen_random_uuid(),
    from_fk uuid NOT NULL,
    to_fk uuid NOT NULL,
    body character varying NOT NULL,
    CONSTRAINT message__from_fk__fk FOREIGN KEY (from_fk)
        REFERENCES public."user" (user_pk) MATCH SIMPLE
        ON UPDATE CASCADE,
    CONSTRAINT message__to_fk__fk FOREIGN KEY (to_fk)
        REFERENCES public."user" (user_pk) MATCH SIMPLE
        ON UPDATE CASCADE
);

And the following code:

let userTable = table<``public``.message>
let messageTable = table<``public``.message>

let! messages =
    selectTask Dto.HydraReader.Read (Shared queryCtx) {
        for m in messageTable do
            join fromUser in userTable on (m.from_fk = fromUser.user_pk)
            join toUser in userTable on (m.to_fk = toUser.user_pk)
            select (m.body, fromUser.username, toUser.username)
    }

You end up with the following SQL error: table name "user" specified more than once

This is because it gets compiled to the following SQL:

"message"."body", "user"."username", "user"."username" FROM "message" 
INNER JOIN "user" ON ("message"."from_fk" = "user"."user_pk")
INNER JOIN "user" ON ("message"."to_fk" = "user"."user_pk")

SQL hydra can solve this by adding some AS clauses to disambiguate the two different usages of this table. It could either be an arbitrary alias, or it could even use the same name as the variable in the F# query (in this case fromUser and toUser).

It should be running something more like this:

"message"."body", "fromUser"."username", "toUser"."username" FROM "message" 
INNER JOIN "user" AS fromUser ON ("message"."from_fk" = "user"."user_pk")
INNER JOIN "user" AS toUser ON ("message"."to_fk" = "user"."user_pk")

Unfortunately I can’t figure out a workaround, so I am having to drop to a lower level and generating a query directly.

Issue Analytics

  • State:closed
  • Created a year ago
  • Comments:12 (12 by maintainers)

github_iconTop GitHub Comments

1reaction
JordanMarrcommented, Dec 13, 2022

Released in v1.1.0! 🎉

1reaction
JordanMarrcommented, Dec 12, 2022

I’ve been putting this one off for a while because it was so involved to finish. But I doubled down over the weekend, and I think it’s pretty much done now. 😅 I cherrypicked some key pieces from your PR (very well done, btw), but I still had to go through a lot of tedious implementation details. Specifically, the:

  • QuotationVisitor and the
  • [<ReflectedDefinition>] forExpr: FSharp.Quotations.Expr<'T -> QuerySource<'T>> in the For builder methods.

I don’t know how you figured out the [<ReflectedDefinition>] thing; I would have never found that in a million years 😄, but that made the whole thing possible.

Integration tests are all passing, so only some query unit tests still need to be changed to reflect the new table alias qualified columns.

EDIT: All tests passing now! Only exception is that Oracle aggregate functions used in having and orderBy clauses no longer fail because Oracle. But I’m not willing to halt progress for one fringe feature on a provider that is 1/20th the downloads of the others.

I think I will add support for .NET 7 in the generators and then release (probably as v1.1.0).

Read more comments on GitHub >

github_iconTop Results From Across the Web

Why do multiple-table joins produce duplicate rows?
When you have related tables you often have one-to-many or many-to-many relationships. So when you join to TableB each record in TableA many ......
Read more >
How Do You Get Rid of Duplicates in an SQL JOIN?
Stuck with unwanted duplicates from an SQL JOIN? Read this article to understand possible reasons and learn how to fix the query.
Read more >
MySQL JOIN query produces wrong result
Join the two tables and fetch values and show the complaint and complaint's reply as a single result set. But the condition is...
Read more >
Understanding Joins - Knowledge Base - Domo
One of the most common reasons for an “Invalid Query” error and duplicated rows is improperly joined data in SQL, or, essentially, a...
Read more >
How do I use the same table twice in an SQL query?
Joining too many tables can lead to complex queries, slow performance, and difficulty in maintaining the database. A common practice is to limit...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found