Re: patch: function xmltable - Mailing list pgsql-hackers
| From | Alvaro Herrera |
|---|---|
| Subject | Re: patch: function xmltable |
| Date | |
| Msg-id | 20161122204730.dgipy6gxi25j4e6a@alvherre.pgsql Whole thread Raw |
| In response to | Re: patch: function xmltable (Pavel Stehule <pavel.stehule@gmail.com>) |
| Responses |
Re: patch: function xmltable
Re: patch: function xmltable |
| List | pgsql-hackers |
I found the whole TableExprGetTupleDesc() function a bit odd in
nodeFuncs.c, so I renamed it to ExecTypeFromTableExpr() and moved it to
execTuples.c -- but only because that's where ExecTypeFromTL and others
already live. I would have liked to move it to tupdesc.c instead, but
it requires knowledge of executor nodes, which is probably the reason
that ExecTypeFromTL is in execTuples. I think we'd eat that bit of
ugliness only because we're not the first. But anyway I quickly ran
into another problem.
I noticed that ExecTypeFromTableExpr is being called from the transform
phase, which is much earlier than the executor. I noticed because of
the warning that the above movement added to nodeFuncs.c,
src/backend/nodes/nodeFuncs.c:509:5: warning: implicit declaration of function 'ExecTypeFromTableExpr'
[-Wimplicit-function-declaration]
so I thought, hm, is it okay to have parse analysis run an executor
function? (I suppose this is the reason you put it in nodeFuncs in the
first place). For fun, I tried this query under GDB, with a breakpoint
on exprTypmod():
SELECT X.*
FROM emp,
XMLTABLE ('//depts/dept/employee' passing doc COLUMNS empID INTEGER PATH '@id', firstname int PATH
'name/first', lastname VARCHAR(25) PATH 'name/last') AS X;
and sure enough, the type is resolved during parse analysis:
Breakpoint 1, exprTypmod (expr=expr@entry=0x1d23ad8) at /pgsql/source/master/src/backend/nodes/nodeFuncs.c:283
283 if (!expr)
(gdb) print *expr
$2 = {type = T_TableExpr}
(gdb) bt
#0 exprTypmod (expr=expr@entry=0x1d23ad8) at /pgsql/source/master/src/backend/nodes/nodeFuncs.c:283
#1 0x000000000080c500 in get_expr_result_type (expr=0x1d23ad8, resultTypeId=0x7ffd482bfdb4,
resultTupleDesc=0x7ffd482bfdb8) at /pgsql/source/master/src/backend/utils/fmgr/funcapi.c:247
#2 0x000000000056de1b in expandRTE (rte=rte@entry=0x1d6b800, rtindex=2, sublevels_up=0, location=location@entry=7,
include_dropped=include_dropped@entry=0 '\000', colnames=colnames@entry=0x7ffd482bfe10, colvars=0x7ffd482bfe18)
at/pgsql/source/master/src/backend/parser/parse_relation.c:2052
#3 0x000000000056e131 in expandRelAttrs (pstate=pstate@entry=0x1d238a8, rte=rte@entry=0x1d6b800, rtindex=<optimized
out>, sublevels_up=<optimized out>, location=location@entry=7) at
/pgsql/source/master/src/backend/parser/parse_relation.c:2435
#4 0x000000000056fa64 in ExpandSingleTable (pstate=pstate@entry=0x1d238a8, rte=rte@entry=0x1d6b800, location=7,
make_target_entry=make_target_entry@entry=1'\001') at /pgsql/source/master/src/backend/parser/parse_target.c:1266
#5 0x000000000057135b in ExpandColumnRefStar (pstate=pstate@entry=0x1d238a8, cref=0x1d22720,
make_target_entry=make_target_entry@entry=1'\001') at /pgsql/source/master/src/backend/parser/parse_target.c:1158
#6 0x00000000005716f9 in transformTargetList (pstate=0x1d238a8, targetlist=<optimized out>,
exprKind=EXPR_KIND_SELECT_TARGET)
This seems fine I guess, and it seems to say that we ought to move the
code that generates the tupdesc to back parse analysis rather than
executor. Okay, fine. But let's find a better place than nodeFuncs.
But if I move the XMLTABLE() call to the target list instead, the type
is resolved at planner time:
SELECT
XMLTABLE ('/dept/employee' passing $$<dept bldg="114"> <employee id="903"> <name>
<first>Mary</first> <last>Jones</last> </name> <office>415</office>
<phone>905-403-6112</phone> <phone>647-504-4546</phone> <salary currency="USD">64000</salary> </employee>
</dept>$$ COLUMNS empID INTEGER PATH '@id', firstname varchar(4) PATH 'name/first', lastname
VARCHAR(25) PATH 'name/last') AS X;
Breakpoint 1, exprTypmod (expr=expr@entry=0x1d6bed8) at /pgsql/source/master/src/backend/nodes/nodeFuncs.c:283
283 if (!expr)
(gdb) bt
#0 exprTypmod (expr=expr@entry=0x1d6bed8) at /pgsql/source/master/src/backend/nodes/nodeFuncs.c:283
#1 0x0000000000654058 in set_pathtarget_cost_width (root=0x1d6bc68, target=0x1d6c728) at
/pgsql/source/master/src/backend/optimizer/path/costsize.c:4729
#2 0x000000000066c197 in grouping_planner (root=0x1d6bc68, inheritance_update=40 '(', inheritance_update@entry=0
'\000', tuple_fraction=0.01, tuple_fraction@entry=0) at
/pgsql/source/master/src/backend/optimizer/plan/planner.c:1745
#3 0x000000000066ef64 in subquery_planner (glob=glob@entry=0x1d6bbd0, parse=parse@entry=0x1d23818,
parent_root=parent_root@entry=0x0, hasRecursion=hasRecursion@entry=0 '\000',
tuple_fraction=tuple_fraction@entry=0) at /pgsql/source/master/src/backend/optimizer/plan/planner.c:795
#4 0x000000000066fe5e in standard_planner (parse=0x1d23818, cursorOptions=256, boundParams=<optimized out>) at
/pgsql/source/master/src/backend/optimizer/plan/planner.c:307
This is surprising, but I'm not sure it's wrong.
--
Álvaro Herrera https://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services
pgsql-hackers by date: