Re: Nested CASE-WHEN scoping

Heikki Linnakangas <heikki.linnakangas@enterprisedb.com>

From: Heikki Linnakangas <heikki.linnakangas@enterprisedb.com>
To: Tom Lane <tgl@sss.pgh.pa.us>
Cc: PostgreSQL-development <pgsql-hackers@postgresql.org>
Date: 2011-06-03T19:46:16Z
Lists: pgsql-hackers

Attachments

On 31.05.2011 19:10, Heikki Linnakangas wrote:
> For index expressions, we could use a function similar to
> ChangeVarNodes(), that shifts all the paramids in the already-planned
> expression, preparing it for inclusion within the enclosing plan. I'm a
> bit worried that that might screw up the logic used to compare if an
> expression matches the index expression, though; the param ids in the
> two expressions won't match.

Yeah, the expression comparison logic gets all confused by this :-(. I 
couldn't figure out a way to make it work without making the comparison 
a whole lot more complicated than it is today. I'm going back to my 
original thoughts of a new kind of node to replace CaseTestExpr, which 
allows referencing values from upper levels in the expression tree.

So, here's a WIP patch using that approach. I've replaced CaseTestExpr 
with ExpressionParam. ExpressionParam has a levelsup field, which is 
similar to varlevelsup in Var. With levelsup == 0, ExpressionParam works 
just like CaseTestExpr did. With levelsup == 1, it refers to the value 
from above the enclosing CaseExpr (or any other node that uses these 
ExpressionParams/CaseTestExprs).

The complicated part is to ensure that levelsup is always set correctly. 
At parse time, levelsup is always set to 0, as the syntax doesn't allow 
referencing upper levels directly. When an SQL function is inlined, any 
ExpressionParams in the expressions that are substituted for Params need 
to have their levelsup adjusted, so that it still refers to the right 
value if there's CASE expressions in the inlined function. Also, when an 
ExpressionParam is replaced with a Const, the levelsup fields of any 
other ExpressionParams within the CaseExpr referring to higher levels 
need to have their levelsup decremented to account for the fact that the 
CaseExpr doesn't push the expression parameter anymore.

At execution time, the expression parameters form a stack. We've always 
done the save-restore logic, but the stack is now represented explicitly 
as a List in ExprContext. When an ExpressionParam is evaluated, the nth 
element is fetched from the stack, corresponding to levelsup.

-- 
   Heikki Linnakangas
   EnterpriseDB   http://www.enterprisedb.com