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