001package gudusoft.gsqlparser.resolver2.namespace;
002
003import gudusoft.gsqlparser.nodes.TObjectName;
004import gudusoft.gsqlparser.nodes.TObjectNameList;
005import gudusoft.gsqlparser.nodes.TTable;
006import gudusoft.gsqlparser.resolver2.ColumnLevel;
007import gudusoft.gsqlparser.resolver2.matcher.INameMatcher;
008import gudusoft.gsqlparser.resolver2.model.ColumnSource;
009
010import java.util.ArrayList;
011import java.util.LinkedHashMap;
012import java.util.List;
013
014/**
015 * The relation a Hive-family LATERAL VIEW adds to its SELECT: {@code lv} in
016 * {@code FROM events LATERAL VIEW explode(items) lv AS item}, with the columns its column aliases name, {@code item}.
017 * A reference to one of them, {@code lv.item}, {@code item} or a field of it, {@code lv.item.name}, resolves to this
018 * relation (Mantis 4845). The parser gives the LATERAL VIEW a table of type {@code ETableSource.lateralView} that
019 * shares its alias clause ({@code TLateralView.createATable}).
020 */
021public class LateralViewNamespace extends AbstractNamespace {
022
023    private final TTable table;
024    private final String alias;
025    private final TObjectNameList columns;
026
027    /** {@code columns}: the LATERAL VIEW's column aliases, {@code item} in {@code lv AS item}; null for none. */
028    public LateralViewNamespace(TTable table, String alias, TObjectNameList columns, INameMatcher nameMatcher) {
029        super(table, nameMatcher);
030        this.table = table;
031        this.alias = alias;
032        this.columns = columns;
033    }
034
035    @Override
036    public String getDisplayName() {
037        return alias;
038    }
039
040    @Override
041    public TTable getFinalTable() {
042        return table;
043    }
044
045    @Override
046    public List<TTable> getAllFinalTables() {
047        List<TTable> tables = new ArrayList<>();
048        tables.add(table);
049        return tables;
050    }
051
052    @Override
053    protected void doValidate() {
054        columnSources = new LinkedHashMap<>();
055        // the aliases themselves: the table's linked columns also get the references the first pass linked to it
056        for (int i = 0; columns != null && i < columns.size(); i++) {
057            TObjectName column = columns.getObjectName(i);
058            if (column != null) {
059                String name = column.toString();
060                columnSources.put(name, new ColumnSource(this, name, column, 1.0, "lateral_view_column"));
061            }
062        }
063    }
064
065    @Override
066    public boolean hasStarColumn() {
067        return false;
068    }
069
070    @Override
071    public boolean supportsDynamicInference() {
072        // the column aliases are all its columns
073        return false;
074    }
075
076    @Override
077    public ColumnLevel hasColumn(String columnName) {
078        ensureValidated();
079        for (String existing : columnSources.keySet()) {
080            if (nameMatcher.matches(existing, columnName)) {
081                return ColumnLevel.EXISTS;
082            }
083        }
084        return ColumnLevel.NOT_EXISTS;
085    }
086
087    @Override
088    public ColumnSource resolveColumn(String columnName) {
089        ensureValidated();
090        return super.resolveColumn(columnName);
091    }
092
093    public TTable getTable() {
094        return table;
095    }
096
097    /** The LATERAL VIEW's own table: the source table of a column resolved through it. */
098    @Override
099    public TTable getSourceTable() {
100        return table;
101    }
102
103    @Override
104    public String toString() {
105        return String.format("LateralViewNamespace(%s, columns=%d)", alias,
106                columnSources != null ? columnSources.size() : 0);
107    }
108}