private function _getJoinForFromClause($searchTables, $searchColumns)
{
// $relations[master_table][foreign_table] => clause
$relations = array();
// Fill $relations with inter table relationship data
foreach ($searchTables as $oneTable) {
$this->_loadRelationsForTable($relations, $oneTable);
}
// Get tables and columns with valid where clauses
$validWhereClauses = $this->_getWhereClauseTablesAndColumns();
$whereClauseTables = $validWhereClauses['where_clause_tables'];
$whereClauseColumns = $validWhereClauses['where_clause_columns'];
// Get master table
$master = $this->_getMasterTable($searchTables, $searchColumns, $whereClauseColumns, $whereClauseTables);
// Will include master tables and all tables that can be combined into
// a cluster by their relation
$finalized = array();
if (strlen($master) > 0) {
// Add master tables
$finalized[$master] = '';
}
// Fill the $finalized array with JOIN clauses for each table
$this->_fillJoinClauses($finalized, $relations, $searchTables);
// JOIN clause
$join = '';
// Tables that can not be combined with the table cluster
// which includes master table
$unfinalized = array_diff($searchTables, array_keys($finalized));
if (count($unfinalized) > 0) {
// We need to look for intermediary tables to JOIN unfinalized tables
// Heuristic to chose intermediary tables is to look for tables
// having relationships with unfinalized tables
foreach ($unfinalized as $oneTable) {
$references = PMA_getChildReferences($this->_db, $oneTable);
foreach ($references as $column => $columnReferences) {
foreach ($columnReferences as $reference) {
// Only from this schema
if ($reference['table_schema'] != $this->_db) {
continue;
}
$table = $reference['table_name'];
$this->_loadRelationsForTable($relations, $table);
// Make copies
$tempFinalized = $finalized;
$tempSearchTables = $searchTables;
$tempSearchTables[] = $table;
// Try joining with the added table
$this->_fillJoinClauses($tempFinalized, $relations, $tempSearchTables);
$tempUnfinalized = array_diff($tempSearchTables, array_keys($tempFinalized));
// Take greedy approach.
// If the unfinalized count drops we keep the new table
// and switch temporary varibles with the original ones
if (count($tempUnfinalized) < count($unfinalized)) {
$finalized = $tempFinalized;
$searchTables = $tempSearchTables;
}
// We are done if no unfinalized tables anymore
if (count($tempUnfinalized) == 0) {
break 3;
}
}
}
}
$unfinalized = array_diff($searchTables, array_keys($finalized));
// If there are still unfinalized tables
if (count($unfinalized) > 0) {
// Add these tables as cartesian product before joined tables
$join .= implode(', ', array_map('Util::backquote', $unfinalized));
}
}
$first = true;
// Add joined tables
foreach ($finalized as $table => $clause) {
if ($first) {
if (!empty($join)) {
$join .= ", ";
}
$join .= Util::backquote($table);
$first = false;
} else {
$join .= "\n LEFT JOIN " . Util::backquote($table) . " ON " . $clause;
}
}
return $join;
}