From 1e12fbdf08ae819a0040140c407937ec90183d0d Mon Sep 17 00:00:00 2001 From: Georg Henzler Date: Thu, 13 Jun 2024 10:24:09 +0200 Subject: [PATCH] Also interpret cost JSON object in case it is returned by oak search engine #730 --- .../cq/tools/actool/helper/QueryHelper.java | 23 ++++++++---- .../tools/actool/helper/QueryHelperTest.java | 35 +++++++++++++++++++ 2 files changed, 51 insertions(+), 7 deletions(-) create mode 100644 accesscontroltool-bundle/src/test/java/biz/netcentric/cq/tools/actool/helper/QueryHelperTest.java diff --git a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/helper/QueryHelper.java b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/helper/QueryHelper.java index 5eee3880..106be229 100644 --- a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/helper/QueryHelper.java +++ b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/helper/QueryHelper.java @@ -42,6 +42,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; @@ -143,14 +145,9 @@ static boolean hasQueryIndexForACLs(final Session session) throws RepositoryExce Row row = queryResult.getRows().nextRow(); // inspired by https://github.com/apache/jackrabbit-oak/blob/cc8adb42d89bc4625138a62ab074e7794a4d39ab/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/query/QueryTest.java#L1092 String plan = row.getValue("plan").getString(); - String costJson = plan.substring(plan.lastIndexOf('{')); - - // use jackson for JSON parsing - ObjectMapper mapper = new ObjectMapper(); + String costJsonStr = plan.substring(plan.lastIndexOf('{')); - // read the json strings and convert it into JsonNode - JsonNode node = mapper.readTree(costJson); - double cost = node.get("s").asDouble(Double.MAX_VALUE); + double cost = getCostFromJsonStr(costJsonStr); // look at https://jackrabbit.apache.org/oak/docs/query/query-engine.html#cost-calculation for the threshold // https://github.com/apache/jackrabbit-oak/blob/cc8adb42d89bc4625138a62ab074e7794a4d39ab/oak-core/src/main/java/org/apache/jackrabbit/oak/query/index/TraversingIndex.java#L75 @@ -160,6 +157,18 @@ static boolean hasQueryIndexForACLs(final Session session) throws RepositoryExce return cost <= COST_THRESHOLD_FOR_QUERY_INDEX; } + static double getCostFromJsonStr(String jsonStr) throws JsonProcessingException, IOException { + // use jackson for JSON parsing + ObjectMapper mapper = new ObjectMapper().configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true); + + // read the json strings and convert it into JsonNode + JsonNode node = mapper.readTree(jsonStr); + + JsonNode sNode = node.get("s"); + double cost = sNode.isContainerNode() ? sNode.get("perExecution").asDouble(Double.MAX_VALUE) : sNode.asDouble(Double.MAX_VALUE); + return cost; + } + /** Get Nodes with XPATH Query. */ public static Set getNodePathsFromQuery(final Session session, final String xpathQuery) throws RepositoryException { diff --git a/accesscontroltool-bundle/src/test/java/biz/netcentric/cq/tools/actool/helper/QueryHelperTest.java b/accesscontroltool-bundle/src/test/java/biz/netcentric/cq/tools/actool/helper/QueryHelperTest.java new file mode 100644 index 00000000..5985a0fc --- /dev/null +++ b/accesscontroltool-bundle/src/test/java/biz/netcentric/cq/tools/actool/helper/QueryHelperTest.java @@ -0,0 +1,35 @@ +/* + * (C) Copyright 2023 Cognizant Netcentric. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package biz.netcentric.cq.tools.actool.helper; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.io.IOException; + +import org.junit.jupiter.api.Test; + +import com.fasterxml.jackson.core.JsonProcessingException; + +public class QueryHelperTest { + + @Test + public void testGetCostFromJsonScalar() throws JsonProcessingException, IOException { + + assertEquals(189540, QueryHelper.getCostFromJsonStr("{ \"s\": 189540.0 }")); + } + + @Test + public void testGetCostFromJsonObject() throws JsonProcessingException, IOException { + + // the keys in sub object happen to be unquoted, the impl needs to use JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES + assertEquals(1, QueryHelper.getCostFromJsonStr("{ \"s\": { perEntry: 1.0, perExecution: 1.0, count: 47814 } }")); + + } + +}