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

Commit2848dc5

Browse files
committed
Make the world safe (more or less) for dropped columns in plpgsql rowtypes.
1 parenta039148 commit2848dc5

File tree

7 files changed

+263
-200
lines changed

7 files changed

+263
-200
lines changed

‎src/backend/executor/execQual.c

Lines changed: 35 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.145 2003/09/2506:57:59 petere Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.146 2003/09/2523:02:11 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -315,23 +315,6 @@ ExecEvalAggref(AggrefExprState *aggref, ExprContext *econtext, bool *isNull)
315315
*
316316
*Returns a Datum whose value is the value of a range
317317
*variable with respect to given expression context.
318-
*
319-
*
320-
*As an entry condition, we expect that the datatype the
321-
*plan expects to get (as told by our "variable" argument) is in
322-
*fact the datatype of the attribute the plan says to fetch (as
323-
*seen in the current context, identified by our "econtext"
324-
*argument).
325-
*
326-
*If we fetch a Type A attribute and Caller treats it as if it
327-
*were Type B, there will be undefined results (e.g. crash).
328-
*One way these might mismatch now is that we're accessing a
329-
*catalog class and the type information in the pg_attribute
330-
*class does not match the hardcoded pg_attribute information
331-
*(in pg_attribute.h) for the class in question.
332-
*
333-
*We have an Assert to make sure this entry condition is met.
334-
*
335318
* ---------------------------------------------------------------- */
336319
staticDatum
337320
ExecEvalVar(Var*variable,ExprContext*econtext,bool*isNull)
@@ -369,11 +352,40 @@ ExecEvalVar(Var *variable, ExprContext *econtext, bool *isNull)
369352

370353
attnum=variable->varattno;
371354

372-
/* (See prolog for explanation of this Assert) */
373-
Assert(attnum <=0||
374-
(attnum-1 <=tuple_type->natts-1&&
375-
tuple_type->attrs[attnum-1]!=NULL&&
376-
variable->vartype==tuple_type->attrs[attnum-1]->atttypid));
355+
/*
356+
* Some checks that are only applied for user attribute numbers
357+
* (bogus system attnums will be caught inside heap_getattr).
358+
*/
359+
if (attnum>0)
360+
{
361+
/*
362+
* This assert checks that the attnum is valid.
363+
*/
364+
Assert(attnum <=tuple_type->natts&&
365+
tuple_type->attrs[attnum-1]!=NULL);
366+
367+
/*
368+
* If the attribute's column has been dropped, we force a NULL result.
369+
* This case should not happen in normal use, but it could happen if
370+
* we are executing a plan cached before the column was dropped.
371+
*/
372+
if (tuple_type->attrs[attnum-1]->attisdropped)
373+
{
374+
*isNull= true;
375+
return (Datum)0;
376+
}
377+
378+
/*
379+
* This assert checks that the datatype the plan expects to get (as
380+
* told by our "variable" argument) is in fact the datatype of the
381+
* attribute being fetched (as seen in the current context, identified
382+
* by our "econtext" argument). Otherwise crashes are likely.
383+
*
384+
* Note that we can't check dropped columns, since their atttypid
385+
* has been zeroed.
386+
*/
387+
Assert(variable->vartype==tuple_type->attrs[attnum-1]->atttypid);
388+
}
377389

378390
/*
379391
* If the attribute number is invalid, then we are supposed to return

‎src/backend/executor/nodeFunctionscan.c

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/executor/nodeFunctionscan.c,v 1.21 2003/09/2506:57:59 petere Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/executor/nodeFunctionscan.c,v 1.22 2003/09/2523:02:12 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -35,7 +35,7 @@
3535

3636

3737
staticTupleTableSlot*FunctionNext(FunctionScanState*node);
38-
staticbooltupledesc_mismatch(TupleDesctupdesc1,TupleDesctupdesc2);
38+
staticbooltupledesc_match(TupleDescdst_tupdesc,TupleDescsrc_tupdesc);
3939

4040
/* ----------------------------------------------------------------
4141
*Scan Support
@@ -86,8 +86,7 @@ FunctionNext(FunctionScanState *node)
8686
* need to do this for functions returning RECORD, but might as
8787
* well do it always.
8888
*/
89-
if (funcTupdesc&&
90-
tupledesc_mismatch(node->tupdesc,funcTupdesc))
89+
if (funcTupdesc&& !tupledesc_match(node->tupdesc,funcTupdesc))
9190
ereport(ERROR,
9291
(errcode(ERRCODE_DATATYPE_MISMATCH),
9392
errmsg("query-specified return row and actual function return row do not match")));
@@ -364,26 +363,36 @@ ExecFunctionReScan(FunctionScanState *node, ExprContext *exprCtxt)
364363
tuplestore_rescan(node->tuplestorestate);
365364
}
366365

367-
366+
/*
367+
* Check that function result tuple type (src_tupdesc) matches or can be
368+
* considered to match what the query expects (dst_tupdesc).
369+
*
370+
* We really only care about number of attributes and data type.
371+
* Also, we can ignore type mismatch on columns that are dropped in the
372+
* destination type, so long as the physical storage matches. This is
373+
* helpful in some cases involving out-of-date cached plans.
374+
*/
368375
staticbool
369-
tupledesc_mismatch(TupleDesctupdesc1,TupleDesctupdesc2)
376+
tupledesc_match(TupleDescdst_tupdesc,TupleDescsrc_tupdesc)
370377
{
371378
inti;
372379

373-
if (tupdesc1->natts!=tupdesc2->natts)
374-
returntrue;
380+
if (dst_tupdesc->natts!=src_tupdesc->natts)
381+
returnfalse;
375382

376-
for (i=0;i<tupdesc1->natts;i++)
383+
for (i=0;i<dst_tupdesc->natts;i++)
377384
{
378-
Form_pg_attributeattr1=tupdesc1->attrs[i];
379-
Form_pg_attributeattr2=tupdesc2->attrs[i];
380-
381-
/*
382-
* We really only care about number of attributes and data type
383-
*/
384-
if (attr1->atttypid!=attr2->atttypid)
385-
return true;
385+
Form_pg_attributedattr=dst_tupdesc->attrs[i];
386+
Form_pg_attributesattr=src_tupdesc->attrs[i];
387+
388+
if (dattr->atttypid==sattr->atttypid)
389+
continue;/* no worries */
390+
if (!dattr->attisdropped)
391+
return false;
392+
if (dattr->attlen!=sattr->attlen||
393+
dattr->attalign!=sattr->attalign)
394+
return false;
386395
}
387396

388-
returnfalse;
397+
returntrue;
389398
}

‎src/pl/plpgsql/src/gram.y

Lines changed: 8 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* procedural language
55
*
66
* IDENTIFICATION
7-
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/gram.y,v 1.46 2003/07/27 21:49:54 tgl Exp $
7+
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/gram.y,v 1.47 2003/09/25 23:02:12 tgl Exp $
88
*
99
* This software is copyrighted by Jan Wieck - Hamburg.
1010
*
@@ -47,7 +47,6 @@ staticPLpgSQL_expr*read_sql_stmt(const char *sqlstart);
4747
staticPLpgSQL_type*read_datatype(int tok);
4848
staticPLpgSQL_stmt*make_select_stmt(void);
4949
staticPLpgSQL_stmt*make_fetch_stmt(void);
50-
staticPLpgSQL_expr*make_tupret_expr(PLpgSQL_row *row);
5150
staticvoidcheck_assignable(PLpgSQL_datum *datum);
5251

5352
%}
@@ -493,7 +492,7 @@ decl_cursor_arglist : decl_cursor_arg
493492
new->dtype = PLPGSQL_DTYPE_ROW;
494493
new->refname = strdup("*internal*");
495494
new->lineno = plpgsql_scanner_lineno();
496-
new->rowtypeclass =InvalidOid;
495+
new->rowtupdesc =NULL;
497496
/*
498497
* We make temporary fieldnames/varnos arrays that
499498
* are much bigger than necessary. We will resize
@@ -1176,24 +1175,24 @@ stmt_return: K_RETURN lno
11761175

11771176
new = malloc(sizeof(PLpgSQL_stmt_return));
11781177
memset(new,0,sizeof(PLpgSQL_stmt_return));
1178+
new->expr =NULL;
1179+
new->retrecno= -1;
1180+
new->retrowno= -1;
11791181

11801182
if (plpgsql_curr_compile->fn_retistuple &&
11811183
!plpgsql_curr_compile->fn_retset)
11821184
{
1183-
new->retrecno= -1;
11841185
switch (yylex())
11851186
{
11861187
case K_NULL:
1187-
new->expr =NULL;
11881188
break;
11891189

11901190
case T_ROW:
1191-
new->expr =make_tupret_expr(yylval.row);
1191+
new->retrowno = yylval.row->rowno;
11921192
break;
11931193

11941194
case T_RECORD:
11951195
new->retrecno = yylval.rec->recno;
1196-
new->expr =NULL;
11971196
break;
11981197

11991198
default:
@@ -1874,7 +1873,7 @@ make_select_stmt(void)
18741873
row->dtype = PLPGSQL_DTYPE_ROW;
18751874
row->refname =strdup("*internal*");
18761875
row->lineno =plpgsql_scanner_lineno();
1877-
row->rowtypeclass =InvalidOid;
1876+
row->rowtupdesc =NULL;
18781877
row->nfields = nfields;
18791878
row->fieldnames =malloc(sizeof(char *) * nfields);
18801879
row->varnos =malloc(sizeof(int) * nfields);
@@ -2007,7 +2006,7 @@ make_fetch_stmt(void)
20072006
row->dtype = PLPGSQL_DTYPE_ROW;
20082007
row->refname =strdup("*internal*");
20092008
row->lineno =plpgsql_scanner_lineno();
2010-
row->rowtypeclass =InvalidOid;
2009+
row->rowtupdesc =NULL;
20112010
row->nfields = nfields;
20122011
row->fieldnames =malloc(sizeof(char *) * nfields);
20132012
row->varnos =malloc(sizeof(int) * nfields);
@@ -2041,36 +2040,6 @@ make_fetch_stmt(void)
20412040
}
20422041

20432042

2044-
static PLpgSQL_expr *
2045-
make_tupret_expr(PLpgSQL_row *row)
2046-
{
2047-
PLpgSQL_dstringds;
2048-
PLpgSQL_expr*expr;
2049-
inti;
2050-
charbuf[16];
2051-
2052-
expr =malloc(sizeof(PLpgSQL_expr) +sizeof(int) * (row->nfields -1));
2053-
expr->dtype= PLPGSQL_DTYPE_EXPR;
2054-
2055-
plpgsql_dstring_init(&ds);
2056-
plpgsql_dstring_append(&ds,"SELECT");
2057-
2058-
for (i =0; i < row->nfields; i++)
2059-
{
2060-
sprintf(buf,"%s$%d", (i >0) ?"," :"", i +1);
2061-
plpgsql_dstring_append(&ds, buf);
2062-
expr->params[i] = row->varnos[i];
2063-
}
2064-
2065-
expr->query=strdup(plpgsql_dstring_get(&ds));
2066-
expr->plan=NULL;
2067-
expr->plan_argtypes =NULL;
2068-
expr->nparams= row->nfields;
2069-
2070-
plpgsql_dstring_free(&ds);
2071-
return expr;
2072-
}
2073-
20742043
staticvoid
20752044
check_assignable(PLpgSQL_datum *datum)
20762045
{

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp