comparison src/iflow.sml @ 1212:fc33072c4d33

Replaced Select predicate with special-case handling for one-or-no-rows queries
author Adam Chlipala <adamc@hcoop.net>
date Tue, 06 Apr 2010 15:17:28 -0400
parents 1d4d65245dd3
children e791d93d4616
comparison
equal deleted inserted replaced
1211:1d4d65245dd3 1212:fc33072c4d33
80 | False 80 | False
81 | Unknown 81 | Unknown
82 | And of prop * prop 82 | And of prop * prop
83 | Or of prop * prop 83 | Or of prop * prop
84 | Reln of reln * exp list 84 | Reln of reln * exp list
85 | Select of int * lvar * lvar * prop * exp 85 | Cond of exp * prop
86 86
87 local 87 local
88 open Print 88 open Print
89 val string = PD.string 89 val string = PD.string
90 in 90 in
160 space, 160 space,
161 string "(", 161 string "(",
162 p_prop p2, 162 p_prop p2,
163 string ")"] 163 string ")"]
164 | Reln (r, es) => p_reln r es 164 | Reln (r, es) => p_reln r es
165 | Select (n1, n2, n3, p, e) => box [string ("select(x" ^ Int.toString n1 165 | Cond (e, p) => box [string "(",
166 ^ ",X" ^ Int.toString n2 166 p_exp e,
167 ^ ",X" ^ Int.toString n3 167 space,
168 ^ "){"), 168 string "==",
169 p_prop p, 169 space,
170 string "}{", 170 p_prop p,
171 p_exp e, 171 string ")"]
172 string "}"]
173 172
174 end 173 end
175 174
176 local 175 local
177 val count = ref 1 176 val count = ref 1
182 in 181 in
183 count := n + 1; 182 count := n + 1;
184 n 183 n
185 end 184 end
186 end 185 end
187
188 fun subExp (v, lv) =
189 let
190 fun sub e =
191 case e of
192 Const _ => e
193 | Var v' => if v' = v then Lvar lv else e
194 | Lvar _ => e
195 | Func (f, es) => Func (f, map sub es)
196 | Recd xes => Recd (map (fn (x, e) => (x, sub e)) xes)
197 | Proj (e, s) => Proj (sub e, s)
198 | Finish => Finish
199 in
200 sub
201 end
202
203 fun subProp (v, lv) =
204 let
205 fun sub p =
206 case p of
207 True => p
208 | False => p
209 | Unknown => p
210 | And (p1, p2) => And (sub p1, sub p2)
211 | Or (p1, p2) => Or (sub p1, sub p2)
212 | Reln (r, es) => Reln (r, map (subExp (v, lv)) es)
213 | Select (v1, lv1, lv2, p, e) => Select (v1, lv1, lv2, sub p, subExp (v, lv) e)
214 in
215 sub
216 end
217 186
218 fun isKnown e = 187 fun isKnown e =
219 case e of 188 case e of
220 Const _ => true 189 Const _ => true
221 | Func (_, es) => List.all isKnown es 190 | Func (_, es) => List.all isKnown es
278 Finish 247 Finish
279 else 248 else
280 Proj (e', s)) 249 Proj (e', s))
281 | Finish => Finish 250 | Finish => Finish
282 251
252 datatype atom =
253 AReln of reln * exp list
254 | ACond of exp * prop
255
256 fun p_atom a =
257 p_prop (case a of
258 AReln x => Reln x
259 | ACond x => Cond x)
260
283 fun decomp fals or = 261 fun decomp fals or =
284 let 262 let
285 fun decomp p k = 263 fun decomp p k =
286 case p of 264 case p of
287 True => k [] 265 True => k []
291 decomp p1 (fn ps1 => 269 decomp p1 (fn ps1 =>
292 decomp p2 (fn ps2 => 270 decomp p2 (fn ps2 =>
293 k (ps1 @ ps2))) 271 k (ps1 @ ps2)))
294 | Or (p1, p2) => 272 | Or (p1, p2) =>
295 or (decomp p1 k, fn () => decomp p2 k) 273 or (decomp p1 k, fn () => decomp p2 k)
296 | Reln x => k [x] 274 | Reln x => k [AReln x]
297 | Select _ => k [] 275 | Cond x => k [ACond x]
298 in 276 in
299 decomp 277 decomp
300 end 278 end
301 279
302 fun lvarIn lv = 280 fun lvarIn lv =
308 | Lvar lv' => lv' = lv 286 | Lvar lv' => lv' = lv
309 | Func (_, es) => List.exists lvi es 287 | Func (_, es) => List.exists lvi es
310 | Recd xes => List.exists (lvi o #2) xes 288 | Recd xes => List.exists (lvi o #2) xes
311 | Proj (e, _) => lvi e 289 | Proj (e, _) => lvi e
312 | Finish => false 290 | Finish => false
291 in
292 lvi
293 end
294
295 fun lvarInP lv =
296 let
297 fun lvi p =
298 case p of
299 True => false
300 | False => false
301 | Unknown => true
302 | And (p1, p2) => lvi p1 orelse lvi p2
303 | Or (p1, p2) => lvi p1 orelse lvi p2
304 | Reln (_, es) => List.exists (lvarIn lv) es
305 | Cond (e, p) => lvarIn lv e orelse lvi p
306 in
307 lvi
308 end
309
310 fun varIn lv =
311 let
312 fun lvi e =
313 case e of
314 Const _ => false
315 | Lvar _ => false
316 | Var lv' => lv' = lv
317 | Func (_, es) => List.exists lvi es
318 | Recd xes => List.exists (lvi o #2) xes
319 | Proj (e, _) => lvi e
320 | Finish => false
321 in
322 lvi
323 end
324
325 fun varInP lv =
326 let
327 fun lvi p =
328 case p of
329 True => false
330 | False => false
331 | Unknown => false
332 | And (p1, p2) => lvi p1 orelse lvi p2
333 | Or (p1, p2) => lvi p1 orelse lvi p2
334 | Reln (_, es) => List.exists (varIn lv) es
335 | Cond (e, p) => varIn lv e orelse lvi p
313 in 336 in
314 lvi 337 lvi
315 end 338 end
316 339
317 fun eq' (e1, e2) = 340 fun eq' (e1, e2) =
397 fun lookup (t, e) = 420 fun lookup (t, e) =
398 case List.find (fn (e', _) => eq (e', e)) t of 421 case List.find (fn (e', _) => eq (e', e)) t of
399 NONE => e 422 NONE => e
400 | SOME (_, e2) => lookup (t, e2) 423 | SOME (_, e2) => lookup (t, e2)
401 424
402 fun assert (t, e1, e2) =
403 let
404 val r1 = lookup (t, e1)
405 val r2 = lookup (t, e2)
406 in
407 if eq (r1, r2) then
408 t
409 else
410 (r1, r2) :: t
411 end
412
413 open Print
414
415 fun query (t, e1, e2) =
416 (if !debug then
417 prefaces "CC query" [("e1", p_exp (simplify e1)),
418 ("e2", p_exp (simplify e2)),
419 ("t", p_list (fn (e1, e2) => box [p_exp (simplify e1),
420 space,
421 PD.string "->",
422 space,
423 p_exp (simplify e2)]) t)]
424 else
425 ();
426 eq (lookup (t, e1), lookup (t, e2)))
427
428 fun allPeers (t, e) = 425 fun allPeers (t, e) =
429 let 426 let
430 val r = lookup (t, e) 427 val r = lookup (t, e)
431 in 428 in
432 r :: List.mapPartial (fn (e1, e2) => 429 r :: List.mapPartial (fn (e1, e2) =>
437 SOME e1 434 SOME e1
438 else 435 else
439 NONE 436 NONE
440 end) t 437 end) t
441 end 438 end
439
440 fun assert (t, e1, e2) =
441 let
442 val r1 = lookup (t, e1)
443 val r2 = lookup (t, e2)
444
445 fun doUn (t', e1, e2) =
446 case e2 of
447 Func (f, [e]) =>
448 if String.isPrefix "un" f then
449 let
450 val f' = String.extract (f, 2, NONE)
451 in
452 foldl (fn (e', t') =>
453 case e' of
454 Func (f'', [e'']) =>
455 if f'' = f' then
456 (lookup (t', e1), e'') :: t'
457 else
458 t'
459 | _ => t') t' (allPeers (t, e))
460 end
461 else
462 t'
463 | _ => t'
464 in
465 if eq (r1, r2) then
466 t
467 else
468 doUn (doUn ((r1, r2) :: t, e1, e2), e2, e1)
469 end
470
471 open Print
472
473 fun query (t, e1, e2) =
474 ((*prefaces "CC query" [("e1", p_exp (simplify e1)),
475 ("e2", p_exp (simplify e2)),
476 ("t", p_list (fn (e1, e2) => box [p_exp (simplify e1),
477 space,
478 PD.string "->",
479 space,
480 p_exp (simplify e2)]) t)];*)
481 eq (lookup (t, e1), lookup (t, e2)))
442 482
443 end 483 end
444 484
445 fun rimp cc ((r1, es1), (r2, es2)) = 485 fun rimp cc ((r1, es1), (r2, es2)) =
446 case (r1, r2) of 486 case (r1, r2) of
502 decomp false (fn (e1, e2) => e1 orelse e2 ()) p2 542 decomp false (fn (e1, e2) => e1 orelse e2 ()) p2
503 (fn goals => 543 (fn goals =>
504 let 544 let
505 val cc = foldl (fn (p, cc) => 545 val cc = foldl (fn (p, cc) =>
506 case p of 546 case p of
507 (Eq, [e1, e2]) => Cc.assert (cc, e1, e2) 547 AReln (Eq, [e1, e2]) => Cc.assert (cc, e1, e2)
508 | _ => cc) Cc.empty hyps 548 | _ => cc) Cc.empty hyps
509 549
510 fun gls goals onFail = 550 fun gls goals onFail =
511 case goals of 551 case goals of
512 [] => true 552 [] => true
513 | g :: goals => 553 | ACond _ :: _ => false
554 | AReln g :: goals =>
514 case (doKnown, g) of 555 case (doKnown, g) of
515 (false, (Known, _)) => gls goals onFail 556 (false, (Known, _)) => gls goals onFail
516 | _ => 557 | _ =>
517 let 558 let
518 fun hps hyps = 559 fun hps hyps =
519 case hyps of 560 case hyps of
520 [] => onFail () 561 [] => onFail ()
521 | h :: hyps => 562 | ACond _ :: hyps => hps hyps
563 | AReln h :: hyps =>
522 let 564 let
523 val saved = save () 565 val saved = save ()
524 in 566 in
525 if rimp cc (h, g) then 567 if rimp cc (h, g) then
526 let 568 let
538 (Eq, [e1, e2]) => Cc.query (cc, e1, e2) 580 (Eq, [e1, e2]) => Cc.query (cc, e1, e2)
539 | _ => false) 581 | _ => false)
540 orelse hps hyps 582 orelse hps hyps
541 end 583 end
542 in 584 in
543 if List.exists (fn (DtCon c1, [e]) => 585 if List.exists (fn AReln (DtCon c1, [e]) =>
544 List.exists (fn (DtCon c2, [e']) => 586 List.exists (fn AReln (DtCon c2, [e']) =>
545 c1 <> c2 andalso 587 c1 <> c2 andalso
546 Cc.query (cc, e, e') 588 Cc.query (cc, e, e')
547 | _ => false) hyps 589 | _ => false) hyps
548 orelse List.exists (fn Func (c2, []) => c1 <> c2 590 orelse List.exists (fn Func (c2, []) => c1 <> c2
549 | Finish => true 591 | Finish => true
551 (Cc.allPeers (cc, e)) 593 (Cc.allPeers (cc, e))
552 | _ => false) hyps 594 | _ => false) hyps
553 orelse gls goals (fn () => false) then 595 orelse gls goals (fn () => false) then
554 true 596 true
555 else 597 else
556 (Print.prefaces "Can't prove" 598 ((*Print.prefaces "Can't prove"
557 [("hyps", Print.p_list (fn x => p_prop (Reln x)) hyps), 599 [("hyps", Print.p_list p_atom hyps),
558 ("goals", Print.p_list (fn x => p_prop (Reln x)) goals)]; 600 ("goals", Print.p_list p_atom goals)];*)
559 false) 601 false)
560 end)) 602 end))
561 in 603 in
562 reset (); 604 reset ();
563 doOne false; 605 doOne false;
566 608
567 fun patCon pc = 609 fun patCon pc =
568 case pc of 610 case pc of
569 PConVar n => "C" ^ Int.toString n 611 PConVar n => "C" ^ Int.toString n
570 | PConFfi {mod = m, datatyp = d, con = c, ...} => m ^ "." ^ d ^ "." ^ c 612 | PConFfi {mod = m, datatyp = d, con = c, ...} => m ^ "." ^ d ^ "." ^ c
571
572
573 613
574 datatype chunk = 614 datatype chunk =
575 String of string 615 String of string
576 | Exp of Mono.exp 616 | Exp of Mono.exp
577 617
869 ls 909 ls
870 else 910 else
871 x :: ls 911 x :: ls
872 end 912 end
873 913
914 datatype queryMode =
915 SomeCol of exp
916 | AllCols of exp
917
874 fun queryProp env rv oe e = 918 fun queryProp env rv oe e =
875 case parse query e of 919 case parse query e of
876 NONE => (print ("Warning: Information flow checker can't parse SQL query at " 920 NONE => (print ("Warning: Information flow checker can't parse SQL query at "
877 ^ ErrorMsg.spanToString (#2 e) ^ "\n"); 921 ^ ErrorMsg.spanToString (#2 e) ^ "\n");
878 (Unknown, [])) 922 (Unknown, []))
897 foldl (fn ((t, v), p) => 941 foldl (fn ((t, v), p) =>
898 And (p, 942 And (p,
899 Reln (Sql t, 943 Reln (Sql t,
900 [Recd (foldl (fn ((v', f), fs) => 944 [Recd (foldl (fn ((v', f), fs) =>
901 if v' = v then 945 if v' = v then
902 (f, Proj (Proj (Lvar rv, v), f)) :: fs 946 (f, Proj (Proj (rv, v), f)) :: fs
903 else 947 else
904 fs) [] allUsed)]))) 948 fs) [] allUsed)])))
905 True (#From r) 949 True (#From r)
906 950
907 fun expIn e = 951 fun expIn e =
908 case e of 952 case e of
909 SqConst p => inl (Const p) 953 SqConst p => inl (Const p)
910 | Field (v, f) => inl (Proj (Proj (Lvar rv, v), f)) 954 | Field (v, f) => inl (Proj (Proj (rv, v), f))
911 | Binop (bo, e1, e2) => 955 | Binop (bo, e1, e2) =>
912 inr (case (bo, expIn e1, expIn e2) of 956 inr (case (bo, expIn e1, expIn e2) of
913 (Exps f, inl e1, inl e2) => f (e1, e2) 957 (Exps f, inl e1, inl e2) => f (e1, e2)
914 | (Props f, inr p1, inr p2) => f (p1, p2) 958 | (Props f, inr p1, inr p2) => f (p1, p2)
915 | _ => Unknown) 959 | _ => Unknown)
929 end 973 end
930 | SqFunc (f, e) => 974 | SqFunc (f, e) =>
931 inl (case expIn e of 975 inl (case expIn e of
932 inl e => Func (f, [e]) 976 inl e => Func (f, [e])
933 | _ => raise Fail ("Iflow: non-expresion passed to function " ^ f)) 977 | _ => raise Fail ("Iflow: non-expresion passed to function " ^ f))
934 | Count => inl (Func ("COUNT", [])) 978 | Count => inl (Proj (rv, "$COUNT"))
935 979
936 val p = case #Where r of 980 val p = case #Where r of
937 NONE => p 981 NONE => p
938 | SOME e => 982 | SOME e =>
939 case expIn e of 983 case expIn e of
940 inr p' => And (p, p') 984 inr p' => And (p, p')
941 | _ => p 985 | _ => p
942 in 986 in
943 (case oe of 987 (And (p, case oe of
944 NONE => p 988 SomeCol oe =>
945 | SOME oe => 989 foldl (fn (si, p) =>
946 And (p, foldl (fn (si, p) =>
947 let 990 let
948 val p' = case si of 991 val p' = case si of
949 SqField (v, f) => Reln (Eq, [oe, Proj (Proj (Lvar rv, v), f)]) 992 SqField (v, f) => Reln (Eq, [oe, Proj (Proj (rv, v), f)])
950 | SqExp (e, f) => 993 | SqExp (e, f) =>
951 case expIn e of 994 case expIn e of
952 inr _ => Unknown 995 inr _ => Unknown
953 | inl e => Reln (Eq, [oe, e]) 996 | inl e => Reln (Eq, [oe, e])
954 in 997 in
955 Or (p, p') 998 Or (p, p')
956 end) 999 end)
957 False (#Select r)), 1000 False (#Select r)
1001 | AllCols oe =>
1002 foldl (fn (si, p) =>
1003 let
1004 val p' = case si of
1005 SqField (v, f) => Reln (Eq, [Proj (Proj (oe, v), f),
1006 Proj (Proj (rv, v), f)])
1007 | SqExp (e, f) =>
1008 case expIn e of
1009 inr p => Cond (Proj (oe, f), p)
1010 | inl e => Reln (Eq, [Proj (oe, f), e])
1011 in
1012 And (p, p')
1013 end)
1014 True (#Select r)),
958 1015
959 case #Where r of 1016 case #Where r of
960 NONE => [] 1017 NONE => []
961 | SOME e => map (fn (v, f) => Proj (Proj (Lvar rv, v), f)) (usedFields e)) 1018 | SOME e => map (fn (v, f) => Proj (Proj (rv, v), f)) (usedFields e))
962 end 1019 end
963 1020
964 fun evalPat env e (pt, _) = 1021 fun evalPat env e (pt, _) =
965 case pt of 1022 case pt of
966 PWild => (env, True) 1023 PWild => (env, True)
994 | (False, False) => true 1051 | (False, False) => true
995 | (Unknown, Unknown) => true 1052 | (Unknown, Unknown) => true
996 | (And (x1, y1), And (x2, y2)) => peq (x1, x2) andalso peq (y1, y2) 1053 | (And (x1, y1), And (x2, y2)) => peq (x1, x2) andalso peq (y1, y2)
997 | (Or (x1, y1), Or (x2, y2)) => peq (x1, x2) andalso peq (y1, y2) 1054 | (Or (x1, y1), Or (x2, y2)) => peq (x1, x2) andalso peq (y1, y2)
998 | (Reln (r1, es1), Reln (r2, es2)) => r1 = r2 andalso ListPair.allEq eeq (es1, es2) 1055 | (Reln (r1, es1), Reln (r2, es2)) => r1 = r2 andalso ListPair.allEq eeq (es1, es2)
999 | (Select (n1, n2, n3, p1, e1), Select (n1', n2', n3', p2, e2)) => 1056 | (Cond (e1, p1), Cond (e2, p2)) => eeq (e1, e2) andalso peq (p1, p2)
1000 n1 = n1' andalso n2 = n2' andalso n3 = n3'
1001 andalso peq (p1, p2) andalso eeq (e1, e2)
1002 | _ => false 1057 | _ => false
1003 1058
1004 fun removeRedundant p1 = 1059 fun removeRedundant p1 =
1005 let 1060 let
1006 fun rr p2 = 1061 fun rr p2 =
1008 True 1063 True
1009 else 1064 else
1010 case p2 of 1065 case p2 of
1011 And (x, y) => And (rr x, rr y) 1066 And (x, y) => And (rr x, rr y)
1012 | Or (x, y) => Or (rr x, rr y) 1067 | Or (x, y) => Or (rr x, rr y)
1013 | Select (n1, n2, n3, p, e) => Select (n1, n2, n3, rr p, e)
1014 | _ => p2 1068 | _ => p2
1015 in 1069 in
1016 rr 1070 rr
1017 end 1071 end
1018 1072
1162 let 1216 let
1163 val (_, st) = evalExp env (q, st) 1217 val (_, st) = evalExp env (q, st)
1164 val (i, st) = evalExp env (i, st) 1218 val (i, st) = evalExp env (i, st)
1165 1219
1166 val r = #1 st 1220 val r = #1 st
1167 val acc = #1 st + 1 1221 val rv = #1 st + 1
1168 val st' = (#1 st + 2, #2 st, #3 st) 1222 val acc = #1 st + 2
1223 val st' = (#1 st + 3, #2 st, #3 st)
1169 1224
1170 val (b, st') = evalExp (Var acc :: Var r :: env) (b, st') 1225 val (b, st') = evalExp (Var acc :: Var r :: env) (b, st')
1171 1226
1172 val r' = newLvar () 1227 val (qp, used) = queryProp env (Var rv) (AllCols (Var r)) q
1173 val acc' = newLvar () 1228
1174 val (qp, used) = queryProp env r' NONE q 1229 val p' = And (qp, #2 st')
1175 1230
1176 val doSubExp = subExp (r, r') o subExp (acc, acc') 1231 val (nvs, p, res) = if varInP acc (#2 st') then
1177 val doSubProp = subProp (r, r') o subProp (acc, acc') 1232 (#1 st + 1, #2 st, Var r)
1178 1233 else
1179 val p = doSubProp (#2 st') 1234 let
1180 val p' = And (p, qp) 1235 val out = #1 st'
1181 val p = Select (r, r', acc', p', doSubExp b) 1236
1182 1237 val p = Or (Reln (Eq, [Var out, i]),
1183 val sent = map (fn (loc, e, p) => (loc, 1238 And (Reln (Eq, [Var out, b]),
1184 doSubExp e, 1239 And (Reln (Gt, [Proj (Var rv, "$COUNT"),
1185 And (qp, doSubProp p))) (#3 st') 1240 Const (Prim.Int 0)]),
1241 p')))
1242 in
1243 (out + 1, p, Var out)
1244 end
1245
1246 val sent = map (fn (loc, e, p) => (loc, e, And (qp, p))) (#3 st')
1186 val sent = map (fn e => (loc, e, p')) used @ sent 1247 val sent = map (fn e => (loc, e, p')) used @ sent
1187 in 1248 in
1188 (Var r, (#1 st + 1, And (#2 st, p), sent)) 1249 (res, (nvs, p, sent))
1189 end 1250 end
1190 | EDml _ => default () 1251 | EDml _ => default ()
1191 | ENextval _ => default () 1252 | ENextval _ => default ()
1192 | ESetval _ => default () 1253 | ESetval _ => default ()
1193 1254
1229 val (e, (_, p, sent)) = evalExp env (e, (nv, p, [])) 1290 val (e, (_, p, sent)) = evalExp env (e, (nv, p, []))
1230 in 1291 in
1231 (sent @ vals, pols) 1292 (sent @ vals, pols)
1232 end 1293 end
1233 1294
1234 | DPolicy (PolQuery e) => (vals, #1 (queryProp [] 0 (SOME (Var 0)) e) :: pols) 1295 | DPolicy (PolQuery e) => (vals, #1 (queryProp [] (Lvar 0) (SomeCol (Var 0)) e) :: pols)
1235 1296
1236 | _ => (vals, pols) 1297 | _ => (vals, pols)
1237 1298
1238 val () = reset () 1299 val () = reset ()
1239 1300