adam@2031: table images : { Id : int, Content : blob }
adam@2031: table tags : { Id : int, Tag : string }
adam@2031:
adam@2031: datatype mode = Present | Absent
adam@2031: type condition = { Tag : string, Mode : mode }
adam@2031:
adam@2031: type tag_query = sql_query [] [] [] [Id = int]
adam@2031:
adam@2031: fun addCondition (c : condition) (q : tag_query) : tag_query =
adam@2031: case c.Mode of
adam@2031: Present => (SELECT I.Id AS Id
adam@2031: FROM ({{q}}) AS I
adam@2031: JOIN tags ON tags.Id = I.Id AND tags.Tag = {[c.Tag]})
adam@2032: | Absent => (SELECT I.Id AS Id
adam@2032: FROM ({{q}}) AS I
adam@2032: LEFT JOIN tags ON tags.Id = I.Id AND tags.Tag = {[c.Tag]}
adam@2032: WHERE tags.Tag IS NULL)
adam@2031:
adam@2031: fun withConditions (cs : list condition) : tag_query =
adam@2031: List.foldl addCondition (SELECT images.Id AS Id FROM images) cs
adam@2031:
adam@2031: fun main (cs : list condition) : transaction page =
adam@2031: x <- queryX (withConditions cs) (fn r => {[r.Id]});
adam@2031: return
adam@2031: {x}
adam@2031: