001package gudusoft.gsqlparser.resolver2.scope; 002 003import gudusoft.gsqlparser.nodes.TExpression; 004import gudusoft.gsqlparser.resolver2.ScopeType; 005 006/** 007 * Scope for HAVING clause. 008 * 009 * <p>Visibility rules: 010 * - Can access GROUP BY columns 011 * - Can access aggregate functions 012 * - Can access SELECT list aliases (in some databases) 013 * - Cannot access non-aggregated columns not in GROUP BY 014 * 015 * <p>Example: 016 * <pre> 017 * SELECT department, COUNT(*) as emp_count 018 * FROM employees 019 * GROUP BY department 020 * HAVING COUNT(*) > 10 -- Can use aggregates 021 * OR emp_count > 10 -- Can use SELECT list alias (database-dependent) 022 * </pre> 023 * 024 * <p>The HAVING scope has access to: 025 * - GROUP BY scope (for grouped columns) 026 * - SELECT scope (for SELECT list aliases, database-dependent) 027 */ 028public class HavingScope extends AbstractScope { 029 030 /** The HAVING condition expression */ 031 private final TExpression havingCondition; 032 033 /** Parent GROUP BY scope (for grouped column resolution) */ 034 private IScope groupByScope; 035 036 /** Parent SELECT scope (for SELECT list alias resolution) */ 037 private IScope selectScope; 038 039 public HavingScope(IScope parent, TExpression havingCondition) { 040 super(parent, havingCondition, ScopeType.HAVING); 041 this.havingCondition = havingCondition; 042 } 043 044 /** 045 * Set the GROUP BY scope for column resolution. 046 * HAVING can reference columns that appear in GROUP BY. 047 * 048 * @param groupByScope the GROUP BY scope 049 */ 050 public void setGroupByScope(IScope groupByScope) { 051 this.groupByScope = groupByScope; 052 } 053 054 /** 055 * Set the SELECT scope for alias resolution. 056 * HAVING can reference SELECT list aliases in some databases. 057 * 058 * @param selectScope the SELECT scope 059 */ 060 public void setSelectScope(IScope selectScope) { 061 this.selectScope = selectScope; 062 } 063 064 /** 065 * Get the GROUP BY scope. 066 * 067 * @return the GROUP BY scope, or null if not set 068 */ 069 public IScope getGroupByScope() { 070 return groupByScope; 071 } 072 073 /** 074 * Get the SELECT scope. 075 * 076 * @return the SELECT scope, or null if not set 077 */ 078 public IScope getSelectScope() { 079 return selectScope; 080 } 081 082 public TExpression getHavingCondition() { 083 return havingCondition; 084 } 085 086 @Override 087 public String toString() { 088 return "HavingScope"; 089 } 090}