Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitdfc5c72

Browse files
committed
Fix ExpandIndirectionStar to handle cases where the expression to be
expanded is of RECORD type, eg'select (foo).* from (select foo(f1) from t1) ss'where foo() is a function declared with multiple OUT parameters.
1 parentea19c87 commitdfc5c72

File tree

1 file changed

+151
-3
lines changed

1 file changed

+151
-3
lines changed

‎src/backend/parser/parse_target.c

Lines changed: 151 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,14 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/parser/parse_target.c,v 1.131 2005/04/06 16:34:06 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/parser/parse_target.c,v 1.132 2005/04/25 21:03:25 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
1515
#include"postgres.h"
1616

1717
#include"commands/dbcommands.h"
18+
#include"funcapi.h"
1819
#include"miscadmin.h"
1920
#include"nodes/bitmapset.h"
2021
#include"nodes/makefuncs.h"
@@ -43,6 +44,8 @@ static Node *transformAssignmentIndirection(ParseState *pstate,
4344
staticList*ExpandColumnRefStar(ParseState*pstate,ColumnRef*cref);
4445
staticList*ExpandAllTables(ParseState*pstate);
4546
staticList*ExpandIndirectionStar(ParseState*pstate,A_Indirection*ind);
47+
staticTupleDescexpandRecordVariable(ParseState*pstate,Var*var,
48+
intlevelsup);
4649
staticintFigureColnameInternal(Node*node,char**name);
4750

4851

@@ -822,8 +825,23 @@ ExpandIndirectionStar(ParseState *pstate, A_Indirection *ind)
822825
/* And transform that */
823826
expr=transformExpr(pstate, (Node*)ind);
824827

825-
/* Verify it's a composite type, and get the tupdesc */
826-
tupleDesc=lookup_rowtype_tupdesc(exprType(expr),exprTypmod(expr));
828+
/*
829+
* Verify it's a composite type, and get the tupdesc. We use
830+
* get_expr_result_type() because that can handle references to
831+
* functions returning anonymous record types. If that fails,
832+
* use lookup_rowtype_tupdesc(), which will almost certainly fail
833+
* as well, but it will give an appropriate error message.
834+
*
835+
* If it's a Var of type RECORD, we have to work even harder: we have
836+
* to find what the Var refers to, and pass that to get_expr_result_type.
837+
* That task is handled by expandRecordVariable().
838+
*/
839+
if (IsA(expr,Var)&&
840+
((Var*)expr)->vartype==RECORDOID)
841+
tupleDesc=expandRecordVariable(pstate, (Var*)expr,0);
842+
elseif (get_expr_result_type(expr,NULL,&tupleDesc)!=TYPEFUNC_COMPOSITE)
843+
tupleDesc=lookup_rowtype_tupdesc(exprType(expr),exprTypmod(expr));
844+
Assert(tupleDesc);
827845

828846
/* Generate a list of references to the individual fields */
829847
numAttrs=tupleDesc->natts;
@@ -874,6 +892,136 @@ ExpandIndirectionStar(ParseState *pstate, A_Indirection *ind)
874892
returnte_list;
875893
}
876894

895+
/*
896+
* expandRecordVariable
897+
*Get the tuple descriptor for a Var of type RECORD, if possible.
898+
*
899+
* Since no actual table or view column is allowed to have type RECORD, such
900+
* a Var must refer to a JOIN or FUNCTION RTE or to a subquery output. We
901+
* drill down to find the ultimate defining expression and attempt to infer
902+
* the tupdesc from it. We ereport if we can't determine the tupdesc.
903+
*
904+
* levelsup is an extra offset to interpret the Var's varlevelsup correctly.
905+
*/
906+
staticTupleDesc
907+
expandRecordVariable(ParseState*pstate,Var*var,intlevelsup)
908+
{
909+
TupleDesctupleDesc;
910+
intnetlevelsup;
911+
RangeTblEntry*rte;
912+
AttrNumberattnum;
913+
Node*expr;
914+
915+
/* Check my caller didn't mess up */
916+
Assert(IsA(var,Var));
917+
Assert(var->vartype==RECORDOID);
918+
919+
netlevelsup=var->varlevelsup+levelsup;
920+
rte=GetRTEByRangeTablePosn(pstate,var->varno,netlevelsup);
921+
attnum=var->varattno;
922+
923+
expr= (Node*)var;/* default if we can't drill down */
924+
925+
switch (rte->rtekind)
926+
{
927+
caseRTE_RELATION:
928+
caseRTE_SPECIAL:
929+
/*
930+
* This case should not occur: a whole-row Var should have the
931+
* table's named rowtype, and a column of a table shouldn't have
932+
* type RECORD either. Fall through and fail (most likely)
933+
* at the bottom.
934+
*/
935+
break;
936+
caseRTE_SUBQUERY:
937+
{
938+
/* Subselect-in-FROM: examine sub-select's output expr */
939+
TargetEntry*ste=get_tle_by_resno(rte->subquery->targetList,
940+
attnum);
941+
942+
if (ste==NULL||ste->resjunk)
943+
elog(ERROR,"subquery %s does not have attribute %d",
944+
rte->eref->aliasname,attnum);
945+
expr= (Node*)ste->expr;
946+
if (IsA(expr,Var))
947+
{
948+
/*
949+
* Recurse into the sub-select to see what its Var refers
950+
* to. We have to build an additional level of ParseState
951+
* to keep in step with varlevelsup in the subselect.
952+
*/
953+
ParseStatemypstate;
954+
955+
MemSet(&mypstate,0,sizeof(mypstate));
956+
mypstate.parentParseState=pstate;
957+
mypstate.p_rtable=rte->subquery->rtable;
958+
/* don't bother filling the rest of the fake pstate */
959+
960+
returnexpandRecordVariable(&mypstate, (Var*)expr,0);
961+
}
962+
/* else fall through to inspect the expression */
963+
}
964+
break;
965+
caseRTE_JOIN:
966+
/* Join RTE */
967+
if (attnum==InvalidAttrNumber)
968+
{
969+
/* Whole-row reference to join, so expand the fields */
970+
List*names,
971+
*vars;
972+
ListCell*lname,
973+
*lvar;
974+
inti;
975+
976+
expandRTE(GetLevelNRangeTable(pstate,netlevelsup),
977+
var->varno,0, false,&names,&vars);
978+
979+
tupleDesc=CreateTemplateTupleDesc(list_length(vars), false);
980+
i=1;
981+
forboth(lname,names,lvar,vars)
982+
{
983+
char*label=strVal(lfirst(lname));
984+
Node*varnode= (Node*)lfirst(lvar);
985+
986+
TupleDescInitEntry(tupleDesc,i,
987+
label,
988+
exprType(varnode),
989+
exprTypmod(varnode),
990+
0);
991+
i++;
992+
}
993+
Assert(lname==NULL&&lvar==NULL);/* lists same len? */
994+
returntupleDesc;
995+
}
996+
/* Else recursively inspect the alias variable */
997+
Assert(attnum>0&&attnum <=list_length(rte->joinaliasvars));
998+
expr= (Node*)list_nth(rte->joinaliasvars,attnum-1);
999+
if (IsA(expr,Var))
1000+
returnexpandRecordVariable(pstate, (Var*)expr,netlevelsup);
1001+
/* else fall through to inspect the expression */
1002+
break;
1003+
caseRTE_FUNCTION:
1004+
expr=rte->funcexpr;
1005+
/* The func expr probably can't be a Var, but check */
1006+
if (IsA(expr,Var))
1007+
returnexpandRecordVariable(pstate, (Var*)expr,netlevelsup);
1008+
/* else fall through to inspect the expression */
1009+
break;
1010+
}
1011+
1012+
/*
1013+
* We now have an expression we can't expand any more, so see if
1014+
* get_expr_result_type() can do anything with it. If not, pass
1015+
* to lookup_rowtype_tupdesc() which will probably fail, but will
1016+
* give an appropriate error message while failing.
1017+
*/
1018+
if (get_expr_result_type(expr,NULL,&tupleDesc)!=TYPEFUNC_COMPOSITE)
1019+
tupleDesc=lookup_rowtype_tupdesc(exprType(expr),exprTypmod(expr));
1020+
1021+
returntupleDesc;
1022+
}
1023+
1024+
8771025
/*
8781026
* FigureColname -
8791027
* if the name of the resulting column is not specified in the target

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp