Skip to content

Commit

Permalink
repo-sqale: added basic m_org mapping + owner_type for refs
Browse files Browse the repository at this point in the history
  • Loading branch information
virgo47 committed May 7, 2021
1 parent a1b284a commit bbf258e
Show file tree
Hide file tree
Showing 12 changed files with 260 additions and 80 deletions.
105 changes: 55 additions & 50 deletions repo/repo-sqale/sql/pgnew-repo.sql
Expand Up @@ -10,6 +10,9 @@
-- FK foreign key, IDX for index, KEY for unique index.
-- TR is suffix for triggers.
-- Names are generally lowercase (despite prefix/suffixes above in uppercase ;-)).
--
-- Other notes:
-- TEXT is used instead of VARCHAR, see: https://dba.stackexchange.com/a/21496/157622

-- noinspection SqlResolveForFile @ operator-class/"gin__int_ops"

Expand Down Expand Up @@ -199,7 +202,7 @@ INSERT INTO m_uri (id, uri)

-- region for abstract tables m_object/container/reference
-- Purely abstract table (no entries are allowed). Represents ObjectType+ArchetypeHolderType.
-- See https://wiki.evolveum.com/display/midPoint/ObjectType
-- See https://docs.evolveum.com/midpoint/architecture/archive/data-model/midpoint-common-schema/objecttype/
-- Following is recommended for each concrete table (see m_resource for example):
-- 1) override OID like this (PK+FK): oid UUID NOT NULL PRIMARY KEY REFERENCES m_object_oid(oid),
-- 2) define object type class (change value): objectType ObjectType GENERATED ALWAYS AS ('XY') STORED,
Expand All @@ -208,8 +211,6 @@ INSERT INTO m_uri (id, uri)
-- 5) the rest varies on the concrete table, other indexes or constraints, etc.
-- 6) any required FK must be created on the concrete table, even for inherited columns

-- TODO EXPERIMENT: consider TEXT instead of VARCHAR, see: https://dba.stackexchange.com/a/21496/157622
-- Even VARCHAR without length can be used.
CREATE TABLE m_object (
-- Default OID value is covered by INSERT triggers. No PK defined on abstract tables.
oid UUID NOT NULL,
Expand Down Expand Up @@ -274,6 +275,7 @@ CREATE TABLE m_container (
CREATE TABLE m_reference (
owner_oid UUID NOT NULL REFERENCES m_object_oid(oid) ON DELETE CASCADE,
-- reference_type will be overridden with GENERATED value in concrete table
owner_type ObjectType NOT NULL,
referenceType ReferenceType NOT NULL,
targetOid UUID NOT NULL, -- soft-references m_object
targetType ObjectType NOT NULL,
Expand Down Expand Up @@ -340,10 +342,12 @@ CREATE TABLE m_ref_object_parent_org (
owner_oid UUID NOT NULL REFERENCES m_object_oid(oid) ON DELETE CASCADE,
referenceType ReferenceType GENERATED ALWAYS AS ('OBJECT_PARENT_ORG') STORED,

-- TODO wouldn't (owner_oid, targetOid, relation_id) perform better for typical queries?
PRIMARY KEY (owner_oid, relation_id, targetOid)
)
INHERITS (m_reference);

-- TODO is this enough? Is target+owner+relation needed too?
CREATE INDEX m_ref_object_parent_org_targetOid_relation_id_idx
ON m_ref_object_parent_org (targetOid, relation_id);

Expand All @@ -361,7 +365,7 @@ CREATE INDEX m_ref_role_member_targetOid_relation_id_idx
-- endregion

-- region FOCUS related tables
-- Represents FocusType (Users, Roles, ...), see https://wiki.evolveum.com/display/midPoint/Focus+and+Projections
-- Represents FocusType (Users, Roles, ...), see https://docs.evolveum.com/midpoint/reference/schema/focus-and-projections/
-- extending m_object, but still abstract, hence DEFAULT for objectType and CHECK (false)
CREATE TABLE m_focus (
-- will be overridden with GENERATED value in concrete table
Expand Down Expand Up @@ -419,7 +423,7 @@ CREATE TABLE m_ref_projection (
CREATE INDEX m_ref_projection_targetOid_relation_id_idx
ON m_ref_projection (targetOid, relation_id);

-- Represents GenericObjectType, see https://wiki.evolveum.com/display/midPoint/Generic+Objects
-- Represents GenericObjectType, see https://docs.evolveum.com/midpoint/reference/schema/generic-objects/
CREATE TABLE m_generic_object (
oid UUID NOT NULL PRIMARY KEY REFERENCES m_object_oid(oid),
objectType ObjectType GENERATED ALWAYS AS ('GENERIC_OBJECT') STORED,
Expand All @@ -441,7 +445,7 @@ ALTER TABLE m_generic_object ADD CONSTRAINT m_generic_object_name_norm_key UNIQU
-- endregion

-- region USER related tables
-- Represents UserType, see https://wiki.evolveum.com/display/midPoint/UserType
-- Represents UserType, see https://docs.evolveum.com/midpoint/architecture/archive/data-model/midpoint-common-schema/usertype/
CREATE TABLE m_user (
oid UUID NOT NULL PRIMARY KEY REFERENCES m_object_oid(oid),
objectType ObjectType GENERATED ALWAYS AS ('USER') STORED,
Expand Down Expand Up @@ -496,7 +500,7 @@ CREATE TABLE m_user_organizational_unit (
-- endregion

-- region ROLE related tables
-- Represents AbstractRoleType, see https://wiki.evolveum.com/display/midPoint/Abstract+Role
-- Represents AbstractRoleType, see https://docs.evolveum.com/midpoint/architecture/concepts/abstract-role/
CREATE TABLE m_abstract_role (
-- will be overridden with GENERATED value in concrete table
objectType ObjectType NOT NULL,
Expand All @@ -511,7 +515,13 @@ CREATE TABLE m_abstract_role (
)
INHERITS (m_focus);

-- Represents RoleType, see https://wiki.evolveum.com/display/midPoint/RoleType
/* TODO: add for sub-tables, role, org... all? how many services?
CREATE INDEX iAbstractRoleIdentifier ON m_abstract_role (identifier);
CREATE INDEX iRequestable ON m_abstract_role (requestable);
CREATE INDEX iAutoassignEnabled ON m_abstract_role(autoassign_enabled);
*/

-- Represents RoleType, see https://docs.evolveum.com/midpoint/architecture/archive/data-model/midpoint-common-schema/roletype/
CREATE TABLE m_role (
oid UUID NOT NULL PRIMARY KEY REFERENCES m_object_oid(oid),
objectType ObjectType GENERATED ALWAYS AS ('ROLE') STORED,
Expand Down Expand Up @@ -565,6 +575,43 @@ CREATE INDEX m_archetype_name_orig_idx ON m_archetype (name_orig);
ALTER TABLE m_archetype ADD CONSTRAINT m_archetype_name_norm_key UNIQUE (name_norm);
-- endregion

-- region Organization hierarchy support
-- Represents OrgType, see https://docs.evolveum.com/midpoint/architecture/archive/data-model/midpoint-common-schema/orgtype/
CREATE TABLE m_org (
oid UUID NOT NULL PRIMARY KEY REFERENCES m_object_oid(oid),
objectType ObjectType GENERATED ALWAYS AS ('ORG') STORED,
displayOrder INTEGER,
tenant BOOLEAN
)
INHERITS (m_abstract_role);

CREATE TRIGGER m_org_oid_insert_tr BEFORE INSERT ON m_org
FOR EACH ROW EXECUTE PROCEDURE insert_object_oid();
CREATE TRIGGER m_org_update_tr BEFORE UPDATE ON m_org
FOR EACH ROW EXECUTE PROCEDURE before_update_object();
CREATE TRIGGER m_org_oid_delete_tr AFTER DELETE ON m_org
FOR EACH ROW EXECUTE PROCEDURE delete_object_oid();

CREATE INDEX m_org_name_orig_idx ON m_org (name_orig);
ALTER TABLE m_org ADD CONSTRAINT m_org_name_norm_key UNIQUE (name_norm);
CREATE INDEX m_org_displayOrder_idx ON m_org (displayOrder);

/*
CREATE TABLE m_org_closure (
ancestor_oid UUID NOT NULL,
descendant_oid UUID NOT NULL,
val INTEGER, -- number of distinct paths
PRIMARY KEY (ancestor_oid, descendant_oid)
);
CREATE INDEX iDescendantAncestor ON m_org_closure (descendant_oid, ancestor_oid);
ALTER TABLE m_org_closure
ADD CONSTRAINT fk_ancestor FOREIGN KEY (ancestor_oid) REFERENCES m_object;
ALTER TABLE m_org_closure
ADD CONSTRAINT fk_descendant FOREIGN KEY (descendant_oid) REFERENCES m_object;
*/
-- endregion

-- region Access Certification object tables
-- Represents AccessCertificationDefinitionType, see https://wiki.evolveum.com/display/midPoint/Access+Certification
CREATE TABLE m_access_cert_definition (
Expand Down Expand Up @@ -1608,21 +1655,7 @@ CREATE TABLE m_object_ext_string (
stringValue TEXT NOT NULL,
PRIMARY KEY (owner_oid, ownerType, item_id, stringValue)
);
CREATE TABLE m_org_closure (
ancestor_oid UUID NOT NULL,
descendant_oid UUID NOT NULL,
val INTEGER,
PRIMARY KEY (ancestor_oid, descendant_oid)
);
CREATE TABLE m_org (
displayOrder INTEGER,
name_norm TEXT,
name_orig TEXT,
tenant BOOLEAN,
oid UUID NOT NULL,
PRIMARY KEY (oid)
);
CREATE INDEX iAExtensionBoolean
ON m_assignment_ext_boolean (booleanValue);
CREATE INDEX iAExtensionDate
Expand Down Expand Up @@ -1680,17 +1713,6 @@ CREATE INDEX iExtensionReference
ON m_object_ext_reference (targetoid);
CREATE INDEX iExtensionString
ON m_object_ext_string (stringValue);
CREATE INDEX iAncestor
ON m_org_closure (ancestor_oid);
CREATE INDEX iDescendant
ON m_org_closure (descendant_oid);
CREATE INDEX iDescendantAncestor
ON m_org_closure (descendant_oid, ancestor_oid);
CREATE INDEX iAbstractRoleIdentifier
ON m_abstract_role (identifier);
CREATE INDEX iRequestable
ON m_abstract_role (requestable);
CREATE INDEX iAutoassignEnabled ON m_abstract_role(autoassign_enabled);
CREATE INDEX iArchetypeNameOrig ON m_archetype(name_orig);
CREATE INDEX iArchetypeNameNorm ON m_archetype(name_norm);
CREATE INDEX iFocusAdministrative
Expand All @@ -1711,12 +1733,6 @@ CREATE INDEX iObjectTemplateNameOrig
ON m_object_template (name_orig);
ALTER TABLE m_object_template
ADD CONSTRAINT uc_object_template_name UNIQUE (name_norm);
CREATE INDEX iDisplayOrder
ON m_org (displayOrder);
CREATE INDEX iOrgNameOrig
ON m_org (name_orig);
ALTER TABLE m_org
ADD CONSTRAINT uc_org_name UNIQUE (name_norm);
CREATE INDEX iSystemConfigurationNameOrig
ON m_system_configuration (name_orig);
ALTER TABLE m_system_configuration
Expand Down Expand Up @@ -1789,22 +1805,12 @@ ALTER TABLE m_object_ext_string
ALTER TABLE m_object_text_info
ADD CONSTRAINT fk_object_text_info_owner FOREIGN KEY (owner_oid) REFERENCES m_object;
ALTER TABLE m_org_closure
ADD CONSTRAINT fk_ancestor FOREIGN KEY (ancestor_oid) REFERENCES m_object;
ALTER TABLE m_org_closure
ADD CONSTRAINT fk_descendant FOREIGN KEY (descendant_oid) REFERENCES m_object;
ALTER TABLE m_org_org_type
ADD CONSTRAINT fk_org_org_type FOREIGN KEY (org_oid) REFERENCES m_org;
ALTER TABLE m_user_employee_type
ADD CONSTRAINT fk_user_employee_type FOREIGN KEY (user_oid) REFERENCES m_user;
ALTER TABLE m_user_organization
ADD CONSTRAINT fk_user_organization FOREIGN KEY (user_oid) REFERENCES m_user;
ALTER TABLE m_user_organizational_unit
ADD CONSTRAINT fk_user_org_unit FOREIGN KEY (user_oid) REFERENCES m_user;
ALTER TABLE m_function_library
ADD CONSTRAINT fk_function_library FOREIGN KEY (oid) REFERENCES m_object;
ALTER TABLE m_org
ADD CONSTRAINT fk_org FOREIGN KEY (oid) REFERENCES m_abstract_role;
-- Indices for foreign keys; maintained manually
CREATE INDEX iUserEmployeeTypeOid ON M_USER_EMPLOYEE_TYPE(USER_OID);
Expand All @@ -1822,7 +1828,6 @@ CREATE INDEX iObjectExtLongItemId ON M_OBJECT_EXT_LONG(ITEM_ID);
CREATE INDEX iObjectExtPolyItemId ON M_OBJECT_EXT_POLY(ITEM_ID);
CREATE INDEX iObjectExtReferenceItemId ON M_OBJECT_EXT_REFERENCE(ITEM_ID);
CREATE INDEX iObjectExtStringItemId ON M_OBJECT_EXT_STRING(ITEM_ID);
CREATE INDEX iOrgOrgTypeOid ON M_ORG_ORG_TYPE(ORG_OID);
-- Thanks to Patrick Lightbody for submitting this...
--
Expand Down
Expand Up @@ -36,6 +36,7 @@
import com.evolveum.midpoint.repo.sqale.qmodel.object.QObjectMapping;
import com.evolveum.midpoint.repo.sqale.qmodel.object.QOperationExecutionMapping;
import com.evolveum.midpoint.repo.sqale.qmodel.object.QTriggerMapping;
import com.evolveum.midpoint.repo.sqale.qmodel.org.QOrgMapping;
import com.evolveum.midpoint.repo.sqale.qmodel.other.*;
import com.evolveum.midpoint.repo.sqale.qmodel.ref.QReferenceMapping;
import com.evolveum.midpoint.repo.sqale.qmodel.report.QReportDataMapping;
Expand Down Expand Up @@ -150,6 +151,7 @@ public SqaleRepoContext sqlRepoContext(
QObjectTemplateMapping.init(repositoryContext))
.register(OperationExecutionType.COMPLEX_TYPE,
QOperationExecutionMapping.init(repositoryContext))
.register(OrgType.COMPLEX_TYPE, QOrgMapping.init(repositoryContext))
.register(ReportType.COMPLEX_TYPE, QReportMapping.init(repositoryContext))
.register(ReportDataType.COMPLEX_TYPE, QReportDataMapping.init(repositoryContext))
.register(ResourceType.COMPLEX_TYPE, QResourceMapping.init(repositoryContext))
Expand Down
Expand Up @@ -81,6 +81,7 @@ protected QAssignmentReference newAliasInstance(String alias) {
public MAssignmentReference newRowObject(MAssignment ownerRow) {
MAssignmentReference row = new MAssignmentReference();
row.ownerOid = ownerRow.ownerOid;
row.ownerType = ownerRow.ownerType;
row.assignmentCid = ownerRow.cid;
return row;
}
Expand Down
Expand Up @@ -95,12 +95,12 @@ protected QObjectMapping(
.addItemMapping(MetadataType.F_MODIFY_TIMESTAMP,
timestampMapper(q -> q.modifyTimestamp))
.addRefMapping(MetadataType.F_CREATE_APPROVER_REF,
QObjectReferenceMapping.initForObjectCreateApprover(repositoryContext))
QObjectReferenceMapping.initForCreateApprover(repositoryContext))
.addRefMapping(MetadataType.F_MODIFY_APPROVER_REF,
QObjectReferenceMapping.initForObjectModifyApprover(repositoryContext));
QObjectReferenceMapping.initForModifyApprover(repositoryContext));

addRefMapping(F_PARENT_ORG_REF,
QObjectReferenceMapping.initForObjectParentOrg(repositoryContext));
QObjectReferenceMapping.initForParentOrg(repositoryContext));

addContainerTableMapping(AssignmentHolderType.F_ASSIGNMENT,
QAssignmentMapping.initAssignment(repositoryContext),
Expand Down Expand Up @@ -245,9 +245,9 @@ public void storeRelatedEntities(
MetadataType metadata = schemaObject.getMetadata();
if (metadata != null) {
storeRefs(row, metadata.getCreateApproverRef(),
QObjectReferenceMapping.getForObjectCreateApprover(), jdbcSession);
QObjectReferenceMapping.getForCreateApprover(), jdbcSession);
storeRefs(row, metadata.getModifyApproverRef(),
QObjectReferenceMapping.getForObjectModifyApprover(), jdbcSession);
QObjectReferenceMapping.getForModifyApprover(), jdbcSession);
}

List<TriggerType> triggers = schemaObject.getTrigger();
Expand All @@ -262,7 +262,7 @@ public void storeRelatedEntities(
}

storeRefs(row, schemaObject.getParentOrgRef(),
QObjectReferenceMapping.getForObjectParentOrg(), jdbcSession);
QObjectReferenceMapping.getForParentOrg(), jdbcSession);

if (schemaObject instanceof AssignmentHolderType) {
storeAssignmentHolderEntities(row, (AssignmentHolderType) schemaObject, jdbcSession);
Expand Down
@@ -0,0 +1,19 @@
/*
* 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.qmodel.org;

import com.evolveum.midpoint.repo.sqale.qmodel.role.MAbstractRole;
import com.evolveum.midpoint.repo.sqale.qmodel.role.QRole;

/**
* Querydsl "row bean" type related to {@link QRole}.
*/
public class MOrg extends MAbstractRole {

public Integer displayOrder;
public Boolean tenant;
}
@@ -0,0 +1,42 @@
/*
* 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.qmodel.org;

import java.sql.Types;

import com.querydsl.core.types.dsl.BooleanPath;
import com.querydsl.core.types.dsl.NumberPath;
import com.querydsl.sql.ColumnMetadata;

import com.evolveum.midpoint.repo.sqale.qmodel.role.QAbstractRole;

/**
* Querydsl query type for {@value #TABLE_NAME} table.
*/
@SuppressWarnings("unused")
public class QOrg extends QAbstractRole<MOrg> {

private static final long serialVersionUID = -7711059436053747571L;

public static final String TABLE_NAME = "m_org";

public static final ColumnMetadata DISPLAY_ORDER =
ColumnMetadata.named("displayOrder").ofType(Types.INTEGER);
public static final ColumnMetadata TENANT =
ColumnMetadata.named("tenant").ofType(Types.BOOLEAN);

public final NumberPath<Integer> displayOrder = createInteger("displayOrder", DISPLAY_ORDER);
public final BooleanPath tenant = createBoolean("tenant", TENANT);

public QOrg(String variable) {
this(variable, DEFAULT_SCHEMA_NAME, TABLE_NAME);
}

public QOrg(String variable, String schema, String table) {
super(MOrg.class, variable, schema, table);
}
}
@@ -0,0 +1,45 @@
/*
* 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.qmodel.org;

import com.querydsl.sql.ColumnMetadata;

import com.evolveum.midpoint.repo.sqlbase.querydsl.FlexibleRelationalPathBase;
import com.evolveum.midpoint.repo.sqlbase.querydsl.UuidPath;

/**
* Querydsl query type for common table expression (CTE) representing org hierarchy on the fly.
* Does not use any backing bean, it is never retrieved directly, only used in the query.
* This does not have to be under {@link FlexibleRelationalPathBase}, but is for convenience.
*/
@SuppressWarnings("unused")
public class QOrgClosure extends FlexibleRelationalPathBase<QOrgClosure> {

private static final long serialVersionUID = 4406075586720866032L;

public static final String DEFAULT_ALIAS_NAME = "orgc";

public static final ColumnMetadata PARENT =
ColumnMetadata.named("parent").ofType(UuidPath.UUID_TYPE);
public static final ColumnMetadata CHILD =
ColumnMetadata.named("child").ofType(UuidPath.UUID_TYPE);

public final UuidPath parent = createUuid("parent", PARENT);
public final UuidPath child = createUuid("child", CHILD);

public QOrgClosure() {
this(DEFAULT_ALIAS_NAME, DEFAULT_SCHEMA_NAME);
}

public QOrgClosure(String variable) {
this(variable, DEFAULT_SCHEMA_NAME);
}

public QOrgClosure(String variable, String schema) {
super(QOrgClosure.class, variable, schema, "orgc"); // not a real table
}
}

0 comments on commit bbf258e

Please sign in to comment.