/**
  * Remaps table/field names in a SELECT query's parts
  *
  * @param mixed $select_fields Either parsed list of tables (SQLparser->parseFromTables()) or list of fields to select from the table. This is what comes right after "SELECT ...". Required value.
  * @param string $from_table Table(s) from which to select. This is what comes right after "FROM ...". Require value.
  * @param string $where_clause Where clause. This is what comes right after "WHERE ...". Can be blank.
  * @param string $groupBy Group by field(s)
  * @param string $orderBy Order by field(s)
  * @return array
  * @see exec_SELECTquery()
  */
 protected function map_remapSELECTQueryParts($select_fields, $from_table, $where_clause, $groupBy, $orderBy)
 {
     // Backup current mapping as it may be altered if aliases on mapped tables are found
     $backupMapping = $this->mapping;
     // Tables:
     $tables = is_array($from_table) ? $from_table : $this->SQLparser->parseFromTables($from_table);
     $defaultTable = $tables[0]['table'];
     // Prepare mapping for aliased tables. This will copy the definition of the original table name.
     // The alias is prefixed with a database-incompatible character to prevent naming clash with real table name
     // Further access to $this->mapping should be made through $this->getMappingKey() method
     foreach ($tables as $k => $v) {
         if ($v['as'] && is_array($this->mapping[$v['table']]['mapFieldNames'])) {
             $mappingKey = $this->getFreeMappingKey($v['as']);
             $this->mapping[$mappingKey]['mapFieldNames'] =& $this->mapping[$v['table']]['mapFieldNames'];
         }
         if (is_array($v['JOIN'])) {
             foreach ($v['JOIN'] as $joinCnt => $join) {
                 if ($join['as'] && is_array($this->mapping[$join['withTable']]['mapFieldNames'])) {
                     $mappingKey = $this->getFreeMappingKey($join['as']);
                     $this->mapping[$mappingKey]['mapFieldNames'] =& $this->mapping[$join['withTable']]['mapFieldNames'];
                 }
             }
         }
     }
     foreach ($tables as $k => $v) {
         $tableKey = $this->getMappingKey($v['table']);
         if ($this->mapping[$tableKey]['mapTableName']) {
             $tables[$k]['table'] = $this->mapping[$tableKey]['mapTableName'];
         }
         // Mapping JOINS
         if (is_array($v['JOIN'])) {
             foreach ($v['JOIN'] as $joinCnt => $join) {
                 // Mapping withTable of the JOIN
                 $withTableKey = $this->getMappingKey($join['withTable']);
                 if ($this->mapping[$withTableKey]['mapTableName']) {
                     $tables[$k]['JOIN'][$joinCnt]['withTable'] = $this->mapping[$withTableKey]['mapTableName'];
                 }
                 $onPartsArray = array();
                 // Mapping ON parts of the JOIN
                 if (is_array($tables[$k]['JOIN'][$joinCnt]['ON'])) {
                     foreach ($tables[$k]['JOIN'][$joinCnt]['ON'] as &$condition) {
                         // Left side of the comparator
                         $leftTableKey = $this->getMappingKey($condition['left']['table']);
                         if (isset($this->mapping[$leftTableKey]['mapFieldNames'][$condition['left']['field']])) {
                             $condition['left']['field'] = $this->mapping[$leftTableKey]['mapFieldNames'][$condition['left']['field']];
                         }
                         if (isset($this->mapping[$leftTableKey]['mapTableName'])) {
                             $condition['left']['table'] = $this->mapping[$leftTableKey]['mapTableName'];
                         }
                         // Right side of the comparator
                         $rightTableKey = $this->getMappingKey($condition['right']['table']);
                         if (isset($this->mapping[$rightTableKey]['mapFieldNames'][$condition['right']['field']])) {
                             $condition['right']['field'] = $this->mapping[$rightTableKey]['mapFieldNames'][$condition['right']['field']];
                         }
                         if (isset($this->mapping[$rightTableKey]['mapTableName'])) {
                             $condition['right']['table'] = $this->mapping[$rightTableKey]['mapTableName'];
                         }
                     }
                 }
             }
         }
     }
     $fromParts = $tables;
     // Where clause:
     $parameterReferences = array();
     $whereParts = $this->SQLparser->parseWhereClause($where_clause, '', $parameterReferences);
     $this->map_sqlParts($whereParts, $defaultTable);
     // Select fields:
     $selectParts = $this->SQLparser->parseFieldList($select_fields);
     $this->map_sqlParts($selectParts, $defaultTable);
     // Group By fields
     $groupByParts = $this->SQLparser->parseFieldList($groupBy);
     $this->map_sqlParts($groupByParts, $defaultTable);
     // Order By fields
     $orderByParts = $this->SQLparser->parseFieldList($orderBy);
     $this->map_sqlParts($orderByParts, $defaultTable);
     // Restore the original mapping
     $this->mapping = $backupMapping;
     return array($selectParts, $fromParts, $whereParts, $groupByParts, $orderByParts, $parameterReferences);
 }