@@ -210,6 +210,8 @@ static List *set_returning_clause_references(PlannerInfo *root,
210210static List * set_windowagg_runcondition_references (PlannerInfo * root ,
211211 List * runcondition ,
212212 Plan * plan );
213+ static bool pull_up_has_session_variables_walker (Node * node ,
214+ PlannerInfo * root );
213215
214216
215217/*****************************************************************************
@@ -1341,6 +1343,50 @@ set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset)
13411343 return plan ;
13421344}
13431345
1346+ /*
1347+ * Search usage of session variables in subqueries
1348+ */
1349+ void
1350+ pull_up_has_session_variables (PlannerInfo * root )
1351+ {
1352+ Query * query = root -> parse ;
1353+
1354+ if (query -> hasSessionVariables )
1355+ {
1356+ root -> hasSessionVariables = true;
1357+ }
1358+ else
1359+ {
1360+ (void ) query_tree_walker (query ,
1361+ pull_up_has_session_variables_walker ,
1362+ (void * ) root , 0 );
1363+ }
1364+ }
1365+
1366+ static bool
1367+ pull_up_has_session_variables_walker (Node * node , PlannerInfo * root )
1368+ {
1369+ if (node == NULL )
1370+ return false;
1371+ if (IsA (node , Query ))
1372+ {
1373+ Query * query = (Query * ) node ;
1374+
1375+ if (query -> hasSessionVariables )
1376+ {
1377+ root -> hasSessionVariables = true;
1378+ return false;
1379+ }
1380+
1381+ /* recurse into subselects */
1382+ return query_tree_walker ((Query * ) node ,
1383+ pull_up_has_session_variables_walker ,
1384+ (void * ) root , 0 );
1385+ }
1386+ return expression_tree_walker (node , pull_up_has_session_variables_walker ,
1387+ (void * ) root );
1388+ }
1389+
13441390/*
13451391 * set_indexonlyscan_references
13461392 * Do set_plan_references processing on an IndexOnlyScan
@@ -2141,6 +2187,10 @@ fix_expr_common(PlannerInfo *root, Node *node)
21412187 * If it's a PARAM_MULTIEXPR, replace it with the appropriate Param from
21422188 * root->multiexpr_params; otherwise no change is needed.
21432189 * Just for paranoia's sake, we make a copy of the node in either case.
2190+ *
2191+ * If it's a PARAM_VARIABLE, then we collect used session variables in
2192+ * the list root->glob->sessionVariable. Also, assign the parameter's
2193+ * "paramid" to the parameter's position in that list.
21442194 */
21452195static Node *
21462196fix_param_node (PlannerInfo * root , Param * p )
@@ -2159,6 +2209,43 @@ fix_param_node(PlannerInfo *root, Param *p)
21592209 elog (ERROR , "unexpected PARAM_MULTIEXPR ID: %d" , p -> paramid );
21602210 return copyObject (list_nth (params , colno - 1 ));
21612211 }
2212+
2213+ if (p -> paramkind == PARAM_VARIABLE )
2214+ {
2215+ int n = 0 ;
2216+
2217+ /* we will modify object */
2218+ p = (Param * ) copyObject (p );
2219+
2220+ /*
2221+ * Now, we can actualize list of session variables, and we can
2222+ * complete paramid parameter.
2223+ */
2224+ foreach_node (Param , paramvar , root -> glob -> sessionVariables )
2225+ {
2226+ if (strcmp (paramvar -> paramvarname , p -> paramvarname ) == 0 )
2227+ {
2228+ p -> paramid = paramvar -> paramid ;
2229+
2230+ return (Node * ) p ;
2231+ }
2232+
2233+ n += 1 ;
2234+ }
2235+
2236+ p -> paramid = n ;
2237+
2238+ /*
2239+ * Because session variables are catalogless, we cannot to use plan
2240+ * invalidation. Then we need to check type, typmod, collid any time,
2241+ * when we load values of session variables to parameter's buffer.
2242+ * For this purpose it is more easy to save complete Param node.
2243+ */
2244+ root -> glob -> sessionVariables = lappend (root -> glob -> sessionVariables , p );
2245+
2246+ return (Node * ) p ;
2247+ }
2248+
21622249 return (Node * ) copyObject (p );
21632250}
21642251
@@ -2220,7 +2307,9 @@ fix_alternative_subplan(PlannerInfo *root, AlternativeSubPlan *asplan,
22202307 * replacing Aggref nodes that should be replaced by initplan output Params,
22212308 * choosing the best implementation for AlternativeSubPlans,
22222309 * looking up operator opcode info for OpExpr and related nodes,
2223- * and adding OIDs from regclass Const nodes into root->glob->relationOids.
2310+ * adding OIDs from regclass Const nodes into root->glob->relationOids,
2311+ * assigning paramvarid to PARAM_VARIABLE params, and collecting the
2312+ * of session variables in the root->glob->sessionVariables list.
22242313 *
22252314 * 'node': the expression to be modified
22262315 * 'rtoffset': how much to increment varnos by
@@ -2242,7 +2331,8 @@ fix_scan_expr(PlannerInfo *root, Node *node, int rtoffset, double num_exec)
22422331 root -> multiexpr_params != NIL ||
22432332 root -> glob -> lastPHId != 0 ||
22442333 root -> minmax_aggs != NIL ||
2245- root -> hasAlternativeSubPlans )
2334+ root -> hasAlternativeSubPlans ||
2335+ root -> hasSessionVariables )
22462336 {
22472337 return fix_scan_expr_mutator (node , & context );
22482338 }
0 commit comments