Skip to content
  • Bruno Carvalho's avatar
    478712e2
    Support UPDATE outer joins on PostgreSQL and SQLite with a self-join transform · 478712e2
    Bruno Carvalho authored
    When an OUTER JOIN references the updated table in the ON clause, the join
    condition cannot be moved to the WHERE clause. Support this case by duplicating
    the updated table into the FROM clause with a perfect self-join on the pk.
    Roughly, transform a hypothetical
    
    UPDATE "products"
    LEFT JOIN "categories" ON "products"."category_id" = "categories"."id"
    ... other joins ...
    WHERE ...
    
    into
    
    UPDATE "products" "alias"
    FROM "products"
    LEFT JOIN "categories" ON "products"."category_id" = "categories"."id"
    ... other joins ...
    WHERE "alias"."id" = "products"."id" AND ...
    
    This reinterprets top-level FULL or RIGHT OUTER JOIN as a LEFT or INNER JOIN.
    This should be ok since we interpret the internal AST as joining with the
    updated table, and rows with no "product" can be ignored in this context.
    
    Unfortunately this introduces an ambiguity when the SET or WHERE references an
    unqualified column of "products". It can be qualified as "products"."column",
    it will reference the introduced table and the problem will be fixed.
    This shouldn't happen with AR generated nodes.
    
    Then PostgreSQL and SQLite use a subquery only when a LIMIT, OFFSET, ORDER BY,
    GROUP BY, or HAVING is present, like MySQL does.
    478712e2
    Support UPDATE outer joins on PostgreSQL and SQLite with a self-join transform
    Bruno Carvalho authored
    When an OUTER JOIN references the updated table in the ON clause, the join
    condition cannot be moved to the WHERE clause. Support this case by duplicating
    the updated table into the FROM clause with a perfect self-join on the pk.
    Roughly, transform a hypothetical
    
    UPDATE "products"
    LEFT JOIN "categories" ON "products"."category_id" = "categories"."id"
    ... other joins ...
    WHERE ...
    
    into
    
    UPDATE "products" "alias"
    FROM "products"
    LEFT JOIN "categories" ON "products"."category_id" = "categories"."id"
    ... other joins ...
    WHERE "alias"."id" = "products"."id" AND ...
    
    This reinterprets top-level FULL or RIGHT OUTER JOIN as a LEFT or INNER JOIN.
    This should be ok since we interpret the internal AST as joining with the
    updated table, and rows with no "product" can be ignored in this context.
    
    Unfortunately this introduces an ambiguity when the SET or WHERE references an
    unqualified column of "products". It can be qualified as "products"."column",
    it will reference the introduced table and the problem will be fixed.
    This shouldn't happen with AR generated nodes.
    
    Then PostgreSQL and SQLite use a subquery only when a LIMIT, OFFSET, ORDER BY,
    GROUP BY, or HAVING is present, like MySQL does.
Loading