AmpersandTarski / Ampersand

Build database applications faster than anyone else, and keep your data pollution free as a bonus.
http://ampersandtarski.github.io/
GNU General Public License v3.0
40 stars 8 forks source link

Switching between invariance and process rule #1379

Open stefjoosten opened 1 year ago

stefjoosten commented 1 year ago

@sjcjoosten If you like, would you refine the following feature?

Is your feature request related to a problem? Please describe. Currently, the difference between an invariant and a process rule is defined statically. If the script defines a role to maintain the rule, it is a process rule and we get yellow violations that do not block progress. Otherwise, we get red violations the user must resolve, or else the system blocks. The problem is that this is decided at compile time. However, in many cases, I want to switch between invariance and process rule at runtime.

Describe the solution you'd like As a user, I want to be able to assign and unassign a rule to a role at run time, so I can influence the manual enforcement dynamically.

In practice, this will be done not by anyone but most likely by a designated role, such as a functional support guy or something. I want to be able to decide on that when writing the script.

Impact This functionality will most likely be a prerequisite to implementing the new paper on incremental development.

hanjoosten commented 1 year ago

This could potentially have great impact on the way rules are currently implemented. Just a few examples:

Michiel-s commented 1 year ago

This could potentially have great impact on the way rules are currently implemented. Just a few examples:

  • The database structure is derived from the rules. Broad tables are defined based on invariants. If an invariant becomes a signal rule at runtime, we cannot rely on the database structure to enforce invariants. Hence, we can only have binary tables. This will likely have a dramatic deterioration effect on performance.

I think it is the opposite; really easy, hardly any impact.

Regarding rules and database structure

@hanjoosten; keep in mind that the UNI, TOT, INJ and SUR annotations for relations are used for 2 purposes. 1) They define the multiplicity of the conceptual model and 2) they are syntactic sugar for invariant rules. You refer to the rules (2) and state that the database structure (1) is derived from the rules. That is simply not the case as I explained before in https://github.com/AmpersandTarski/Ampersand/issues/398#issuecomment-969270445.

To simply test that database structure is not derived from rules, just rewrite:

RELATION r[A*B] [UNI]

to

RELATION r[A*B]
RULE "uni" : r~;r |- I[B]

and notice that for the first script r gets a single column in table A and for the second script r gets its own binary table. So rules are derived from relation annotations, but not the other way around.

The actual rule that is derived from RELATION r[A*B] [UNI] is btw r [A*B]; -I[B];r [A*B]~ |- -I[A], but also using that specific rule in your script doesn't impact the database scheme.

Moving to the feature request

The application runtime is implemented by our prototype framework, which is configured by the output of the compiler (json files). The type of rule (invariant or process/signal rule) and the role assignment for signal rules is currently static. Below an example of the output of the compiler for a certain rule r1:

{
    "invariants": [...],
    "signals": [
        {
            "name": "r1",
            "message": "There are projects that don't have a name\n",
            "meaning": "Every project MUST have a name\n",
            "ruleAdl": "I[Project] |- projectName [Project*ProjectName];projectName [Project*ProjectName]~",
            "conjunctIds": ["conj_57"],
            "origin": "./project-administration/src/ProjectAdministration.adl:30:3",
            "pairView": [
            ],
            "srcConceptId": "Project",
            "tgtConceptId": "Project"
        },
        ...
    ]
}

As you can see there are two lists. Currently the backend determines the type of rule (invariant/signal) based on the list the rule is defined in. But that is not the only option we have. We can also derive this from the rule being mentioned in the roles.json. Rules that are maintained by a role are signal rules; others are invariants.

{
    "id": "Planner",
    "name": "Planner",
    "maintains": ["r1"]
}

Making this dynamic at runtime

Like how we did with interface roles (determining the allowed acces to interfaces based on active roles), we can move the rule-role assignment to the database (=metadata). This would require to extend the model for the PrototypeContext and have that metadata inserted by the backend during (re)installation of the application using the compiler output.

We can then pick up the information about maintains from the database and create Ampersand interfaces to alter this relation on the fly. In the same way as you currently can do for interface-role access. Try it out in your prototype app at http://localhost/#/List_32_all_32_interfaces.

My conclusion

Very easy to implement; we've done the trick before.

Steps to take: Compiler repo

hanjoosten commented 1 year ago

I think it is the opposite; really easy, hardly any impact.

I don't see how easy it would be to facilitate the removal of a UNI rule during runtime. IMHO the database structure must be modified to facilitate this.

hanjoosten commented 1 year ago

I do agree however that we could implement this feature for a subset of rules: The rules that do not impact the database structure. So all rules except for the propertyrules of { UNI, INJ}.

Michiel-s commented 1 year ago

I think it is the opposite; really easy, hardly any impact.

I don't see how easy it would be to facilitate the removal of a UNI rule during runtime. IMHO the database structure must be modified to facilitate this.

You're right, we cannot change the database scheme at runtime. Therefore I tried to explain that specifying UNI at a relation definition have two affects: 1) it determines the multiplicity constraints on the model, used for database schema and 2) it creates an invariant RULE for the uni constraint. The latter is not needed because the constraint is already enforced by the database. We cannot change (1) during runtime, but (2) can be changed to a signal rule.

So only when you specify a univalence using RULE definition without using a the UNI for a relation, it's possible.

But let's focus on the main reason for this feature request. I think it's not about the multiplicity constraints, but for all those other rules that can be specified.