Folks,

I'd like to make it possible to see qualifiers from inside functions
in PostgreSQL.  For my particular case, and for dblink, it would
allow user-space code to some remove bottlenecks which make currently
make inter-DBMS communication extremely inefficient.

The current code returns one (potentially) big string with the quals
ANDed together.  I'm thinking that the new code would:

1.  Return just a pointer.

2.  Add some functions like rsinfo_get_node_tree_str() which can turn
same into (in this case, a string, but others might get tree
structures) on demand from client code.

3.  Add wrapper functions in each untrusted PL (trusted PLs shouldn't
be doing anything that needs this).

4.  Document the above.

Please find attached the patch, and thanks to Neil Conway and Korry
Douglas for the code, and to Jan Wieck for helping me hammer out the
scheme above.  Mistakes are all mine ;)

Comments?  Questions?

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.73
diff -c -c -r1.73 dblink.c
*** contrib/dblink/dblink.c     4 Apr 2008 17:02:56 -0000       1.73
--- contrib/dblink/dblink.c     8 Apr 2008 18:29:05 -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     8 Apr 2008 18:29:06 -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     8 Apr 2008 18:29:06 -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.147
diff -c -c -r1.147 executor.h
*** src/include/executor/executor.h     28 Mar 2008 00:21:56 -0000      1.147
--- src/include/executor/executor.h     8 Apr 2008 18:29:06 -0000
***************
*** 176,181 ****
--- 176,182 ----
                                           ExprDoneCond *isDone);
  extern Tuplestorestate *ExecMakeTableFunctionResult(ExprState *funcexpr,
                                                        ExprContext *econtext,
+                                                       List *qual, List 
*rtable,
                                                        TupleDesc expectedDesc,
                                                        TupleDesc *returnDesc);
  extern Datum ExecEvalExprSwitchContext(ExprState *expression, ExprContext 
*econtext,
***************
*** 187,192 ****
--- 188,194 ----
  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       8 Apr 2008 18:29:06 -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.139
diff -c -c -r1.139 plperl.c
*** src/pl/plperl/plperl.c      28 Mar 2008 00:21:56 -0000      1.139
--- src/pl/plperl/plperl.c      8 Apr 2008 18:29:07 -0000
***************
*** 950,956 ****
        ENTER;
        SAVETMPS;
        PUSHMARK(SP);
!       XPUSHs(sv_2mortal(newSVstring("our $_TD; local $_TD=$_[0]; shift;")));
        XPUSHs(sv_2mortal(newSVstring(s)));
        PUTBACK;
  
--- 950,956 ----
        ENTER;
        SAVETMPS;
        PUSHMARK(SP);
!       XPUSHs(sv_2mortal(newSVstring("our $_TD; local $_TD=$_[0]; shift; our 
$_QUAL; local $_QUAL=$_[0]; shift;")));
        XPUSHs(sv_2mortal(newSVstring(s)));
        PUTBACK;
  
***************
*** 1058,1063 ****
--- 1058,1075 ----
  
        XPUSHs(&PL_sv_undef);           /* no trigger data */
  
+       if (fcinfo->resultinfo && ((ReturnSetInfo *)fcinfo->resultinfo)->qual)
+       {
+               ReturnSetInfo *rsi = (ReturnSetInfo *)fcinfo->resultinfo;
+               HV *hv = newHV();
+ 
+               hv_store_string(hv, "qual_string", 
newSVstring(rsinfo_get_qual_str(rsi)));
+ 
+               XPUSHs(newRV_noinc((SV *)hv));
+       }
+       else
+               XPUSHs(&PL_sv_undef);   /* no qualifier string */
+ 
        for (i = 0; i < desc->nargs; i++)
        {
                if (fcinfo->argnull[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