adam@6: (** Common metaprogramming patterns for SQL syntax construction *) adam@6: adam@6: val sqexps : env ::: {{Type}} -> fields ::: {Type} -> folder fields -> $(map sql_injectable fields) adam@6: -> $fields -> $(map (sql_exp env [] []) fields) adam@6: (* Convert a record of Ur values into a record of SQL expressions *) adam@6: adam@6: val selector : tn :: Name -> fs ::: {Type} -> ofs ::: {Type} -> [fs ~ ofs] adam@6: => folder fs -> $(map sql_injectable fs) -> $fs adam@6: -> sql_exp [tn = ofs ++ fs] [] [] bool adam@6: (* Build a boolean SQL expression expressing equality of some fields of a table adam@6: * row with a record of Ur values *) adam@13: adam@13: val joiner : tn1 :: Name -> tn2 :: Name -> fs ::: {Type} -> ofs1 ::: {Type} -> ofs2 ::: {Type} adam@13: -> [[tn1] ~ [tn2]] => [fs ~ ofs1] => [fs ~ ofs2] adam@13: => folder fs adam@13: -> sql_exp [tn1 = ofs1 ++ fs, tn2 = ofs2 ++ fs] [] [] bool adam@13: (* Declare equality of same-named columns from two tables. *) adam@15: adam@15: val insertIfMissing : keyCols ::: {Type} -> otherCols ::: {Type} -> otherKeys ::: {{Unit}} adam@15: -> [keyCols ~ otherCols] => [[Pkey] ~ otherKeys] adam@16: => folder keyCols -> $(map sql_injectable keyCols) adam@16: -> folder otherCols -> $(map sql_injectable otherCols) adam@16: -> sql_table (keyCols ++ otherCols) ([Pkey = map (fn _ => ()) keyCols] ++ otherKeys) adam@15: -> $(keyCols ++ otherCols) adam@15: -> transaction bool adam@15: (* Insert a row into an SQL table if its key isn't already present, returning [False] iff the key was already present *) adam@15: adam@15: val deleteByKey : keyCols ::: {Type} -> otherCols ::: {Type} -> otherKeys ::: {{Unit}} adam@15: -> [keyCols ~ otherCols] => [[Pkey] ~ otherKeys] adam@16: => folder keyCols -> $(map sql_injectable keyCols) adam@16: -> sql_table (keyCols ++ otherCols) ([Pkey = map (fn _ => ()) keyCols] ++ otherKeys) adam@16: -> $keyCols adam@15: -> transaction {} adam@15: (* Delete a row from a table by matching its primary key against a given record. *) adam@19: adam@19: val lookup : keyCols ::: {Type} -> otherCols ::: {Type} -> otherKeys ::: {{Unit}} adam@19: -> [keyCols ~ otherCols] => [[Pkey] ~ otherKeys] adam@19: => folder keyCols -> $(map sql_injectable keyCols) adam@19: -> sql_table (keyCols ++ otherCols) ([Pkey = map (fn _ => ()) keyCols] ++ otherKeys) adam@19: -> $keyCols -> transaction (option $otherCols) adam@19: (* Get the further columns associated with a table key. *) adam@26: adam@26: val listify : lead :: Name -> cols ::: {Type} -> rest ::: {{Type}} -> [[lead] ~ rest] adam@26: => folder cols -> $(map eq cols) adam@26: -> sql_query [] [] ([lead = cols] ++ rest) [] adam@26: -> transaction (list ($cols * list $(map (fn ts => $ts) rest))) adam@26: (* Shrink a set of table rows by summarizing into lists, keyed off of a lead table *)