001package gudusoft.gsqlparser.resolver2.expansion;
002
003import gudusoft.gsqlparser.nodes.TResultColumn;
004
005import java.util.ArrayList;
006import java.util.HashMap;
007import java.util.List;
008import java.util.Map;
009
010/**
011 * Result of star column expansion.
012 *
013 * <p>Tracks:
014 * - Which star columns were expanded
015 * - Which star columns could not be expanded (and why)
016 * - Non-star columns (passed through)
017 * - Statistics about the expansion
018 *
019 * <p>Example:
020 * <pre>
021 * SELECT t1.*, t2.id, t3.*
022 * FROM t1 JOIN t2 JOIN t3
023 *
024 * ExpansionResult:
025 * - expandedStars: {t1.* -> [t1.id, t1.name], t3.* -> [t3.id, t3.status]}
026 * - nonStarColumns: [t2.id]
027 * - unexpandableStars: {}
028 * </pre>
029 */
030public class ExpansionResult {
031
032    /** Star columns that were successfully expanded */
033    private final Map<TResultColumn, List<ExpandedColumn>> expandedStars = new HashMap<>();
034
035    /** Star columns that could not be expanded */
036    private final Map<TResultColumn, String> unexpandableStars = new HashMap<>();
037
038    /** Non-star columns (passed through unchanged) */
039    private final List<TResultColumn> nonStarColumns = new ArrayList<>();
040
041    /**
042     * Add a successfully expanded star column.
043     *
044     * @param starColumn the original star column
045     * @param expandedColumns the expanded columns
046     */
047    public void addExpandedStar(TResultColumn starColumn, List<ExpandedColumn> expandedColumns) {
048        if (starColumn != null && expandedColumns != null) {
049            expandedStars.put(starColumn, new ArrayList<>(expandedColumns));
050        }
051    }
052
053    /**
054     * Add a star column that could not be expanded.
055     *
056     * @param starColumn the star column
057     * @param reason why it could not be expanded
058     */
059    public void addUnexpandableStar(TResultColumn starColumn, String reason) {
060        if (starColumn != null) {
061            unexpandableStars.put(starColumn, reason != null ? reason : "Unknown reason");
062        }
063    }
064
065    /**
066     * Add a non-star column.
067     *
068     * @param column the non-star column
069     */
070    public void addNonStarColumn(TResultColumn column) {
071        if (column != null) {
072            nonStarColumns.add(column);
073        }
074    }
075
076    /**
077     * Get all expanded stars.
078     *
079     * @return map of star column to expanded columns
080     */
081    public Map<TResultColumn, List<ExpandedColumn>> getExpandedStars() {
082        return new HashMap<>(expandedStars);
083    }
084
085    /**
086     * Get all unexpandable stars.
087     *
088     * @return map of star column to reason
089     */
090    public Map<TResultColumn, String> getUnexpandableStars() {
091        return new HashMap<>(unexpandableStars);
092    }
093
094    /**
095     * Get all non-star columns.
096     *
097     * @return list of non-star columns
098     */
099    public List<TResultColumn> getNonStarColumns() {
100        return new ArrayList<>(nonStarColumns);
101    }
102
103    /**
104     * Get all expanded columns (flattened list).
105     *
106     * @return all expanded columns from all stars
107     */
108    public List<ExpandedColumn> getAllExpandedColumns() {
109        List<ExpandedColumn> all = new ArrayList<>();
110        for (List<ExpandedColumn> columns : expandedStars.values()) {
111            all.addAll(columns);
112        }
113        return all;
114    }
115
116    /**
117     * Get the total number of columns after expansion.
118     * This includes expanded star columns and non-star columns.
119     *
120     * @return total column count
121     */
122    public int getTotalColumnCount() {
123        int count = nonStarColumns.size();
124        for (List<ExpandedColumn> columns : expandedStars.values()) {
125            count += columns.size();
126        }
127        return count;
128    }
129
130    /**
131     * Get the number of star columns that were expanded.
132     *
133     * @return expanded star count
134     */
135    public int getExpandedStarCount() {
136        return expandedStars.size();
137    }
138
139    /**
140     * Get the number of star columns that could not be expanded.
141     *
142     * @return unexpandable star count
143     */
144    public int getUnexpandableStarCount() {
145        return unexpandableStars.size();
146    }
147
148    /**
149     * Check if all stars were successfully expanded.
150     *
151     * @return true if no unexpandable stars, false otherwise
152     */
153    public boolean isFullyExpanded() {
154        return unexpandableStars.isEmpty();
155    }
156
157    /**
158     * Check if any stars were expanded.
159     *
160     * @return true if at least one star was expanded
161     */
162    public boolean hasExpandedStars() {
163        return !expandedStars.isEmpty();
164    }
165
166    /**
167     * Get statistics about the expansion.
168     *
169     * @return statistics string
170     */
171    public String getStatistics() {
172        return String.format(
173            "ExpansionResult[expanded=%d stars -> %d columns, unexpandable=%d, non-star=%d, total=%d]",
174            expandedStars.size(),
175            getAllExpandedColumns().size(),
176            unexpandableStars.size(),
177            nonStarColumns.size(),
178            getTotalColumnCount()
179        );
180    }
181
182    @Override
183    public String toString() {
184        return getStatistics();
185    }
186}