Folks,

Neil Conway sent me a patch that sketched out a plan to make quals
visible to functions, and Korry Douglas filled in much of the rest of
what you see attached here.  Mistakes are all mine. :)

Random observations:

* It appears I've botched the call to deparse_context_for_plan in
  src/backend/executor/execQual.c and/or made some more fundamental
  error because when testing with PL/Perl, I only see quals inside the
  function when there is just one.  Where are the APIs for things like
  deparse_context_for_plan() documented?

* This stuff should be available to all the PLs.  How might it work in
  PL/PgSQL, etc.?

* The patch just appends a WHERE clause on when it finds quals in
  contrib/dblink/dblink.c.  While this is probably a good place to
  start, it might be good to explore some kind of approach that allows
  more subtlety.

* In PL/Perl, $_TD->{_quals} gets the qualifiers, but they really
  should go in their own variable.  I'm thinking that one should be
  called $_QUAL.

* More generally, it would be nice to have the quals in some kind of
  data structure so the calling code could do smarter things with them
  than the current string-mashing the example code does.

Help, comments, brickbats, etc. appreciated :)

Cheers,
David.
-- 
David Fetter <[EMAIL PROTECTED]> http://fetter.org/
Phone: +1 415 235 3778  AIM: dfetter666  Yahoo!: dfetter
Skype: davidfetter      XMPP: [EMAIL PROTECTED]

Remember to vote!
Consider donating to Postgres: http://www.postgresql.org/about/donate
Index: contrib/dblink/dblink.c
===================================================================
RCS file: /projects/cvsroot/pgsql/contrib/dblink/dblink.c,v
retrieving revision 1.70
diff -c -c -r1.70 dblink.c
*** contrib/dblink/dblink.c     25 Mar 2008 22:42:41 -0000      1.70
--- contrib/dblink/dblink.c     25 Mar 2008 23:24:42 -0000
***************
*** 752,757 ****
--- 752,758 ----
                char       *conname = NULL;
                remoteConn *rconn = NULL;
                bool            fail = true;    /* default to backward 
compatible */
+               ReturnSetInfo   *rsi;
  
                /* create a function context for cross-call persistence */
                funcctx = SRF_FIRSTCALL_INIT();
***************
*** 826,831 ****
--- 827,843 ----
                                elog(ERROR, "wrong number of arguments");
                }
  
+               if (sql && rsi->qual)
+               {
+                       char *quals = rsinfo_get_qual_str(rsi);
+                       char *qualifiedQuery = palloc(strlen(sql) + strlen(" 
WHERE ") +
+                                                                               
  strlen(quals) + 1);
+ 
+                       sprintf(qualifiedQuery, "%s WHERE %s", sql, quals);
+ 
+                       sql = qualifiedQuery;
+               }
+ 
                if (!conn)
                        DBLINK_CONN_NOT_AVAIL;
  
Index: src/backend/executor/execQual.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/executor/execQual.c,v
retrieving revision 1.228
diff -c -c -r1.228 execQual.c
*** src/backend/executor/execQual.c     25 Mar 2008 22:42:43 -0000      1.228
--- src/backend/executor/execQual.c     25 Mar 2008 23:24:43 -0000
***************
*** 45,50 ****
--- 45,51 ----
  #include "funcapi.h"
  #include "miscadmin.h"
  #include "nodes/makefuncs.h"
+ #include "optimizer/clauses.h"
  #include "optimizer/planmain.h"
  #include "parser/parse_expr.h"
  #include "utils/acl.h"
***************
*** 1415,1420 ****
--- 1416,1440 ----
        return result;
  }
  
+ /*
+  *
+  * Get either an empty string or a batch of qualifiers.
+  *
+  */
+ char *
+ rsinfo_get_qual_str(ReturnSetInfo *rsinfo)
+ {
+       Node    *qual;
+       List    *context;
+ 
+       if (rsinfo->qual == NIL)
+               return pstrdup("");
+ 
+       qual = (Node *) make_ands_explicit(rsinfo->qual);
+       context = deparse_context_for_plan(NULL, NULL, rsinfo->rtable);
+ 
+       return deparse_expression(qual, context, false, false);
+ }
  
  /*
   *            ExecMakeTableFunctionResult
***************
*** 1426,1431 ****
--- 1446,1452 ----
  Tuplestorestate *
  ExecMakeTableFunctionResult(ExprState *funcexpr,
                                                        ExprContext *econtext,
+                                                       List *qual, List 
*rtable,
                                                        TupleDesc expectedDesc,
                                                        TupleDesc *returnDesc)
  {
***************
*** 1458,1463 ****
--- 1479,1486 ----
        InitFunctionCallInfoData(fcinfo, NULL, 0, NULL, (Node *) &rsinfo);
        rsinfo.type = T_ReturnSetInfo;
        rsinfo.econtext = econtext;
+       rsinfo.qual = qual;
+       rsinfo.rtable = rtable;
        rsinfo.expectedDesc = expectedDesc;
        rsinfo.allowedModes = (int) (SFRM_ValuePerCall | SFRM_Materialize);
        rsinfo.returnMode = SFRM_ValuePerCall;
Index: src/backend/executor/nodeFunctionscan.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/executor/nodeFunctionscan.c,v
retrieving revision 1.46
diff -c -c -r1.46 nodeFunctionscan.c
*** src/backend/executor/nodeFunctionscan.c     29 Feb 2008 02:49:39 -0000      
1.46
--- src/backend/executor/nodeFunctionscan.c     25 Mar 2008 23:24:43 -0000
***************
*** 68,73 ****
--- 68,75 ----
                node->tuplestorestate = tuplestorestate =
                        ExecMakeTableFunctionResult(node->funcexpr,
                                                                                
econtext,
+                                                                               
node->ss.ps.plan->qual,
+                                                                               
estate->es_range_table,
                                                                                
node->tupdesc,
                                                                                
&funcTupdesc);
  
Index: src/include/executor/executor.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/executor/executor.h,v
retrieving revision 1.146
diff -c -c -r1.146 executor.h
*** src/include/executor/executor.h     1 Jan 2008 19:45:57 -0000       1.146
--- src/include/executor/executor.h     25 Mar 2008 23:24:43 -0000
***************
*** 171,176 ****
--- 171,177 ----
                                           ExprDoneCond *isDone);
  extern Tuplestorestate *ExecMakeTableFunctionResult(ExprState *funcexpr,
                                                        ExprContext *econtext,
+                                                       List *qual, List 
*rtable,
                                                        TupleDesc expectedDesc,
                                                        TupleDesc *returnDesc);
  extern Datum ExecEvalExprSwitchContext(ExprState *expression, ExprContext 
*econtext,
***************
*** 182,187 ****
--- 183,189 ----
  extern int    ExecCleanTargetListLength(List *targetlist);
  extern TupleTableSlot *ExecProject(ProjectionInfo *projInfo,
                        ExprDoneCond *isDone);
+ extern char *rsinfo_get_qual_str(ReturnSetInfo *rsinfo);
  
  /*
   * prototypes from functions in execScan.c
Index: src/include/nodes/execnodes.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/nodes/execnodes.h,v
retrieving revision 1.183
diff -c -c -r1.183 execnodes.h
*** src/include/nodes/execnodes.h       1 Jan 2008 19:45:58 -0000       1.183
--- src/include/nodes/execnodes.h       25 Mar 2008 23:24:44 -0000
***************
*** 168,173 ****
--- 168,175 ----
        ExprContext *econtext;          /* context function is being called in 
*/
        TupleDesc       expectedDesc;   /* tuple descriptor expected by caller 
*/
        int                     allowedModes;   /* bitmask: return modes caller 
can handle */
+       List            *qual;                  /* any quals to be applied to 
result */
+       List            *rtable;
        /* result status from function (but pre-initialized by caller): */
        SetFunctionReturnMode returnMode;       /* actual return mode */
        ExprDoneCond isDone;            /* status for ValuePerCall mode */
Index: src/pl/plperl/plperl.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/pl/plperl/plperl.c,v
retrieving revision 1.138
diff -c -c -r1.138 plperl.c
*** src/pl/plperl/plperl.c      25 Mar 2008 22:42:45 -0000      1.138
--- src/pl/plperl/plperl.c      25 Mar 2008 23:24:44 -0000
***************
*** 1048,1060 ****
        int                     i;
        int                     count;
        SV                 *sv;
  
        ENTER;
        SAVETMPS;
  
        PUSHMARK(SP);
  
!       XPUSHs(&PL_sv_undef);           /* no trigger data */
  
        for (i = 0; i < desc->nargs; i++)
        {
--- 1048,1073 ----
        int                     i;
        int                     count;
        SV                 *sv;
+       HV                 *hv;
  
        ENTER;
        SAVETMPS;
  
        PUSHMARK(SP);
  
!       if (fcinfo->resultinfo && ((ReturnSetInfo *)fcinfo->resultinfo)->qual)
!       {
!               ReturnSetInfo *rsi = (ReturnSetInfo *)fcinfo->resultinfo;
!               HV *hv = newHV();
! 
!               hv_store_string(hv, "_quals", 
newSVstring(rsinfo_get_qual_str(rsi)));
! 
!               XPUSHs(newRV_noinc((SV *)hv));
!       }
!       else
!       {
!               XPUSHs(&PL_sv_undef);           /* no trigger or qual data */
!       }
  
        for (i = 0; i < desc->nargs; i++)
        {
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to