sparql-view-unfold
    Preparing search index...

    Class ClusterSolver

    Solver for determining variable equality clusters during query rewriting.

    When rewriting a triple pattern against a mapping head, variables from both sides may need to be unified. The solver tracks which variables are equivalent, what concrete terms they may be bound to, and which expressions their value has to satisfy.

    Since a triple term the mapping head writes is a shape whose three positions are groups in their own right (assertTerm) rather than a value a group is pinned to, the structure is a DAG, which resolvedTermOf reads a term back off and the occurs check of TermClusterSet keeps well founded.

    // Given mapping head: ?t rdf:reifies <<( ?s ?p ?o )>>
    // And triple pattern: ?x rdf:reifies <<( ?x ?y ?z )>>
    // The solver determines: ?t = ?x = ?s, ?y = ?p, ?z = ?o

    Hierarchy (View Summary)

    Index

    Constructors

    Properties

    cleanNumber: number

    Counter for generating unique group IDs

    groupMergeHistory: Record<number, number>

    A history of oldGroups (keys) that got merged into newGroups (values). Needed to dereference removed groups still used in a pin.

    groupToExpressions: Record<number, Algebra.Expression[]>

    Maps group ID to the expressions its value has to satisfy - read through getExpressions.

    groupToPin: Record<number, Pin<Term> | undefined>

    Maps group ID to what the group is pinned to (if anything) - read through pinOf.

    groupToRange: Record<number, RangeSet>

    Maps group ID to the term types its value may have - read through rangeOf.

    groupToValues: Record<number, T[]>

    Maps group ID to the values in it - read through valuesOf and groupEntries.

    meetPins: (
        a: Pin<RawBasicTerm>,
        b: Pin<RawBasicTerm>,
    ) => false | PinMeet<RawBasicTerm>

    Meets the two pins a group is asked to carry at once, reporting false when no value satisfies both

    staticExpressionValidation: { expression: Expression; term: RawTerm }[]

    Static expression validations where no variable group is involved. These occur when an expression must equal a concrete term.

    toId: (value: RangedVar) => string
    valueToGroup: Record<string, number | undefined>

    Maps a value to the group it is in - read through groupOf.

    Accessors

    • get revision(): number

      The state the set is in, as a stamp that no two states of any two sets share.

      Every method that writes anything moves it on (touch), so a memo taken off the set is valid for exactly as long as this is what it was taken at - which is a check the memo cannot forget to make, there being nothing to invalidate.

      Returns number

    Methods

    • Asserts that every value of the group equals the term.

      A triple term is not pinned but decomposed: the group takes the shape of one, and each position is asserted onto the group that position is - the same unification the rest of the mapping head goes through. Three things come with that: a second triple term on the group unifies with the first rather than being reported unequal, every position is held to the range it can have, and the occurs check refuses ?y ≡ <<( ... ?y )>>.

      Parameters

      • group: number

        The group to assert on

      • term: RawTerm

        The term every value of the group equals

      Returns boolean

      false on a contradiction, after which the solver holds no meaningful state

    • Gets the cluster information for a variable.

      Parameters

      • from: Variable

        The variable to look up

      Returns { group: number; term: RawTerm | undefined; vars: Variable[] }

      the term its cluster is bound to (if any), the other variables in the cluster, and the group ID

    • Gets all expressions that must equal the given variable's value.

      Parameters

      • from: Variable

        The variable to look up

      Returns Expression[]

      the expressions

    • Gets all expression-to-term equality checks with no variable involved.

      Returns { expression: Expression; term: RawTerm }[]

      the expression-term pairs to validate

      //   UQ: ?s <p> <<(?s a "b")>>
      // MH: <x> <p> ?y
      // --> ?s = <x> = subject(?y) ;
      // AND ALSO: predicate(?y) = rdf:type ; object(?y) = "b"
    • Narrows the group of a variable to the range that variable carries.

      Parameters

      • variable: RangedVar

        The variable whose range to register

      Returns void

      RewriteNoMatchError if the narrowed range leaves the group nothing to be

    • A group a live pin points at survives however few members it has: it is a position of a shape, and dropping it would leave that shape naming a group that is no longer there.

      Parameters

      • group: number

        The group to check

      Returns boolean

      whether it is worth keeping

    • The variables of the mapping in a group, as against the user query variables the rewriting binds from them.

      Parameters

      • group: number

        The group to look up

      Returns readonly RangedVar[]

      its mapping variables, ordered by sortClusters so that the first is the one every rewrite names the group by

    • Merges two groups by id, which is what a group nothing names can be merged by - the values-only half of a merge, whatever else a subclass hangs off a group being migrated by migrateGroupData.

      Parameters

      • fromGroup: number

        One group

      • toGroup: number

        The other

      Returns { newGroup: number; oldGroup: number } | undefined

      the ids involved, or undefined when the two ids are the same group

    • Merges the groups of two mapping variables.

      Parameters

      Returns { conflict: boolean; newGroup: number; oldGroup: number } | undefined

      the ids involved, or undefined when both were already in one group

      RewriteNoMatchError when the two are fixed to different terms, which no solution can satisfy

    • Carries the expressions of the disappearing group over - it is no longer reachable, so the constraints it holds would otherwise be lost. Ranges and terms are merged by TermClusterSet itself.

      Parameters

      • oldGroup: number

        The group disappearing

      • newGroup: number

        The group surviving

      Returns void

    • Registers an equality constraint between two terms, variables or expressions - the main entry point for adding constraints.

      Parameters

      • from: Term | Expression

        Term, variable, or expression (typically from the mapping head)

      • to: Term

        Term or variable (typically from the triple pattern)

      Returns void

      RewriteNoMatchError if the terms do not match, or the constraints conflict

    • Registers an expression the group's value has to equal.

      TODO: narrow the group by what the expression can produce - the term type an operator returns is a range like any other, and one that no longer meets the group's is a contradiction the rewriting currently leaves to evaluation.

      Parameters

      • group: number

        The group ID

      • expression: Expression

        The expression every value of the group equals

      Returns void

    • Registers a concrete term binding to a group: the throwing wrapper around assertTerm the unfolding needs, a group asked to be two terms at once matching nothing at all.

      Parameters

      • group: number

        The group ID

      • term: RawTerm

        The term to bind, a triple term included

      Returns void

      RewriteNoMatchError if the term conflicts with an existing binding or range

    • The term every value of the group equals, reading a shape back as the triple term it stands for.

      Every position is whatever fixes it, or else the mapping variable naming it - the same variable the mapping body binds, which is what lets the BIND(<<( ?mi_s ?mi_p ?mi_o )>> AS ?uq_o) this feeds name values the subselect really projects.

      Parameters

      • group: number

        The group to look up

      Returns RawTerm | undefined

      the term, or undefined when nothing fixes the group, or when a position of its shape is fixed by nothing and named by nothing

    • Sorts the variables within each cluster, mapping variables first and by name within each of the two.

      The mapping variables coming first is what resolvedTermOf and the rewriting read a cluster by: the first variable of a cluster is the one the subselect really projects, so a user query variable landing there would name a variable nothing binds. It is ordered on isUserQueryVar rather than left to the names, which only happen to sort that way while the prefixes both start where they do.

      Sorts the lists in place, which is a write like any other: what a group's first value is decides what every read of it names, so the stamp has to move on even though the members themselves do not change.

      Returns void