diff --git a/src/ORM/DataList.php b/src/ORM/DataList.php index 1392933c4..e9180c34c 100644 --- a/src/ORM/DataList.php +++ b/src/ORM/DataList.php @@ -806,6 +806,25 @@ class DataList extends ViewableData implements SS_List, Filterable, Sortable, Li }); } + /** + * Return a new DataList instance with a right join clause added to this list's query. + * + * @param string $table Table name (unquoted and as escaped SQL) + * @param string $onClause Escaped SQL statement, e.g. '"Table1"."ID" = "Table2"."ID"' + * @param string $alias - if you want this table to be aliased under another name + * @param int $order A numerical index to control the order that joins are added to the query; lower order values + * will cause the query to appear first. The default is 20, and joins created automatically by the + * ORM have a value of 10. + * @param array $parameters Any additional parameters if the join is a parameterised subquery + * @return static + */ + public function rightJoin($table, $onClause, $alias = null, $order = 20, $parameters = []) + { + return $this->alterDataQuery(function (DataQuery $query) use ($table, $onClause, $alias, $order, $parameters) { + $query->rightJoin($table, $onClause, $alias, $order, $parameters); + }); + } + /** * Return an array of the actual items that this DataList contains at this stage. * This is when the query is actually executed. diff --git a/tests/php/ORM/DataListTest.php b/tests/php/ORM/DataListTest.php index d046c6cba..b5fbdf63a 100755 --- a/tests/php/ORM/DataListTest.php +++ b/tests/php/ORM/DataListTest.php @@ -304,12 +304,33 @@ class DataListTest extends SapphireTest $this->assertSQLEquals($expected, $list->sql($parameters)); } - public function testInnerJoin() + public function provideJoin() + { + return [ + [ + 'joinMethod' => 'innerJoin', + 'joinType' => 'INNER JOIN', + ], + [ + 'joinMethod' => 'leftJoin', + 'joinType' => 'LEFT JOIN', + ], + [ + 'joinMethod' => 'rightJoin', + 'joinType' => 'RIGHT JOIN', + ], + ]; + } + + /** + * @dataProvider provideJoin + */ + public function testJoin(string $joinMethod, string $joinType) { $db = DB::get_conn(); $list = TeamComment::get(); - $list = $list->innerJoin( + $list = $list->$joinMethod( 'DataObjectTest_Team', '"DataObjectTest_Team"."ID" = "DataObjectTest_TeamComment"."TeamID"', 'Team' @@ -322,22 +343,24 @@ class DataListTest extends SapphireTest . 'CASE WHEN "DataObjectTest_TeamComment"."ClassName" IS NOT NULL' . ' THEN "DataObjectTest_TeamComment"."ClassName" ELSE ' . $db->quoteString(DataObjectTest\TeamComment::class) - . ' END AS "RecordClassName" FROM "DataObjectTest_TeamComment" INNER JOIN ' - . '"DataObjectTest_Team" AS "Team" ON "DataObjectTest_Team"."ID" = ' + . ' END AS "RecordClassName" FROM "DataObjectTest_TeamComment" ' . $joinType + . ' "DataObjectTest_Team" AS "Team" ON "DataObjectTest_Team"."ID" = ' . '"DataObjectTest_TeamComment"."TeamID"' . ' ORDER BY "DataObjectTest_TeamComment"."Name" ASC'; - $this->assertSQLEquals($expected, $list->sql($parameters)); $this->assertEmpty($parameters); } - public function testInnerJoinParameterised() + /** + * @dataProvider provideJoin + */ + public function testJoinParameterised(string $joinMethod, string $joinType) { $db = DB::get_conn(); $list = TeamComment::get(); - $list = $list->innerJoin( + $list = $list->$joinMethod( 'DataObjectTest_Team', '"DataObjectTest_Team"."ID" = "DataObjectTest_TeamComment"."TeamID" ' . 'AND "DataObjectTest_Team"."Title" LIKE ?', @@ -353,66 +376,8 @@ class DataListTest extends SapphireTest . 'CASE WHEN "DataObjectTest_TeamComment"."ClassName" IS NOT NULL' . ' THEN "DataObjectTest_TeamComment"."ClassName" ELSE ' . $db->quoteString(DataObjectTest\TeamComment::class) - . ' END AS "RecordClassName" FROM "DataObjectTest_TeamComment" INNER JOIN ' - . '"DataObjectTest_Team" AS "Team" ON "DataObjectTest_Team"."ID" = ' - . '"DataObjectTest_TeamComment"."TeamID" ' - . 'AND "DataObjectTest_Team"."Title" LIKE ?' - . ' ORDER BY "DataObjectTest_TeamComment"."Name" ASC'; - - $this->assertSQLEquals($expected, $list->sql($parameters)); - $this->assertEquals(['Team%'], $parameters); - } - - public function testLeftJoin() - { - $db = DB::get_conn(); - - $list = TeamComment::get(); - $list = $list->leftJoin( - 'DataObjectTest_Team', - '"DataObjectTest_Team"."ID" = "DataObjectTest_TeamComment"."TeamID"', - 'Team' - ); - - $expected = 'SELECT DISTINCT "DataObjectTest_TeamComment"."ClassName", ' - . '"DataObjectTest_TeamComment"."LastEdited", "DataObjectTest_TeamComment"."Created", ' - . '"DataObjectTest_TeamComment"."Name", "DataObjectTest_TeamComment"."Comment", ' - . '"DataObjectTest_TeamComment"."TeamID", "DataObjectTest_TeamComment"."ID", ' - . 'CASE WHEN "DataObjectTest_TeamComment"."ClassName" IS NOT NULL ' - . 'THEN "DataObjectTest_TeamComment"."ClassName" ELSE ' - . $db->quoteString(DataObjectTest\TeamComment::class) - . ' END AS "RecordClassName" FROM "DataObjectTest_TeamComment" LEFT JOIN "DataObjectTest_Team" ' - . 'AS "Team" ON "DataObjectTest_Team"."ID" = "DataObjectTest_TeamComment"."TeamID"' - . ' ORDER BY "DataObjectTest_TeamComment"."Name" ASC'; - - - $this->assertSQLEquals($expected, $list->sql($parameters)); - $this->assertEmpty($parameters); - } - - public function testLeftJoinParameterised() - { - $db = DB::get_conn(); - - $list = TeamComment::get(); - $list = $list->leftJoin( - 'DataObjectTest_Team', - '"DataObjectTest_Team"."ID" = "DataObjectTest_TeamComment"."TeamID" ' - . 'AND "DataObjectTest_Team"."Title" LIKE ?', - 'Team', - 20, - ['Team%'] - ); - - $expected = 'SELECT DISTINCT "DataObjectTest_TeamComment"."ClassName", ' - . '"DataObjectTest_TeamComment"."LastEdited", "DataObjectTest_TeamComment"."Created", ' - . '"DataObjectTest_TeamComment"."Name", "DataObjectTest_TeamComment"."Comment", ' - . '"DataObjectTest_TeamComment"."TeamID", "DataObjectTest_TeamComment"."ID", ' - . 'CASE WHEN "DataObjectTest_TeamComment"."ClassName" IS NOT NULL' - . ' THEN "DataObjectTest_TeamComment"."ClassName" ELSE ' - . $db->quoteString(DataObjectTest\TeamComment::class) - . ' END AS "RecordClassName" FROM "DataObjectTest_TeamComment" LEFT JOIN ' - . '"DataObjectTest_Team" AS "Team" ON "DataObjectTest_Team"."ID" = ' + . ' END AS "RecordClassName" FROM "DataObjectTest_TeamComment" ' . $joinType + . ' "DataObjectTest_Team" AS "Team" ON "DataObjectTest_Team"."ID" = ' . '"DataObjectTest_TeamComment"."TeamID" ' . 'AND "DataObjectTest_Team"."Title" LIKE ?' . ' ORDER BY "DataObjectTest_TeamComment"."Name" ASC';