Skip to content

Commit

Permalink
MID-6319: AuditService#search will return result of AuditEventRecordType
Browse files Browse the repository at this point in the history
  • Loading branch information
virgo47 committed Jun 26, 2020
1 parent 990c351 commit c79027a
Show file tree
Hide file tree
Showing 9 changed files with 156 additions and 117 deletions.
Expand Up @@ -19,6 +19,7 @@
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.task.api.Task;
import com.evolveum.midpoint.util.exception.SchemaException;
import com.evolveum.midpoint.xml.ns._public.common.audit_3.AuditEventRecordType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.CleanupPolicyType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.SystemConfigurationAuditType;

Expand Down Expand Up @@ -76,7 +77,7 @@ long countObjects(ObjectQuery query,
throws SchemaException;

@NotNull
SearchResultList<AuditEventRecord> searchObjects(ObjectQuery query,
SearchResultList<AuditEventRecordType> searchObjects(ObjectQuery query,
Collection<SelectorOptions<GetOperationOptions>> options, OperationResult parentResult)
throws SchemaException;
}
Expand Up @@ -31,6 +31,7 @@
import com.evolveum.midpoint.schema.SelectorOptions;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.task.api.Task;
import com.evolveum.midpoint.xml.ns._public.common.audit_3.AuditEventRecordType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.CleanupPolicyType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType;

Expand Down Expand Up @@ -193,7 +194,7 @@ public long countObjects(ObjectQuery query,

@Override
@NotNull
public SearchResultList<AuditEventRecord> searchObjects(ObjectQuery query,
public SearchResultList<AuditEventRecordType> searchObjects(ObjectQuery query,
Collection<SelectorOptions<GetOperationOptions>> options, OperationResult parentResult) {
throw new UnsupportedOperationException("searchObjects not supported");
}
Expand Down
Expand Up @@ -11,7 +11,6 @@
import org.springframework.test.context.ContextConfiguration;
import org.testng.annotations.Test;

import com.evolveum.midpoint.audit.api.AuditEventRecord;
import com.evolveum.midpoint.prism.query.ObjectQuery;
import com.evolveum.midpoint.schema.SearchResultList;
import com.evolveum.midpoint.tools.testng.UnusedTestElement;
Expand All @@ -34,7 +33,7 @@ public void initSystem() throws Exception {
public void test100SearchAllAuditEvents() throws SchemaException {
when("Searching audit with query without any conditions");
ObjectQuery query = prismContext.queryFor(AuditEventRecordType.class).build();
SearchResultList<AuditEventRecord> prismObjects =
SearchResultList<AuditEventRecordType> prismObjects =
auditService.searchObjects(query, null, null);

then("All audit events are returned");
Expand All @@ -48,7 +47,7 @@ public void test110SearchAllAuditEventsOfSomeType() throws SchemaException {
ObjectQuery query = prismContext.queryFor(AuditEventRecordType.class)
.item(AuditEventRecordType.F_EVENT_TYPE).eq(AuditEventTypeType.ADD_OBJECT)
.build();
SearchResultList<AuditEventRecord> prismObjects =
SearchResultList<AuditEventRecordType> prismObjects =
auditService.searchObjects(query, null, null);

then("only audit events of a particular type are returned");
Expand Down
Expand Up @@ -53,7 +53,10 @@
import com.evolveum.midpoint.repo.sql.util.GetObjectResult;
import com.evolveum.midpoint.repo.sql.util.RUtil;
import com.evolveum.midpoint.repo.sql.util.TemporaryTableDialect;
import com.evolveum.midpoint.schema.*;
import com.evolveum.midpoint.schema.GetOperationOptions;
import com.evolveum.midpoint.schema.ObjectDeltaOperation;
import com.evolveum.midpoint.schema.SearchResultList;
import com.evolveum.midpoint.schema.SelectorOptions;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.task.api.Task;
import com.evolveum.midpoint.util.DebugUtil;
Expand Down Expand Up @@ -913,16 +916,20 @@ public long countObjects(ObjectQuery query,

@Override
@NotNull
public SearchResultList<AuditEventRecord> searchObjects(
public SearchResultList<AuditEventRecordType> searchObjects(
ObjectQuery query,
Collection<SelectorOptions<GetOperationOptions>> options, OperationResult parentResult) {
// TODO MID-6319
// support for options, skipped for now
// do something with the OperationResult... skipped for now
// TODO why the duality of AuditEventRecordType and AuditEventRecord?
SearchResultList<AuditEventRecord> result =
sqlQueryExecutor.list(AuditEventRecordType.class, query);

return result;
SearchResultList<AuditEventRecordType> result =
null;
try {
return sqlQueryExecutor.list(AuditEventRecordType.class, query);
} catch (SQLException e) {
// TODO
throw new RuntimeException(e);
}
}
}
Expand Up @@ -16,10 +16,11 @@
import com.querydsl.core.types.Path;
import com.querydsl.core.types.Projections;
import com.querydsl.core.types.QMap;
import com.querydsl.sql.Configuration;
import com.querydsl.sql.RelationalPath;
import com.querydsl.sql.SQLQuery;
import com.querydsl.sql.SQLQueryFactory;
import com.querydsl.sql.SQLTemplates;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import com.evolveum.midpoint.repo.sql.pure.metamodel.QAuditEventRecord;
Expand All @@ -28,6 +29,7 @@
@Deprecated
public class SqlGeneration {


public static void main(String[] args) throws Exception {
org.h2.Driver.load();
/* this requires querydsl-sql-codegen
Expand All @@ -39,54 +41,52 @@ public static void main(String[] args) throws Exception {
exporter.export(conn.getMetaData());
*/

SQLQueryFactory queryFactory = new SQLQueryFactory(
SQLTemplates.DEFAULT, () -> getConnection());

QAuditEventRecord.EXTENSION_COLUMNS.registerExtensionColumn(QAuditEventRecord.EVENT_TYPE);
try (Connection connection = getConnection()) {
QAuditEventRecord.EXTENSION_COLUMNS.registerExtensionColumn(QAuditEventRecord.EVENT_TYPE);

QAuditEventRecord aer = new QAuditEventRecord("aer");
SQLQuery<?> query = queryFactory.select(aer.all())
.from(aer)
;
QAuditEventRecord aer = new QAuditEventRecord("aer");
SQLQuery<?> query = newQuery(connection)
.select(aer.all())
.from(aer);

System.out.println(query);
System.out.println(query);

List<?> result = query.limit(3).fetch();
System.out.println("\nresult = " + result);
Object o = ((Tuple) result.get(0)).get(2, Object.class);
System.out.println("o = " + o);
System.out.println("class = " + o.getClass());
List<?> result = query.limit(3).fetch();
System.out.println("\nresult = " + result);
Object o = ((Tuple) result.get(0)).get(2, Object.class);
System.out.println("o = " + o);
System.out.println("class = " + o.getClass());
}
}

private static void extensionExperiments1() {
SQLQueryFactory queryFactory = new SQLQueryFactory(
SQLTemplates.DEFAULT, () -> getConnection());
private static void extensionExperiments1() throws SQLException {
try (Connection conn = getConnection()) {
QAuditEventRecord aer = new QAuditEventRecord("aer");
System.out.println("M_AUDIT_EVENT.meta.size = " + M_AUDIT_EVENT.all().length);
System.out.println("M_AUDIT_DELTA.meta.size = " + M_AUDIT_DELTA.all().length);

QAuditEventRecord aer = new QAuditEventRecord("aer");
System.out.println("M_AUDIT_EVENT.meta.size = " + M_AUDIT_EVENT.all().length);
System.out.println("M_AUDIT_DELTA.meta.size = " + M_AUDIT_DELTA.all().length);

QMap auditDelta = Projections.map(M_AUDIT_DELTA.all());
QMap auditEvent = Projections.map(M_AUDIT_EVENT.all());
QMap auditDelta = Projections.map(M_AUDIT_DELTA.all());
QMap auditEvent = Projections.map(M_AUDIT_EVENT.all());
// List<Tuple> result = queryFactory
List<?> result = queryFactory
// this way we don't use M-beans, which is more flexible, and still get close to "select whole entity A+B"
List<?> result = newQuery(conn)
// this way we don't use M-beans, which is more flexible, and still get close to "select whole entity A+B"
// .select(expand(M_AUDIT_EVENT.id, M_AUDIT_DELTA))

// This is also interesting, we instruct to create map for auditDelta paths.
// .all() above is necessary, otherwise the map contains only one M-bean, which we want to avoid
// Also, we want to extract this expression as variable, so we can use it later, e.g. to get from a tuple, or mapOneToMany processing, etc.
// This is also interesting, we instruct to create map for auditDelta paths.
// .all() above is necessary, otherwise the map contains only one M-bean, which we want to avoid
// Also, we want to extract this expression as variable, so we can use it later, e.g. to get from a tuple, or mapOneToMany processing, etc.
// .select(M_AUDIT_EVENT.id, auditDelta)
.select(M_AUDIT_EVENT)
.from(M_AUDIT_EVENT)
.select(M_AUDIT_EVENT)
.from(M_AUDIT_EVENT)
// .leftJoin(M_AUDIT_EVENT._auditDeltaFk, M_AUDIT_DELTA)
.fetch();
.fetch();
// Map<Long, Collection<Map<Expression<?>, ?>>> mapResult =
// mapOneToMany(result, M_AUDIT_EVENT.id, auditDelta);
// System.out.println("result = " + Joiner.on("\n").withKeyValueSeparator(" = ").join(mapResult));
// System.out.println(mapResult.size());

System.out.println(result);
System.out.println(result);
}
}

/**
Expand All @@ -109,55 +109,57 @@ private static Expression<?>[] expand(Path<?>... paths) {
return pathsCombined.toArray(new Expression<?>[0]);
}

private static void examples() {
System.out.println(M_AUDIT_EVENT);
System.out.println("\nColumns: " + M_AUDIT_EVENT.getColumns());
System.out.println("\nAnnotated element: " + M_AUDIT_EVENT.getAnnotatedElement());
System.out.println("\nFKs: " + M_AUDIT_EVENT.getForeignKeys());
System.out.println("\nInverse FKs: " + M_AUDIT_EVENT.getInverseForeignKeys());
System.out.println();

SQLQueryFactory queryFactory = new SQLQueryFactory(
SQLTemplates.DEFAULT, () -> getConnection());

System.out.println("audit size = " + queryFactory.selectFrom(M_AUDIT_EVENT).fetchCount());

SQLQuery<Tuple> query = queryFactory
.select(M_AUDIT_EVENT, M_AUDIT_DELTA)
private static void examples() throws SQLException {
try (Connection conn = getConnection()) {
System.out.println(M_AUDIT_EVENT);
System.out.println("\nColumns: " + M_AUDIT_EVENT.getColumns());
System.out.println("\nAnnotated element: " + M_AUDIT_EVENT.getAnnotatedElement());
System.out.println("\nFKs: " + M_AUDIT_EVENT.getForeignKeys());
System.out.println("\nInverse FKs: " + M_AUDIT_EVENT.getInverseForeignKeys());
System.out.println();

System.out.println("audit size = " + newQuery(conn)
.select(M_AUDIT_EVENT)
.from(M_AUDIT_EVENT)
.fetchCount());

SQLQuery<Tuple> query = newQuery(conn)
.select(M_AUDIT_EVENT, M_AUDIT_DELTA)
// .select(M_AUDIT_EVENT.id, M_AUDIT_DELTA.checksum)
// .from(M_AUDIT_EVENT)
// leftJoin if we want also events without deltas
// leftJoin if we want also events without deltas
// .join(M_AUDIT_EVENT._auditDeltaFk, M_AUDIT_DELTA)
// alternatively:
// .join(M_AUDIT_DELTA).on(M_AUDIT_DELTA.recordId.eq(M_AUDIT_EVENT.id))
// alternatively:
// .join(M_AUDIT_DELTA).on(M_AUDIT_DELTA.recordId.eq(M_AUDIT_EVENT.id))
// .orderBy(M_AUDIT_EVENT.id.asc())
.from(M_AUDIT_EVENT, M_AUDIT_DELTA)
.where(M_AUDIT_EVENT.id.eq(M_AUDIT_DELTA.recordId)) // this replaces "join-on", but only inner
.where(M_AUDIT_EVENT.id.eq(452L)); // "Works on my computer! :-)"

List<Tuple> result = query.fetch();
System.out.println("result = " + result);
System.out.println("\nsize: " + result.size());

System.out.println("\ncount: " + query.transform(groupBy(M_AUDIT_EVENT.id).as(M_AUDIT_DELTA.count())));
Map<?, ?> transform = query.transform(GroupBy.groupBy(M_AUDIT_EVENT.id).as(GroupBy.list(M_AUDIT_DELTA)));
System.out.println("transform = " + transform);

// "manual" transformation of one-to-many to proper graph
List<Tuple> plainResult = queryFactory
.select(M_AUDIT_EVENT, M_AUDIT_DELTA)
.from(M_AUDIT_EVENT)
.leftJoin(M_AUDIT_EVENT._auditDeltaFk, M_AUDIT_DELTA)
// alternatively:
// .leftJoin(M_AUDIT_DELTA).on(M_AUDIT_DELTA.recordId.eq(M_AUDIT_EVENT.id))
.from(M_AUDIT_EVENT, M_AUDIT_DELTA)
.where(M_AUDIT_EVENT.id.eq(M_AUDIT_DELTA.recordId)) // this replaces "join-on", but only inner
.where(M_AUDIT_EVENT.id.eq(452L)); // "Works on my computer! :-)"

List<Tuple> result = query.fetch();
System.out.println("result = " + result);
System.out.println("\nsize: " + result.size());

System.out.println("\ncount: " + query.transform(groupBy(M_AUDIT_EVENT.id).as(M_AUDIT_DELTA.count())));
Map<?, ?> transform = query.transform(GroupBy.groupBy(M_AUDIT_EVENT.id).as(GroupBy.list(M_AUDIT_DELTA)));
System.out.println("transform = " + transform);

// "manual" transformation of one-to-many to proper graph
List<Tuple> plainResult = newQuery(conn)
.select(M_AUDIT_EVENT, M_AUDIT_DELTA)
.from(M_AUDIT_EVENT)
.leftJoin(M_AUDIT_EVENT._auditDeltaFk, M_AUDIT_DELTA)
// alternatively:
// .leftJoin(M_AUDIT_DELTA).on(M_AUDIT_DELTA.recordId.eq(M_AUDIT_EVENT.id))
// .orderBy(M_AUDIT_EVENT.id.asc())
.where(M_AUDIT_EVENT.id.eq(452L))
.fetch();
Map<MAuditEventRecord, Collection<MAuditDelta>> resultMap =
mapOneToMany(plainResult, M_AUDIT_EVENT, M_AUDIT_DELTA, (o, m) -> o.addDelta(m));
System.out.println("\nFinal result" + resultMap);
.where(M_AUDIT_EVENT.id.eq(452L))
.fetch();
Map<MAuditEventRecord, Collection<MAuditDelta>> resultMap =
mapOneToMany(plainResult, M_AUDIT_EVENT, M_AUDIT_DELTA, (o, m) -> o.addDelta(m));
System.out.println("\nFinal result" + resultMap);

System.out.println("deltas for 1st item: " + resultMap.keySet().iterator().next().deltas);
System.out.println("deltas for 1st item: " + resultMap.keySet().iterator().next().deltas);
}
}

/**
Expand Down Expand Up @@ -224,4 +226,9 @@ private static Connection getConnection() {
throw new RuntimeException(e);
}
}

@NotNull
public static SQLQuery<Object> newQuery(Connection connection) {
return new SQLQuery<>(connection, SqlQueryExecutor.QUERYDSL_CONFIGURATION);
}
}
@@ -1,14 +1,21 @@
package com.evolveum.midpoint.repo.sql.pure;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import javax.sql.DataSource;
import java.util.List;

import com.querydsl.sql.Configuration;
import com.querydsl.sql.SQLQuery;
import com.querydsl.sql.SQLTemplates;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.evolveum.midpoint.audit.api.AuditEventRecord;
import com.evolveum.midpoint.prism.Containerable;
import com.evolveum.midpoint.prism.query.ObjectQuery;
import com.evolveum.midpoint.repo.sql.DataSourceFactory;
import com.evolveum.midpoint.repo.sql.pure.metamodel.QAuditEventRecord;
import com.evolveum.midpoint.schema.SearchResultList;
import com.evolveum.midpoint.schema.SearchResultMetadata;

Expand All @@ -18,20 +25,45 @@
@Component
public class SqlQueryExecutor {

// TODO configuration should reflect the used DB of course
public static final Configuration QUERYDSL_CONFIGURATION =
new Configuration(SQLTemplates.DEFAULT);

@Autowired
private DataSource dataSource;
private DataSourceFactory dataSourceFactory;

public SearchResultList<AuditEventRecord> list(
Class<? extends Containerable> prismType, ObjectQuery query) {
public <T extends Containerable> SearchResultList<T> list(
Class<T> prismType, // ignored for the moment
ObjectQuery query) throws SQLException {
// TODO: what if we declare AuditEventRecordType, but we want transformed result?
// some mapping function as an argument?
// some builder to construct the whole definition that will be an argument?

List<MAuditEventRecord> records = executeQuery();

SearchResultMetadata metadata = new SearchResultMetadata();
SearchResultList<AuditEventRecord> result = new SearchResultList<>(
return new SearchResultList<>(
new ArrayList<>(),
metadata);
}

public List<MAuditEventRecord> executeQuery() throws SQLException {
try (Connection connection = getConnection()) {
QAuditEventRecord aer = new QAuditEventRecord();
return newQuery(connection)
.select(aer)
.from(aer)
.limit(3)
.fetch();
}
}

private Connection getConnection() throws SQLException {
return dataSourceFactory.getDataSource().getConnection();
}

return result;
@NotNull
public SQLQuery<Object> newQuery(Connection connection) {
return new SQLQuery<>(connection, QUERYDSL_CONFIGURATION);
}
}

0 comments on commit c79027a

Please sign in to comment.