'Return the list of columns to use in the select statement. If no
columns have been specified, returns all columns relating to fields in
the model.
If \'with_aliases\' is true, any column names that are duplicated
(without the table names) are given unique aliases. This is needed in
some cases to avoid ambiguitity with nested queries.
This routine is overridden from Query to handle customized selection of
geometry columns.'

def get_columns(self, with_aliases=False):

    qn = self.quote_name_unless_alias
    qn2 = self.connection.ops.quote_name
    result = [('(%s)    AS    %s' % ((self.get_extra_select_format(alias) % col[0]), qn2(alias))) for (alias, col) in six.iteritems(self.query.extra_select)]
    params = []
    aliases = set(self.query.extra_select.keys())
    if with_aliases:
        col_aliases = aliases.copy()
    else:
        col_aliases = set()
    if self.query.select:
        only_load = self.deferred_to_columns()
        for (col, field) in self.query.select:
            if isinstance(col, (list, tuple)):
                (alias, column) = col
                table = self.query.alias_map[alias].table_name
                if ((table in only_load) and (column not in only_load[table])):
                    continue
                r = self.get_field_select(field, alias, column)
                if with_aliases:
                    if (col[1] in col_aliases):
                        c_alias = ('Col%d' % len(col_aliases))
                        result.append(('%s    AS    %s' % (r, c_alias)))
                        aliases.add(c_alias)
                        col_aliases.add(c_alias)
                    else:
                        result.append(('%s    AS    %s' % (r, qn2(col[1]))))
                        aliases.add(r)
                        col_aliases.add(col[1])
                else:
                    result.append(r)
                    aliases.add(r)
                    col_aliases.add(col[1])
            else:
                (col_sql, col_params) = col.as_sql(qn, self.connection)
                result.append(col_sql)
                params.extend(col_params)
                if hasattr(col, 'alias'):
                    aliases.add(col.alias)
                    col_aliases.add(col.alias)
    elif self.query.default_cols:
        (cols, new_aliases) = self.get_default_columns(with_aliases, col_aliases)
        result.extend(cols)
        aliases.update(new_aliases)
    max_name_length = self.connection.ops.max_name_length()
    for (alias, aggregate) in self.query.aggregate_select.items():
        (agg_sql, agg_params) = aggregate.as_sql(qn, self.connection)
        if (alias is None):
            result.append(agg_sql)
        else:
            result.append(('%s    AS    %s' % (agg_sql, qn(truncate_name(alias, max_name_length)))))
        params.extend(agg_params)
    for ((table, col), field) in self.query.related_select_cols:
        r = self.get_field_select(field, table, col)
        if (with_aliases and (col in col_aliases)):
            c_alias = ('Col%d' % len(col_aliases))
            result.append(('%s    AS    %s' % (r, c_alias)))
            aliases.add(c_alias)
            col_aliases.add(c_alias)
        else:
            result.append(r)
            aliases.add(r)
            col_aliases.add(col)
    self._select_aliases = aliases
    return (result, params)
