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

Commit12b1b5d

Browse files
committed
Instead of supposing (wrongly, in the general case) that the rowtype
of an inheritance child table is binary-compatible with the rowtype ofits parent, invent an expression node type that does the conversioncorrectly. Fixes the new bug exhibited by Kris Shannon as well as alot of old bugs that would only show up when using multiple inheritanceor after altering the parent table.
1 parentfd536dd commit12b1b5d

File tree

15 files changed

+356
-71
lines changed

15 files changed

+356
-71
lines changed

‎src/backend/executor/execQual.c

Lines changed: 137 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.169 2004/09/22 17:41:50 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.170 2004/12/11 23:26:29 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -87,6 +87,9 @@ static Datum ExecEvalOr(BoolExprState *orExpr, ExprContext *econtext,
8787
bool*isNull,ExprDoneCond*isDone);
8888
staticDatumExecEvalAnd(BoolExprState*andExpr,ExprContext*econtext,
8989
bool*isNull,ExprDoneCond*isDone);
90+
staticDatumExecEvalConvertRowtype(ConvertRowtypeExprState*cstate,
91+
ExprContext*econtext,
92+
bool*isNull,ExprDoneCond*isDone);
9093
staticDatumExecEvalCase(CaseExprState*caseExpr,ExprContext*econtext,
9194
bool*isNull,ExprDoneCond*isDone);
9295
staticDatumExecEvalCaseTestExpr(ExprState*exprstate,
@@ -428,7 +431,8 @@ ExecEvalAggref(AggrefExprState *aggref, ExprContext *econtext,
428431
*
429432
*Returns a Datum whose value is the value of a range
430433
*variable with respect to given expression context.
431-
* ---------------------------------------------------------------- */
434+
* ----------------------------------------------------------------
435+
*/
432436
staticDatum
433437
ExecEvalVar(ExprState*exprstate,ExprContext*econtext,
434438
bool*isNull,ExprDoneCond*isDone)
@@ -1844,6 +1848,75 @@ ExecEvalAnd(BoolExprState *andExpr, ExprContext *econtext,
18441848
returnBoolGetDatum(!AnyNull);
18451849
}
18461850

1851+
/* ----------------------------------------------------------------
1852+
*ExecEvalConvertRowtype
1853+
*
1854+
*Evaluate a rowtype coercion operation. This may require
1855+
*rearranging field positions.
1856+
* ----------------------------------------------------------------
1857+
*/
1858+
staticDatum
1859+
ExecEvalConvertRowtype(ConvertRowtypeExprState*cstate,
1860+
ExprContext*econtext,
1861+
bool*isNull,ExprDoneCond*isDone)
1862+
{
1863+
HeapTupleresult;
1864+
DatumtupDatum;
1865+
HeapTupleHeadertuple;
1866+
HeapTupleDatatmptup;
1867+
AttrNumber*attrMap=cstate->attrMap;
1868+
Datum*invalues=cstate->invalues;
1869+
char*innulls=cstate->innulls;
1870+
Datum*outvalues=cstate->outvalues;
1871+
char*outnulls=cstate->outnulls;
1872+
inti;
1873+
intoutnatts=cstate->outdesc->natts;
1874+
1875+
tupDatum=ExecEvalExpr(cstate->arg,econtext,isNull,isDone);
1876+
1877+
/* this test covers the isDone exception too: */
1878+
if (*isNull)
1879+
returntupDatum;
1880+
1881+
tuple=DatumGetHeapTupleHeader(tupDatum);
1882+
1883+
Assert(HeapTupleHeaderGetTypeId(tuple)==cstate->indesc->tdtypeid);
1884+
Assert(HeapTupleHeaderGetTypMod(tuple)==cstate->indesc->tdtypmod);
1885+
1886+
/*
1887+
* heap_deformtuple needs a HeapTuple not a bare HeapTupleHeader.
1888+
*/
1889+
tmptup.t_len=HeapTupleHeaderGetDatumLength(tuple);
1890+
tmptup.t_data=tuple;
1891+
1892+
/*
1893+
* Extract all the values of the old tuple, offsetting the arrays
1894+
* so that invalues[0] is NULL and invalues[1] is the first
1895+
* source attribute; this exactly matches the numbering convention
1896+
* in attrMap.
1897+
*/
1898+
heap_deformtuple(&tmptup,cstate->indesc,invalues+1,innulls+1);
1899+
invalues[0]= (Datum)0;
1900+
innulls[0]='n';
1901+
1902+
/*
1903+
* Transpose into proper fields of the new tuple.
1904+
*/
1905+
for (i=0;i<outnatts;i++)
1906+
{
1907+
intj=attrMap[i];
1908+
1909+
outvalues[i]=invalues[j];
1910+
outnulls[i]=innulls[j];
1911+
}
1912+
1913+
/*
1914+
* Now form the new tuple.
1915+
*/
1916+
result=heap_formtuple(cstate->outdesc,outvalues,outnulls);
1917+
1918+
returnHeapTupleGetDatum(result);
1919+
}
18471920

18481921
/* ----------------------------------------------------------------
18491922
*ExecEvalCase
@@ -2969,6 +3042,68 @@ ExecInitExpr(Expr *node, PlanState *parent)
29693042
state= (ExprState*)gstate;
29703043
}
29713044
break;
3045+
caseT_ConvertRowtypeExpr:
3046+
{
3047+
ConvertRowtypeExpr*convert= (ConvertRowtypeExpr*)node;
3048+
ConvertRowtypeExprState*cstate=makeNode(ConvertRowtypeExprState);
3049+
inti;
3050+
intn;
3051+
3052+
cstate->xprstate.evalfunc= (ExprStateEvalFunc)ExecEvalConvertRowtype;
3053+
cstate->arg=ExecInitExpr(convert->arg,parent);
3054+
/* save copies of needed tuple descriptors */
3055+
cstate->indesc=lookup_rowtype_tupdesc(exprType((Node*)convert->arg),-1);
3056+
cstate->indesc=CreateTupleDescCopy(cstate->indesc);
3057+
cstate->outdesc=lookup_rowtype_tupdesc(convert->resulttype,-1);
3058+
cstate->outdesc=CreateTupleDescCopy(cstate->outdesc);
3059+
/* prepare map from old to new attribute numbers */
3060+
n=cstate->outdesc->natts;
3061+
cstate->attrMap= (AttrNumber*)palloc0(n*sizeof(AttrNumber));
3062+
for (i=0;i<n;i++)
3063+
{
3064+
Form_pg_attributeatt=cstate->outdesc->attrs[i];
3065+
char*attname;
3066+
Oidatttypid;
3067+
int32atttypmod;
3068+
intj;
3069+
3070+
if (att->attisdropped)
3071+
continue;/* attrMap[i] is already 0 */
3072+
attname=NameStr(att->attname);
3073+
atttypid=att->atttypid;
3074+
atttypmod=att->atttypmod;
3075+
for (j=0;j<cstate->indesc->natts;j++)
3076+
{
3077+
att=cstate->indesc->attrs[j];
3078+
if (att->attisdropped)
3079+
continue;
3080+
if (strcmp(attname,NameStr(att->attname))==0)
3081+
{
3082+
/* Found it, check type */
3083+
if (atttypid!=att->atttypid||atttypmod!=att->atttypmod)
3084+
elog(ERROR,"attribute \"%s\" of type %s does not match corresponding attribute of type %s",
3085+
attname,
3086+
format_type_be(cstate->indesc->tdtypeid),
3087+
format_type_be(cstate->outdesc->tdtypeid));
3088+
cstate->attrMap[i]= (AttrNumber) (j+1);
3089+
break;
3090+
}
3091+
}
3092+
if (cstate->attrMap[i]==0)
3093+
elog(ERROR,"attribute \"%s\" of type %s does not exist",
3094+
attname,
3095+
format_type_be(cstate->indesc->tdtypeid));
3096+
}
3097+
/* preallocate workspace for Datum arrays */
3098+
n=cstate->indesc->natts+1;/* +1 for NULL */
3099+
cstate->invalues= (Datum*)palloc(n*sizeof(Datum));
3100+
cstate->innulls= (char*)palloc(n*sizeof(char));
3101+
n=cstate->outdesc->natts;
3102+
cstate->outvalues= (Datum*)palloc(n*sizeof(Datum));
3103+
cstate->outnulls= (char*)palloc(n*sizeof(char));
3104+
state= (ExprState*)cstate;
3105+
}
3106+
break;
29723107
caseT_CaseExpr:
29733108
{
29743109
CaseExpr*caseexpr= (CaseExpr*)node;

‎src/backend/nodes/copyfuncs.c

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
* Portions Copyright (c) 1994, Regents of the University of California
1616
*
1717
* IDENTIFICATION
18-
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.293 2004/11/05 19:15:59 tgl Exp $
18+
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.294 2004/12/11 23:26:33 tgl Exp $
1919
*
2020
*-------------------------------------------------------------------------
2121
*/
@@ -876,6 +876,21 @@ _copyRelabelType(RelabelType *from)
876876
returnnewnode;
877877
}
878878

879+
/*
880+
* _copyConvertRowtypeExpr
881+
*/
882+
staticConvertRowtypeExpr*
883+
_copyConvertRowtypeExpr(ConvertRowtypeExpr*from)
884+
{
885+
ConvertRowtypeExpr*newnode=makeNode(ConvertRowtypeExpr);
886+
887+
COPY_NODE_FIELD(arg);
888+
COPY_SCALAR_FIELD(resulttype);
889+
COPY_SCALAR_FIELD(convertformat);
890+
891+
returnnewnode;
892+
}
893+
879894
/*
880895
* _copyCaseExpr
881896
*/
@@ -2696,6 +2711,9 @@ copyObject(void *from)
26962711
caseT_RelabelType:
26972712
retval=_copyRelabelType(from);
26982713
break;
2714+
caseT_ConvertRowtypeExpr:
2715+
retval=_copyConvertRowtypeExpr(from);
2716+
break;
26992717
caseT_CaseExpr:
27002718
retval=_copyCaseExpr(from);
27012719
break;

‎src/backend/nodes/equalfuncs.c

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
* Portions Copyright (c) 1994, Regents of the University of California
1919
*
2020
* IDENTIFICATION
21-
* $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.232 2004/11/05 19:15:59 tgl Exp $
21+
* $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.233 2004/12/11 23:26:33 tgl Exp $
2222
*
2323
*-------------------------------------------------------------------------
2424
*/
@@ -380,6 +380,24 @@ _equalRelabelType(RelabelType *a, RelabelType *b)
380380
return true;
381381
}
382382

383+
staticbool
384+
_equalConvertRowtypeExpr(ConvertRowtypeExpr*a,ConvertRowtypeExpr*b)
385+
{
386+
COMPARE_NODE_FIELD(arg);
387+
COMPARE_SCALAR_FIELD(resulttype);
388+
389+
/*
390+
* Special-case COERCE_DONTCARE, so that planner can build coercion
391+
* nodes that are equal() to both explicit and implicit coercions.
392+
*/
393+
if (a->convertformat!=b->convertformat&&
394+
a->convertformat!=COERCE_DONTCARE&&
395+
b->convertformat!=COERCE_DONTCARE)
396+
return false;
397+
398+
return true;
399+
}
400+
383401
staticbool
384402
_equalCaseExpr(CaseExpr*a,CaseExpr*b)
385403
{
@@ -1844,6 +1862,9 @@ equal(void *a, void *b)
18441862
caseT_RelabelType:
18451863
retval=_equalRelabelType(a,b);
18461864
break;
1865+
caseT_ConvertRowtypeExpr:
1866+
retval=_equalConvertRowtypeExpr(a,b);
1867+
break;
18471868
caseT_CaseExpr:
18481869
retval=_equalCaseExpr(a,b);
18491870
break;

‎src/backend/nodes/outfuncs.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.243 2004/08/29 05:06:43 momjian Exp $
11+
* $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.244 2004/12/11 23:26:33 tgl Exp $
1212
*
1313
* NOTES
1414
* Every node type that can appear in stored rules' parsetrees *must*
@@ -767,6 +767,16 @@ _outRelabelType(StringInfo str, RelabelType *node)
767767
WRITE_ENUM_FIELD(relabelformat,CoercionForm);
768768
}
769769

770+
staticvoid
771+
_outConvertRowtypeExpr(StringInfostr,ConvertRowtypeExpr*node)
772+
{
773+
WRITE_NODE_TYPE("CONVERTROWTYPEEXPR");
774+
775+
WRITE_NODE_FIELD(arg);
776+
WRITE_OID_FIELD(resulttype);
777+
WRITE_ENUM_FIELD(convertformat,CoercionForm);
778+
}
779+
770780
staticvoid
771781
_outCaseExpr(StringInfostr,CaseExpr*node)
772782
{
@@ -1728,6 +1738,9 @@ _outNode(StringInfo str, void *obj)
17281738
caseT_RelabelType:
17291739
_outRelabelType(str,obj);
17301740
break;
1741+
caseT_ConvertRowtypeExpr:
1742+
_outConvertRowtypeExpr(str,obj);
1743+
break;
17311744
caseT_CaseExpr:
17321745
_outCaseExpr(str,obj);
17331746
break;

‎src/backend/nodes/readfuncs.c

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.173 2004/08/29 04:12:33 momjian Exp $
11+
* $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.174 2004/12/11 23:26:34 tgl Exp $
1212
*
1313
* NOTES
1414
* Path and Plan nodes do not have any readfuncs support, because we
@@ -575,6 +575,21 @@ _readRelabelType(void)
575575
READ_DONE();
576576
}
577577

578+
/*
579+
* _readConvertRowtypeExpr
580+
*/
581+
staticConvertRowtypeExpr*
582+
_readConvertRowtypeExpr(void)
583+
{
584+
READ_LOCALS(ConvertRowtypeExpr);
585+
586+
READ_NODE_FIELD(arg);
587+
READ_OID_FIELD(resulttype);
588+
READ_ENUM_FIELD(convertformat,CoercionForm);
589+
590+
READ_DONE();
591+
}
592+
578593
/*
579594
* _readCaseExpr
580595
*/
@@ -971,6 +986,8 @@ parseNodeString(void)
971986
return_value=_readFieldStore();
972987
elseif (MATCH("RELABELTYPE",11))
973988
return_value=_readRelabelType();
989+
elseif (MATCH("CONVERTROWTYPEEXPR",18))
990+
return_value=_readConvertRowtypeExpr();
974991
elseif (MATCH("CASE",4))
975992
return_value=_readCaseExpr();
976993
elseif (MATCH("WHEN",4))

‎src/backend/optimizer/prep/prepjointree.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
*
1717
*
1818
* IDENTIFICATION
19-
* $PostgreSQL: pgsql/src/backend/optimizer/prep/prepjointree.c,v 1.23 2004/08/29 05:06:44 momjian Exp $
19+
* $PostgreSQL: pgsql/src/backend/optimizer/prep/prepjointree.c,v 1.24 2004/12/11 23:26:37 tgl Exp $
2020
*
2121
*-------------------------------------------------------------------------
2222
*/
@@ -839,6 +839,13 @@ find_nonnullable_rels(Node *node, bool top_level)
839839

840840
result=find_nonnullable_rels((Node*)expr->arg,top_level);
841841
}
842+
elseif (IsA(node,ConvertRowtypeExpr))
843+
{
844+
/* not clear this is useful, but it can't hurt */
845+
ConvertRowtypeExpr*expr= (ConvertRowtypeExpr*)node;
846+
847+
result=find_nonnullable_rels((Node*)expr->arg,top_level);
848+
}
842849
elseif (IsA(node,NullTest))
843850
{
844851
NullTest*expr= (NullTest*)node;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp