comparison src/sqlcache.sml @ 2274:0730e217fc9c

First draft of more specific formulas for queries.
author Ziv Scully <ziv@mit.edu>
date Thu, 05 Nov 2015 01:48:42 -0500
parents a3cac6cea625
children ce96e166d938
comparison
equal deleted inserted replaced
2273:a3cac6cea625 2274:0730e217fc9c
6 structure IM = IntBinaryMap 6 structure IM = IntBinaryMap
7 structure SK = struct type ord_key = string val compare = String.compare end 7 structure SK = struct type ord_key = string val compare = String.compare end
8 structure SS = BinarySetFn(SK) 8 structure SS = BinarySetFn(SK)
9 structure SM = BinaryMapFn(SK) 9 structure SM = BinaryMapFn(SK)
10 structure SIMM = MultimapFn(structure KeyMap = SM structure ValSet = IS) 10 structure SIMM = MultimapFn(structure KeyMap = SM structure ValSet = IS)
11
12 (* ASK: how do we deal with heap reallocation? *)
13
14 fun id x = x
11 15
12 fun iterate f n x = if n < 0 16 fun iterate f n x = if n < 0
13 then raise Fail "Can't iterate function negative number of times." 17 then raise Fail "Can't iterate function negative number of times."
14 else if n = 0 18 else if n = 0
15 then x 19 then x
225 fun mapFormula mf = 229 fun mapFormula mf =
226 fn Atom x => Atom (mf x) 230 fn Atom x => Atom (mf x)
227 | Negate f => Negate (mapFormula mf f) 231 | Negate f => Negate (mapFormula mf f)
228 | Combo (j, fs) => Combo (j, map (mapFormula mf) fs) 232 | Combo (j, fs) => Combo (j, map (mapFormula mf) fs)
229 233
234 fun mapFormulaExps mf = mapFormula (fn (cmp, e1, e2) => (cmp, mf e1, mf e2))
235
230 236
231 (****************) 237 (****************)
232 (* SQL Analysis *) 238 (* SQL Analysis *)
233 (****************) 239 (****************)
234 240
580 NONE => table 586 NONE => table
581 | SOME (realTable, _) => realTable 587 | SOME (realTable, _) => realTable
582 val renameSqexp = 588 val renameSqexp =
583 fn Sql.Field (table, field) => Sql.Field (renameString table, field) 589 fn Sql.Field (table, field) => Sql.Field (renameString table, field)
584 | e => e 590 | e => e
585 fun renameAtom (cmp, e1, e2) = (cmp, renameSqexp e1, renameSqexp e2) 591 (* fun renameAtom (cmp, e1, e2) = (cmp, renameSqexp e1, renameSqexp e2) *)
586 in 592 in
587 mapFormula renameAtom 593 mapFormulaExps renameSqexp
588 end 594 end
589 595
590 val rec queryToFormula = 596 fun queryToFormula marker =
591 fn Sql.Query1 {Where = NONE, ...} => Combo (Conj, []) 597 fn Sql.Query1 {Select = sitems, From = tablePairs, Where = wher} =>
592 | Sql.Query1 {From = tablePairs, Where = SOME e, ...} => 598 let
593 renameTables tablePairs (sqexpToFormula e) 599 val fWhere = case wher of
594 | Sql.Union (q1, q2) => Combo (Disj, [queryToFormula q1, queryToFormula q2]) 600 NONE => Combo (Conj, [])
595 601 | SOME e => sqexpToFormula e
596 fun valsToFormula (table, vals) = 602 in
597 Combo (Conj, map (fn (field, v) => Atom (Sql.Eq, Sql.Field (table, field), v)) vals) 603 renameTables tablePairs
598 604 (case marker of
599 val rec dmlToFormula = 605 NONE => fWhere
600 fn Sql.Insert (table, vals) => valsToFormula (table, vals) 606 | SOME markFields =>
601 | Sql.Delete (table, wher) => renameTables [(table, "T")] (sqexpToFormula wher) 607 let
608 val fWhereMarked = mapFormulaExps markFields fWhere
609 val toSqexp =
610 fn Sql.SqField tf => Sql.Field tf
611 | Sql.SqExp (se, _) => se
612 fun ineq se = Atom (Sql.Ne, se, markFields se)
613 val fIneqs = Combo (Disj, map (ineq o toSqexp) sitems)
614 in
615 (Combo (Conj,
616 [fWhere,
617 Combo (Disj,
618 [Negate fWhereMarked,
619 Combo (Conj, [fWhereMarked, fIneqs])])]))
620 end)
621 end
622 | Sql.Union (q1, q2) => Combo (Disj, [queryToFormula marker q1, queryToFormula marker q2])
623
624 fun valsToFormula (markLeft, markRight) (table, vals) =
625 Combo (Conj,
626 map (fn (field, v) => Atom (Sql.Eq, markLeft (Sql.Field (table, field)), markRight v))
627 vals)
628
629 (* TODO: verify logic for insertion and deletion. *)
630 val rec dmlToFormulaMarker =
631 fn Sql.Insert (table, vals) => (valsToFormula (id, id) (table, vals), NONE)
632 | Sql.Delete (table, wher) => (renameTables [(table, "T")] (sqexpToFormula wher), NONE)
602 | Sql.Update (table, vals, wher) => 633 | Sql.Update (table, vals, wher) =>
603 let 634 let
604 val fWhere = sqexpToFormula wher 635 val fWhere = sqexpToFormula wher
605 val fVals = valsToFormula (table, vals) 636 fun fVals marks = valsToFormula marks (table, vals)
606 val modifiedFields = SS.addList (SS.empty, map #1 vals) 637 val modifiedFields = SS.addList (SS.empty, map #1 vals)
607 (* TODO: don't use field name hack. *) 638 (* TODO: don't use field name hack. *)
608 val markField = 639 fun markFields table =
609 fn e as Sql.Field (t, v) => if SS.member (modifiedFields, v) 640 fn e as Sql.Field (t, v) => if t = table andalso SS.member (modifiedFields, v)
610 then Sql.Field (t, v ^ "'") 641 then Sql.Field (t, v ^ "'")
611 else e 642 else e
643 | Sql.SqNot e => Sql.SqNot (markFields table e)
644 | Sql.Binop (r, e1, e2) => Sql.Binop (r, markFields table e1, markFields table e2)
645 | Sql.SqKnown e => Sql.SqKnown (markFields table e)
646 | Sql.SqFunc (s, e) => Sql.SqFunc (s, markFields table e)
612 | e => e 647 | e => e
613 val mark = mapFormula (fn (cmp, e1, e2) => (cmp, markField e1, markField e2)) 648 val mark = mapFormulaExps (markFields "T")
614 in 649 in
615 renameTables [(table, "T")] 650 (* Inside renameTables, we mark with table "T". Outside, we use the real table name. *)
616 (Combo (Disj, [Combo (Conj, [fVals, mark fWhere]), 651 (renameTables [(table, "T")]
617 Combo (Conj, [mark fVals, fWhere])])) 652 (Combo (Disj, [Combo (Conj, [fVals (id, markFields "T"), mark fWhere]),
618 end 653 Combo (Conj, [fVals (markFields "T", id), fWhere])])),
619 654 SOME (markFields table))
620 (* val rec toFormula = *) 655 end
621 (* fn (Sql.Union (q1, q2), d) => Combo (Disj, [toFormula (q1, d), toFormula (q2, d)]) *) 656
622 (* | (q as Sql.Query1 {Select = items, ...}, d) => *) 657 fun pairToFormulas (query, dml) =
623 (* let *) 658 let
624 (* val selected = osequence (map (fn )) *) 659 val (fDml, marker) = dmlToFormulaMarker dml
625 (* in *) 660 in
626 (* case selected of *) 661 (queryToFormula marker query, fDml)
627 (* NONE => (Combo (Conj, [markQuery (), markDml fDml])) *) 662 end
628 (* end *) 663
664 (* structure ToFormula = struct *)
665
666 (* val testOfQuery : Sql.query1 -> (Sql.cmp * Sql.sqexp * Sql.sqexp) formula = *)
667 (* fn {From = tablePairs, Where = SOME e, ...} => renameTables tablePairs (sqexpToFormula e) *)
668 (* | {Where = NONE, ...} => Combo (Conj, []) *)
669
670 (* (* If selecting some parsable subset of fields, says which ones. [NONE] *)
671 (* means anything could be selected. *) *)
672 (* fun fieldsOfQuery (q : Sql.query1) = *)
673 (* osequence (map (fn Sql.SqField tf => SOME tf *)
674 (* | Sql.SqExp (Sql.Field tf) => SOME tf *)
675 (* | _ => NONE) (#Select q)) *)
676
677 (* fun fieldsOfVals (table, vals, wher) = *)
678 (* let *)
679 (* val fWhere = renameTables [(table, "T")] (sqexpToFormula wher) *)
680 (* val fVals = valsToFormula (table, vals) *)
681 (* val modifiedFields = SS.addList (SS.empty, map #1 vals) *)
682 (* (* TODO: don't use field name hack. *) *)
683 (* val markField = *)
684 (* fn e as Sql.Field (t, v) => if SS.member (modifiedFields, v) *)
685 (* then Sql.Field (t, v ^ "'") *)
686 (* else e *)
687 (* | e => e *)
688 (* val mark = mapFormula (fn (cmp, e1, e2) => (cmp, markField e1, markField e2)) *)
689 (* in *)
690 (* renameTables [(table, "T")] *)
691 (* (Combo (Disj, [Combo (Conj, [fVals, mark fWhere]), *)
692 (* Combo (Conj, [mark fVals, fWhere])])) *)
693 (* end *)
694 (* end *)
629 695
630 structure ConflictMaps = struct 696 structure ConflictMaps = struct
631 697
632 structure TK = TripleKeyFn(structure I = CmpKey 698 structure TK = TripleKeyFn(structure I = CmpKey
633 structure J = AtomOptionKey 699 structure J = AtomOptionKey
634 structure K = AtomOptionKey) 700 structure K = AtomOptionKey)
701
635 structure TS : ORD_SET = BinarySetFn(TK) 702 structure TS : ORD_SET = BinarySetFn(TK)
636 703
637 val toKnownEquality = 704 val toKnownEquality =
638 (* [NONE] here means unkown. Anything that isn't a comparison between two 705 (* [NONE] here means unkown. Anything that isn't a comparison between two
639 knowns shouldn't be used, and simply dropping unused terms is okay in 706 knowns shouldn't be used, and simply dropping unused terms is okay in
640 disjunctive normal form. *) 707 disjunctive normal form. *)
641 fn (Sql.Eq, SOME e1, SOME e2) => SOME (e1, e2) 708 fn (Sql.Eq, SOME e1, SOME e2) => SOME (e1, e2)
642 | _ => NONE 709 | _ => NONE
643 710
644 val equivClasses : (Sql.cmp * atomExp option * atomExp option) list -> atomExp list list = 711 fun equivClasses atoms : atomExp list list option =
645 UF.classes 712 let
646 o List.foldl UF.union' UF.empty 713 val uf = List.foldl UF.union' UF.empty (List.mapPartial toKnownEquality atoms)
647 o List.mapPartial toKnownEquality 714 val ineqs = List.filter (fn (cmp, _, _) =>
715 cmp = Sql.Ne orelse cmp = Sql.Lt orelse cmp = Sql.Gt)
716 atoms
717 val contradiction =
718 fn (cmp, SOME ae1, SOME ae2) => (cmp = Sql.Ne orelse cmp = Sql.Lt orelse cmp = Sql.Gt)
719 andalso not (UF.together (uf, ae1, ae2))
720 (* If we don't know one side of the comparision, not a contradiction. *)
721 | _ => false
722 in
723 not (List.exists contradiction atoms) <\oguard\> SOME (UF.classes uf)
724 end
648 725
649 fun addToEqs (eqs, n, e) = 726 fun addToEqs (eqs, n, e) =
650 case IM.find (eqs, n) of 727 case IM.find (eqs, n) of
651 (* Comparing to a constant is probably better than comparing to a 728 (* Comparing to a constant is probably better than comparing to a
652 variable? Checking that existing constants match a new ones is 729 variable? Checking that existing constants match a new ones is
732 o map (fn xs => TS.addList (TS.empty, xs)) 809 o map (fn xs => TS.addList (TS.empty, xs))
733 810
734 fun dnf (fQuery, fDml) = 811 fun dnf (fQuery, fDml) =
735 normalize simplify normalizeAtom Disj (Combo (Conj, [markQuery fQuery, markDml fDml])) 812 normalize simplify normalizeAtom Disj (Combo (Conj, [markQuery fQuery, markDml fDml]))
736 813
737 val conflictMaps = List.mapPartial (mergeEqs o map eqsOfClass o equivClasses) o dnf 814 val conflictMaps =
815 List.mapPartial (mergeEqs o map eqsOfClass)
816 o List.mapPartial equivClasses
817 o dnf
738 818
739 end 819 end
740 820
741 val conflictMaps = ConflictMaps.conflictMaps 821 val conflictMaps = ConflictMaps.conflictMaps
742 822
1228 in 1308 in
1229 (map (map optionAtomExpToExp) 1309 (map (map optionAtomExpToExp)
1230 o removeRedundant madeRedundantBy 1310 o removeRedundant madeRedundantBy
1231 o map (eqsToInvalidation numArgs) 1311 o map (eqsToInvalidation numArgs)
1232 o conflictMaps) 1312 o conflictMaps)
1233 (queryToFormula query, dmlToFormula dml) 1313 (pairToFormulas (query, dml))
1234 end 1314 end
1235 1315
1236 end 1316 end
1237 1317
1238 val invalidations = Invalidations.invalidations 1318 val invalidations = Invalidations.invalidations
1267 (* TODO: fail more gracefully. *) 1347 (* TODO: fail more gracefully. *)
1268 NONE => raise Match 1348 NONE => raise Match
1269 | SOME invs => sequence (flushes invs @ [dmlExp]) 1349 | SOME invs => sequence (flushes invs @ [dmlExp])
1270 end 1350 end
1271 | e' => e' 1351 | e' => e'
1352 val file = fileMap doExp file
1353
1272 in 1354 in
1273 (* DEBUG *) 1355 (* DEBUG *)
1274 (* gunk := []; *) 1356 (* gunk := []; *)
1275 ffiInfoRef := ffiInfo; 1357 ffiInfoRef := ffiInfo;
1276 fileMap doExp file 1358 file
1277 end 1359 end
1278 1360
1279 1361
1280 (************************) 1362 (************************)
1281 (* Compiler Entry Point *) 1363 (* Compiler Entry Point *)