bitemyapp / esqueleto

New home of Esqueleto, please file issues so we can get things caught up!
BSD 3-Clause "New" or "Revised" License
370 stars 107 forks source link

Support For Update Of Skip Locked #316

Closed josephsumabat closed 1 year ago

josephsumabat commented 2 years ago

Context: Support FOR UPDATE Of tablename SKIP LOCKED syntax:

This allows a the FOR UPDATE SKIP LOCKED behaviour when you have a LEFT OUTER JOIN with a nullable side. Currently you will get the error:

FOR UPDATE cannot be applied to the nullable side of an outer join

The workaround currently using esqueleto is to do seperate queries and then join them manually if you want to select rows for an update while skipping locked rows (or to just do a raw query). I ran into this situation at work.

See: https://www.postgresql.org/docs/current/sql-select.html namely:

FOR { UPDATE | NO KEY UPDATE | SHARE | KEY SHARE } [ OF table_name [, ...] ] [ NOWAIT | SKIP LOCKED ] [...] ]

also documented in MySQL: https://dev.mysql.com/doc/refman/8.0/en/select.html

    [FOR {UPDATE | SHARE}
        [OF tbl_name [, tbl_name] ...]
        [NOWAIT | SKIP LOCKED]
      | LOCK IN SHARE MODE]
    [into_option]

Usage example would be

select $ do
    (p :& bp) <- from $ 
        table @Person
        `innerJoin` table @BlogPost
            `on` do
                \(p :& bp) -> p ^. PersonId ==. b ^. BlogPostAuthorId
    forUpdateOfSkipLocked [LockableEntity p,LockableEntity b]
    return p

After submitting your PR: