Documentation

Provenance.AggQueryClosure

The compositional closure of the rewriting rules #

ProvSQL rewrites whole queries in which classical blocks, GROUP BY … HAVING blocks and bare GROUP BY blocks occur as subqueries. The relation AggQuery.RewritesTo below closes the three base rewritings – the classical rules (AggQuery.rewritingOf), the HAVING site (AggQuery.havingPredRew, the aggregate-exposing shape ProvSQL actually emits, for an arbitrary Boolean combination of aggregate comparisons) and the bare grouping (AggQuery.gammaRew) – under the operators that may sit above them, and AggQuery.rewritesTo_valid extends the correctness to every query so obtained.

Token-bearing outputs #

The base rules do not share an output shape: a classical or HAVING block produces all-regular data columns, whereas a bare grouping produces aggregate-token columns. The relation is therefore indexed by the rewritten query's own kind vector, and correctness is stated at the token level, through GenRow.toCompositeRow. On all-regular outputs this specializes to the all-regular statement, AggQuery.rewritesTo_valid_reg.

The natural rewritten kind vector of a query of kinds κ is ColKind.rewKindsOf κ – the source kinds followed by the provenance column. Casting terms, predicates and projection columns into it is uniform: a column keeps its kind, so no all-regular hypothesis is needed anywhere (TermG.castRew and friends), unlike the composite casts of the classical rewriting. The gate TermG.cmpAgg, whose generic semantics is the junk value 𝟘, casts to that constant.

Scope #

Selection, projection and union close over arbitrary kinds – in particular over a bare grouping, which is the SELECT … FROM (GROUP BY …) shape. Deduplication closes over any subquery whose output is all-regular, which is what the kind discipline permits: the rewritten rule AggQuery.dedupRew is ProvSQL's ε (group by the data columns, -sum the provenance column), proven correct against an arbitrary rewritten subquery rather than only against rewriting's output.

Product closes over arbitrary kinds too. Reassembling a join needs a projection column whose kind is read off the operand's kind vector – ProjCol.copy, which dispatches on that kind – and its faithfulness needs the operands' rows to conform; that comes for free from the subderivations, since their rows are embeddings of rows of the general evaluator, which conforms by AggQuery.evaluate_conform.

Difference closes as well (AggQuery.diffRew). The closure is therefore complete for the operators the kind discipline admits above a grouping: there is no remaining structural gap.

The rewritten kind vector #

@[reducible, inline]
abbrev ColKind.rewKindsOf {n : } (κ : Fin nColKind) :
Fin (n + 1)ColKind

The rewritten kind vector of a query of kinds κ: the source kinds, followed by the provenance column.

Equations
Instances For
    Dependency graph
    @[simp]
    theorem ColKind.rewKindsOf_castAdd {n : } (κ : Fin nColKind) (k : Fin n) :
    rewKindsOf κ (Fin.castAdd 1 k) = κ k
    Dependency graph
    @[simp]
    theorem ColKind.rewKindsOf_last {n : } (κ : Fin nColKind) :
    Dependency graph
    theorem ColKind.rewKindsOf_base_of_reg {n : } {κ : Fin nColKind} ( : ∀ (k : Fin n), κ k = reg) (k : Fin (n + 1)) :

    On all-regular kinds the uniform rewritten kind vector agrees pointwise with the classical rewriting's ColKind.rewKinds.

    Dependency graph

    Uniform casts into the rewritten world #

    def TermG.castRew {T : Type} [ValueType T] {K : Type} {n : } {κ : Fin nColKind} :
    TermG T κTermG (T K) (ColKind.rewKindsOf κ)

    A term over the source kinds, read on the rewritten schema: every column keeps its kind and its position, so no all-regular hypothesis is needed. The gate, whose generic semantics is the junk value 𝟘, casts to that constant.

    Equations
    Instances For
      Dependency graph
      def GenPred.castRew {T : Type} [ValueType T] {K : Type} {n : } {κ : Fin nColKind} :

      An aggregate-atom-free predicate is unnecessary here: the cast is total, aggregate atoms comparing a token's deterministic reading.

      Equations
      Instances For
        Dependency graph
        def ProjCol.castRew {T : Type} [ValueType T] {K : Type} {n : } {κ : Fin nColKind} :

        A projection column, read on the rewritten schema.

        Equations
        Instances For
          Dependency graph
          @[simp]
          theorem ProjCol.castRew_kind {T : Type} [ValueType T] {K : Type} {n : } {κ : Fin nColKind} (p : ProjCol T κ) :
          Dependency graph

          The casts evaluate faithfully #

          theorem TermG.castRew_evalRew {T : Type} [ValueType T] {K : Type} [CommSemiringWithMonus K] [DecidableEq K] [HasAltLinearOrder K] {n : } {κ : Fin nColKind} (t : TermG T κ) (r : GenRow T K n) :
          Dependency graph
          theorem GenPred.castRew_holdsRew {T : Type} [ValueType T] {K : Type} [CommSemiringWithMonus K] [DecidableEq K] [HasAltLinearOrder K] {n : } {κ : Fin nColKind} (φ : GenPred T κ) (r : GenRow T K n) :
          Dependency graph
          Dependency graph
          theorem AggQuery.map_toCompositeRow_of_reg {T : Type} [ValueType T] {K : Type} [CommSemiringWithMonus K] [DecidableEq K] [HasAltLinearOrder K] {n : } {κ : Fin nColKind} (q : AggQuery T n κ) ( : ∀ (k : Fin n), κ k = ColKind.reg) (d : AnnotatedDatabase T K) :
          Multiset.map GenRow.toCompositeRow (q.evaluate d) = Multiset.map (fun (t : Tuple (T K) (n + 1)) (k : Fin (n + 1)) => Sum.inl (t k)) (q.evaluateAnnotated d).toComposite

          On an all-regular query the token-aware embedding is the embedding of the classical and HAVING-site correctness statements.

          Dependency graph
          theorem ColKind.rewKindsOf_of_lt {n : } (κ : Fin nColKind) {j : Fin (n + 1)} (h : j < n) :
          rewKindsOf κ j = κ j, h

          A data column of a rewritten kind vector, positionally.

          Dependency graph
          theorem ColKind.rewKindsOf_of_not_lt {n : } (κ : Fin nColKind) {j : Fin (n + 1)} (h : ¬j < n) :

          The trailing column of a rewritten kind vector.

          Dependency graph

          Copying a column of unknown kind #

          def ProjCol.copy {T' : Type} {N : } {κ' : Fin NColKind} (i : Fin N) :
          ProjCol T' κ'

          Copy the i-th column verbatim, whatever its kind: a regular or provenance column is read as a value term, a token column is a verbatim token copy. This is the projection column a join reassembly needs, since the operand's kind vector is not statically known there.

          Equations
          Instances For
            Dependency graph
            @[simp]
            theorem ProjCol.copy_kind {T' : Type} {N : } {κ' : Fin NColKind} (i : Fin N) :
            (copy i).kind = κ' i
            Dependency graph
            @[simp]

            The kind of a transported value is the kind of the value.

            Dependency graph
            theorem GenRow.toCompositeRow_conform {T : Type} [ValueType T] {K : Type} [CommSemiringWithMonus K] {n : } {κ : Fin nColKind} (r : GenRow T K n) (hr : ∀ (k : Fin n), (r.1 k).kindOf = (κ k).base) (j : Fin (n + 1)) :

            Kind conformance of the token-aware embedding: a row conforming to κ embeds to one conforming to ColKind.rewKindsOf κ.

            Dependency graph
            theorem ProjCol.copy_evalRew {T : Type} [ValueType T] {K : Type} [CommSemiringWithMonus K] [DecidableEq K] [HasAltLinearOrder K] {N : } {κ' : Fin NColKind} (i : Fin N) (u : Tuple (GenValue (T K) K) N) (hu : (u i).kindOf = (κ' i).base) :
            (copy i).evalRew u = u i

            A copied column evaluates to the column, on a conformant row.

            Dependency graph

            HAVING predicates as gate terms #

            The HAVING site rewriting of Provenance.AggQueryHavingRewriting takes one aggregate comparison. An arbitrary Boolean combination of atoms is just as expressible: the predicate provenance predsem is ∧ ↦ ⊗, ∨ ↦ ⊕ and ¬ pushed to the atoms by De Morgan duality with operator complementation, and the rewritten world's terms have mul, add and the two gates – provsql_having for an aggregate atom, the indicator gate for a regular one. GenPred.gateTerm is that translation; it is faithful for an arbitrary predicate (GenPred.gateTerm_evalRew), the gates being the primitives the correctness is relative to.

            Regular atoms do change the fate of the group guard. An aggregate atom's predicate provenance ranges over non-empty worlds only, so it supersedes the guard; a regular atom's χ does not entail the group's existence (GenPred.entailsExistence), and mixing one in can leave the whole predicate non-entailing – count(*) > 5 ∨ city = 'Paris' fires in worlds where the group is empty. The site rewriting therefore keeps the guard as a factor in that case (GenPred.siteProvTerm), reproducing what the general evaluator does with the pending group factor.

            def GenPred.aggOnly {T : Type} {n : } {κ : Fin nColKind} :
            GenPred T κBool

            A predicate all of whose atoms are aggregate comparisons.

            Equations
            Instances For
              Dependency graph
              theorem GenPred.aggOnly_entailsExistence {T : Type} {n : } {κ : Fin nColKind} (φ : GenPred T κ) :
              φ.aggOnly = true∀ (neg : Bool), φ.entailsExistence neg = true

              An aggregate-only predicate entails its groups' existence, whatever the polarity: every atom does, and both connectives preserve that.

              Dependency graph
              theorem GenPred.hasAggAtom_comparedCols_nonempty {T : Type} {n : } {κ : Fin nColKind} (φ : GenPred T κ) :

              A predicate with an aggregate atom compares at least one token column.

              Dependency graph
              def GenPred.gateTerm {T : Type} [ValueType T] {K : Type} {n : } {κ : Fin nColKind} :
              GenPred T κBoolTermG (T K) (ColKind.rewKindsOf κ)

              The predicate provenance as a rewritten term: the predsem algebra – aggregate atoms to provsql_having gates, regular atoms to indicator gates, ∧ ↦ ⊗, ∨ ↦ ⊕, ¬ pushed down with operator complementation.

              Equations
              Instances For
                Dependency graph
                theorem GenPred.gateTerm_evalRew {T : Type} [ValueType T] {K : Type} [CommSemiringWithMonus K] [DecidableEq K] [HasAltLinearOrder K] {n : } {κ : Fin nColKind} (φ : GenPred T κ) (neg : Bool) (r : GenRow T K n) :

                The gate term computes the predicate provenance, for an arbitrary predicate: relative to the two gate primitives, which is exactly the sense in which ProvSQL's own rewriting is correct.

                Dependency graph
                theorem GenPred.aggOnly_hasAggAtom {T : Type} {n : } {κ : Fin nColKind} (φ : GenPred T κ) :

                An aggregate-only predicate has an aggregate atom.

                Dependency graph
                theorem GenPred.comparedCols_agg {T : Type} {n : } {κ : Fin nColKind} (φ : GenPred T κ) {k : Fin n} :

                Compared columns are token columns – by construction of the aggregate atom.

                Dependency graph
                theorem gammaRow_conform {T K : Type} {n₁ n₂ : } (g : Tuple T n₁) (h : Fin n₂AggValue T K) (k : Fin (n₁ + n₂)) :
                (Fin.append (fun (i : Fin n₁) => Sum.inl (g i)) (fun (j : Fin n₂) => Sum.inr (h j)) k).kindOf = (ColKind.gammaKinds n₁ n₂ k).base

                Kind conformance of a grouping row.

                Dependency graph
                theorem GenRow.toCompositeRow_gammaRow_conform {T : Type} [ValueType T] {K : Type} [CommSemiringWithMonus K] {n₁ n₂ : } (g : Tuple T n₁) (h : Fin n₂AggValue T K) (a : GenAnn K) (i : Fin (n₁ + n₂ + 1)) :
                (toCompositeRow (Fin.append (fun (k : Fin n₁) => Sum.inl (g k)) fun (j : Fin n₂) => Sum.inr (h j), a) i).kindOf = (ColKind.gammaRewKinds n₁ n₂ i).base

                Kind conformance of the embedding of a grouping row.

                Dependency graph
                theorem gammaRow_agg_col {T : Type} [ValueType T] {K : Type} {m n₁ n₂ : } (g : Tuple T n₁) (ts : Tuple (Term T m) n₂) (fs : Tuple (SeqAggFunc T) n₂) (U : List (AnnotatedTuple T K m)) {k : Fin (n₁ + n₂)} (hk : ColKind.gammaKinds n₁ n₂ k = ColKind.agg) :
                ∃ (a : AggValue T K), Fin.append (fun (i : Fin n₁) => Sum.inl (g i)) (fun (j : Fin n₂) => Sum.inr (AggValue.ofGroup (fs j) (ts j) U)) k = Sum.inr a List.map Prod.snd a.occs = List.map Prod.snd U

                A token column of a grouping row carries the group's annotation list.

                Dependency graph
                theorem GenAnn.finalize_supersede {K : Type} [CommSemiringWithMonus K] [DecidableEq K] (b : K) (l₀ : List K) (C : Multiset (List K)) (hne : C 0) (hall : l'C, l' = l₀) :
                { base := b, pending := Multiset.filter (fun (l : List K) => ¬(C 0 l'C, l' = l)) {l₀} }.finalize = b

                Superseding the group guard: when the compared occurrence lists are non-empty and all equal to the single pending group's list, the selection's filter removes that group factor, so the row finalizes to its concrete part.

                Dependency graph

                The general HAVING site #

                def GenPred.siteProvTerm {T : Type} [ValueType T] {K : Type} {n₁ n₂ : } (φ : GenPred T (ColKind.gammaKinds n₁ n₂)) :
                TermG (T K) (ColKind.gammaRewKinds n₁ n₂)

                The provenance column of a rewritten HAVING site: the predicate's gate term, times the group-existence guard δ(⊕ U) – which the rewritten grouping has left in the provenance column – unless the predicate already entails the group's existence, in which case the gate term supersedes it. This is ProvSQL's having_entails_group_existence test: the supersede of the δ gate is licensed exactly when every world the predicate accepts has the group non-empty.

                Equations
                Instances For
                  Dependency graph
                  def AggQuery.havingPredCols {T : Type} [ValueType T] {K : Type} {n₁ n₂ : } (φ : GenPred T (ColKind.gammaKinds n₁ n₂)) :
                  Tuple (ProjCol (T K) (ColKind.gammaRewKinds n₁ n₂)) (n₁ + n₂ + 1)

                  The output columns of a general HAVING site: the group keys and the aggregate tokens copied verbatim, and the predicate's provenance term in the provenance column.

                  Equations
                  Instances For
                    Dependency graph
                    theorem AggQuery.havingPredCols_kind {T : Type} [ValueType T] {K : Type} {n₁ n₂ : } (φ : GenPred T (ColKind.gammaKinds n₁ n₂)) (j : Fin (n₁ + n₂ + 1)) :

                    The site's output columns have exactly the rewritten Gamma kinds.

                    Dependency graph
                    def AggQuery.havingPredRew {T : Type} [ValueType T] {K : Type} [CommSemiringWithMonus K] [HasAltLinearOrder K] {m n₁ n₂ : } (is : Tuple (Fin m) n₁) (ts : Tuple (Term T m) n₂) (fs : Tuple (SeqAggFunc T) n₂) (φ : GenPred T (ColKind.gammaKinds n₁ n₂)) (qg : AggQuery T m (ColKind.allReg m)) (hq : qg.classical) :
                    AggQuery (T K) (n₁ + n₂ + 1) (ColKind.gammaRewKinds n₁ n₂)

                    The rewritten HAVING site, for an arbitrary predicate: the token-building grouping of AggQuery.gammaRew, with a projection keeping the group keys and the aggregate tokens and replacing the group-existence guard by the predicate's provenance term – the gate term alone when the predicate entails the group's existence, the gate term times the guard otherwise.

                    Equations
                    Instances For
                      Dependency graph
                      theorem AggQuery.havingPredRew_valid {T : Type} [ValueType T] {K : Type} [CommSemiringWithMonus K] [DecidableEq K] [HasAltLinearOrder K] {m n₁ n₂ : } (is : Tuple (Fin m) n₁) (ts : Tuple (Term T m) n₂) (fs : Tuple (SeqAggFunc T) n₂) (φ : GenPred T (ColKind.gammaKinds n₁ n₂)) ( : φ.hasAggAtom = true) (qg : AggQuery T m (ColKind.allReg m)) (hq : qg.classical) (d : AnnotatedDatabase T K) :

                      Correctness of the general HAVING site rewriting, relative to the gate primitives, for an arbitrary predicate with an aggregate atom – regular atoms mixed in included. The gate term computes the predicate provenance; the group guard is superseded exactly when the predicate entails the group's existence, and kept as a factor otherwise, matching the general evaluator's treatment of the pending group factor.

                      Dependency graph

                      Duplicate elimination in the rewritten world #

                      theorem fold_addFn_inr {T : Type} [ValueType T] {K : Type} [CommSemiringWithMonus K] [HasAltLinearOrder K] {α : Type} (f : αK) (M : Multiset α) :
                      Multiset.fold addFn 0 (Multiset.map (fun (x : α) => Sum.inr (f x)) M) = Sum.inr (Multiset.map f M).sum

                      Folding embedded annotations with the value-type addition is the annotation sum.

                      Dependency graph
                      theorem GenRow.toCompositeRow_ofAnnotated {T : Type} [ValueType T] {K : Type} [CommSemiringWithMonus K] {n : } (p : AnnotatedTuple T K n) :
                      (ofAnnotated p).toCompositeRow = Fin.append (fun (k : Fin n) => Sum.inl (Sum.inl (p.1 k))) fun (x : Fin 1) => Sum.inl (Sum.inr p.2)

                      The embedding of a row rebuilt from an annotated tuple.

                      Dependency graph

                      The data reading of an embedded row is the embedded data reading.

                      Dependency graph

                      The provenance column of an embedded row is its finalized annotation.

                      Dependency graph

                      The rewritten duplicate elimination: ProvSQL's ε rule – group by the data columns and -sum the provenance column – applied to an arbitrary rewritten subquery, as AggQuery.rewriting does for the classical fragment.

                      Equations
                      Instances For
                        Dependency graph

                        Correctness of the rewritten duplicate elimination, for an arbitrary rewritten subquery.

                        Dependency graph

                        Products of token-bearing blocks #

                        def AggQuery.prodRewCols {T K : Type} {n₁ n₂ : } (κ₁ : Fin n₁ColKind) (κ₂ : Fin n₂ColKind) :
                        Tuple (ProjCol (T K) (Fin.append (ColKind.rewKindsOf κ₁) (ColKind.rewKindsOf κ₂))) (n₁ + n₂ + 1)

                        The reassembly columns of a rewritten product: the two operands' data columns copied verbatim (whatever their kinds), and the product of the two provenance columns.

                        Equations
                        • One or more equations did not get rendered due to their size.
                        Instances For
                          Dependency graph
                          theorem AggQuery.prodRewCols_kind {T K : Type} {n₁ n₂ : } (κ₁ : Fin n₁ColKind) (κ₂ : Fin n₂ColKind) (j : Fin (n₁ + n₂ + 1)) :
                          (prodRewCols κ₁ κ₂ j).kind = ColKind.rewKindsOf (Fin.append κ₁ κ₂) j

                          The reassembly columns have the rewritten kinds of the product.

                          Dependency graph
                          def AggQuery.prodRew {T K : Type} {n₁ n₂ : } {κ₁ : Fin n₁ColKind} {κ₂ : Fin n₂ColKind} (q₁' : AggQuery (T K) (n₁ + 1) (ColKind.rewKindsOf κ₁)) (q₂' : AggQuery (T K) (n₂ + 1) (ColKind.rewKindsOf κ₂)) :
                          AggQuery (T K) (n₁ + n₂ + 1) (ColKind.rewKindsOf (Fin.append κ₁ κ₂))

                          The rewritten product, over operands of arbitrary kinds: the two rewritten blocks joined, the data columns reassembled by kind-preserving copies, and the provenance columns multiplied.

                          Equations
                          Instances For
                            Dependency graph
                            theorem AggQuery.prodRew_valid {T : Type} [ValueType T] {K : Type} [CommSemiringWithMonus K] [DecidableEq K] [HasAltLinearOrder K] {n₁ n₂ : } {κ₁ : Fin n₁ColKind} {κ₂ : Fin n₂ColKind} {q₁ : AggQuery T n₁ κ₁} {q₂ : AggQuery T n₂ κ₂} {q₁' : AggQuery (T K) (n₁ + 1) (ColKind.rewKindsOf κ₁)} {q₂' : AggQuery (T K) (n₂ + 1) (ColKind.rewKindsOf κ₂)} (d : AnnotatedDatabase T K) (ih₁ : Multiset.map GenRow.toCompositeRow (q₁.evaluate d) = q₁'.evaluateRew d.toComposite) (ih₂ : Multiset.map GenRow.toCompositeRow (q₂.evaluate d) = q₂'.evaluateRew d.toComposite) :

                            Correctness of the rewritten product, for arbitrary operand kinds: conformance of the operands' rows makes the kind-dispatched column copies faithful.

                            Dependency graph

                            Difference in the rewritten world #

                            The general evaluator keeps every row of the left operand, rewriting its annotation to α ⊖ Σβ – the monus against the -sum of the matching rows on the right. ProvSQL's rewriting encodes that missing left outer join as a union of two branches: rows whose data part is absent from the right operand keep their annotation, rows whose data part is present are joined against the per-key sums and subtract them. The rewritten world's TermG.sub supplies the monus directly, so both branches are plain projections of joins, and the two semijoin identities of Provenance.QueryRewriting reduce them to filters of the left operand.

                            theorem inl_append {T K : Type} {n m : } (t : Tuple (T K) n) (s : Tuple (T K) m) :
                            (Fin.append (fun (k : Fin n) => Sum.inl (t k)) fun (k : Fin m) => Sum.inl (s k)) = fun (k : Fin (n + m)) => Sum.inl (Fin.append t s k)

                            The inl embedding commutes with appending rows.

                            Dependency graph

                            The embedding of a rebuilt annotated row is the inl-image of its composite encoding.

                            Dependency graph
                            def AggQuery.diffKeyProj {T K : Type} {n : } (q : AggQuery (T K) (n + 1) (ColKind.rewKindsOf (ColKind.allReg n))) :

                            The data columns of a rewritten block, as an all-regular query: the provenance column dropped.

                            Equations
                            Instances For
                              Dependency graph

                              The output columns of the unmatched branch: the left block copied verbatim, provenance column included.

                              Equations
                              Instances For
                                Dependency graph

                                The output columns of the matched branch: the left block's data columns, and the monus of the two provenance columns.

                                Equations
                                • One or more equations did not get rendered due to their size.
                                Instances For
                                  Dependency graph
                                  Dependency graph
                                  Dependency graph

                                  The unmatched branch: left rows whose data part is among the surviving keys, keeping their annotation.

                                  Equations
                                  • One or more equations did not get rendered due to their size.
                                  Instances For
                                    Dependency graph

                                    The matched branch: left rows joined against the per-key -sums, subtracting them.

                                    Equations
                                    • One or more equations did not get rendered due to their size.
                                    Instances For
                                      Dependency graph

                                      The rewritten difference.

                                      Equations
                                      Instances For
                                        Dependency graph
                                        theorem inlTuple_injective {T K : Type} {n : } :
                                        Function.Injective fun (u : Tuple T n) (k : Fin n) => Sum.inl (u k)

                                        The data embedding of tuples is injective.

                                        Dependency graph
                                        theorem AggQuery.diffKeyProj_evaluateRew {T : Type} [ValueType T] {K : Type} [CommSemiringWithMonus K] [DecidableEq K] [HasAltLinearOrder K] {n : } (q' : AggQuery (T K) (n + 1) (ColKind.rewKindsOf (ColKind.allReg n))) (D : Database (T K)) (A : AnnotatedRelation T K n) (h : q'.evaluateRew D = Multiset.map (fun (p : AnnotatedTuple T K n) (k : Fin (n + 1)) => Sum.inl (p.toComposite k)) A) :
                                        q'.diffKeyProj.evaluateRew D = Multiset.map (fun (p : AnnotatedTuple T K n) (k : Fin n) => Sum.inl (Sum.inl (p.1 k))) A

                                        The data projection of a rewritten block.

                                        Dependency graph
                                        theorem AggQuery.diffSurvivors_evaluateRew {T : Type} [ValueType T] {K : Type} [CommSemiringWithMonus K] [DecidableEq K] [HasAltLinearOrder K] {n : } (q₁' q₂' : AggQuery (T K) (n + 1) (ColKind.rewKindsOf (ColKind.allReg n))) (D : Database (T K)) (A₁ A₂ : AnnotatedRelation T K n) (h₁ : q₁'.evaluateRew D = Multiset.map (fun (p : AnnotatedTuple T K n) (k : Fin (n + 1)) => Sum.inl (p.toComposite k)) A₁) (h₂ : q₂'.evaluateRew D = Multiset.map (fun (p : AnnotatedTuple T K n) (k : Fin (n + 1)) => Sum.inl (p.toComposite k)) A₂) :
                                        (q₁'.diffKeyProj.Diff q₂'.diffKeyProj).Dedup.evaluateRew D = Multiset.map (fun (u : Tuple T n) (k : Fin n) => Sum.inl (Sum.inl (u k))) (Multiset.filter (fun (u : Tuple T n) => uMultiset.map Prod.fst A₂) (Multiset.map Prod.fst A₁)).dedup

                                        The surviving keys: the deduplicated data tuples of the left operand absent from the right one.

                                        Dependency graph
                                        theorem AggQuery.diffBranchU_evaluateRew {T : Type} [ValueType T] {K : Type} [CommSemiringWithMonus K] [DecidableEq K] [HasAltLinearOrder K] {n : } (q₁' : AggQuery (T K) (n + 1) (ColKind.rewKindsOf (ColKind.allReg n))) (qs : AggQuery (T K) n (ColKind.allReg n)) (D : Database (T K)) (A₁ : AnnotatedRelation T K n) (S : Multiset (Tuple T n)) (hS : S.Nodup) (h₁ : q₁'.evaluateRew D = Multiset.map (fun (p : AnnotatedTuple T K n) (k : Fin (n + 1)) => Sum.inl (p.toComposite k)) A₁) (hs : qs.evaluateRew D = Multiset.map (fun (u : Tuple T n) (k : Fin n) => Sum.inl (Sum.inl (u k))) S) :
                                        (q₁'.diffBranchU qs).evaluateRew D = Multiset.map (fun (p : AnnotatedTuple T K n) (k : Fin (n + 1)) => Sum.inl (p.toComposite k)) (Multiset.filter (fun (p : AnnotatedTuple T K n) => p.1 S) A₁)

                                        The unmatched branch: by the semijoin identity, the left rows whose data part is a surviving key, with their annotation.

                                        Dependency graph
                                        theorem AggQuery.diffBranchM_evaluateRew {T : Type} [ValueType T] {K : Type} [CommSemiringWithMonus K] [DecidableEq K] [HasAltLinearOrder K] {n : } (q₁' qs : AggQuery (T K) (n + 1) (ColKind.rewKindsOf (ColKind.allReg n))) (D : Database (T K)) (A₁ : AnnotatedRelation T K n) (S : Multiset (Tuple T n)) (hS : S.Nodup) (V : Tuple T nK) (h₁ : q₁'.evaluateRew D = Multiset.map (fun (p : AnnotatedTuple T K n) (k : Fin (n + 1)) => Sum.inl (p.toComposite k)) A₁) (hs : qs.evaluateRew D = Multiset.map (fun (u : Tuple T n) (k : Fin (n + 1)) => Sum.inl (AnnotatedTuple.toComposite (u, V u) k)) S) :
                                        (q₁'.diffBranchM qs).evaluateRew D = Multiset.map (fun (p : AnnotatedTuple T K n) (k : Fin (n + 1)) => Sum.inl (AnnotatedTuple.toComposite (p.1, p.2 - V p.1) k)) (Multiset.filter (fun (p : AnnotatedTuple T K n) => p.1 S) A₁)

                                        The matched branch: by the keyed-projection semijoin, the left rows whose data part carries a per-key sum, with that sum subtracted.

                                        Dependency graph

                                        Correctness of the rewritten difference, for arbitrary rewritten operands: the two branches partition the left operand by whether its data part occurs on the right, and on the unmatched part the subtracted sum is 𝟘.

                                        Dependency graph

                                        The classical rewriting at the uniform kind vector #

                                        def AggQuery.rewritingOf {T : Type} [ValueType T] {K : Type} [CommSemiringWithMonus K] [HasAltLinearOrder K] {n : } {κ : Fin nColKind} (q : AggQuery T n κ) (hq : q.classical) :
                                        AggQuery (T K) (n + 1) (ColKind.rewKindsOf κ)

                                        The classical rewriting, retagged to ColKind.rewKindsOf κ. AggQuery.rewriting targets ColKind.rewKinds n – the per-index if k < n form – which is only pointwise equal to the uniform Fin.append κ prov the congruences below consume. Retagging once here (semantically the identity) lets a congruence sit directly above the classical base rule instead of threading an explicit retag step.

                                        Equations
                                        Instances For
                                          Dependency graph

                                          The closure #

                                          inductive AggQuery.RewritesTo {T : Type} [ValueType T] {K : Type} [CommSemiringWithMonus K] [HasAltLinearOrder K] {n : } {κ : Fin nColKind} {κ' : Fin (n + 1)ColKind} :
                                          AggQuery T n κAggQuery (T K) (n + 1) κ'Prop

                                          The compositional closure of the rewriting rules: the three base rewritings – classical blocks, fused HAVING sites and bare groupings – composed under union, selection, projection, deduplication, product and difference, with the kind-retagging of AggQuery.Retag available to adapt a subderivation's output kinds. The HAVING-site rule havingPred keeps the group keys and the aggregate tokens as output columns and admits any predicate with an aggregate atom.

                                          Instances For
                                            Dependency graph
                                            theorem AggQuery.rewritesTo_valid {T : Type} [ValueType T] {K : Type} [CommSemiringWithMonus K] [DecidableEq K] [HasAltLinearOrder K] {n : } {κ : Fin nColKind} {κ' : Fin (n + 1)ColKind} {q : AggQuery T n κ} {q' : AggQuery (T K) (n + 1) κ'} (h : q.RewritesTo q') (d : AnnotatedDatabase T K) :

                                            Whole-query correctness of the compositional rewriting: along the closure, the general evaluator's rows, embedded token-aware into the composite domain, are exactly the rewritten world's evaluation.

                                            Dependency graph
                                            theorem AggQuery.rewritesTo_valid_reg {T : Type} [ValueType T] {K : Type} [CommSemiringWithMonus K] [DecidableEq K] [HasAltLinearOrder K] {n : } {κ : Fin nColKind} {κ' : Fin (n + 1)ColKind} {q : AggQuery T n κ} {q' : AggQuery (T K) (n + 1) κ'} (h : q.RewritesTo q') ( : ∀ (k : Fin n), κ k = ColKind.reg) (d : AnnotatedDatabase T K) :
                                            Multiset.map (fun (t : Tuple (T K) (n + 1)) (k : Fin (n + 1)) => Sum.inl (t k)) (q.evaluateAnnotated d).toComposite = q'.evaluateRew d.toComposite

                                            On an all-regular source the correctness specializes to the shape of the classical and HAVING-site statements: the annotated semantics, folded into composite tuples and embedded by inl.

                                            Dependency graph