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 more locking kind #333

Closed josephsumabat closed 1 year ago

josephsumabat commented 1 year ago

Context: Support FOR UPDATE Of tablename SKIP LOCKED syntax:

Going to look at adding FOR x OF [tables] syntax to the rest of the locking kinds hence making this a draft (Plus updating to use the ( &: ) esqueleto style instead of an existential type

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 :& b) -> p ^. PersonId ==. b ^. BlogPostAuthorId
                EP.forUpdateOf (p :& b) EP.skipLocked
    return p

After submitting your PR: