Mercurial > urweb
comparison demo/crud.ur @ 1302:d008c4c43a0a
Flex kinds for type-level tuples; ::_ notation
author | Adam Chlipala <adam@chlipala.net> |
---|---|
date | Sun, 10 Oct 2010 13:07:38 -0400 |
parents | e8d68fd8ed4b |
children | c7b9a33c26c8 |
comparison
equal
deleted
inserted
replaced
1301:4359e185d3af | 1302:d008c4c43a0a |
---|---|
3 Show : db -> xbody, | 3 Show : db -> xbody, |
4 Widget : nm :: Name -> xml form [] [nm = widget], | 4 Widget : nm :: Name -> xml form [] [nm = widget], |
5 WidgetPopulated : nm :: Name -> db -> xml form [] [nm = widget], | 5 WidgetPopulated : nm :: Name -> db -> xml form [] [nm = widget], |
6 Parse : widget -> db, | 6 Parse : widget -> db, |
7 Inject : sql_injectable db} | 7 Inject : sql_injectable db} |
8 con colsMeta = fn cols :: {(Type * Type)} => $(map colMeta cols) | 8 con colsMeta = fn cols => $(map colMeta cols) |
9 | 9 |
10 fun default [t] (sh : show t) (rd : read t) (inj : sql_injectable t) | 10 fun default [t] (sh : show t) (rd : read t) (inj : sql_injectable t) |
11 name : colMeta (t, string) = | 11 name : colMeta (t, string) = |
12 {Nam = name, | 12 {Nam = name, |
13 Show = txt, | 13 Show = txt, |
49 rows <- queryX (SELECT * FROM tab AS T) | 49 rows <- queryX (SELECT * FROM tab AS T) |
50 (fn (fs : {T : $([Id = int] ++ map fst M.cols)}) => <xml> | 50 (fn (fs : {T : $([Id = int] ++ map fst M.cols)}) => <xml> |
51 <tr> | 51 <tr> |
52 <td>{[fs.T.Id]}</td> | 52 <td>{[fs.T.Id]}</td> |
53 {@mapX2 [fst] [colMeta] [tr] | 53 {@mapX2 [fst] [colMeta] [tr] |
54 (fn [nm :: Name] [t :: (Type * Type)] [rest :: {(Type * Type)}] | 54 (fn [nm :: Name] [t ::_] [rest ::_] [[nm] ~ rest] v col => <xml> |
55 [[nm] ~ rest] v col => <xml> | 55 <td>{col.Show v}</td> |
56 <td>{col.Show v}</td> | 56 </xml>) |
57 </xml>) | |
58 M.fl (fs.T -- #Id) M.cols} | 57 M.fl (fs.T -- #Id) M.cols} |
59 <td> | 58 <td> |
60 <a link={upd fs.T.Id}>[Update]</a> | 59 <a link={upd fs.T.Id}>[Update]</a> |
61 <a link={confirm fs.T.Id}>[Delete]</a> | 60 <a link={confirm fs.T.Id}>[Delete]</a> |
62 </td> | 61 </td> |
65 return <xml> | 64 return <xml> |
66 <table border={1}> | 65 <table border={1}> |
67 <tr> | 66 <tr> |
68 <th>ID</th> | 67 <th>ID</th> |
69 {@mapX [colMeta] [tr] | 68 {@mapX [colMeta] [tr] |
70 (fn [nm :: Name] [t :: (Type * Type)] [rest :: {(Type * Type)}] | 69 (fn [nm :: Name] [t ::_] [rest ::_] [[nm] ~ rest] col => <xml> |
71 [[nm] ~ rest] col => <xml> | 70 <th>{cdata col.Nam}</th> |
72 <th>{cdata col.Nam}</th> | 71 </xml>) |
73 </xml>) | |
74 M.fl M.cols} | 72 M.fl M.cols} |
75 </tr> | 73 </tr> |
76 {rows} | 74 {rows} |
77 </table> | 75 </table> |
78 | 76 |
79 <br/><hr/><br/> | 77 <br/><hr/><br/> |
80 | 78 |
81 <form> | 79 <form> |
82 {@foldR [colMeta] [fn cols :: {(Type * Type)} => xml form [] (map snd cols)] | 80 {@foldR [colMeta] [fn cols => xml form [] (map snd cols)] |
83 (fn [nm :: Name] [t :: (Type * Type)] [rest :: {(Type * Type)}] | 81 (fn [nm :: Name] [t ::_] [rest ::_] [[nm] ~ rest] (col : colMeta t) (acc : xml form [] (map snd rest)) => <xml> |
84 [[nm] ~ rest] (col : colMeta t) (acc : xml form [] (map snd rest)) => <xml> | 82 <li> {cdata col.Nam}: {col.Widget [nm]}</li> |
85 <li> {cdata col.Nam}: {col.Widget [nm]}</li> | 83 {useMore acc} |
86 {useMore acc} | 84 </xml>) |
87 </xml>) | |
88 <xml/> | 85 <xml/> |
89 M.fl M.cols} | 86 M.fl M.cols} |
90 | 87 |
91 <submit action={create}/> | 88 <submit action={create}/> |
92 </form> | 89 </form> |
94 | 91 |
95 and create (inputs : $(map snd M.cols)) = | 92 and create (inputs : $(map snd M.cols)) = |
96 id <- nextval seq; | 93 id <- nextval seq; |
97 dml (insert tab | 94 dml (insert tab |
98 (@foldR2 [snd] [colMeta] | 95 (@foldR2 [snd] [colMeta] |
99 [fn cols => $(map (fn t :: (Type * Type) => | 96 [fn cols => $(map (fn t => sql_exp [] [] [] t.1) cols)] |
100 sql_exp [] [] [] t.1) cols)] | 97 (fn [nm :: Name] [t ::_] [rest ::_] [[nm] ~ rest] => |
101 (fn [nm :: Name] [t :: (Type * Type)] [rest :: {(Type * Type)}] | |
102 [[nm] ~ rest] => | |
103 fn input col acc => acc ++ {nm = @sql_inject col.Inject (col.Parse input)}) | 98 fn input col acc => acc ++ {nm = @sql_inject col.Inject (col.Parse input)}) |
104 {} M.fl inputs M.cols | 99 {} M.fl inputs M.cols |
105 ++ {Id = (SQL {[id]})})); | 100 ++ {Id = (SQL {[id]})})); |
106 ls <- list (); | 101 ls <- list (); |
107 return <xml><body> | 102 return <xml><body> |
113 and upd (id : int) = | 108 and upd (id : int) = |
114 let | 109 let |
115 fun save (inputs : $(map snd M.cols)) = | 110 fun save (inputs : $(map snd M.cols)) = |
116 dml (update [map fst M.cols] | 111 dml (update [map fst M.cols] |
117 (@foldR2 [snd] [colMeta] | 112 (@foldR2 [snd] [colMeta] |
118 [fn cols => $(map (fn t :: (Type * Type) => | 113 [fn cols => $(map (fn t => sql_exp [T = [Id = int] ++ map fst M.cols] [] [] t.1) cols)] |
119 sql_exp [T = [Id = int] | 114 (fn [nm :: Name] [t ::_] [rest ::_] [[nm] ~ rest] => |
120 ++ map fst M.cols] | |
121 [] [] t.1) cols)] | |
122 (fn [nm :: Name] [t :: (Type * Type)] [rest :: {(Type * Type)}] | |
123 [[nm] ~ rest] => | |
124 fn input col acc => acc ++ {nm = | 115 fn input col acc => acc ++ {nm = |
125 @sql_inject col.Inject (col.Parse input)}) | 116 @sql_inject col.Inject (col.Parse input)}) |
126 {} M.fl inputs M.cols) | 117 {} M.fl inputs M.cols) |
127 tab (WHERE T.Id = {[id]})); | 118 tab (WHERE T.Id = {[id]})); |
128 ls <- list (); | 119 ls <- list (); |
134 in | 125 in |
135 fso <- oneOrNoRows (SELECT tab.{{map fst M.cols}} FROM tab WHERE tab.Id = {[id]}); | 126 fso <- oneOrNoRows (SELECT tab.{{map fst M.cols}} FROM tab WHERE tab.Id = {[id]}); |
136 case fso : (Basis.option {Tab : $(map fst M.cols)}) of | 127 case fso : (Basis.option {Tab : $(map fst M.cols)}) of |
137 None => return <xml><body>Not found!</body></xml> | 128 None => return <xml><body>Not found!</body></xml> |
138 | Some fs => return <xml><body><form> | 129 | Some fs => return <xml><body><form> |
139 {@foldR2 [fst] [colMeta] [fn cols :: {(Type * Type)} => xml form [] (map snd cols)] | 130 {@foldR2 [fst] [colMeta] [fn cols => xml form [] (map snd cols)] |
140 (fn [nm :: Name] [t :: (Type * Type)] [rest :: {(Type * Type)}] | 131 (fn [nm :: Name] [t ::_] [rest ::_] [[nm] ~ rest] (v : t.1) (col : colMeta t) |
141 [[nm] ~ rest] (v : t.1) (col : colMeta t) | |
142 (acc : xml form [] (map snd rest)) => | 132 (acc : xml form [] (map snd rest)) => |
143 <xml> | 133 <xml> |
144 <li> {cdata col.Nam}: {col.WidgetPopulated [nm] v}</li> | 134 <li> {cdata col.Nam}: {col.WidgetPopulated [nm] v}</li> |
145 {useMore acc} | 135 {useMore acc} |
146 </xml>) | 136 </xml>) |