presto-main/src/main/java/io/prestosql/sql/analyzer/StatementAnalyzer.java/Visitor/analyzeSelectAllColumns
class Visitor:        private void analyzeSelectAllColumns(
                AllColumns allColumns,
                QuerySpecification node,
                Scope scope,
                ImmutableList.Builder<Expression> outputExpressionBuilder,
                ImmutableList.Builder<SelectExpression> selectExpressionBuilder)
        {
            // expand * and expression.*
            if (allColumns.getTarget().isPresent()) {
                // analyze AllColumns with target expression (expression.*)
                Expression expression = allColumns.getTarget().get();

                QualifiedName prefix = asQualifiedName(expression);
                if (prefix != null) {
                    // analyze prefix as an 'asterisked identifier chain'
                    Optional<AsteriskedIdentifierChainBasis> identifierChainBasis = scope.resolveAsteriskedIdentifierChainBasis(prefix, allColumns);
                    if (!identifierChainBasis.isPresent()) {
                        throw semanticException(TABLE_NOT_FOUND, allColumns, "Unable to resolve reference " + prefix);
                    }
                    if (identifierChainBasis.get().getBasisType() == TABLE) {
                        RelationType relationType = identifierChainBasis.get().getRelationType().get();
                        List<Field> fields = relationType.resolveVisibleFieldsWithRelationPrefix(Optional.of(prefix));
                        if (fields.isEmpty()) {
                            throw semanticException(COLUMN_NOT_FOUND, allColumns, "SELECT * not allowed from relation that has no columns");
                        }
                        boolean local = scope.isLocalScope(identifierChainBasis.get().getScope().get());
                        analyzeAllColumnsFromTable(
                                fields,
                                allColumns,
                                node,
                                local ? scope : identifierChainBasis.get().getScope().get(),
                                outputExpressionBuilder,
                                selectExpressionBuilder,
                                relationType,
                                local);
                        return;
                    }
                }
                // identifierChainBasis.get().getBasisType == FIELD or target expression isn't a QualifiedName
                analyzeAllFieldsFromRowTypeExpression(expression, allColumns, node, scope, outputExpressionBuilder, selectExpressionBuilder);
            }
            else {
                // analyze AllColumns without target expression ('*')
                if (!allColumns.getAliases().isEmpty()) {
                    throw semanticException(NOT_SUPPORTED, allColumns, "Column aliases not supported");
                }

                List<Field> fields = (List<Field>) scope.getRelationType().getVisibleFields();
                if (fields.isEmpty()) {
                    if (!node.getFrom().isPresent()) {
                        throw semanticException(COLUMN_NOT_FOUND, allColumns, "SELECT * not allowed in queries without FROM clause");
                    }
                    throw semanticException(COLUMN_NOT_FOUND, allColumns, "SELECT * not allowed from relation that has no columns");
                }

                analyzeAllColumnsFromTable(fields, allColumns, node, scope, outputExpressionBuilder, selectExpressionBuilder, scope.getRelationType(), true);
            }
        }