From 47f54f5227d8504910d537a1b5eb999c066d38d0 Mon Sep 17 00:00:00 2001 From: luxbe Date: Wed, 20 Nov 2024 10:42:01 +0100 Subject: [PATCH 1/2] [Enhancement #278] allow for entity attribute projection in SOQL --- .../jopa/query/soql/SoqlQueryListener.java | 22 ++++++++-- .../jopa/query/soql/SoqlQueryParserTest.java | 44 +++++++++++++++++++ 2 files changed, 62 insertions(+), 4 deletions(-) diff --git a/jopa-impl/src/main/java/cz/cvut/kbss/jopa/query/soql/SoqlQueryListener.java b/jopa-impl/src/main/java/cz/cvut/kbss/jopa/query/soql/SoqlQueryListener.java index fd22579df..eeceee25e 100644 --- a/jopa-impl/src/main/java/cz/cvut/kbss/jopa/query/soql/SoqlQueryListener.java +++ b/jopa-impl/src/main/java/cz/cvut/kbss/jopa/query/soql/SoqlQueryListener.java @@ -784,19 +784,33 @@ public String getSparqlQuery() { return sparql; } + private String getSelectParameter(SoqlAttribute attribute) { + SoqlNode firstNode = attribute.getFirstNode(); + if(!firstNode.hasChild()) { + return rootVariable; + } + + setIris(firstNode); // we have to reassign the iris, because the table was not initialized when the first attribute was set + return attribute.getAsValue(rootVariable); + } + //Methods to build new Query private void buildSparqlQueryString() { if (attributes.isEmpty()) { return; } + + // the first attribute is either a projected parameter or a type attribute + String selectParameter = getSelectParameter(attributes.get(0)); + StringBuilder newQueryBuilder = new StringBuilder(typeDef); if (isSelectedParamCount) { - newQueryBuilder.append(getCountPart()); + newQueryBuilder.append(getCountPart(selectParameter)); } else { if (isSelectedParamDistinct) { newQueryBuilder.append(' ').append(SoqlConstants.DISTINCT); } - newQueryBuilder.append(' ').append(rootVariable).append(' '); + newQueryBuilder.append(' ').append(selectParameter).append(' '); } newQueryBuilder.append("WHERE { "); newQueryBuilder.append(processSupremeAttributes()); @@ -818,12 +832,12 @@ private void buildSparqlQueryString() { LOG.trace("Translated SOQL query '{}' to SPARQL '{}'.", soql, sparql); } - private StringBuilder getCountPart() { + private StringBuilder getCountPart(String selectParameter) { StringBuilder countPart = new StringBuilder(" (COUNT("); if (isSelectedParamDistinct) { countPart.append(SoqlConstants.DISTINCT).append(' '); } - countPart.append(rootVariable).append(") AS ?count) "); + countPart.append(selectParameter).append(") AS ?count) "); return countPart; } diff --git a/jopa-impl/src/test/java/cz/cvut/kbss/jopa/query/soql/SoqlQueryParserTest.java b/jopa-impl/src/test/java/cz/cvut/kbss/jopa/query/soql/SoqlQueryParserTest.java index 1ece1e86a..303673fee 100644 --- a/jopa-impl/src/test/java/cz/cvut/kbss/jopa/query/soql/SoqlQueryParserTest.java +++ b/jopa-impl/src/test/java/cz/cvut/kbss/jopa/query/soql/SoqlQueryParserTest.java @@ -749,6 +749,50 @@ void parseQueryWithMemberOfPluralAttribute() { parseAndAssertEquality(soql, expectedSparql); } + @Test + void parseQuerySupportsCountWithProjectedAttribute() { + final String soqlIdFirst = "SELECT COUNT(d.owlClassA) FROM OWLClassD d WHERE d.uri = :uri"; + final String expectedSparql = "SELECT (COUNT(?owlClassA) AS ?count) WHERE { ?uri a " + strUri(Vocabulary.c_OwlClassD) + " . " + + "?uri " + strUri(Vocabulary.p_h_hasA) + " ?owlClassA . }"; + parseAndAssertEquality(soqlIdFirst, expectedSparql); + } + + @Test + void parseQuerySupportsDistinctCountWithProjectedAttribute() { + final String soqlIdFirst = "SELECT DISTINCT COUNT(d.owlClassA) FROM OWLClassD d WHERE d.uri = :uri"; + final String expectedSparql = "SELECT (COUNT(DISTINCT ?owlClassA) AS ?count) WHERE { ?uri a " + strUri(Vocabulary.c_OwlClassD) + " . " + + "?uri " + strUri(Vocabulary.p_h_hasA) + " ?owlClassA . }"; + parseAndAssertEquality(soqlIdFirst, expectedSparql); + } + + @Test + void parseQueryWithProjectedAttribute() { + final String soqlIdFirst = "SELECT d.owlClassA FROM OWLClassD d WHERE d.uri = :uri"; + final String expectedSparql = "SELECT ?owlClassA WHERE { ?uri a " + strUri(Vocabulary.c_OwlClassD) + " . " + + "?uri " + strUri(Vocabulary.p_h_hasA) + " ?owlClassA . }"; + parseAndAssertEquality(soqlIdFirst, expectedSparql); + } + + @Test + void parseQueryWithProjectedAttributeAndRelatedAttribute() { + final String soqlIdFirst = "SELECT d.owlClassA FROM OWLClassD d WHERE d.uri = :uri AND d.owlClassA.stringAttribute = :stringAtt"; + final String expectedSparql = "SELECT ?owlClassA WHERE { ?uri a " + strUri(Vocabulary.c_OwlClassD) + " . " + + "?uri " + strUri(Vocabulary.p_h_hasA) + " ?owlClassA . " + // FIXME: Duplicated SPARQL #281 + "?uri " + strUri(Vocabulary.p_h_hasA) + " ?owlClassA . " + + "?owlClassA " + strUri(Vocabulary.p_a_stringAttribute) + " ?stringAtt . }"; + parseAndAssertEquality(soqlIdFirst, expectedSparql); + } + + @Test + void parseQueryWithDistinctProjectedAttributeAndRelatedAttribute() { + final String soqlIdFirst = "SELECT DISTINCT d.owlClassA FROM OWLClassD d WHERE d.uri = :uri AND d.owlClassA.stringAttribute = :stringAtt"; + final String expectedSparql = "SELECT DISTINCT ?owlClassA WHERE { ?uri a " + strUri(Vocabulary.c_OwlClassD) + " . " + + "?uri " + strUri(Vocabulary.p_h_hasA) + " ?owlClassA . " + // FIXME: Duplicated SPARQL #281 + "?uri " + strUri(Vocabulary.p_h_hasA) + " ?owlClassA . " + + "?owlClassA " + strUri(Vocabulary.p_a_stringAttribute) + " ?stringAtt . }"; + parseAndAssertEquality(soqlIdFirst, expectedSparql); + } + /** * Bug #178 */ From 9b8e22b25023abcc3e4dd7dda187382399326d40 Mon Sep 17 00:00:00 2001 From: luxbe Date: Wed, 20 Nov 2024 11:03:11 +0100 Subject: [PATCH 2/2] [Enhancement #278] test attribute projection in CriteriaQuery --- .../CriteriaQueryTranslateQueryTest.java | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/jopa-impl/src/test/java/cz/cvut/kbss/jopa/query/criteria/CriteriaQueryTranslateQueryTest.java b/jopa-impl/src/test/java/cz/cvut/kbss/jopa/query/criteria/CriteriaQueryTranslateQueryTest.java index 8e6e4bf88..718923b9e 100644 --- a/jopa-impl/src/test/java/cz/cvut/kbss/jopa/query/criteria/CriteriaQueryTranslateQueryTest.java +++ b/jopa-impl/src/test/java/cz/cvut/kbss/jopa/query/criteria/CriteriaQueryTranslateQueryTest.java @@ -145,6 +145,51 @@ public void testTranslateQuerySelectProperty() { assertEquals(expectedSoqlQuery, generatedSoqlQuery); } + @Test + void testTranslateQueryCountProperty() { + CriteriaQueryImpl query = cb.createQuery(Integer.class); + Root root = query.from(OWLClassD.class); + query.select(cb.count(root.getAttr("owlClassA"))); + + final String generatedSoqlQuery = query.translateQuery(criteriaParameterFiller); + final String expectedSoqlQuery = "SELECT COUNT(owlclassd.owlClassA) FROM OWLClassD owlclassd"; + assertEquals(expectedSoqlQuery, generatedSoqlQuery); + } + + @Test + void testTranslateQueryDistinctCountProperty() { + CriteriaQueryImpl query = cb.createQuery(Integer.class); + Root root = query.from(OWLClassD.class); + query.select(cb.count(root.getAttr("owlClassA"))).distinct(); + + final String generatedSoqlQuery = query.translateQuery(criteriaParameterFiller); + final String expectedSoqlQuery = "SELECT DISTINCT COUNT(owlclassd.owlClassA) FROM OWLClassD owlclassd"; + assertEquals(expectedSoqlQuery, generatedSoqlQuery); + } + + @Test + void parseQuerySupportsCountWithProjectedAttribute() { + CriteriaQueryImpl query = cb.createQuery(Integer.class); + Root root = query.from(OWLClassD.class); + query.select(cb.count(root.getAttr("owlClassA"))).distinct(); + + final String generatedSoqlQuery = query.translateQuery(criteriaParameterFiller); + final String expectedSoqlQuery = "SELECT DISTINCT COUNT(owlclassd.owlClassA) FROM OWLClassD owlclassd"; + assertEquals(expectedSoqlQuery, generatedSoqlQuery); + } + + @Test + void parseQuerySupportsCountWithProjectedAttributeAndRelatedAttribute() { + CriteriaQueryImpl query = cb.createQuery(Integer.class); + Root root = query.from(OWLClassD.class); + query.select(cb.count(root.getAttr("owlClassA"))).distinct() + .where(cb.equal(root.getAttr("owlClassA").getAttr("stringAttribute"), "")); + + final String generatedSoqlQuery = query.translateQuery(criteriaParameterFiller); + final String expectedSoqlQuery = "SELECT DISTINCT COUNT(owlclassd.owlClassA) FROM OWLClassD owlclassd WHERE owlclassd.owlClassA.stringAttribute = :generatedName0"; + assertEquals(expectedSoqlQuery, generatedSoqlQuery); + } + @Test public void testTranslateQuerySelectPropertyPath() { CriteriaQueryImpl query = cb.createQuery(String.class);