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)) {
|
||||
$this->from = array_merge($this->from, $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;
|
||||
|
@ -1327,4 +1327,101 @@ class SQLSelectTest extends SapphireTest
|
||||
|
||||
$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