mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
FIX Don't generate table alias for "from" statement that are not column names.
This commit is contained in:
parent
d9bccaff3d
commit
f91b279ef0
@ -78,7 +78,18 @@ abstract class SQLConditionalExpression extends SQLExpression
|
|||||||
if (is_array($from)) {
|
if (is_array($from)) {
|
||||||
$this->from = array_merge($this->from, $from);
|
$this->from = array_merge($this->from, $from);
|
||||||
} elseif (!empty($from)) {
|
} elseif (!empty($from)) {
|
||||||
$this->from[str_replace(['"','`'], '', $from)] = $from;
|
// Check if the from clause looks like a regular table name
|
||||||
|
// Table name most be an uninterrupted string, with no spaces.
|
||||||
|
// It may be padded with spaces. e.g. ` TableName ` will be
|
||||||
|
// treated as Table Name, but not ` Table Name `.
|
||||||
|
if (preg_match('/^\s*[^\s]+\s*$/', $from)) {
|
||||||
|
// Add an alias for the table name, stripping any quotes
|
||||||
|
$this->from[str_replace(['"','`'], '', $from)] = $from;
|
||||||
|
} else {
|
||||||
|
// Add from clause without an alias - this is probably a full
|
||||||
|
// sub-select with its own explicit alias.
|
||||||
|
$this->from[] = $from;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
|
@ -1327,4 +1327,101 @@ class SQLSelectTest extends SapphireTest
|
|||||||
|
|
||||||
$select->addWith('cte', new SQLSelect());
|
$select->addWith('cte', new SQLSelect());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function subqueryProvider()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'no-explicit-alias-string' => ['( SELECT DISTINCT "SQLSelectTest_DO"."ClassName" FROM "SQLSelectTest_DO") AS "FINAL"'],
|
||||||
|
'no-alias-array' => [['( SELECT DISTINCT "SQLSelectTest_DO"."ClassName" FROM "SQLSelectTest_DO") AS "FINAL"']],
|
||||||
|
'no-alias-array-numeric-key' => [[0 => '( SELECT DISTINCT "SQLSelectTest_DO"."ClassName" FROM "SQLSelectTest_DO") AS "FINAL"']],
|
||||||
|
'explicit-alias-string' => [['FINAL' => '( SELECT DISTINCT "SQLSelectTest_DO"."ClassName" FROM "SQLSelectTest_DO")']],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider subqueryProvider
|
||||||
|
*/
|
||||||
|
public function testSubqueries($subquery)
|
||||||
|
{
|
||||||
|
$query = new SQLSelect('*', $subquery);
|
||||||
|
|
||||||
|
$actualSQL = $query->sql();
|
||||||
|
|
||||||
|
$this->assertSQLEquals(
|
||||||
|
'SELECT * FROM ( SELECT DISTINCT "SQLSelectTest_DO"."ClassName" FROM "SQLSelectTest_DO") AS "FINAL"',
|
||||||
|
$actualSQL
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addFromProvider()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'string' => [
|
||||||
|
'MyTable', ['MyTable' => 'MyTable'],
|
||||||
|
'Plain table name get alias automatic alias'
|
||||||
|
],
|
||||||
|
'string padded with spaces' => [
|
||||||
|
' MyTable ', [' MyTable ' => ' MyTable '],
|
||||||
|
'Plain table name get alias automatic alias'
|
||||||
|
],
|
||||||
|
'quoted string' => [
|
||||||
|
'"MyTable"', ['MyTable' => '"MyTable"'],
|
||||||
|
'Quoted table name get alias without the quotes'
|
||||||
|
],
|
||||||
|
'underscore in table name string' => [
|
||||||
|
'"My_Table_123"', ['My_Table_123' => '"My_Table_123"'],
|
||||||
|
'Numbers and underscores are allowed in table names'
|
||||||
|
],
|
||||||
|
'backtick string' => [
|
||||||
|
'`MyTable`', ['MyTable' => '`MyTable`'],
|
||||||
|
'Backtick quoted table name get alias without the quotes'
|
||||||
|
],
|
||||||
|
'subquery string' => [
|
||||||
|
' (SELECT * from "FooBar") as FooBar ', [' (SELECT * from "FooBar") as FooBar '],
|
||||||
|
'String that don\'t look like table name don\'t get alias'
|
||||||
|
],
|
||||||
|
'array' => [
|
||||||
|
['MyTable'], ['MyTable'],
|
||||||
|
'Arrays are passed through as is'
|
||||||
|
],
|
||||||
|
'array-associative-key' => [
|
||||||
|
['MyTableAlias' => 'MyTable'], ['MyTableAlias' => 'MyTable'],
|
||||||
|
'Associative arrays are passed through as is and aliases are preserved'
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider addFromProvider
|
||||||
|
*/
|
||||||
|
public function testAddFrom($input, $out, $message = ""): void
|
||||||
|
{
|
||||||
|
$query = new SQLSelect();
|
||||||
|
$query->addFrom($input);
|
||||||
|
$this->assertEquals($out, $query->getFrom(), $message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAddFromRetainPreviousData()
|
||||||
|
{
|
||||||
|
// Initial setup
|
||||||
|
$query = new SQLSelect();
|
||||||
|
$query->addFrom('MyTable');
|
||||||
|
$query->addFrom('"MyOtherTable"');
|
||||||
|
|
||||||
|
// This will override some value and add a new one
|
||||||
|
$query->addFrom([
|
||||||
|
'MyTable' => '(SELECT * FROM "MyTable" where "Foo" = "Bar")',
|
||||||
|
'ThirdTable',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->assertEquals(
|
||||||
|
[
|
||||||
|
'MyTable' => '(SELECT * FROM "MyTable" where "Foo" = "Bar")',
|
||||||
|
'MyOtherTable' => '"MyOtherTable"',
|
||||||
|
'ThirdTable',
|
||||||
|
],
|
||||||
|
$query->getFrom(),
|
||||||
|
'MyTable entry got merge over, MyOtherTable was retained, ThirdTable was added'
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user