presto-main/src/main/java/io/prestosql/sql/analyzer/StatementAnalyzer.java/StatementAnalyzer/analyzeAllFieldsFromRowTypeExpression
class StatementAnalyzer:        private void analyzeAllFieldsFromRowTypeExpression(
                Expression expression,
                AllColumns allColumns,
                QuerySpecification node,
                Scope scope,
                ImmutableList.Builder<Expression> outputExpressionBuilder,
                ImmutableList.Builder<SelectExpression> selectExpressionBuilder)
        {
            ImmutableList.Builder<Field> itemOutputFieldBuilder = ImmutableList.builder();

            ExpressionAnalysis expressionAnalysis = analyzeExpression(expression, scope);
            Type type = expressionAnalysis.getType(expression);
            if (!(type instanceof RowType)) {
                throw semanticException(TYPE_MISMATCH, node.getSelect(), "expected expression of type Row");
            }
            int referencedFieldsCount = ((RowType) type).getFields().size();
            if (!allColumns.getAliases().isEmpty()) {
                validateColumnAliasesCount(allColumns.getAliases(), referencedFieldsCount);
            }
            analysis.recordSubqueries(node, expressionAnalysis);

            ImmutableList.Builder<Expression> unfoldedExpressionsBuilder = ImmutableList.builder();
            for (int i = 0; i < referencedFieldsCount; i++) {
                Expression outputExpression = new SubscriptExpression(expression, new LongLiteral("" + (i + 1)));
                outputExpressionBuilder.add(outputExpression);
                analyzeExpression(outputExpression, scope);
                unfoldedExpressionsBuilder.add(outputExpression);

                Type outputExpressionType = type.getTypeParameters().get(i);
                if (node.getSelect().isDistinct() && !(outputExpressionType.isComparable())) {
                    throw semanticException(TYPE_MISMATCH, node.getSelect(), "DISTINCT can only be applied to comparable types (actual: %s)", type.getTypeParameters().get(i));
                }

                Optional<String> name = ((RowType) type).getFields().get(i).getName();
                if (!allColumns.getAliases().isEmpty()) {
                    name = Optional.of((allColumns.getAliases().get(i)).getValue());
                }
                itemOutputFieldBuilder.add(Field.newUnqualified(name, outputExpressionType));
            }
            selectExpressionBuilder.add(new SelectExpression(expression, Optional.of(unfoldedExpressionsBuilder.build())));
            analysis.setSelectAllResultFields(allColumns, itemOutputFieldBuilder.build());
        }