Skip to content

Commit

Permalink
repo-sqale: implemented inducements in the assignment table + tests
Browse files Browse the repository at this point in the history
  • Loading branch information
virgo47 committed Apr 29, 2021
1 parent 30eac25 commit f84cc55
Show file tree
Hide file tree
Showing 9 changed files with 236 additions and 66 deletions.
47 changes: 7 additions & 40 deletions repo/repo-sqale/sql/pgnew-repo.sql
Expand Up @@ -1198,19 +1198,17 @@ CREATE INDEX m_form_name_orig_idx ON m_form (name_orig);
ALTER TABLE m_form ADD CONSTRAINT m_form_name_norm_key UNIQUE (name_norm);
-- endregion

-- region Assignment/Inducement tables
-- region Assignment/Inducement table
-- Represents AssignmentType, see https://wiki.evolveum.com/display/midPoint/Assignment
-- and also https://wiki.evolveum.com/display/midPoint/Assignment+vs+Inducement
-- TODO: if we never need mix of inducements and assignments then let's have two separate tables
-- consult with Rado/Katka/Palo
-- TODO: partitioning, not by object type, it's not even... hash-something?
-- TODO: partitioning, probably not by object type, it's not even... hash-something?
-- select assignmentowner, count(*) From m_assignment group by assignmentowner;
--1 45 (inducements)
--0 48756229
-- abstract common structure for m_assignment and m_inducement
CREATE TABLE m_assignment_type (
-- owner_oid + containerType from m_container, final specification in sub-tables
-- new column may avoid join to object for some queries
CREATE TABLE m_assignment (
owner_oid UUID NOT NULL REFERENCES m_object_oid(oid) ON DELETE CASCADE,
-- this is different from other containers, this is not generated, app must provide it
containerType ContainerType NOT NULL CHECK (containerType IN ('ASSIGNMENT', 'INDUCEMENT')),
owner_type ObjectType NOT NULL,
lifecycleState TEXT/*VARCHAR(255)*/,
orderValue INTEGER,
Expand Down Expand Up @@ -1255,21 +1253,9 @@ CREATE TABLE m_assignment_type (
modifyChannel_id INTEGER,
modifyTimestamp TIMESTAMPTZ,

-- create PRIMARY KEY (owner_oid, cid) on sub-tables
-- no need to index owner_oid, it's part of the PK index

CHECK (FALSE) NO INHERIT
)
INHERITS(m_container);

CREATE TABLE m_assignment (
owner_oid UUID NOT NULL REFERENCES m_object_oid(oid) ON DELETE CASCADE,
containerType ContainerType GENERATED ALWAYS AS ('ASSIGNMENT') STORED,

PRIMARY KEY (owner_oid, cid)
-- no need to index owner_oid, it's part of the PK index
)
INHERITS(m_assignment_type);
INHERITS(m_container);

CREATE INDEX m_assignment_policySituation_idx ON m_assignment USING GIN(policysituations gin__int_ops);
CREATE INDEX m_assignment_ext_idx ON m_assignment USING gin (ext);
Expand Down Expand Up @@ -1313,25 +1299,6 @@ ALTER TABLE m_assignment_ref_modify_approver ADD CONSTRAINT m_assignment_ref_mod
FOREIGN KEY (owner_oid, assignment_cid) REFERENCES m_assignment (owner_oid, cid);

-- TODO index targetOid, relation_id?

CREATE TABLE m_inducement (
owner_oid UUID NOT NULL REFERENCES m_object_oid(oid) ON DELETE CASCADE,
containerType ContainerType GENERATED ALWAYS AS ('INDUCEMENT') STORED,

PRIMARY KEY (owner_oid, cid)
-- no need to index owner_oid, it's part of the PK index
)
INHERITS(m_assignment_type);

CREATE INDEX m_inducement_ext_idx ON m_inducement USING gin (ext);
CREATE INDEX m_inducement_validFrom_idx ON m_inducement (validFrom);
CREATE INDEX m_inducement_validTo_idx ON m_inducement (validTo);
CREATE INDEX m_inducement_targetRef_targetOid_idx ON m_inducement (targetRef_targetOid);
CREATE INDEX m_inducement_tenantRef_targetOid_idx ON m_inducement (tenantRef_targetOid);
CREATE INDEX m_inducement_orgRef_targetOid_idx ON m_inducement (orgRef_targetOid);
CREATE INDEX m_inducement_resourceRef_targetOid_idx ON m_inducement (resourceRef_targetOid);

-- TODO other tables like for assignments needed? policy situations, refs?
-- endregion

-- region Other object containers
Expand Down
Expand Up @@ -18,12 +18,9 @@
public class ObjectTemplateSqlTransformer
extends ObjectSqlTransformer<ObjectTemplateType, QObjectTemplate, MObject> {

private final QObjectTemplateMapping mapping;

public ObjectTemplateSqlTransformer(
SqlTransformerSupport transformerSupport, QObjectTemplateMapping mapping) {
super(transformerSupport, mapping);
this.mapping = mapping;
}

@Override
Expand Down
Expand Up @@ -8,9 +8,11 @@

import static com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType.*;

import com.evolveum.midpoint.repo.sqale.qmodel.common.MContainerType;
import com.evolveum.midpoint.repo.sqale.qmodel.common.QContainerMapping;
import com.evolveum.midpoint.repo.sqale.qmodel.object.MObject;
import com.evolveum.midpoint.repo.sqale.qmodel.ref.QReferenceMapping;
import com.evolveum.midpoint.repo.sqale.qmodel.role.MAbstractRole;
import com.evolveum.midpoint.repo.sqlbase.SqlTransformerSupport;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ActivationType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType;
Expand All @@ -19,6 +21,10 @@

/**
* Mapping between {@link QAssignment} and {@link AssignmentType}.
* There are separate instances for assignments and inducements and the instance also knows
* the {@link MAssignment#containerType} it should set.
* Only the instance for assignments is registered for queries as there is no way to distinguish
* between assignments and inducements when searching containers in the Query API anyway.
*
* @param <OR> type of the owner row
*/
Expand All @@ -27,13 +33,22 @@ public class QAssignmentMapping<OR extends MObject>

public static final String DEFAULT_ALIAS_NAME = "a";

public static final QAssignmentMapping<MObject> INSTANCE = new QAssignmentMapping<>();
/** Default assignment mapping instance, for queries it works for inducements too. */
public static final QAssignmentMapping<MObject> INSTANCE =
new QAssignmentMapping<>(MContainerType.ASSIGNMENT);

/** Inducement mapping instance, this must be used for inserting inducements. */
public static final QAssignmentMapping<MAbstractRole> INSTANCE_INDUCEMENT =
new QAssignmentMapping<>(MContainerType.INDUCEMENT);

private final MContainerType containerType;

// We can't declare Class<QAssignment<OR>>.class, so we cheat a bit.
@SuppressWarnings({ "unchecked", "rawtypes" })
private QAssignmentMapping() {
private QAssignmentMapping(MContainerType containerType) {
super(QAssignment.TABLE_NAME, DEFAULT_ALIAS_NAME,
AssignmentType.class, (Class) QAssignment.class);
this.containerType = containerType;

// TODO OWNER_TYPE is new thing and can help avoid join to concrete object table
// But this will likely require special treatment/heuristic.
Expand Down Expand Up @@ -121,7 +136,9 @@ public AssignmentSqlTransformer<OR> createTransformer(SqlTransformerSupport tran

@Override
public MAssignment newRowObject() {
return new MAssignment();
MAssignment row = new MAssignment();
row.containerType = this.containerType;
return row;
}

@Override
Expand Down
Expand Up @@ -17,12 +17,14 @@
public class FocusSqlTransformer<S extends FocusType, Q extends QFocus<R>, R extends MFocus>
extends ObjectSqlTransformer<S, Q, R> {

private final QFocusMapping<S, Q, R> mapping;

public FocusSqlTransformer(
SqlTransformerSupport transformerSupport, QFocusMapping<S, Q, R> mapping) {
super(transformerSupport, mapping);
this.mapping = mapping;
}

@Override
protected QFocusMapping<S, Q, R> mapping() {
return (QFocusMapping<S, Q, R>) super.mapping();
}

@SuppressWarnings("DuplicatedCode") // activation code duplicated with assignment
Expand Down Expand Up @@ -79,8 +81,8 @@ public void storeRelatedEntities(
super.storeRelatedEntities(row, schemaObject, jdbcSession);

storeRefs(row, schemaObject.getLinkRef(),
mapping.projectionReferenceMapping(), jdbcSession);
mapping().projectionReferenceMapping(), jdbcSession);
storeRefs(row, schemaObject.getPersonaRef(),
mapping.personaReferenceMapping(), jdbcSession);
mapping().personaReferenceMapping(), jdbcSession);
}
}
Expand Up @@ -6,12 +6,16 @@
*/
package com.evolveum.midpoint.repo.sqale.qmodel.role;

import java.util.List;

import org.jetbrains.annotations.NotNull;

import com.evolveum.midpoint.repo.sqale.qmodel.assignment.AssignmentSqlTransformer;
import com.evolveum.midpoint.repo.sqale.qmodel.focus.FocusSqlTransformer;
import com.evolveum.midpoint.repo.sqlbase.JdbcSession;
import com.evolveum.midpoint.repo.sqlbase.SqlTransformerSupport;
import com.evolveum.midpoint.xml.ns._public.common.common_3.AbstractRoleType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.AutoassignSpecificationType;

public class AbstractRoleSqlTransformer<
Expand All @@ -38,4 +42,23 @@ public AbstractRoleSqlTransformer(
row.riskLevel = abstractRole.getRiskLevel();
return row;
}

@Override
public void storeRelatedEntities(
@NotNull R row, @NotNull S schemaObject, @NotNull JdbcSession jdbcSession) {
super.storeRelatedEntities(row, schemaObject, jdbcSession);

List<AssignmentType> inducement = schemaObject.getInducement();
if (!inducement.isEmpty()) {
AssignmentSqlTransformer<R> transformer =
mapping().inducementMapping().createTransformer(transformerSupport);
inducement.forEach(assignment ->
transformer.insert(assignment, row, jdbcSession));
}
}

@Override
protected QAbstractRoleMapping<S, Q, R> mapping() {
return (QAbstractRoleMapping<S, Q, R>) super.mapping();
}
}
Expand Up @@ -13,7 +13,7 @@
*/
public class MAbstractRole extends MFocus {

public Boolean autoAssignEnabled;
public Boolean autoAssignEnabled; // autoassign/enabled
public String displayNameOrig;
public String displayNameNorm;
public String identifier;
Expand Down
Expand Up @@ -10,6 +10,7 @@

import org.jetbrains.annotations.NotNull;

import com.evolveum.midpoint.repo.sqale.qmodel.assignment.QAssignmentMapping;
import com.evolveum.midpoint.repo.sqale.qmodel.focus.QFocusMapping;
import com.evolveum.midpoint.repo.sqlbase.SqlTransformerSupport;
import com.evolveum.midpoint.xml.ns._public.common.common_3.AbstractRoleType;
Expand Down Expand Up @@ -48,6 +49,16 @@ protected QAbstractRoleMapping(
addItemMapping(F_IDENTIFIER, stringMapper(q -> q.identifier));
addItemMapping(F_REQUESTABLE, booleanMapper(q -> q.requestable));
addItemMapping(F_RISK_LEVEL, stringMapper(q -> q.riskLevel));

addContainerTableMapping(F_INDUCEMENT, inducementMapping(),
joinOn((o, a) -> o.oid.eq(a.ownerOid)));
}

/** Fixes rigid parametric types of static mapping instance to this instance. */
@NotNull
public QAssignmentMapping<R> inducementMapping() {
//noinspection unchecked
return (QAssignmentMapping<R>) QAssignmentMapping.INSTANCE_INDUCEMENT;
}

@Override
Expand Down
Expand Up @@ -110,13 +110,13 @@ public QueryTableMapping<S, Q, R> mapping() {
private void processModification(ItemDelta<?, ?> modification)
throws RepositoryException, SchemaException {
cidGenerator.processModification(modification);
resolveContainerIdsForDeletedValues(modification);
resolveContainerIdsForValuesToDelete(modification);
modification.applyTo(getPrismObject());

new DelegatingItemDeltaProcessor(this).process(modification);
}

private void resolveContainerIdsForDeletedValues(ItemDelta<?, ?> modification) {
private void resolveContainerIdsForValuesToDelete(ItemDelta<?, ?> modification) {
if (!modification.isDelete()) {
return;
}
Expand Down

0 comments on commit f84cc55

Please sign in to comment.