This repository has been archived by the owner on Jul 27, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 21
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ISAICP-6242: Use a newer version of the sparql patch.
- Loading branch information
1 parent
3c09621
commit 37851f3
Showing
3 changed files
with
146 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
143 changes: 143 additions & 0 deletions
143
resources/patch/sparql_entity_storage_support_not_exists.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
diff --git a/src/Entity/Query/Sparql/Query.php b/src/Entity/Query/Sparql/Query.php | ||
index 9215946..3097e69 100644 | ||
--- a/src/Entity/Query/Sparql/Query.php | ||
+++ b/src/Entity/Query/Sparql/Query.php | ||
@@ -355,6 +355,16 @@ class Query extends QueryBase implements SparqlQueryInterface { | ||
if (!in_array($direction, ['ASC', 'DESC'])) { | ||
throw new \RuntimeException('Only "ASC" and "DESC" are allowed as sort order.'); | ||
} | ||
+ | ||
+ // Unlike the normal SQL queries where a column not defined can be used for | ||
+ // sorting if exists in the table, in SPARQL, the sort argument must be | ||
+ // defined in the WHERE clause. Any sort property, therefore, must will be | ||
+ // included with an EXISTS condition. | ||
+ // Also, the $idKey and $bundleKey properties cannot be added as triples as | ||
+ // they cannot be the object of the triple. | ||
+ if (!in_array($field, [$this->idKey, $this->bundleKey])) { | ||
+ $this->exists($field); | ||
+ } | ||
return parent::sort($field, $direction, $langcode); | ||
} | ||
|
||
diff --git a/src/Entity/Query/Sparql/SparqlCondition.php b/src/Entity/Query/Sparql/SparqlCondition.php | ||
index 582416f..da6bee1 100644 | ||
--- a/src/Entity/Query/Sparql/SparqlCondition.php | ||
+++ b/src/Entity/Query/Sparql/SparqlCondition.php | ||
@@ -70,7 +70,7 @@ class SparqlCondition extends ConditionFundamentals implements SparqlConditionIn | ||
'ENDS WITH' => ['prefix' => 'FILTER(STRENDS(', 'suffix' => '))'], | ||
'LIKE' => ['prefix' => 'FILTER(CONTAINS(', 'suffix' => '))'], | ||
'NOT LIKE' => ['prefix' => 'FILTER(!CONTAINS(', 'suffix' => '))'], | ||
- 'EXISTS' => ['prefix' => 'FILTER EXISTS {', 'suffix' => '}'], | ||
+ 'EXISTS' => ['prefix' => '', 'suffix' => ''], | ||
'NOT EXISTS' => ['prefix' => 'FILTER NOT EXISTS {', 'suffix' => '}'], | ||
'<' => ['prefix' => '', 'suffix' => ''], | ||
'>' => ['prefix' => '', 'suffix' => ''], | ||
@@ -271,10 +271,6 @@ class SparqlCondition extends ConditionFundamentals implements SparqlConditionIn | ||
'lang' => $lang, | ||
'column' => $column, | ||
]; | ||
- | ||
- if (!in_array($operator, ['EXISTS', 'NOT EXISTS'])) { | ||
- $this->requiresDefaultPattern = FALSE; | ||
- } | ||
} | ||
|
||
return $this; | ||
@@ -384,6 +380,7 @@ class SparqlCondition extends ConditionFundamentals implements SparqlConditionIn | ||
} | ||
|
||
$mappings = $this->fieldHandler->getFieldPredicates($entity_type_id, $field, $column); | ||
+ $mappings = array_values(array_unique($mappings)); | ||
$field_name = $field . '__' . $column; | ||
if (count($mappings) === 1) { | ||
$this->fieldMappings[$field_name] = reset($mappings); | ||
@@ -396,10 +393,10 @@ class SparqlCondition extends ConditionFundamentals implements SparqlConditionIn | ||
// loaded by the database. There is no way that in a single request, | ||
// the same predicate is found with a single and multiple mappings. | ||
// There is no filter per bundle in the query. | ||
- $this->fieldMappingConditions[] = [ | ||
+ $this->fieldMappingConditions[$field_name] = [ | ||
'field' => $field, | ||
'column' => $column, | ||
- 'value' => array_values(array_unique($mappings)), | ||
+ 'value' => $mappings, | ||
'operator' => 'IN', | ||
]; | ||
} | ||
@@ -504,7 +501,7 @@ class SparqlCondition extends ConditionFundamentals implements SparqlConditionIn | ||
|
||
case 'EXISTS': | ||
case 'NOT EXISTS': | ||
- $this->addConditionFragment($this->compileExists($condition)); | ||
+ $this->compileExists($condition); | ||
break; | ||
|
||
case 'CONTAINS': | ||
@@ -593,14 +590,31 @@ class SparqlCondition extends ConditionFundamentals implements SparqlConditionIn | ||
* | ||
* @param array $condition | ||
* An array that contains the 'field', 'value', 'operator' values. | ||
- * | ||
- * @return string | ||
- * A condition fragment string. | ||
*/ | ||
- protected function compileExists(array $condition): string { | ||
+ protected function compileExists(array $condition): void { | ||
$prefix = self::$filterOperatorMap[$condition['operator']]['prefix']; | ||
$suffix = self::$filterOperatorMap[$condition['operator']]['suffix']; | ||
- return $prefix . self::ID_KEY . ' ' . $this->escapePredicate($this->fieldMappings[$condition['field']]) . ' ' . SparqlArg::toVar($condition['field']) . $suffix; | ||
+ | ||
+ $field_predicate = $this->fieldMappings[$condition['field']]; | ||
+ $condition_string = self::ID_KEY . ' ' . $this->escapePredicate($field_predicate) . ' ' . SparqlArg::toVar($condition['field']); | ||
+ | ||
+ if (isset($this->fieldMappingConditions[$condition['field']])) { | ||
+ $mapping_condition = $this->fieldMappingConditions[$condition['field']]; | ||
+ $mapping_condition['value'] = SparqlArg::toResourceUris($mapping_condition['value']); | ||
+ $mapping_condition['field'] = $field_predicate; | ||
+ $condition_string .= ' . ' . $this->compileValuesFilter($mapping_condition); | ||
+ } | ||
+ | ||
+ $key = array_search($condition_string, $this->conditionFragments); | ||
+ // Only add a condition if the mapping condition is not found. If found, | ||
+ // replace it, in order to avoid creating an EXISTS and NOT EXISTS on the | ||
+ // same property. | ||
+ if ($key !== FALSE) { | ||
+ $this->conditionFragments[$key] = $prefix . $this->conditionFragments[$key] . $suffix; | ||
+ } | ||
+ else { | ||
+ $this->addConditionFragment($prefix . $condition_string . $suffix); | ||
+ } | ||
} | ||
|
||
/** | ||
diff --git a/tests/src/Kernel/SparqlEntityQueryTest.php b/tests/src/Kernel/SparqlEntityQueryTest.php | ||
index a8fe4b7..ace3e25 100644 | ||
--- a/tests/src/Kernel/SparqlEntityQueryTest.php | ||
+++ b/tests/src/Kernel/SparqlEntityQueryTest.php | ||
@@ -448,6 +448,26 @@ class SparqlEntityQueryTest extends SparqlKernelTestBase { | ||
]; | ||
} | ||
|
||
+ /** | ||
+ * Tests the NOT EXISTS operator. | ||
+ */ | ||
+ public function testNotExists() { | ||
+ $entity = SparqlTest::create([ | ||
+ 'id' => 'http://fruit.example.com/not_exists', | ||
+ 'title' => 'fruit title not exists', | ||
+ 'type' => 'fruit', | ||
+ ]); | ||
+ $entity->save(); | ||
+ $this->entities[] = $entity; | ||
+ | ||
+ $results = $this->getQuery() | ||
+ ->condition('type', 'fruit') | ||
+ ->notExists('text') | ||
+ ->execute(); | ||
+ | ||
+ $this->assertNotEmpty($results); | ||
+ } | ||
+ | ||
/** | ||
* Asserts that arrays are identical. | ||
*/ |