Skip to content

Commit

Permalink
repo-sqale: MObjectType introduced as PG enum + few columns migrated
Browse files Browse the repository at this point in the history
  • Loading branch information
virgo47 committed Mar 10, 2021
1 parent 7824688 commit 6747f94
Show file tree
Hide file tree
Showing 16 changed files with 335 additions and 209 deletions.
226 changes: 112 additions & 114 deletions repo/repo-sqale/sql/pgnew-repo.sql

Large diffs are not rendered by default.

Expand Up @@ -37,46 +37,47 @@
import com.evolveum.midpoint.schema.constants.ObjectTypes;
import com.evolveum.midpoint.xml.ns._public.common.common_3.*;

public enum MObjectTypeMapping {
public enum MObjectType {

// mapping of codes and schema types must be unique, but one Q-class can serve multiple types
// mapping of codes and schema types must be unique
ABSTRACT_ROLE(16, QAbstractRole.CLASS, AbstractRoleType.class),
ACCESS_CERTIFICATION_CAMPAIGN(22, null, AccessCertificationCampaignType.class),
ACCESS_CERTIFICATION_DEFINITION(21, null, AccessCertificationDefinitionType.class),
ARCHETYPE(29, QArchetype.class, ArchetypeType.class),
ASSIGNMENT_HOLDER(18, QAssignmentHolder.class, AssignmentHolderType.class),
CASE(26, QCase.class, CaseType.class),
CONNECTOR(0, QConnector.class, ConnectorType.class),
CONNECTOR_HOST(1, QConnectorHost.class, ConnectorHostType.class),
DASHBOARD(30, QDashboard.class, DashboardType.class),
FOCUS(17, QFocus.CLASS, FocusType.class),
FORM(25, null, FormType.class),
FUNCTION_LIBRARY(27, null, FunctionLibraryType.class),
GENERIC_OBJECT(2, null, GenericObjectType.class),
LOOKUP_TABLE(20, QLookupTable.class, LookupTableType.class),
NODE(14, QNode.class, NodeType.class),
OBJECT(3, QObject.CLASS, ObjectType.class),
VALUE_POLICY(4, QValuePolicy.class, ValuePolicyType.class),
RESOURCE(5, null, ResourceType.class),
SHADOW(6, null, ShadowType.class),
ROLE(7, QRole.class, RoleType.class),
SYSTEM_CONFIGURATION(8, QSystemConfiguration.class, SystemConfigurationType.class),
TASK(9, QTask.class, TaskType.class),
USER(10, QUser.class, UserType.class),
REPORT(11, QReport.class, ReportType.class),
REPORT_DATA(12, QReportData.class, ReportDataType.class),
OBJECT_COLLECTION(28, QObjectCollection.class, ObjectCollectionType.class),
OBJECT_TEMPLATE(13, null, ObjectTemplateType.class),
NODE(14, QNode.class, NodeType.class),
ORG(15, null, OrgType.class),
ABSTRACT_ROLE(16, QAbstractRole.CLASS, AbstractRoleType.class),
FOCUS(17, QFocus.CLASS, FocusType.class),
ASSIGNMENT_HOLDER(18, QAssignmentHolder.class, AssignmentHolderType.class),
REPORT(11, QReport.class, ReportType.class),
REPORT_DATA(12, QReportData.class, ReportDataType.class),
RESOURCE(5, null, ResourceType.class),
ROLE(7, QRole.class, RoleType.class),
SECURITY_POLICY(19, QSecurityPolicy.class, SecurityPolicyType.class),
LOOKUP_TABLE(20, QLookupTable.class, LookupTableType.class),
ACCESS_CERTIFICATION_DEFINITION(21, null, AccessCertificationDefinitionType.class),
ACCESS_CERTIFICATION_CAMPAIGN(22, null, AccessCertificationCampaignType.class),
SEQUENCE(23, null, SequenceType.class),
SERVICE(24, QService.class, ServiceType.class),
FORM(25, null, FormType.class),
CASE(26, QCase.class, CaseType.class),
FUNCTION_LIBRARY(27, null, FunctionLibraryType.class),
OBJECT_COLLECTION(28, QObjectCollection.class, ObjectCollectionType.class),
ARCHETYPE(29, QArchetype.class, ArchetypeType.class),
DASHBOARD(30, QDashboard.class, DashboardType.class);
SHADOW(6, null, ShadowType.class),
SYSTEM_CONFIGURATION(8, QSystemConfiguration.class, SystemConfigurationType.class),
TASK(9, QTask.class, TaskType.class),
USER(10, QUser.class, UserType.class),
VALUE_POLICY(4, QValuePolicy.class, ValuePolicyType.class);

// TODO drop the codes, pg enum type will cover it
private final int code;
private final Class<? extends QObject<?>> queryType;
private final Class<? extends ObjectType> schemaType;

MObjectTypeMapping(
MObjectType(
int code,
Class<? extends QObject<?>> queryType,
Class<? extends ObjectType> schemaType) {
Expand All @@ -86,14 +87,14 @@ public enum MObjectTypeMapping {
}

// DB code -> enum conversion
public static final Map<Integer, MObjectTypeMapping> CODE_TO_ENUM = new HashMap<>();
public static final Map<Integer, MObjectType> CODE_TO_ENUM = new HashMap<>();

// schema type QName -> enum conversion
public static final Map<Class<? extends ObjectType>, MObjectTypeMapping> SCHEMA_TYPE_TO_ENUM =
public static final Map<Class<? extends ObjectType>, MObjectType> SCHEMA_TYPE_TO_ENUM =
new HashMap<>();

static {
for (MObjectTypeMapping value : values()) {
for (MObjectType value : values()) {
if (CODE_TO_ENUM.put(value.code, value) != null) {
throw new IllegalArgumentException("MObjectTypeMapping value " + value
+ " uses duplicate code: " + value.code);
Expand All @@ -106,18 +107,18 @@ public enum MObjectTypeMapping {
}

@NotNull
public static MObjectTypeMapping fromCode(int code) {
public static MObjectType fromCode(int code) {
return Objects.requireNonNull(CODE_TO_ENUM.get(code),
"No MObjectTypeMapping found for object type code " + code);
}

@NotNull
public static MObjectTypeMapping fromTypeQName(QName typeQName) {
public static MObjectType fromTypeQName(QName typeQName) {
return fromSchemaType(ObjectTypes.getObjectTypeClass(typeQName));
}

@NotNull
public static MObjectTypeMapping fromSchemaType(Class<? extends ObjectType> objectTypeClass) {
public static MObjectType fromSchemaType(Class<? extends ObjectType> objectTypeClass) {
return Objects.requireNonNull(SCHEMA_TYPE_TO_ENUM.get(objectTypeClass),
"No MObjectTypeMapping found for object type " + objectTypeClass);
}
Expand Down
Expand Up @@ -13,6 +13,7 @@
import com.querydsl.core.types.EntityPath;
import com.querydsl.core.types.ExpressionUtils;
import com.querydsl.core.types.Predicate;
import com.querydsl.core.types.dsl.EnumPath;
import com.querydsl.core.types.dsl.NumberPath;

import com.evolveum.midpoint.prism.PrismConstants;
Expand All @@ -26,7 +27,7 @@

/**
* Filter processor for reference item paths embedded in table as three columns.
* OID is represented by UUID column, type by ID (see {@link MObjectTypeMapping} and relation
* OID is represented by UUID column, type by ID (see {@link MObjectType} and relation
* by Integer (foreign key) to {@link QUri}.
*/
public class RefItemFilterProcessor extends ItemFilterProcessor<RefFilter> {
Expand All @@ -36,21 +37,21 @@ public class RefItemFilterProcessor extends ItemFilterProcessor<RefFilter> {
*/
public static ItemSqlMapper mapper(
Function<EntityPath<?>, UuidPath> rootToOidPath,
Function<EntityPath<?>, NumberPath<Integer>> rootToTypePath,
Function<EntityPath<?>, EnumPath<MObjectType>> rootToTypePath,
Function<EntityPath<?>, NumberPath<Integer>> rootToRelationIdPath) {
return new ItemSqlMapper(ctx -> new RefItemFilterProcessor(
ctx, rootToOidPath, rootToTypePath, rootToRelationIdPath));
}

// only oidPath is strictly not-null, but then the filter better not ask for type or relation
private final UuidPath oidPath;
private final NumberPath<Integer> typePath;
private final EnumPath<MObjectType> typePath;
private final NumberPath<Integer> relationIdPath;

private RefItemFilterProcessor(
SqlQueryContext<?, ?, ?> context,
Function<EntityPath<?>, UuidPath> rootToOidPath,
Function<EntityPath<?>, NumberPath<Integer>> rootToTypePath,
Function<EntityPath<?>, EnumPath<MObjectType>> rootToTypePath,
Function<EntityPath<?>, NumberPath<Integer>> rootToRelationIdPath) {
this(context,
rootToOidPath.apply(context.path()),
Expand All @@ -60,7 +61,7 @@ private RefItemFilterProcessor(

// exposed mainly for RefTableItemFilterProcessor
RefItemFilterProcessor(SqlQueryContext<?, ?, ?> context,
UuidPath oidPath, NumberPath<Integer> typePath, NumberPath<Integer> relationIdPath) {
UuidPath oidPath, EnumPath<MObjectType> typePath, NumberPath<Integer> relationIdPath) {
super(context);
this.oidPath = oidPath;
this.typePath = typePath;
Expand Down Expand Up @@ -106,9 +107,9 @@ private Predicate processSingleValue(RefFilter filter, PrismReferenceValue ref)
predicateWithNotTreated(relationIdPath, relationIdPath.eq(relationId)));
}
if (ref.getTargetType() != null) {
int typeCode = MObjectTypeMapping.fromTypeQName(ref.getTargetType()).code();
MObjectType objectType = MObjectType.fromTypeQName(ref.getTargetType());
predicate = ExpressionUtils.and(predicate,
predicateWithNotTreated(typePath, typePath.eq(typeCode)));
predicateWithNotTreated(typePath, typePath.eq(objectType)));
} else if (!filter.isTargetTypeNullAsAny()) {
predicate = ExpressionUtils.and(predicate, typePath.isNull());
}
Expand Down
@@ -0,0 +1,119 @@
/*
* Copyright (C) 2010-2021 Evolveum and contributors
*
* This work is dual-licensed under the Apache License 2.0
* and European Union Public License. See LICENSE file for details.
*/
package com.evolveum.midpoint.repo.sqale;

import java.util.List;
import java.util.UUID;
import java.util.function.Function;

import com.querydsl.core.types.EntityPath;
import com.querydsl.core.types.ExpressionUtils;
import com.querydsl.core.types.Predicate;
import com.querydsl.core.types.dsl.NumberPath;

import com.evolveum.midpoint.prism.PrismConstants;
import com.evolveum.midpoint.prism.PrismReferenceValue;
import com.evolveum.midpoint.prism.query.RefFilter;
import com.evolveum.midpoint.repo.sqale.qmodel.common.QUri;
import com.evolveum.midpoint.repo.sqlbase.SqlQueryContext;
import com.evolveum.midpoint.repo.sqlbase.mapping.item.ItemFilterProcessor;
import com.evolveum.midpoint.repo.sqlbase.mapping.item.ItemSqlMapper;
import com.evolveum.midpoint.repo.sqlbase.querydsl.UuidPath;

/**
* Filter processor for reference item paths embedded in table as three columns.
* TODO: This version supports integer target type path while migrating to enum version.
* OID is represented by UUID column, type by ID (see {@link MObjectType} and relation
* by Integer (foreign key) to {@link QUri}.
*/
@Deprecated
public class RefItemIntFilterProcessor extends ItemFilterProcessor<RefFilter> {

/**
* Returns the mapper function creating the ref-filter processor from query context.
*/
public static ItemSqlMapper mapper(
Function<EntityPath<?>, UuidPath> rootToOidPath,
Function<EntityPath<?>, NumberPath<Integer>> rootToTypePath,
Function<EntityPath<?>, NumberPath<Integer>> rootToRelationIdPath) {
return new ItemSqlMapper(ctx -> new RefItemIntFilterProcessor(
ctx, rootToOidPath, rootToTypePath, rootToRelationIdPath));
}

// only oidPath is strictly not-null, but then the filter better not ask for type or relation
private final UuidPath oidPath;
private final NumberPath<Integer> typePath;
private final NumberPath<Integer> relationIdPath;

private RefItemIntFilterProcessor(
SqlQueryContext<?, ?, ?> context,
Function<EntityPath<?>, UuidPath> rootToOidPath,
Function<EntityPath<?>, NumberPath<Integer>> rootToTypePath,
Function<EntityPath<?>, NumberPath<Integer>> rootToRelationIdPath) {
this(context,
rootToOidPath.apply(context.path()),
rootToTypePath != null ? rootToTypePath.apply(context.path()) : null,
rootToRelationIdPath != null ? rootToRelationIdPath.apply(context.path()) : null);
}

// exposed mainly for RefTableItemFilterProcessor
RefItemIntFilterProcessor(SqlQueryContext<?, ?, ?> context,
UuidPath oidPath, NumberPath<Integer> typePath, NumberPath<Integer> relationIdPath) {
super(context);
this.oidPath = oidPath;
this.typePath = typePath;
this.relationIdPath = relationIdPath;
}

@Override
public Predicate process(RefFilter filter) {
List<PrismReferenceValue> values = filter.getValues();
if (values == null || values.isEmpty()) {
return oidPath.isNull();
}
if (values.size() == 1) {
return processSingleValue(filter, values.get(0));
}

Predicate predicate = null;
for (PrismReferenceValue ref : values) {
predicate = ExpressionUtils.or(predicate, processSingleValue(filter, ref));
}
return predicate;
}

private Predicate processSingleValue(RefFilter filter, PrismReferenceValue ref) {
Predicate predicate = null;
if (ref.getOid() != null) {
predicate = predicateWithNotTreated(oidPath,
oidPath.eq(UUID.fromString(ref.getOid())));
} else if (!filter.isOidNullAsAny()) {
predicate = oidPath.isNull();
}
if (ref.getRelation() == null) {
Integer defaultRelationId = ((SqaleRepoContext) context.sqlRepoContext())
.searchCachedUriId(context.prismContext().getDefaultRelation());
predicate = ExpressionUtils.and(predicate,
predicateWithNotTreated(relationIdPath, relationIdPath.eq(defaultRelationId)));
} else if (ref.getRelation().equals(PrismConstants.Q_ANY)) {
// no additional predicate needed
} else {
Integer relationId = ((SqaleRepoContext) context.sqlRepoContext())
.searchCachedUriId(ref.getRelation());
predicate = ExpressionUtils.and(predicate,
predicateWithNotTreated(relationIdPath, relationIdPath.eq(relationId)));
}
if (ref.getTargetType() != null) {
int typeCode = MObjectType.fromTypeQName(ref.getTargetType()).code();
predicate = ExpressionUtils.and(predicate,
predicateWithNotTreated(typePath, typePath.eq(typeCode)));
} else if (!filter.isTargetTypeNullAsAny()) {
predicate = ExpressionUtils.and(predicate, typePath.isNull());
}
return predicate;
}
}
Expand Up @@ -19,7 +19,7 @@

/**
* Filter processor for reference item paths resolved via {@link QReference} tables.
* This just joins the reference table and then delegates to {@link RefItemFilterProcessor}.
* This just joins the reference table and then delegates to {@link RefItemIntFilterProcessor}.
*/
public class RefTableItemFilterProcessor
extends ItemFilterProcessor<RefFilter> {
Expand All @@ -46,7 +46,7 @@ public Predicate process(RefFilter filter) {
.leftJoin(qReferenceMapping, (o, r) -> o.oid.eq(r.ownerOid));
QReference ref = refContext.path();

return new RefItemFilterProcessor(context, ref.targetOid, ref.targetType, ref.relationId)
return new RefItemIntFilterProcessor(context, ref.targetOid, ref.targetType, ref.relationId)
.process(filter);
}
}
Expand Up @@ -37,6 +37,7 @@ public SqaleRepoContext(

// each enum type must be registered if we want to map it as objects (to PG enum types)
querydslConfig.register(new EnumAsObjectType<>(MContainerType.class));
querydslConfig.register(new EnumAsObjectType<>(MObjectType.class));
querydslConfig.register(new EnumAsObjectType<>(MReferenceType.class));
querydslConfig.register(new EnumAsObjectType<>(OperationResultStatusType.class));
querydslConfig.register(new EnumAsObjectType<>(TaskExecutionStateType.class));
Expand Down
Expand Up @@ -17,7 +17,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.evolveum.midpoint.repo.sqale.MObjectTypeMapping;
import com.evolveum.midpoint.repo.sqale.MObjectType;
import com.evolveum.midpoint.repo.sqale.SqaleTransformerSupport;
import com.evolveum.midpoint.repo.sqlbase.JdbcSession;
import com.evolveum.midpoint.repo.sqlbase.SqlTransformerSupport;
Expand Down Expand Up @@ -77,13 +77,13 @@ protected void processExtensionColumns(S schemaObject, Tuple tuple, Q entityPath

/**
* Returns {@link ObjectReferenceType} with specified oid, proper type based on
* {@link MObjectTypeMapping} and, optionally, target name/description.
* {@link MObjectType} and, optionally, target name/description.
* Returns {@code null} if OID is null.
* Fails if OID is not null and {@code repoObjectType} is null.
*/
@Nullable
protected ObjectReferenceType objectReferenceType(
@Nullable String oid, MObjectTypeMapping repoObjectType, String targetName) {
@Nullable String oid, MObjectType repoObjectType, String targetName) {
if (oid == null) {
return null;
}
Expand All @@ -100,26 +100,26 @@ protected ObjectReferenceType objectReferenceType(
}

/**
* Returns {@link MObjectTypeMapping} from ordinal Integer or specified default value.
* Returns {@link MObjectType} from ordinal Integer or specified default value.
*/
protected @NotNull MObjectTypeMapping objectTypeMapping(
@Nullable Integer repoObjectTypeId, @NotNull MObjectTypeMapping defaultValue) {
protected @NotNull MObjectType objectTypeMapping(
@Nullable Integer repoObjectTypeId, @NotNull MObjectType defaultValue) {
return repoObjectTypeId != null
? MObjectTypeMapping.fromCode(repoObjectTypeId)
? MObjectType.fromCode(repoObjectTypeId)
: defaultValue;
}

/**
* Returns nullable {@link MObjectTypeMapping} from ordinal Integer.
* If null is returned it will not fail immediately unlike {@link MObjectTypeMapping#fromCode(int)}.
* Returns nullable {@link MObjectType} from ordinal Integer.
* If null is returned it will not fail immediately unlike {@link MObjectType#fromCode(int)}.
* This is practical for eager argument resolution for
* {@link #objectReferenceType(String, MObjectTypeMapping, String)}.
* {@link #objectReferenceType(String, MObjectType, String)}.
* Null may still be OK if OID is null as well - which means no reference.
*/
protected @Nullable MObjectTypeMapping objectTypeMapping(
protected @Nullable MObjectType objectTypeMapping(
@Nullable Integer repoObjectTypeId) {
return repoObjectTypeId != null
? MObjectTypeMapping.fromCode(repoObjectTypeId)
? MObjectType.fromCode(repoObjectTypeId)
: null;
}

Expand Down Expand Up @@ -170,7 +170,13 @@ protected Integer processCachedUri(String uri, JdbcSession jdbcSession) {

protected Integer schemaTypeToCode(QName schemaType) {
return schemaType == null ? null :
MObjectTypeMapping.fromSchemaType(
MObjectType.fromSchemaType(
transformerSupport.qNameToSchemaClass(schemaType)).code();
}

protected MObjectType schemaTypeToObjectType(QName schemaType) {
return schemaType == null ? null :
MObjectType.fromSchemaType(
transformerSupport.qNameToSchemaClass(schemaType));
}
}

0 comments on commit 6747f94

Please sign in to comment.