mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
BUG Fix joins on tables containing "select" being mistaken for sub-selects
Fix PHPDoc on SQLQuery::addFrom and SQLQuery::setFrom Fixes #3965
This commit is contained in:
parent
c1a7a8d7bd
commit
b34c236b3c
@ -239,10 +239,10 @@ class SQLQuery {
|
|||||||
/**
|
/**
|
||||||
* Set table for the SELECT clause.
|
* Set table for the SELECT clause.
|
||||||
*
|
*
|
||||||
* @example $query->setFrom("MyTable"); // SELECT * FROM MyTable
|
* @example $query->setFrom('"MyTable"'); // SELECT * FROM "MyTable"
|
||||||
*
|
*
|
||||||
* @param string|array $from Escaped SQL statement, usually an unquoted table name
|
* @param string|array $from Single, or list of, ANSI quoted table names
|
||||||
* @return SQLQuery
|
* @return self
|
||||||
*/
|
*/
|
||||||
public function setFrom($from) {
|
public function setFrom($from) {
|
||||||
$this->from = array();
|
$this->from = array();
|
||||||
@ -252,10 +252,10 @@ class SQLQuery {
|
|||||||
/**
|
/**
|
||||||
* Add a table to the SELECT clause.
|
* Add a table to the SELECT clause.
|
||||||
*
|
*
|
||||||
* @example $query->addFrom("MyTable"); // SELECT * FROM MyTable
|
* @example $query->addFrom('"MyTable"'); // SELECT * FROM "MyTable"
|
||||||
*
|
*
|
||||||
* @param string|array $from Escaped SQL statement, usually an unquoted table name
|
* @param string|array $from Single, or list of, ANSI quoted table names
|
||||||
* @return SQLQuery
|
* @return self Self reference
|
||||||
*/
|
*/
|
||||||
public function addFrom($from) {
|
public function addFrom($from) {
|
||||||
if(is_array($from)) {
|
if(is_array($from)) {
|
||||||
@ -903,9 +903,13 @@ class SQLQuery {
|
|||||||
else if(sizeof($join['filter']) == 1) $filter = $join['filter'][0];
|
else if(sizeof($join['filter']) == 1) $filter = $join['filter'][0];
|
||||||
else $filter = "(" . implode(") AND (", $join['filter']) . ")";
|
else $filter = "(" . implode(") AND (", $join['filter']) . ")";
|
||||||
|
|
||||||
$table = strpos(strtoupper($join['table']), 'SELECT') ? $join['table'] : "\""
|
// Ensure tables are quoted, unless the table is actually a sub-select
|
||||||
. $join['table'] . "\"";
|
$table = preg_match('/\bSELECT\b/i', $join['table'])
|
||||||
$aliasClause = ($alias != $join['table']) ? " AS \"" . Convert::raw2sql($alias) . "\"" : "";
|
? $join['table']
|
||||||
|
: "\"{$join['table']}\"";
|
||||||
|
$aliasClause = ($alias != $join['table'])
|
||||||
|
? " AS \"{$alias}\""
|
||||||
|
: "";
|
||||||
$this->from[$alias] = strtoupper($join['type']) . " JOIN "
|
$this->from[$alias] = strtoupper($join['type']) . " JOIN "
|
||||||
. $table . "$aliasClause ON $filter";
|
. $table . "$aliasClause ON $filter";
|
||||||
}
|
}
|
||||||
|
@ -344,23 +344,34 @@ class SQLQueryTest extends SapphireTest {
|
|||||||
|
|
||||||
public function testJoinSubSelect() {
|
public function testJoinSubSelect() {
|
||||||
|
|
||||||
|
// Test sub-select works
|
||||||
$query = new SQLQuery();
|
$query = new SQLQuery();
|
||||||
$query->setFrom('MyTable');
|
$query->setFrom('"MyTable"');
|
||||||
$query->addInnerJoin('(SELECT * FROM MyOtherTable)',
|
$query->addInnerJoin('(SELECT * FROM "MyOtherTable")',
|
||||||
'Mot.MyTableID = MyTable.ID', 'Mot');
|
'"Mot"."MyTableID" = "MyTable"."ID"', 'Mot');
|
||||||
$query->addLeftJoin('(SELECT MyLastTable.MyOtherTableID, COUNT(1) as MyLastTableCount FROM MyLastTable '
|
$query->addLeftJoin('(SELECT "MyLastTable"."MyOtherTableID", COUNT(1) as "MyLastTableCount" '
|
||||||
. 'GROUP BY MyOtherTableID)',
|
. 'FROM "MyLastTable" GROUP BY "MyOtherTableID")',
|
||||||
'Mlt.MyOtherTableID = Mot.ID', 'Mlt');
|
'"Mlt"."MyOtherTableID" = "Mot"."ID"', 'Mlt');
|
||||||
$query->setOrderBy('COALESCE(Mlt.MyLastTableCount, 0) DESC');
|
$query->setOrderBy('COALESCE("Mlt"."MyLastTableCount", 0) DESC');
|
||||||
|
|
||||||
$this->assertEquals('SELECT *, COALESCE(Mlt.MyLastTableCount, 0) AS "_SortColumn0" FROM MyTable '.
|
$this->assertEquals('SELECT *, COALESCE("Mlt"."MyLastTableCount", 0) AS "_SortColumn0" FROM "MyTable" '.
|
||||||
'INNER JOIN (SELECT * FROM MyOtherTable) AS "Mot" ON Mot.MyTableID = MyTable.ID ' .
|
'INNER JOIN (SELECT * FROM "MyOtherTable") AS "Mot" ON "Mot"."MyTableID" = "MyTable"."ID" ' .
|
||||||
'LEFT JOIN (SELECT MyLastTable.MyOtherTableID, COUNT(1) as MyLastTableCount FROM MyLastTable '
|
'LEFT JOIN (SELECT "MyLastTable"."MyOtherTableID", COUNT(1) as "MyLastTableCount" FROM "MyLastTable" '
|
||||||
. 'GROUP BY MyOtherTableID) AS "Mlt" ON Mlt.MyOtherTableID = Mot.ID ' .
|
. 'GROUP BY "MyOtherTableID") AS "Mlt" ON "Mlt"."MyOtherTableID" = "Mot"."ID" ' .
|
||||||
'ORDER BY "_SortColumn0" DESC',
|
'ORDER BY "_SortColumn0" DESC',
|
||||||
$query->sql()
|
$query->sql()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Test that table names do not get mistakenly identified as sub-selects
|
||||||
|
$query = new SQLQuery();
|
||||||
|
$query->setFrom('"MyTable"');
|
||||||
|
$query->addInnerJoin('NewsArticleSelected', '"News"."MyTableID" = "MyTable"."ID"', 'News');
|
||||||
|
$this->assertEquals(
|
||||||
|
'SELECT * FROM "MyTable" INNER JOIN "NewsArticleSelected" AS "News" ON '.
|
||||||
|
'"News"."MyTableID" = "MyTable"."ID"',
|
||||||
|
$query->sql()
|
||||||
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSetWhereAny() {
|
public function testSetWhereAny() {
|
||||||
|
Loading…
Reference in New Issue
Block a user