Skip to content

Commit

Permalink
FIX Don't generate table alias for "from" statement that are not colu…
Browse files Browse the repository at this point in the history
…mn names.
  • Loading branch information
maxime-rainville committed Jul 26, 2024
1 parent 4693e3f commit 9a8905f
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 1 deletion.
13 changes: 12 additions & 1 deletion src/ORM/Queries/SQLConditionalExpression.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,18 @@ public function addFrom($from)
if (is_array($from)) {
$this->from = array_merge($this->from, $from);
} elseif (!empty($from)) {
$this->from[str_replace(['"','`'], '', $from)] = $from;
// Make sure we don't have any pointless blank space in our From clause
$from = trim($from);

// Check if the from clause looks like a regular table name
// Table name can contain only alphanumeric characters and underscores
if (preg_match('/^["`]?([a-zA-Z0-9_]+)["`]?$/', $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->from[] = $from;
}
}

return $this;
Expand Down
93 changes: 93 additions & 0 deletions tests/php/ORM/SQLSelectTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1327,4 +1327,97 @@ public function testMultipleWithDuplicateName()

$select->addWith('cte', new SQLSelect());
}

public function subqueryProvider()
{
return [
'no-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'
],
'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'
);
}
}

0 comments on commit 9a8905f

Please sign in to comment.