On 5 April 2017 at 08:23, Craig Ringer <[email protected]> wrote:
> On 5 April 2017 at 08:00, Craig Ringer <[email protected]> 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 ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers