PMA\libraries\DbQbe::_getJoinForFromClause PHP Method

_getJoinForFromClause() private method

Formulates the WHERE clause by JOINing tables
private _getJoinForFromClause ( array $searchTables, array $searchColumns ) : string
$searchTables array Tables involved in the search
$searchColumns array Columns involved in the search
return string table name
    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;
    }