mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 12:05:37 +00:00
ENH Enable allowing collisions for field statements (#10957)
This commit is contained in:
parent
bbc0295f86
commit
fac3356739
@ -49,6 +49,11 @@ class DataQuery
|
||||
*/
|
||||
protected $collidingFields = [];
|
||||
|
||||
/**
|
||||
* If true, collisions are allowed for statements aliased as db columns
|
||||
*/
|
||||
private $allowCollidingFieldStatements = false;
|
||||
|
||||
/**
|
||||
* Allows custom callback to be registered before getFinalisedQuery is called.
|
||||
*
|
||||
@ -287,6 +292,7 @@ class DataQuery
|
||||
if ($this->collidingFields) {
|
||||
foreach ($this->collidingFields as $collisionField => $collisions) {
|
||||
$caseClauses = [];
|
||||
$lastClauses = [];
|
||||
foreach ($collisions as $collision) {
|
||||
if (preg_match('/^"(?<table>[^"]+)"\./', $collision ?? '', $matches)) {
|
||||
$collisionTable = $matches['table'];
|
||||
@ -298,9 +304,14 @@ class DataQuery
|
||||
$caseClauses[] = "WHEN {$collisionClassColumn} IN ({$collisionClassesSQL}) THEN $collision";
|
||||
}
|
||||
} else {
|
||||
user_error("Bad collision item '$collision'", E_USER_WARNING);
|
||||
if ($this->getAllowCollidingFieldStatements()) {
|
||||
$lastClauses[] = "WHEN $collision IS NOT NULL THEN $collision";
|
||||
} else {
|
||||
user_error("Bad collision item '$collision'", E_USER_WARNING);
|
||||
}
|
||||
}
|
||||
}
|
||||
$caseClauses = array_merge($caseClauses, $lastClauses);
|
||||
$query->selectField("CASE " . implode(" ", $caseClauses) . " ELSE NULL END", $collisionField);
|
||||
}
|
||||
}
|
||||
@ -1379,6 +1390,25 @@ class DataQuery
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get whether field statements aliased as columns are allowed when that column is already
|
||||
* being selected
|
||||
*/
|
||||
public function getAllowCollidingFieldStatements(): bool
|
||||
{
|
||||
return $this->allowCollidingFieldStatements;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether field statements aliased as columns are allowed when that column is already
|
||||
* being selected
|
||||
*/
|
||||
public function setAllowCollidingFieldStatements(bool $value): static
|
||||
{
|
||||
$this->allowCollidingFieldStatements = $value;
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function validateColumnField($field, SQLSelect $query)
|
||||
{
|
||||
// standard column - nothing to process here
|
||||
|
@ -183,6 +183,33 @@ class DataQueryTest extends SapphireTest
|
||||
$this->assertTrue(true);
|
||||
}
|
||||
|
||||
public function provideFieldCollision()
|
||||
{
|
||||
return [
|
||||
'allow collisions' => [true],
|
||||
'disallow collisions' => [false],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideFieldCollision
|
||||
*/
|
||||
public function testFieldCollision($allowCollisions)
|
||||
{
|
||||
$dataQuery = new DataQuery(DataQueryTest\ObjectB::class);
|
||||
$dataQuery->selectField('COALESCE(NULL, 1) AS "Title"');
|
||||
$dataQuery->setAllowCollidingFieldStatements($allowCollisions);
|
||||
|
||||
if ($allowCollisions) {
|
||||
$this->assertSQLContains('THEN "DataQueryTest_B"."Title" WHEN COALESCE(NULL, 1) AS "Title" IS NOT NULL THEN COALESCE(NULL, 1) AS "Title" ELSE NULL END AS "Title"', $dataQuery->sql());
|
||||
} else {
|
||||
$this->expectError();
|
||||
$this->expectErrorMessageMatches('/^Bad collision item /');
|
||||
}
|
||||
|
||||
$dataQuery->getFinalisedQuery();
|
||||
}
|
||||
|
||||
public function testDisjunctiveGroup()
|
||||
{
|
||||
$dq = new DataQuery(DataQueryTest\ObjectA::class);
|
||||
|
Loading…
x
Reference in New Issue
Block a user