Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
mederly committed Apr 26, 2022
2 parents ca5d1d4 + 6c65f55 commit 1213e3d
Show file tree
Hide file tree
Showing 8 changed files with 158 additions and 132 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2010-2015 Evolveum
~ Copyright (C) 2010-2022 Evolveum
~
~ This work is dual-licensed under the Apache License 2.0
~ and European Union Public License. See LICENSE file for details.
Expand Down Expand Up @@ -41,11 +41,7 @@ <h3><div wicket:id="queryLabel"/></h3>
<h4>
<wicket:message key="PageRepositoryQuery.hibernateParameters"/>
</h4>
<p class="small" wicket:id="hibernateParametersNote"/>
<textarea wicket:id="parameters"></textarea>
<div class="form-group" style="margin-top: 15px">
<a class="btn btn-primary" wicket:id="executeHibernate"/>
</div>
</div>
</div>

Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2010-2021 Evolveum and contributors
* Copyright (C) 2010-2022 Evolveum and contributors
*
* This work is dual-licensed under the Apache License 2.0
* and European Union Public License. See LICENSE file for details.
Expand All @@ -9,33 +9,27 @@
import java.io.Serializable;
import java.util.Collection;

import com.evolveum.midpoint.prism.Containerable;
import com.evolveum.midpoint.prism.query.ObjectQuery;
import com.evolveum.midpoint.util.annotation.Experimental;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType;

/**
* Query diagnostics request: contains query to be executed (or at least translated) and some options.
*/
@Experimental
public class RepositoryQueryDiagRequest implements Serializable {

private Class<? extends ObjectType> type;
private Class<? extends Containerable> type;
private ObjectQuery query;
private Collection<SelectorOptions<GetOperationOptions>> options;

/**
* We actually don't want this anymore.
*/
@Deprecated
private Serializable implementationLevelQuery;

private boolean translateOnly;

public Class<? extends ObjectType> getType() {
public Class<? extends Containerable> getType() {
return type;
}

public void setType(Class<? extends ObjectType> type) {
public void setType(Class<? extends Containerable> type) {
this.type = type;
}

Expand All @@ -55,16 +49,6 @@ public void setOptions(Collection<SelectorOptions<GetOperationOptions>> options)
this.options = options;
}

@Deprecated
public Serializable getImplementationLevelQuery() {
return implementationLevelQuery;
}

@Deprecated
public void setImplementationLevelQuery(Serializable implementationLevelQuery) {
this.implementationLevelQuery = implementationLevelQuery;
}

public boolean isTranslateOnly() {
return translateOnly;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ public RepositoryQueryDiagResponse executeRepositoryQuery(
OperationResult result = parentResult.createSubresult(EXECUTE_REPOSITORY_QUERY);
try {
boolean isAdmin;
if (request.getImplementationLevelQuery() == null && request.isTranslateOnly()) {
if (request.isTranslateOnly()) {
// special case - no hibernate query and translate-only: does not require authorization
isAdmin = false;
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1671,11 +1671,6 @@ public RepositoryQueryDiagResponse executeQueryDiagnostics(
.build();

try {
if (request.getImplementationLevelQuery() != null) {
throw new UnsupportedOperationException(
"Only midPoint query diagnostics is supported for Native repository");
}

ObjectQuery query = request.getQuery();
query = simplifyQuery(query);
if (isNoneQuery(query)) {
Expand All @@ -1694,7 +1689,7 @@ public RepositoryQueryDiagResponse executeQueryDiagnostics(
}
}

private <S extends ObjectType, Q extends FlexibleRelationalPathBase<R>, R> RepositoryQueryDiagResponse
private <S extends Containerable, Q extends FlexibleRelationalPathBase<R>, R> RepositoryQueryDiagResponse
executeExecuteQueryDiagnostics(RepositoryQueryDiagRequest request, @NotNull Class<S> type)
throws RepositoryException, SchemaException {
long opHandle = registerOperationStart(OP_EXECUTE_QUERY_DIAGNOSTICS, (Class<? extends Containerable>) null);
Expand All @@ -1720,7 +1715,7 @@ public RepositoryQueryDiagResponse executeQueryDiagnostics(
result = context.executeQuery(jdbcSession);
PageOf<S> transformedResult = context.transformToSchemaType(result, jdbcSession);
//noinspection unchecked
resultList = transformedResult.map(o -> (PrismObject<S>) o.asPrismObject()).content();
resultList = transformedResult.map(o -> (PrismContainerValue<S>) o.asPrismContainerValue()).content();
} catch (RuntimeException e) {
if (e != SimulatedSqlQuery.SIMULATION_EXCEPTION) {
throw e; // OK, this was unexpected, so rethrow it
Expand Down Expand Up @@ -1817,7 +1812,8 @@ public <O extends ObjectType> boolean selectorMatches(
ObjectQueryUtil.assertPropertyOnly(specFilter, logMessagePrefix + " filter is not property-only filter");
}
try {
if (!ObjectQuery.match(object, specFilter, sqlRepoContext.matchingRuleRegistry())) {
if (specFilter != null
&& !ObjectQuery.match(object, specFilter, sqlRepoContext.matchingRuleRegistry())) {
logger.trace("{} object OID {}", logMessagePrefix, object.getOid());
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import com.evolveum.midpoint.repo.sqale.qmodel.object.MObjectType;
import com.evolveum.midpoint.repo.sqale.qmodel.object.QAssignmentHolder;
import com.evolveum.midpoint.repo.sqale.qmodel.object.QObject;
import com.evolveum.midpoint.repo.sqlbase.QueryException;
import com.evolveum.midpoint.repo.sqlbase.filtering.item.PolyStringItemFilterProcessor;
import com.evolveum.midpoint.schema.SchemaService;
import com.evolveum.midpoint.schema.SearchResultList;
Expand Down Expand Up @@ -296,13 +297,17 @@ public void initObjects() throws Exception {
.assignment(new AssignmentType()
.lifecycleState("ls-user3-ass1")
.metadata(new MetadataType()
.creatorRef(user2Oid, UserType.COMPLEX_TYPE, ORG_DEFAULT)
.createApproverRef(user1Oid, UserType.COMPLEX_TYPE, ORG_DEFAULT))
.activation(new ActivationType()
.validFrom("2021-01-01T00:00:00Z"))
.subtype("ass-subtype-1")
.subtype("ass-subtype-2"))
.linkRef(shadow1Oid, ShadowType.COMPLEX_TYPE)
.assignment(new AssignmentType()
.lifecycleState("ls-user3-ass2")
.metadata(new MetadataType()
.creatorRef(user1Oid, UserType.COMPLEX_TYPE, ORG_DEFAULT))
.activation(new ActivationType()
.validTo("2022-01-01T00:00:00Z")))
.operationExecution(new OperationExecutionType()
Expand Down Expand Up @@ -1893,9 +1898,9 @@ public void test602SearchContainerWithExistsParent() throws SchemaException {
}

@Test
public void test603SearchContainerWithExistsParent() throws SchemaException {
public void test603SearchAccessCertificationCaseContainer() throws SchemaException {
SearchResultList<AccessCertificationCaseType> result = searchContainerTest(
"by owner OID exists", AccessCertificationCaseType.class,
"by stage number", AccessCertificationCaseType.class,
f -> f.item(AccessCertificationCaseType.F_STAGE_NUMBER).gt(1));
assertThat(result)
.extracting(a -> a.getStageNumber())
Expand All @@ -1905,7 +1910,7 @@ public void test603SearchContainerWithExistsParent() throws SchemaException {
@Test
public void test605SearchCaseWorkItemContainer() throws SchemaException {
SearchResultList<CaseWorkItemType> result = searchContainerTest(
"by owner OID exists", CaseWorkItemType.class,
"by stage number", CaseWorkItemType.class,
f -> f.item(CaseWorkItemType.F_STAGE_NUMBER).eq(1));
assertThat(result)
.singleElement()
Expand Down Expand Up @@ -1936,7 +1941,7 @@ public void test610SearchCaseWIContainerByAssigneeName() throws SchemaException
}

@Test
public void test615SearchAssignmentByApproverName() throws SchemaException {
public void test615SearchAssignmentByApproverNameWithOrder() throws SchemaException {
SearchResultList<AssignmentType> result = searchContainerTest(
"by approver name", AssignmentType.class,
f -> f.item(AssignmentType.F_METADATA, MetadataType.F_CREATE_APPROVER_REF,
Expand All @@ -1947,6 +1952,34 @@ public void test615SearchAssignmentByApproverName() throws SchemaException {
.matches(a -> a.getLifecycleState().equals("ls-user3-ass1"));
}

@Test
public void test616OrderByMultiValueReferenceTargetPropertyIsNotPossible() {
assertThatThrownBy(() -> searchContainerTest(
"having any approver (with order)", AssignmentType.class,
f -> f.not().item(AssignmentType.F_METADATA, MetadataType.F_CREATE_APPROVER_REF,
T_OBJECT_REFERENCE, UserType.F_NAME)
.isNull()
.asc(AssignmentType.F_METADATA, MetadataType.F_CREATE_APPROVER_REF,
T_OBJECT_REFERENCE, UserType.F_NAME)))
.isInstanceOf(SystemException.class)
.hasCauseInstanceOf(QueryException.class)
.hasMessageFindingMatch("Item path .* cannot be used for ordering because subquery is used to resolve it");
}

@Test
public void test620OrderBySingleValueReferenceTargetPropertyIsSupported() throws SchemaException {
SearchResultList<AssignmentType> result = searchContainerTest(
"having creator ref name and order by it", AssignmentType.class,
f -> f.not().item(AssignmentType.F_METADATA, MetadataType.F_CREATOR_REF,
T_OBJECT_REFERENCE, UserType.F_NAME)
.isNull()
.asc(AssignmentType.F_METADATA, MetadataType.F_CREATOR_REF,
T_OBJECT_REFERENCE, UserType.F_NAME));
assertThat(result)
.extracting(a -> a.getLifecycleState())
.containsExactly("ls-user3-ass2", "ls-user3-ass1");
}

@Test
public void test690SearchErrorOperationExecutionForTask() throws SchemaException {
SearchResultList<OperationExecutionType> result = searchContainerTest(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

import static com.evolveum.midpoint.prism.PrismConstants.T_OBJECT_REFERENCE;
import static com.evolveum.midpoint.repo.sqlbase.querydsl.FlexibleRelationalPathBase.DEFAULT_SCHEMA_NAME;

import java.sql.SQLException;
Expand All @@ -23,6 +24,7 @@
import com.evolveum.midpoint.audit.api.AuditEventStage;
import com.evolveum.midpoint.audit.api.AuditEventType;
import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.prism.PrismObjectValue;
import com.evolveum.midpoint.prism.xml.XmlTypeConverter;
import com.evolveum.midpoint.repo.api.DeleteObjectResult;
import com.evolveum.midpoint.repo.api.RepoModifyOptions;
Expand Down Expand Up @@ -499,7 +501,7 @@ public void test500ExecuteQueryDiagnostics() throws Exception {
then("query is executed and low-level info returned");
assertThat(response).isNotNull();
assertThat(response.getQueryResult()).hasSize(1)
.extracting(o -> ((PrismObject<?>) o).asObjectable().getName().getOrig())
.extracting(o -> ((PrismObjectValue<?>) o).asObjectable().getName().getOrig())
.containsExactly(name);
assertThat(response.getImplementationLevelQuery()).asString()
.isEqualToIgnoringWhitespace("select u.oid, u.fullObject from m_user u"
Expand Down Expand Up @@ -537,6 +539,43 @@ public void test501ExecuteQueryDiagnosticsTranslateOnly() {
assertThat(queryRecorder.getQueryBuffer()).isEmpty();
}

@Test
public void test505ExecuteQueryDiagnosticsContainerSearch() {
OperationResult result = createOperationResult();

given("diag request with container search");
queryRecorder.clearBufferAndStartRecording();
RepositoryQueryDiagRequest request = new RepositoryQueryDiagRequest();
request.setType(AssignmentType.class);
request.setQuery(prismContext.queryFor(AssignmentType.class)
.not().item(AssignmentType.F_METADATA, MetadataType.F_CREATOR_REF,
T_OBJECT_REFERENCE, UserType.F_NAME)
.isNull()
.asc(AssignmentType.F_METADATA, MetadataType.F_CREATOR_REF,
T_OBJECT_REFERENCE, UserType.F_NAME)
.build());

when("executeQueryDiagnostics is called with query");
RepositoryQueryDiagResponse response = repositoryService.executeQueryDiagnostics(request, result);

then("query is translated");
assertThat(response).isNotNull();
assertThat(response.getQueryResult()).isNullOrEmpty();
assertThat(response.getImplementationLevelQuery()).asString()
// contains, I don't care about select part here
.containsIgnoringWhitespaces("from m_assignment a\n"
+ "left join m_user u\n"
+ "on a.creatorRefTargetOid = u.oid\n"
// TODO this second join is wrong
+ "left join m_user u2\n"
+ "on a.creatorRefTargetOid = u2.oid\n"
+ "where not (u.nameNorm is null and u.nameOrig is null)\n"
+ "order by u2.nameOrig asc");
// TODO split to two tests - one for container, one for reusing join for order (which can be also tested on object, BTW)

assertThat(queryRecorder.getQueryBuffer()).hasSize(1);
}

@Test
public void test600AuditRecord() {
given("audit event record");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1023,36 +1023,32 @@ public boolean isAnySubordinateAttempt(String upperOrgOid, Collection<String> lo
public RepositoryQueryDiagResponse executeQueryDiagnosticsRequest(RepositoryQueryDiagRequest request, OperationResult result) {
LOGGER_PERFORMANCE.debug("> execute query diagnostics {}", request);

Class<? extends Containerable> type = request.getType();
// if (!ObjectType.class.isAssignableFrom(type)) {
// TODO add this branch too, perhaps not here
// }

Session session = null;
try {
session = baseHelper.beginReadOnlyTransaction(); // beware, not all databases support read-only transactions!

final String implementationLevelQuery;
final Map<String, RepositoryQueryDiagResponse.ParameterValue> implementationLevelQueryParameters;
final Query<?> query;
final boolean isMidpointQuery = request.getImplementationLevelQuery() == null;
if (isMidpointQuery) {
QueryEngine engine = new QueryEngine(getConfiguration(), extItemDictionary, prismContext, relationRegistry);
RQueryImpl rQuery = (RQueryImpl) engine.interpret(request.getQuery(), request.getType(), request.getOptions(), false, session);
query = rQuery.getQuery();
implementationLevelQuery = query.getQueryString();
implementationLevelQueryParameters = new HashMap<>();
for (Map.Entry<String, QueryParameterValue> entry : rQuery.getQuerySource().getParameters().entrySet()) {
implementationLevelQueryParameters.put(entry.getKey(),
new RepositoryQueryDiagResponse.ParameterValue(entry.getValue().getValue(), entry.getValue().toString()));
}
} else {
implementationLevelQuery = (String) request.getImplementationLevelQuery();
implementationLevelQueryParameters = new HashMap<>();
query = session.createQuery(implementationLevelQuery);
QueryEngine engine = new QueryEngine(getConfiguration(), extItemDictionary, prismContext, relationRegistry);
RQueryImpl rQuery = (RQueryImpl) engine.interpret(request.getQuery(), type, request.getOptions(), false, session);
query = rQuery.getQuery();
implementationLevelQuery = query.getQueryString();
implementationLevelQueryParameters = new HashMap<>();
for (Map.Entry<String, QueryParameterValue> entry : rQuery.getQuerySource().getParameters().entrySet()) {
implementationLevelQueryParameters.put(entry.getKey(),
new RepositoryQueryDiagResponse.ParameterValue(entry.getValue().getValue(), entry.getValue().toString()));
}

List<?> objects = request.isTranslateOnly() ? null : query.list();
if (isMidpointQuery && objects != null) {
// raw GetObjectResult instances are useless outside repo-sql-impl module, so we'll convert them to objects
@SuppressWarnings("unchecked")
List<GetObjectResult> listOfGetObjectResults = (List<GetObjectResult>) objects;
objects = queryResultToPrismObjects(listOfGetObjectResults, request.getType(), null, session, result);
if (objects != null) {
//noinspection unchecked
objects = queryResultToPrismObjects((List<GetObjectResult>) objects, (Class<? extends ObjectType>) type, null, session, result);
}

RepositoryQueryDiagResponse response = new RepositoryQueryDiagResponse(objects, implementationLevelQuery, implementationLevelQueryParameters);
Expand Down

0 comments on commit 1213e3d

Please sign in to comment.