Skip to content

Commit

Permalink
repo-sqale: we're inserting containers during modification, finally
Browse files Browse the repository at this point in the history
Introduced QOwnedByMapping and TransformerForOwnedBy, this helped unify
the way how owned rows are inserted.
RefTableItemDeltaProcessor and TableContainerDeltaProcessor finished.
MObjectType was fixed with missing Q-types (noncritical but nice).
  • Loading branch information
virgo47 committed Apr 22, 2021
1 parent 2107d0a commit 8d092e3
Show file tree
Hide file tree
Showing 25 changed files with 141 additions and 62 deletions.
Expand Up @@ -34,6 +34,7 @@
import com.evolveum.midpoint.repo.sqale.operations.AddObjectOperation;
import com.evolveum.midpoint.repo.sqale.qmodel.SqaleTableMapping;
import com.evolveum.midpoint.repo.sqale.qmodel.object.MObject;
import com.evolveum.midpoint.repo.sqale.qmodel.object.MObjectType;
import com.evolveum.midpoint.repo.sqale.qmodel.object.QObject;
import com.evolveum.midpoint.repo.sqlbase.*;
import com.evolveum.midpoint.repo.sqlbase.mapping.QueryTableMapping;
Expand Down Expand Up @@ -412,10 +413,14 @@ RootUpdateContext<S, Q, R> prepareUpdateContext(

S object = rootMapping.createTransformer(transformerSupport)
.toSchemaObject(result, root, Collections.emptyList());

R rootRow = rootMapping.newRowObject();
rootRow.oid = oid;
rootRow.containerIdSeq = result.get(root.containerIdSeq);
// This column is generated, some sub-entities need it, but we can't push it to DB.
rootRow.objectType = MObjectType.fromSchemaType(object.getClass());
// we don't care about full object in row

return new RootUpdateContext<>(transformerSupport, jdbcSession, object, rootRow);
}

Expand Down
Expand Up @@ -10,6 +10,8 @@

import com.querydsl.core.types.Path;

import com.evolveum.midpoint.repo.sqale.qmodel.ref.QOwnedByMapping;
import com.evolveum.midpoint.repo.sqale.qmodel.ref.TransformerForOwnedBy;
import com.evolveum.midpoint.repo.sqlbase.JdbcSession;
import com.evolveum.midpoint.repo.sqlbase.querydsl.FlexibleRelationalPathBase;

Expand Down Expand Up @@ -55,4 +57,11 @@ public R row() {
public abstract Q path();

public abstract <P extends Path<T>, T> void set(P path, T value);

@SuppressWarnings("UnusedReturnValue")
public <TS, TR> TR insertOwnedRow(QOwnedByMapping<TS, TR, R> mapping, TS schemaObject) {
TransformerForOwnedBy<TS, TR, R> transformer =
mapping.createTransformer(transformerSupport());
return transformer.insert(schemaObject, row, jdbcSession);
}
}
Expand Up @@ -14,7 +14,6 @@
import com.evolveum.midpoint.repo.sqale.delta.ItemDeltaValueProcessor;
import com.evolveum.midpoint.repo.sqale.qmodel.ref.QReference;
import com.evolveum.midpoint.repo.sqale.qmodel.ref.QReferenceMapping;
import com.evolveum.midpoint.repo.sqale.qmodel.ref.ReferenceSqlTransformer;
import com.evolveum.midpoint.repo.sqlbase.querydsl.FlexibleRelationalPathBase;

/**
Expand All @@ -38,15 +37,7 @@ public RefTableItemDeltaProcessor(

@Override
public void addValues(Collection<Referencable> values) {
OR ownerRow = context.row();
ReferenceSqlTransformer<?, ?, OR> transformer =
refTableMapping.createTransformer(context.transformerSupport());

// TODO fix after common insert "child" contract is in place for refs and containers
// It looks like the insert belongs to context, but there is no common insert contract.
// Each transformer has different types and needs. What? No, I don't want to introduce
// owner row type as another parametrized type on the transformer, thank you.
values.forEach(ref -> transformer.insert(ref, ownerRow, context.jdbcSession()));
values.forEach(ref -> context.insertOwnedRow(refTableMapping, ref));
}

@Override
Expand Down
Expand Up @@ -16,7 +16,6 @@
import com.evolveum.midpoint.repo.sqale.qmodel.common.MContainer;
import com.evolveum.midpoint.repo.sqale.qmodel.common.QContainer;
import com.evolveum.midpoint.repo.sqale.qmodel.common.QContainerMapping;
import com.evolveum.midpoint.repo.sqale.qmodel.object.ContainerSqlTransformer;
import com.evolveum.midpoint.repo.sqlbase.querydsl.FlexibleRelationalPathBase;

/**
Expand Down Expand Up @@ -46,16 +45,7 @@ public TableContainerDeltaProcessor(

@Override
public void addValues(Collection<T> values) {
OR ownerRow = context.row();
ContainerSqlTransformer<T, Q, R, OR> transformer =
containerTableMapping.createTransformer(context.transformerSupport());

// It looks like the insert belongs to context, but there is no common insert contract.
// Each transformer has different types and needs. What? No, I don't want to introduce
// owner row type as another parametrized type on the transformer, thank you.
// TODO introduce owner type to sub-tables and revisit also RefTableItemDeltaProcessor
// perhaps it can go under context after all?
// values.forEach(ref -> transformer.insert(ref, ownerRow, context.jdbcSession()));
values.forEach(ref -> context.insertOwnedRow(containerTableMapping, ref));
}

@Override
Expand Down
Expand Up @@ -109,7 +109,7 @@ private String addObjectWithOid() throws SchemaException {
.populate(row)
.executeWithKey(root.oid);

row.objectType = objectType;
row.objectType = objectType; // sub-entities can use it, now it's safe to set it
transformer.storeRelatedEntities(row, schemaObject, jdbcSession);

jdbcSession.commit();
Expand Down Expand Up @@ -144,7 +144,7 @@ private String addObjectWithoutOid() throws SchemaException {
.execute();

row.oid = oid;
row.objectType = objectType;
row.objectType = objectType; // sub-entities can use it, now it's safe to set it
transformer.storeRelatedEntities(row, schemaObject, jdbcSession);

jdbcSession.commit();
Expand Down
Expand Up @@ -41,7 +41,7 @@
/**
* @param <S> schema type
* @param <Q> type of entity path
* @param <R> type of the transformed data, a row bean
* @param <R> type of the row bean for the table
*/
public abstract class SqaleTransformerBase<S, Q extends FlexibleRelationalPathBase<R>, R>
implements SqlTransformer<S, Q, R> {
Expand Down
Expand Up @@ -26,8 +26,8 @@ public AssignmentSqlTransformer(

// about duplication see the comment in ObjectSqlTransformer.toRowObjectWithoutFullObject
@SuppressWarnings("DuplicatedCode")
public MAssignment insert(
AssignmentType assignment, MObject ownerRow, JdbcSession jdbcSession) {
@Override
public MAssignment insert(AssignmentType assignment, OR ownerRow, JdbcSession jdbcSession) {
MAssignment row = initRowObject(assignment, ownerRow.oid);

row.ownerType = ownerRow.objectType;
Expand Down
Expand Up @@ -11,6 +11,7 @@
import com.evolveum.midpoint.prism.Containerable;
import com.evolveum.midpoint.repo.sqale.qmodel.SqaleTableMapping;
import com.evolveum.midpoint.repo.sqale.qmodel.object.ContainerSqlTransformer;
import com.evolveum.midpoint.repo.sqale.qmodel.ref.QOwnedByMapping;
import com.evolveum.midpoint.repo.sqlbase.SqlTransformerSupport;

/**
Expand All @@ -22,7 +23,8 @@
* @param <OR> type of the owner row
*/
public class QContainerMapping<S extends Containerable, Q extends QContainer<R, OR>, R extends MContainer, OR>
extends SqaleTableMapping<S, Q, R> {
extends SqaleTableMapping<S, Q, R>
implements QOwnedByMapping<S, R, OR> {

public static final String DEFAULT_ALIAS_NAME = "c";

Expand Down
Expand Up @@ -20,7 +20,8 @@ public LookupTableRowSqlTransformer(
super(transformerSupport, mapping);
}

public void insert(LookupTableRowType lookupTableRow,
@Override
public MLookupTableRow insert(LookupTableRowType lookupTableRow,
MLookupTable ownerRow, JdbcSession jdbcSession) {

MLookupTableRow row = initRowObject(lookupTableRow, ownerRow.oid);
Expand All @@ -30,5 +31,6 @@ public void insert(LookupTableRowType lookupTableRow,
row.lastChangeTimestamp = MiscUtil.asInstant(lookupTableRow.getLastChangeTimestamp());

insert(row, jdbcSession);
return row;
}
}
Expand Up @@ -13,17 +13,20 @@
import com.evolveum.midpoint.repo.sqale.qmodel.common.MContainer;
import com.evolveum.midpoint.repo.sqale.qmodel.common.QContainer;
import com.evolveum.midpoint.repo.sqale.qmodel.common.QContainerMapping;
import com.evolveum.midpoint.repo.sqale.qmodel.ref.TransformerForOwnedBy;
import com.evolveum.midpoint.repo.sqlbase.JdbcSession;
import com.evolveum.midpoint.repo.sqlbase.SqlTransformerSupport;

/**
* @param <S> schema type
* @param <Q> type of entity path
* @param <R> type of the transformed data, a row bean
* @param <R> type of the row bean for the table
* @param <OR> type of the owner row (table owning the container)
*/
public class ContainerSqlTransformer
<S extends Containerable, Q extends QContainer<R, OR>, R extends MContainer, OR>
extends SqaleTransformerBase<S, Q, R> {
extends SqaleTransformerBase<S, Q, R>
implements TransformerForOwnedBy<S, R, OR> {

private final QContainerMapping<S, Q, R, OR> mapping;

Expand All @@ -48,4 +51,9 @@ public R initRowObject(S schemaObject, UUID ownerOid) {
// containerType is generated in DB, must be left null!
return row;
}

@Override
public R insert(S schemaObject, OR ownerRow, JdbcSession jdbcSession) {
throw new UnsupportedOperationException("insert not implemented in the subclass");
}
}
Expand Up @@ -19,7 +19,7 @@
public class MObject {

public UUID oid;
// objectType is read-only, it must be null before insert/updates of the whole M-bean
// generated column must be null for insert/updates, but trigger fixes it, so we can use it!
public MObjectType objectType;
public String nameOrig;
public String nameNorm;
Expand Down
Expand Up @@ -13,22 +13,26 @@

import org.jetbrains.annotations.NotNull;

import com.evolveum.midpoint.repo.sqale.qmodel.QObjectTemplate;
import com.evolveum.midpoint.repo.sqale.qmodel.accesscert.QAccessCertificationDefinition;
import com.evolveum.midpoint.repo.sqale.qmodel.cases.QCase;
import com.evolveum.midpoint.repo.sqale.qmodel.connector.QConnector;
import com.evolveum.midpoint.repo.sqale.qmodel.connector.QConnectorHost;
import com.evolveum.midpoint.repo.sqale.qmodel.focus.QFocus;
import com.evolveum.midpoint.repo.sqale.qmodel.focus.QGenericObject;
import com.evolveum.midpoint.repo.sqale.qmodel.focus.QUser;
import com.evolveum.midpoint.repo.sqale.qmodel.lookuptable.QLookupTable;
import com.evolveum.midpoint.repo.sqale.qmodel.node.QNode;
import com.evolveum.midpoint.repo.sqale.qmodel.object.QAssignmentHolderMapping.QAssignmentHolder;
import com.evolveum.midpoint.repo.sqale.qmodel.other.QDashboard;
import com.evolveum.midpoint.repo.sqale.qmodel.other.QObjectCollection;
import com.evolveum.midpoint.repo.sqale.qmodel.other.*;
import com.evolveum.midpoint.repo.sqale.qmodel.report.QReport;
import com.evolveum.midpoint.repo.sqale.qmodel.report.QReportData;
import com.evolveum.midpoint.repo.sqale.qmodel.resource.QResource;
import com.evolveum.midpoint.repo.sqale.qmodel.role.QAbstractRole;
import com.evolveum.midpoint.repo.sqale.qmodel.role.QArchetype;
import com.evolveum.midpoint.repo.sqale.qmodel.role.QRole;
import com.evolveum.midpoint.repo.sqale.qmodel.role.QService;
import com.evolveum.midpoint.repo.sqale.qmodel.shadow.QShadow;
import com.evolveum.midpoint.repo.sqale.qmodel.system.QSecurityPolicy;
import com.evolveum.midpoint.repo.sqale.qmodel.system.QSystemConfiguration;
import com.evolveum.midpoint.repo.sqale.qmodel.system.QValuePolicy;
Expand All @@ -40,32 +44,33 @@ public enum MObjectType {

// mapping of codes and schema types must be unique
ABSTRACT_ROLE(QAbstractRole.CLASS, AbstractRoleType.class),
ACCESS_CERTIFICATION_CAMPAIGN(null, AccessCertificationCampaignType.class),
ACCESS_CERTIFICATION_DEFINITION(null, AccessCertificationDefinitionType.class),
ACCESS_CERTIFICATION_CAMPAIGN(null, AccessCertificationCampaignType.class), // TODO
ACCESS_CERTIFICATION_DEFINITION(
QAccessCertificationDefinition.class, AccessCertificationDefinitionType.class),
ARCHETYPE(QArchetype.class, ArchetypeType.class),
ASSIGNMENT_HOLDER(QAssignmentHolder.class, AssignmentHolderType.class),
CASE(QCase.class, CaseType.class),
CONNECTOR(QConnector.class, ConnectorType.class),
CONNECTOR_HOST(QConnectorHost.class, ConnectorHostType.class),
DASHBOARD(QDashboard.class, DashboardType.class),
FOCUS(QFocus.CLASS, FocusType.class),
FORM(null, FormType.class),
FUNCTION_LIBRARY(null, FunctionLibraryType.class),
GENERIC_OBJECT(null, GenericObjectType.class),
FORM(QForm.class, FormType.class),
FUNCTION_LIBRARY(QFunctionLibrary.class, FunctionLibraryType.class),
GENERIC_OBJECT(QGenericObject.class, GenericObjectType.class),
LOOKUP_TABLE(QLookupTable.class, LookupTableType.class),
NODE(QNode.class, NodeType.class),
OBJECT(QObject.CLASS, ObjectType.class),
OBJECT_COLLECTION(QObjectCollection.class, ObjectCollectionType.class),
OBJECT_TEMPLATE(null, ObjectTemplateType.class),
ORG(null, OrgType.class),
OBJECT_TEMPLATE(QObjectTemplate.class, ObjectTemplateType.class),
ORG(null, OrgType.class), // TODO
REPORT(QReport.class, ReportType.class),
REPORT_DATA(QReportData.class, ReportDataType.class),
RESOURCE(null, ResourceType.class),
RESOURCE(QResource.class, ResourceType.class),
ROLE(QRole.class, RoleType.class),
SECURITY_POLICY(QSecurityPolicy.class, SecurityPolicyType.class),
SEQUENCE(null, SequenceType.class),
SEQUENCE(QSequence.class, SequenceType.class),
SERVICE(QService.class, ServiceType.class),
SHADOW(null, ShadowType.class),
SHADOW(QShadow.class, ShadowType.class),
SYSTEM_CONFIGURATION(QSystemConfiguration.class, SystemConfigurationType.class),
TASK(QTask.class, TaskType.class),
USER(QUser.class, UserType.class),
Expand Down
Expand Up @@ -21,7 +21,6 @@
import com.evolveum.midpoint.repo.sqale.SqaleUtils;
import com.evolveum.midpoint.repo.sqale.qmodel.SqaleTransformerBase;
import com.evolveum.midpoint.repo.sqale.qmodel.assignment.AssignmentSqlTransformer;
import com.evolveum.midpoint.repo.sqale.qmodel.assignment.QAssignmentMapping;
import com.evolveum.midpoint.repo.sqale.qmodel.common.QUri;
import com.evolveum.midpoint.repo.sqlbase.JdbcSession;
import com.evolveum.midpoint.repo.sqlbase.SqlTransformerSupport;
Expand Down Expand Up @@ -96,7 +95,7 @@ public R toRowObjectWithoutFullObject(S schemaObject, JdbcSession jdbcSession) {
R row = mapping.newRowObject();

row.oid = oidToUUid(schemaObject.getOid());
// objectType MUST be left NULL, it's determined by PG
// objectType MUST be left NULL for INSERT, it's determined by PG
setPolyString(schemaObject.getName(), o -> row.nameOrig = o, n -> row.nameNorm = n);
// fullObject is managed outside of this method
setReference(schemaObject.getTenantRef(),
Expand Down Expand Up @@ -150,6 +149,9 @@ public void storeRelatedEntities(
@NotNull R row, @NotNull S schemaObject, @NotNull JdbcSession jdbcSession) {
Objects.requireNonNull(row.oid);

// We're after insert, we can set this for the needs of owned entities (assignments).
row.objectType = MObjectType.fromSchemaType(schemaObject.getClass());

MetadataType metadata = schemaObject.getMetadata();
if (metadata != null) {
storeRefs(row, metadata.getCreateApproverRef(),
Expand All @@ -160,15 +162,15 @@ public void storeRelatedEntities(

List<TriggerType> triggers = schemaObject.getTrigger();
if (!triggers.isEmpty()) {
TriggerSqlTransformer transformer =
QTriggerMapping.INSTANCE.createTransformer(transformerSupport);
TriggerSqlTransformer<R> transformer =
mapping.triggerMapping().createTransformer(transformerSupport);
triggers.forEach(t -> transformer.insert(t, row, jdbcSession));
}

List<OperationExecutionType> operationExecutions = schemaObject.getOperationExecution();
if (!operationExecutions.isEmpty()) {
OperationExecutionSqlTransformer transformer =
QOperationExecutionMapping.INSTANCE.createTransformer(transformerSupport);
OperationExecutionSqlTransformer<R> transformer =
mapping.operationExecutionMapping().createTransformer(transformerSupport);
operationExecutions.forEach(oe -> transformer.insert(oe, row, jdbcSession));
}

Expand All @@ -190,8 +192,8 @@ private void storeAssignmentHolderEntities(
R row, AssignmentHolderType schemaObject, JdbcSession jdbcSession) {
List<AssignmentType> assignments = schemaObject.getAssignment();
if (!assignments.isEmpty()) {
AssignmentSqlTransformer transformer =
QAssignmentMapping.INSTANCE.createTransformer(transformerSupport);
AssignmentSqlTransformer<R> transformer =
mapping.assignmentMapping().createTransformer(transformerSupport);
assignments.forEach(assignment ->
transformer.insert(assignment, row, jdbcSession));
}
Expand Down
Expand Up @@ -19,7 +19,9 @@ public OperationExecutionSqlTransformer(
super(transformerSupport, mapping);
}

public void insert(OperationExecutionType schemaObject, MObject ownerRow, JdbcSession jdbcSession) {
@Override
public MOperationExecution insert(
OperationExecutionType schemaObject, OR ownerRow, JdbcSession jdbcSession) {
MOperationExecution row = initRowObject(schemaObject, ownerRow.oid);

row.status = schemaObject.getStatus();
Expand All @@ -35,5 +37,6 @@ public void insert(OperationExecutionType schemaObject, MObject ownerRow, JdbcSe
row.timestampValue = MiscUtil.asInstant(schemaObject.getTimestamp());

insert(row, jdbcSession);
return row;
}
}
Expand Up @@ -100,21 +100,21 @@ protected QObjectMapping(

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

/** Fixes rigid parametric types of static mapping instance to this instance. */
@NotNull
private QOperationExecutionMapping<R> operationExecutionMapping() {
public QOperationExecutionMapping<R> operationExecutionMapping() {
//noinspection unchecked
return (QOperationExecutionMapping<R>) QOperationExecutionMapping.INSTANCE;
}

/** Fixes rigid parametric types of static mapping instance to this instance. */
@NotNull
private QTriggerMapping<R> triggerMapping() {
public QTriggerMapping<R> triggerMapping() {
//noinspection unchecked
return (QTriggerMapping<R>) QTriggerMapping.INSTANCE;
}
Expand Down
Expand Up @@ -27,6 +27,14 @@ public class QOperationExecution<OR extends MObject> extends QContainer<MOperati

private static final long serialVersionUID = -6856661540710930040L;

/**
* If `QOperationExecution.class` is not enough because of generics,
* try `QOperationExecution.CLASS`.
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public static final Class<QOperationExecution<MObject>> CLASS =
(Class) QOperationExecution.class;

public static final String TABLE_NAME = "m_operation_execution";

public static final ColumnMetadata STATUS =
Expand Down

0 comments on commit 8d092e3

Please sign in to comment.