adamc@469: functor Make(M : sig
adamc@469:                  type key
adamc@469:                  con id :: Name
adamc@469:                  con parent :: Name
adamc@469:                  con cols :: {Type}
adamc@469:                  constraint [id] ~ [parent]
adamc@469:                  constraint [id, parent] ~ cols
adamc@469: 
adamc@723:                  val key_inj : sql_injectable_prim key
adamc@469: 
adamc@706:                  table tab : ([id = key, parent = option key] ++ cols)
adamc@469:              end) = struct
adamc@469: 
adamc@469:     open M
adamc@469: 
adamc@469:     fun tree (f : $([id = key, parent = option key] ++ cols) -> xbody)
adamc@469:              (root : option M.key) =
adamc@469:         let
adamc@469:             fun recurse (root : option key) =
adamc@471:                 queryX' (SELECT * FROM tab WHERE {eqNullable' (SQL tab.{parent}) root})
adamc@469:                         (fn r =>
adamc@469:                             children <- recurse (Some r.Tab.id);
adamc@469:                             return <xml>
adamc@469:                               <li> {f r.Tab}</li>
adamc@469:                               
adamc@469:                               <ul>
adamc@469:                                 {children}
adamc@469:                               </ul>
adamc@469:                             </xml>)
adamc@469:         in
adamc@469:             recurse root
adamc@469:         end
adamc@469: 
adamc@469: end