annotate demo/more/dbgrid.ur @ 915:5e8b6fa5b48f

Start 'more' demo with dbgrid
author Adam Chlipala <adamc@hcoop.net>
date Tue, 08 Sep 2009 07:48:57 -0400
parents
children 51bc7681c47e
rev   line source
adamc@915 1 con rawMeta = fn t :: Type =>
adamc@915 2 {New : transaction t,
adamc@915 3 Inj : sql_injectable t}
adamc@915 4
adamc@915 5 con colMeta' = fn (row :: {Type}) (t :: Type) =>
adamc@915 6 {Header : string,
adamc@915 7 Project : $row -> transaction t,
adamc@915 8 Update : $row -> t -> transaction ($row),
adamc@915 9 Display : t -> xbody,
adamc@915 10 Edit : t -> xbody,
adamc@915 11 Validate : t -> signal bool}
adamc@915 12
adamc@915 13 con colMeta = fn (row :: {Type}) (global_t :: (Type * Type)) =>
adamc@915 14 {Initialize : transaction global_t.1,
adamc@915 15 Handlers : global_t.1 -> colMeta' row global_t.2}
adamc@915 16
adamc@915 17 structure Direct = struct
adamc@915 18 con meta = fn global_actual_input :: (Type * Type * Type) =>
adamc@915 19 {Initialize : transaction global_actual_input.1,
adamc@915 20 Handlers : global_actual_input.1
adamc@915 21 -> {Display : global_actual_input.3 -> xbody,
adamc@915 22 Edit : global_actual_input.3 -> xbody,
adamc@915 23 Initialize : global_actual_input.2 -> transaction global_actual_input.3,
adamc@915 24 Parse : global_actual_input.3 -> signal (option global_actual_input.2)}}
adamc@915 25
adamc@915 26 con editableState (ts :: (Type * Type * Type)) = (ts.1, ts.3)
adamc@915 27 fun editable [ts] [rest] [nm :: Name] [[nm] ~ rest] name (m : meta ts) : colMeta ([nm = ts.2] ++ rest)
adamc@915 28 (editableState ts) =
adamc@915 29 {Initialize = m.Initialize,
adamc@915 30 Handlers = fn data => {Header = name,
adamc@915 31 Project = fn r => (m.Handlers data).Initialize r.nm,
adamc@915 32 Update = fn r s =>
adamc@915 33 vo <- current ((m.Handlers data).Parse s);
adamc@915 34 return (case vo of
adamc@915 35 None => r
adamc@915 36 | Some v => r -- nm ++ {nm = v}),
adamc@915 37 Display = (m.Handlers data).Display,
adamc@915 38 Edit = (m.Handlers data).Edit,
adamc@915 39 Validate = fn s => vo <- (m.Handlers data).Parse s; return (Option.isSome vo)}}
adamc@915 40
adamc@915 41 con readOnlyState (ts :: (Type * Type * Type)) = (ts.1, ts.3)
adamc@915 42 fun readOnly [ts] [rest] [nm :: Name] [[nm] ~ rest] name (m : meta ts) : colMeta ([nm = ts.2] ++ rest)
adamc@915 43 (readOnlyState ts) =
adamc@915 44 {Initialize = m.Initialize,
adamc@915 45 Handlers = fn data => {Header = name,
adamc@915 46 Project = fn r => (m.Handlers data).Initialize r.nm,
adamc@915 47 Update = fn r _ => return r,
adamc@915 48 Display = (m.Handlers data).Display,
adamc@915 49 Edit = (m.Handlers data).Display,
adamc@915 50 Validate = fn _ => return True}}
adamc@915 51
adamc@915 52 con metaBasic = fn actual_input :: (Type * Type) =>
adamc@915 53 {Display : actual_input.2 -> xbody,
adamc@915 54 Edit : source actual_input.2 -> xbody,
adamc@915 55 Initialize : actual_input.1 -> actual_input.2,
adamc@915 56 Parse : actual_input.2 -> option actual_input.1}
adamc@915 57
adamc@915 58 con basicState = source
adamc@915 59 fun basic [ts ::: (Type * Type)] (m : metaBasic ts) : meta (unit, ts.1, basicState ts.2) =
adamc@915 60 {Initialize = return (),
adamc@915 61 Handlers = fn () => {Display = fn s => <xml><dyn signal={v <- signal s; return (m.Display v)}/></xml>,
adamc@915 62 Edit = m.Edit,
adamc@915 63 Initialize = fn v => source (m.Initialize v),
adamc@915 64 Parse = fn s => v <- signal s; return (m.Parse v)}}
adamc@915 65
adamc@915 66 type intGlobal = unit
adamc@915 67 type intInput = basicState string
adamc@915 68 val int : meta (intGlobal, int, intInput) =
adamc@915 69 basic {Display = fn s => <xml>{[s]}</xml>,
adamc@915 70 Edit = fn s => <xml><ctextbox source={s}/></xml>,
adamc@915 71 Initialize = fn n => show n,
adamc@915 72 Parse = fn v => read v}
adamc@915 73
adamc@915 74 type stringGlobal = unit
adamc@915 75 type stringInput = basicState string
adamc@915 76 val string : meta (stringGlobal, string, stringInput) =
adamc@915 77 basic {Display = fn s => <xml>{[s]}</xml>,
adamc@915 78 Edit = fn s => <xml><ctextbox source={s}/></xml>,
adamc@915 79 Initialize = fn s => s,
adamc@915 80 Parse = fn s => Some s}
adamc@915 81
adamc@915 82 type boolGlobal = unit
adamc@915 83 type boolInput = basicState bool
adamc@915 84 val bool : meta (boolGlobal, bool, boolInput) =
adamc@915 85 basic {Display = fn b => <xml>{[b]}</xml>,
adamc@915 86 Edit = fn s => <xml><ccheckbox source={s}/></xml>,
adamc@915 87 Initialize = fn b => b,
adamc@915 88 Parse = fn b => Some b}
adamc@915 89
adamc@915 90 functor Foreign (M : sig
adamc@915 91 con row :: {Type}
adamc@915 92 con t :: Type
adamc@915 93 val show_t : show t
adamc@915 94 val read_t : read t
adamc@915 95 val eq_t : eq t
adamc@915 96 val inj_t : sql_injectable t
adamc@915 97 con nm :: Name
adamc@915 98 constraint [nm] ~ row
adamc@915 99 table tab : ([nm = t] ++ row)
adamc@915 100 val render : $([nm = t] ++ row) -> string
adamc@915 101 end) = struct
adamc@915 102 open M
adamc@915 103
adamc@915 104 con global = list (t * string)
adamc@915 105 con input = source string * t * $row
adamc@915 106
adamc@915 107 val getChoices = List.mapQuery (SELECT * FROM tab AS T)
adamc@915 108 (fn r => (r.T.nm, render r.T))
adamc@915 109
adamc@915 110 fun getChoice k =
adamc@915 111 r <- oneRow (SELECT T.{{row}} FROM tab AS T WHERE T.{nm} = {[k]});
adamc@915 112 return r.T
adamc@915 113
adamc@915 114 val meta =
adamc@915 115 {Initialize = getChoices,
adamc@915 116 Handlers = fn choices =>
adamc@915 117 {Display = fn (_, k, r) => <xml>{[render ({nm = k} ++ r)]}</xml>,
adamc@915 118 Edit = fn (s, k, _) =>
adamc@915 119 <xml><cselect source={s}>
adamc@915 120 {List.mapX (fn (k', rend) =>
adamc@915 121 <xml><coption value={show k'} selected={k' = k}>{[rend]}</coption>
adamc@915 122 </xml>)
adamc@915 123 choices}
adamc@915 124 </cselect></xml>,
adamc@915 125 Initialize = fn k => s <- source (show k);
adamc@915 126 r <- rpc (getChoice k);
adamc@915 127 return (s, k, r),
adamc@915 128 Parse = fn (s, _, _) => k <- signal s; return (read k)}}
adamc@915 129 end
adamc@915 130 end
adamc@915 131
adamc@915 132 con computedState = (unit, xbody)
adamc@915 133 fun computed [row] [t] (_ : show t) name (f : $row -> t) : colMeta row computedState =
adamc@915 134 {Initialize = return (),
adamc@915 135 Handlers = fn () => {Header = name,
adamc@915 136 Project = fn r => return <xml>{[f r]}</xml>,
adamc@915 137 Update = fn r _ => return r,
adamc@915 138 Display = fn x => x,
adamc@915 139 Edit = fn _ => <xml>...</xml>,
adamc@915 140 Validate = fn _ => return True}}
adamc@915 141 fun computedHtml [row] name (f : $row -> xbody) : colMeta row computedState =
adamc@915 142 {Initialize = return (),
adamc@915 143 Handlers = fn () => {Header = name,
adamc@915 144 Project = fn r => return (f r),
adamc@915 145 Update = fn r _ => return r,
adamc@915 146 Display = fn x => x,
adamc@915 147 Edit = fn _ => <xml>...</xml>,
adamc@915 148 Validate = fn _ => return True}}
adamc@915 149
adamc@915 150 functor Make(M : sig
adamc@915 151 con key :: {Type}
adamc@915 152 con row :: {Type}
adamc@915 153 constraint key ~ row
adamc@915 154 table tab : (key ++ row)
adamc@915 155
adamc@915 156 val raw : $(map rawMeta (key ++ row))
adamc@915 157
adamc@915 158 con cols :: {(Type * Type)}
adamc@915 159 val cols : $(map (colMeta (key ++ row)) cols)
adamc@915 160
adamc@915 161 val keyFolder : folder key
adamc@915 162 val rowFolder : folder row
adamc@915 163 val colsFolder : folder cols
adamc@915 164 end) = struct
adamc@915 165 open Grid.Make(struct
adamc@915 166 val list = query (SELECT * FROM {{M.tab}} AS T) (fn r rs => return (r.T :: rs)) []
adamc@915 167
adamc@915 168 val wholeRow = @Folder.concat ! M.keyFolder M.rowFolder
adamc@915 169
adamc@915 170 fun ensql [env] (r : $(M.key ++ M.row)) =
adamc@915 171 map2 [rawMeta] [id] [sql_exp env [] []]
adamc@915 172 (fn [t] meta v => @sql_inject meta.Inj v)
adamc@915 173 [_] wholeRow M.raw r
adamc@915 174
adamc@915 175 val new =
adamc@915 176 row <- Monad.mapR [rawMeta] [id]
adamc@915 177 (fn [nm :: Name] [t :: Type] meta => meta.New)
adamc@915 178 [_] wholeRow M.raw;
adamc@915 179 dml (insert M.tab (ensql row));
adamc@915 180 return row
adamc@915 181
adamc@915 182 fun selector (r : $(M.key ++ M.row)) : sql_exp [T = M.key ++ M.row] [] [] bool =
adamc@915 183 foldR2 [rawMeta] [id]
adamc@915 184 [fn key => rest :: {Type} -> [rest ~ key] => sql_exp [T = key ++ rest] [] [] bool]
adamc@915 185 (fn [nm :: Name] [t :: Type] [key :: {Type}] [[nm] ~ key]
adamc@915 186 (meta : rawMeta t) (v : t)
adamc@915 187 (exp : rest :: {Type} -> [rest ~ key] => sql_exp [T = key ++ rest] [] [] bool)
adamc@915 188 [rest :: {Type}] [rest ~ [nm = t] ++ key] =>
adamc@915 189 (WHERE T.{nm} = {@sql_inject meta.Inj v} AND {exp [[nm = t] ++ rest] !}))
adamc@915 190 (fn [rest :: {Type}] [rest ~ []] => (WHERE TRUE))
adamc@915 191 [_] M.keyFolder (M.raw --- map rawMeta M.row) (r --- M.row)
adamc@915 192 [_] !
adamc@915 193
adamc@915 194 fun save {Old = row, New = row'} =
adamc@915 195 dml (update [M.key ++ M.row] !
adamc@915 196 (ensql row')
adamc@915 197 M.tab
adamc@915 198 (selector row))
adamc@915 199
adamc@915 200 fun delete row =
adamc@915 201 dml (Basis.delete M.tab (selector row))
adamc@915 202
adamc@915 203 val cols = M.cols
adamc@915 204
adamc@915 205 val folder = M.colsFolder
adamc@915 206 end)
adamc@915 207 end