001package gudusoft.gsqlparser.resolver2.scope;
002
003import gudusoft.gsqlparser.nodes.TParseTreeNode;
004import gudusoft.gsqlparser.resolver2.ScopeType;
005import gudusoft.gsqlparser.resolver2.matcher.INameMatcher;
006import gudusoft.gsqlparser.resolver2.model.QualifiedName;
007import gudusoft.gsqlparser.resolver2.model.ScopeChild;
008import gudusoft.gsqlparser.resolver2.namespace.INamespace;
009
010import java.util.List;
011
012/**
013 * Represents a name resolution scope in SQL.
014 * Each scope defines what names (tables, columns, CTEs) are visible at a given point.
015 *
016 * Design based on:
017 * - Apache Calcite's SqlValidatorScope
018 * - Classic compiler scope chain
019 *
020 * Key concepts:
021 * 1. Delegation: Most scopes delegate unknown names to parent scope
022 * 2. Hierarchy: Scopes form a tree matching SQL structure
023 * 3. Children: FROM clause scopes contain table/subquery children
024 */
025public interface IScope {
026
027    /**
028     * Get the parent scope.
029     * Root scope (GlobalScope) has EmptyScope as parent.
030     *
031     * @return Parent scope, never null
032     */
033    IScope getParent();
034
035    /**
036     * Get the associated AST node
037     *
038     * @return AST node for this scope
039     */
040    TParseTreeNode getNode();
041
042    /**
043     * Get the scope type
044     *
045     * @return Scope type enum
046     */
047    ScopeType getScopeType();
048
049    /**
050     * Resolve a qualified or unqualified name.
051     * This is the core method for name resolution.
052     *
053     * @param names Name parts (e.g., ["schema", "table", "column"])
054     * @param matcher Name matcher for case sensitivity rules
055     * @param deep Whether to recursively resolve into record fields
056     * @param resolved Callback to collect all matches
057     */
058    void resolve(List<String> names,
059                INameMatcher matcher,
060                boolean deep,
061                IResolved resolved);
062
063    /**
064     * Resolve a table name or alias to its namespace.
065     *
066     * @param tableName Table name or alias
067     * @return Namespace if found, null otherwise
068     */
069    INamespace resolveTable(String tableName);
070
071    /**
072     * Add a child namespace to this scope.
073     * Typically used in FROM clauses to add tables/subqueries.
074     *
075     * @param namespace The namespace to add
076     * @param alias The alias for this namespace
077     * @param nullable Whether this namespace is nullable (e.g., RIGHT side of LEFT JOIN)
078     */
079    void addChild(INamespace namespace, String alias, boolean nullable);
080
081    /**
082     * Get all child namespaces in this scope.
083     *
084     * @return List of scope children
085     */
086    List<ScopeChild> getChildren();
087
088    /**
089     * Get all namespaces visible in this scope.
090     * Includes children and namespaces from parent scopes.
091     *
092     * @return List of visible namespaces
093     */
094    List<INamespace> getVisibleNamespaces();
095
096    /**
097     * Fully qualify a name based on this scope.
098     * E.g., "col" -> "table.col" if only one table has that column
099     *
100     * @param name Name to qualify
101     * @return Qualified name
102     */
103    QualifiedName fullyQualify(String name);
104
105    /**
106     * Check if this scope is within (nested inside) another scope.
107     *
108     * @param ancestorScope Potential ancestor scope
109     * @return true if this scope is nested within ancestorScope
110     */
111    boolean isWithin(IScope ancestorScope);
112}