On 5 April 2017 at 08:23, Craig Ringer <cr...@2ndquadrant.com> wrote: > On 5 April 2017 at 08:00, Craig Ringer <cr...@2ndquadrant.com> wrote: > >> Taking a look at this now. > > Rebased to current master with conflicts and whitespace errors fixed. > Review pending.
This patch fails to update the documentation at all. https://www.postgresql.org/docs/devel/static/spi.html The patch crashes in initdb with --enable-cassert builds: performing post-bootstrap initialization ... TRAP: FailedAssertion("!(myState->pub.mydest == DestSQLFunction)", File: "functions.c", Line: 800) sh: line 1: 30777 Aborted (core dumped) "/home/craig/projects/2Q/postgres/tmp_install/home/craig/pg/10/bin/postgres" --single -F -O -j -c search_path=pg_catalog -c exit_on_error=true template1 > /dev/null child process exited with exit code 134 Backtrace attached. Details on patch 1: missing newline +} +int +SPI_execute_callback(const char *src, bool read_only, long tcount, +/* Execute a previously prepared plan with a callback Destination */ caps "Destination" + // XXX throw error if callback is set ^^ +static DestReceiver spi_callbackDR = { + donothingReceive, donothingStartup, donothingCleanup, donothingCleanup, + DestSPICallback +}; Is the callback destreceiver supposed to be a blackhole? Why? Its name, spi_callbackDR and DestSPICallback, doesn't seem to indicate that it drops its input. Presumably that's a default destination you're then supposed to modify with your own callbacks? There aren't any comments to indicate what's going on here. Comments on patch 2: If this is the "bare minimum" patch, what is pending? Does it impose any downsides or limits? +/* Get switch execution contexts */ +extern PLyExecutionContext *PLy_switch_execution_context(PLyExecutionContext *new); Comment makes no sense to me. This seems something like memory context switch, where you supply the new and return the old. But the comment doesn't explain it at all. +void PLy_CSStartup(DestReceiver *self, int operation, TupleDesc typeinfo); +void PLy_CSDestroy(DestReceiver *self); These are declared in the plpy_spi.c. Why aren't these static? + volatile MemoryContext oldcontext; + volatile ResourceOwner oldowner; int rv; - volatile MemoryContext oldcontext; - volatile ResourceOwner oldowner; Unnecessary code movement. In PLy_Callback_New, I think your use of a sub-context is sensible. Is it necessary to palloc0 though? +static CallbackState * +PLy_Callback_Free(CallbackState *callback) The code here looks like it could be part of spi.c's callback support, rather than plpy_spi specific, since you provide a destroy callback in the SPI callback struct. + /* We need to store this because the TupleDesc the receive function gets has no names. */ + myState->desc = typeinfo; Is it safe to just store the pointer to the TupleDesc here? What's the lifetime? + * will clean it up when the time is right. XXX This might result in a leak + * if an error happens and the result doesn't get dereferenced. + */ + MemoryContextSwitchTo(TopMemoryContext); + result->tupdesc = CreateTupleDescCopy(typeinfo); especially given this XXX comment... Patch needs bug fix, docs updates, fixes for issues marked in comments. But overall approach looks sensible enough. -- Craig Ringer http://www.2ndQuadrant.com/ PostgreSQL Development, 24x7 Support, Training & Services
#0 0x00007f9d5d64ea28 in raise () from /lib64/libc.so.6 No symbol table info available. #1 0x00007f9d5d65062a in abort () from /lib64/libc.so.6 No symbol table info available. #2 0x000000000083a521 in ExceptionalCondition (conditionName=conditionName@entry=0x9b68d0 "!(myState->pub.mydest == DestSQLFunction)", errorType=errorType@entry=0x882d29 "FailedAssertion", fileName=fileName@entry=0x9b6920 "functions.c", lineNumber=lineNumber@entry=800) at assert.c:54 No locals. #3 0x00000000006166e8 in postquel_start (fcache=0x27772c0, es=0x284eb58) at functions.c:800 myState = 0x284eeb8 dest = 0x284eeb8 #4 fmgr_sql (fcinfo=0x27a7a28) at functions.c:1149 fcache = 0x27772c0 sqlerrcontext = {previous = 0x0, callback = 0x614910 <sql_exec_error_callback>, arg = 0x27a79d0} randomAccess = 0 '\000' lazyEvalOK = <optimized out> is_first = <optimized out> pushed_snapshot = 0 '\000' es = 0x284eb58 slot = <optimized out> result = <optimized out> eslist = <optimized out> eslc = 0x284eb90 __func__ = "fmgr_sql" #5 0x000000000060810b in ExecInterpExpr (state=0x27a7528, econtext=0x27a4ce0, isnull=<optimized out>) at execExprInterp.c:670 fcinfo = 0x27a7a28 argnull = 0x27a7d68 "" argno = <optimized out> op = 0x27a76f8 resultslot = 0x27a7130 innerslot = <optimized out> outerslot = 0x27a5930 scanslot = 0x0 dispatch_table = {0x608960 <ExecInterpExpr+3424>, 0x607e00 <ExecInterpExpr+512>, 0x607e20 <ExecInterpExpr+544>, 0x607e38 <ExecInterpExpr+568>, 0x607c90 <ExecInterpExpr+144>, 0x607cb0 <ExecInterpExpr+176>, 0x607cf8 <ExecInterpExpr+248>, 0x607d14 <ExecInterpExpr+276>, 0x607d58 <ExecInterpExpr+344>, 0x607d73 <ExecInterpExpr+371>, 0x607e50 <ExecInterpExpr+592>, 0x607ea8 <ExecInterpExpr+680>, 0x607ee0 <ExecInterpExpr+736>, 0x607f18 <ExecInterpExpr+792>, 0x607f30 <ExecInterpExpr+816>, 0x607f80 <ExecInterpExpr+896>, 0x607fb8 <ExecInterpExpr+952>, 0x607ff0 <ExecInterpExpr+1008>, 0x608018 <ExecInterpExpr+1048>, 0x608050 <ExecInterpExpr+1104>, 0x608070 <ExecInterpExpr+1136>, 0x6080b0 <ExecInterpExpr+1200>, 0x608130 <ExecInterpExpr+1328>, 0x608238 <ExecInterpExpr+1592>, 0x607db0 <ExecInterpExpr+432>, 0x607db7 <ExecInterpExpr+439>, 0x6081f8 <ExecInterpExpr+1528>, 0x607c60 <ExecInterpExpr+96>, 0x607c67 <ExecInterpExpr+103>, 0x608190 <ExecInterpExpr+1424>, 0x6081b0 <ExecInterpExpr+1456>, 0x6081c8 <ExecInterpExpr+1480>, 0x6082d0 <ExecInterpExpr+1744>, 0x6082d8 <ExecInterpExpr+1752>, 0x6082f0 <ExecInterpExpr+1776>, 0x608308 <ExecInterpExpr+1800>, 0x608330 <ExecInterpExpr+1840>, 0x608350 <ExecInterpExpr+1872>, 0x608360 <ExecInterpExpr+1888>, 0x608380 <ExecInterpExpr+1920>, 0x608388 <ExecInterpExpr+1928>, 0x6083b0 <ExecInterpExpr+1968>, 0x6083d8 <ExecInterpExpr+2008>, 0x6083f8 <ExecInterpExpr+2040>, 0x608410 <ExecInterpExpr+2064>, 0x608430 <ExecInterpExpr+2096>, 0x608448 <ExecInterpExpr+2120>, 0x6084a0 <ExecInterpExpr+2208>, 0x6084c0 <ExecInterpExpr+2240>, 0x608550 <ExecInterpExpr+2384>, 0x6085a0 <ExecInterpExpr+2464>, 0x6085d8 <ExecInterpExpr+2520>, 0x6085f0 <ExecInterpExpr+2544>, 0x608600 <ExecInterpExpr+2560>, 0x608618 <ExecInterpExpr+2584>, 0x608630 <ExecInterpExpr+2608>, 0x608648 <ExecInterpExpr+2632>, 0x6086c0 <ExecInterpExpr+2752>, 0x608710 <ExecInterpExpr+2832>, 0x608728 <ExecInterpExpr+2856>, 0x608740 <ExecInterpExpr+2880>, 0x608760 <ExecInterpExpr+2912>, 0x608780 <ExecInterpExpr+2944>, 0x6087a8 <ExecInterpExpr+2984>, 0x6087c0 <ExecInterpExpr+3008>, 0x6087d8 <ExecInterpExpr+3032>, 0x608478 <ExecInterpExpr+2168>, 0x608828 <ExecInterpExpr+3112>, 0x608840 <ExecInterpExpr+3136>, 0x6087f0 <ExecInterpExpr+3056>, 0x608810 <ExecInterpExpr+3088>, 0x608868 <ExecInterpExpr+3176>, 0x608880 <ExecInterpExpr+3200>, 0x6088c0 <ExecInterpExpr+3264>, 0x6088d8 <ExecInterpExpr+3288>, 0x608908 <ExecInterpExpr+3336>, 0x608920 <ExecInterpExpr+3360>, 0x608940 <ExecInterpExpr+3392>} #6 0x0000000000621952 in ExecEvalExprSwitchContext (isNull=0x7ffe9582565c "", econtext=0x27a4ce0, state=0x27a7528) at ../../../src/include/executor/executor.h:289 oldContext = 0x268ac20 #7 ExecProject (projInfo=0x27a7520) at ../../../src/include/executor/executor.h:323 econtext = 0x27a4ce0 state = 0x27a7528 slot = 0x27a7130 isnull = 0 '\000' #8 ExecHashJoin (node=node@entry=0x27a4bc8) at nodeHashjoin.c:325 outerNode = <optimized out> hashNode = <optimized out> otherqual = <optimized out> hashtable = 0x2773678 hashvalue = 1944640558 batchno = 0 __func__ = "ExecHashJoin" #9 0x000000000060ffd8 in ExecProcNode (node=0x27a4bc8) at execProcnode.c:520 result = <optimized out> __func__ = "ExecProcNode" #10 0x000000000062df64 in CteScanNext (node=node@entry=0x27a9908) at nodeCtescan.c:103 cteslot = <optimized out> estate = <optimized out> dir = ForwardScanDirection forward = 1 '\001' tuplestorestate = 0x27a9a20 eof_tuplestore = <optimized out> slot = 0x27aa750 #11 0x000000000061123a in ExecScanFetch (recheckMtd=0x62de60 <CteScanRecheck>, accessMtd=0x62de70 <CteScanNext>, node=0x27a9908) at execScan.c:95 estate = <optimized out> #12 ExecScan (node=node@entry=0x27a9908, accessMtd=accessMtd@entry=0x62de70 <CteScanNext>, recheckMtd=recheckMtd@entry=0x62de60 <CteScanRecheck>) at execScan.c:162 econtext = 0x27a9c50 qual = 0x27a9d10 projInfo = 0x0 #13 0x000000000062dfbf in ExecCteScan (node=node@entry=0x27a9908) at nodeCtescan.c:155 No locals. #14 0x0000000000610048 in ExecProcNode (node=node@entry=0x27a9908) at execProcnode.c:489 result = <optimized out> __func__ = "ExecProcNode" #15 0x00000000006218a4 in ExecHashJoin (node=node@entry=0x27a8e10) at nodeHashjoin.c:136 outerNode = <optimized out> hashNode = <optimized out> otherqual = <optimized out> hashtable = 0x0 hashvalue = 0 batchno = 41365104 __func__ = "ExecHashJoin" #16 0x000000000060ffd8 in ExecProcNode (node=node@entry=0x27a8e10) at execProcnode.c:520 result = <optimized out> __func__ = "ExecProcNode" #17 0x0000000000628b3e in ExecModifyTable (node=node@entry=0x27a8a00) at nodeModifyTable.c:1462 estate = 0x27a4940 operation = CMD_INSERT saved_resultRelInfo = 0x0 resultRelInfo = 0x27a4ab0 subplanstate = 0x27a8e10 junkfilter = 0x0 slot = <optimized out> planSlot = <optimized out> tupleid = 0x0 tuple_ctid = {ip_blkid = {bi_hi = 35328, bi_lo = 634}, ip_posid = 0} oldtupdata = {t_len = 216, t_self = {ip_blkid = {bi_hi = 0, bi_lo = 0}, ip_posid = 61367}, t_tableOid = 0, t_data = 0x279fbe8} oldtuple = <optimized out> __func__ = "ExecModifyTable" #18 0x0000000000610128 in ExecProcNode (node=node@entry=0x27a8a00) at execProcnode.c:424 result = <optimized out> __func__ = "ExecProcNode" #19 0x000000000060b75e in ExecutePlan (execute_once=<optimized out>, dest=0xd10be0 <debugtupDR>, direction=<optimized out>, numberTuples=0, sendTuples=<optimized out>, operation=CMD_INSERT, use_parallel_mode=<optimized out>, planstate=0x27a8a00, estate=0x27a4940) at execMain.c:1651 slot = <optimized out> current_tuple_count = 0 #20 standard_ExecutorRun (queryDesc=0x2722300, direction=<optimized out>, count=0, execute_once=<optimized out>) at execMain.c:360 estate = 0x27a4940 operation = CMD_INSERT dest = 0xd10be0 <debugtupDR> sendTuples = <optimized out> __func__ = "standard_ExecutorRun" #21 0x000000000073fb42 in ProcessQuery (plan=<optimized out>, sourceText=0x2673150 "WITH funcdescs AS ( SELECT p.oid as p_oid, oprname, coalesce(obj_description(o.oid, 'pg_operator'),'') as opdesc FROM pg_proc p JOIN pg_operator o ON oprcode = p.oid ) INSERT INTO pg_description SEL"..., params=0x0, queryEnv=0x0, dest=0xd10be0 <debugtupDR>, completionTag=0x7ffe95825c30 "") at pquery.c:162 queryDesc = 0x2722300 #22 0x000000000073fdb3 in PortalRunMulti (portal=portal@entry=0x26a9760, isTopLevel=isTopLevel@entry=1 '\001', setHoldSnapshot=setHoldSnapshot@entry=0 '\000', dest=dest@entry=0xd10be0 <debugtupDR>, altdest=altdest@entry=0xd10be0 <debugtupDR>, completionTag=completionTag@entry=0x7ffe95825c30 "") at pquery.c:1287 active_snapshot_set = 1 '\001' stmtlist_item = 0x2754000 #23 0x00000000007409b3 in PortalRun (portal=portal@entry=0x26a9760, count=count@entry=9223372036854775807, isTopLevel=isTopLevel@entry=1 '\001', run_once=run_once@entry=1 '\001', dest=dest@entry=0xd10be0 <debugtupDR>, altdest=altdest@entry=0xd10be0 <debugtupDR>, completionTag=0x7ffe95825c30 "") at pquery.c:800 save_exception_stack = 0x7ffe95825ea0 save_context_stack = 0x0 local_sigjmp_buf = {{__jmpbuf = {39972528, 3065876441714304163, 40606192, 13700064, 40540000, 140731406769200, -3066668012307307357, 3065872022924731555}, __mask_was_saved = 0, __saved_mask = {__val = {0, 0, 0, 39972528, 8681844, 1, 40053440, 10715902, 40540000, 10715902, 1, 1, 1, 140731406769200, 8801570, 41499144}}}} result = <optimized out> nprocessed = <optimized out> saveTopTransactionResourceOwner = 0x261eeb0 saveTopTransactionContext = 0x26872a0 saveActivePortal = 0x0 saveResourceOwner = 0x261eeb0 savePortalContext = 0x0 saveMemoryContext = 0x26872a0 __func__ = "PortalRun" #24 0x000000000073c6b9 in exec_simple_query (query_string=0x2673150 "WITH funcdescs AS ( SELECT p.oid as p_oid, oprname, coalesce(obj_description(o.oid, 'pg_operator'),'') as opdesc FROM pg_proc p JOIN pg_operator o ON oprcode = p.oid ) INSERT INTO pg_description SEL"...) at postgres.c:1105 portal = 0x26a9760 snapshot_set = <optimized out> commandTag = <optimized out> completionTag = "\000\\\202\225\376\177\000\000\357݈\225\376\177\000\000\000\000\000\000\000\000\000\000\n\000\000\000\000\000\000\000P1g\002\000\000\000\000\300r_\002\000\000\000\000\351\003", '\000' <repeats 13 times> querytree_list = <optimized out> plantree_list = <optimized out> receiver = 0xd10be0 <debugtupDR> format = 0 dest = DestDebug parsetree_list = 0x26b9a18 parsetree_item = 0x26b99f0 save_log_statement_stats = 0 '\000' was_logged = 0 '\000' isTopLevel = 1 '\001' msec_str = "\000\\\202\225\376\177\000\000\357݈\225\376\177\000\000\000\000\000\000\000\000\000\000\n\000\000\000\000\000\000" __func__ = "exec_simple_query" #25 0x000000000073dacc in PostgresMain (argc=argc@entry=10, argv=argv@entry=0x25f18b0, dbname=0x26123c0 "template1", dbname@entry=0x0, username=<optimized out>) at postgres.c:4075 query_string = 0x2673150 "WITH funcdescs AS ( SELECT p.oid as p_oid, oprname, coalesce(obj_description(o.oid, 'pg_operator'),'') as opdesc FROM pg_proc p JOIN pg_operator o ON oprcode = p.oid ) INSERT INTO pg_description SEL"... firstchar = 40317264 input_message = {data = 0x2673150 "WITH funcdescs AS ( SELECT p.oid as p_oid, oprname, coalesce(obj_description(o.oid, 'pg_operator'),'') as opdesc FROM pg_proc p JOIN pg_operator o ON oprcode = p.oid ) INSERT INTO pg_description SEL"..., len = 451, maxlen = 1024, cursor = 451, long_ok = 0 '\000'} local_sigjmp_buf = {{__jmpbuf = {39786672, 3065872400647890083, 39809728, 1001, 0, 0, -3066668012108077917, 3065871986567586979}, __mask_was_saved = 1, __saved_mask = {__val = {0, 472446402651, 0, 0, 532575944823, 1001, 0, 0, 140313854087694, 0, 140313857186624, 6, 39786672, 1001, 0, 0}}}} send_ready_for_query = 0 '\000' disable_idle_in_transaction_timeout = <optimized out> __func__ = "PostgresMain" #26 0x0000000000478a4c in main (argc=10, argv=0x25f18b0) at main.c:224 No locals.
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers