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

Commit1788828

Browse files
committed
Remove PLPGSQL_DTYPE_ARRAYELEM datum type within pl/pgsql.
In the wake of the previous commit, we don't really need this anymore,since array assignment is primarily handled by the core code.The only way that that code could still be reached is that a GETDIAGNOSTICS target variable could be an array element. But thatdoesn't seem like a particularly essential feature. I'd added itin commit55caaae, but just because it was easy not becauseanyone had actually asked for it. Hence, revert that patch andthen remove the now-unreachable stuff. (If we really had to,we could probably reimplement GET DIAGNOSTICS using the newassignment machinery; but the cost/benefit ratio looks very poor,and it'd likely be a bit slower.)Note that PLPGSQL_DTYPE_RECFIELD remains. It's possible that wecould get rid of that too, but maintaining the existing behaviorsfor RECORD-type variables seems like it might be difficult. Sincethere's not any functional limitation in those code paths as therewas in the ARRAYELEM code, I've not pursued the idea.Discussion:https://postgr.es/m/4165684.1607707277@sss.pgh.pa.us
1 parentc9d5298 commit1788828

File tree

6 files changed

+26
-286
lines changed

6 files changed

+26
-286
lines changed

‎src/pl/plpgsql/src/pl_exec.c

Lines changed: 4 additions & 200 deletions
Original file line numberDiff line numberDiff line change
@@ -1311,12 +1311,11 @@ copy_plpgsql_datums(PLpgSQL_execstate *estate,
13111311

13121312
casePLPGSQL_DTYPE_ROW:
13131313
casePLPGSQL_DTYPE_RECFIELD:
1314-
casePLPGSQL_DTYPE_ARRAYELEM:
13151314

13161315
/*
13171316
* These datum records are read-only at runtime, so no need to
1318-
* copy them (well, RECFIELDand ARRAYELEM contain cached
1319-
*data, but we'djust as soon centralize the caching anyway).
1317+
* copy them (well, RECFIELDcontains cached data, but we'd
1318+
* just as soon centralize the caching anyway).
13201319
*/
13211320
outdatum=indatum;
13221321
break;
@@ -4136,9 +4135,6 @@ plpgsql_estate_setup(PLpgSQL_execstate *estate,
41364135
*
41374136
* NB: the result of the evaluation is no longer valid after this is done,
41384137
* unless it is a pass-by-value datatype.
4139-
*
4140-
* NB: if you change this code, see also the hacks in exec_assign_value's
4141-
* PLPGSQL_DTYPE_ARRAYELEM case for partial cleanup after subscript evals.
41424138
* ----------
41434139
*/
41444140
staticvoid
@@ -5288,198 +5284,6 @@ exec_assign_value(PLpgSQL_execstate *estate,
52885284
break;
52895285
}
52905286

5291-
casePLPGSQL_DTYPE_ARRAYELEM:
5292-
{
5293-
/*
5294-
* Target is an element of an array
5295-
*/
5296-
PLpgSQL_arrayelem*arrayelem;
5297-
intnsubscripts;
5298-
inti;
5299-
PLpgSQL_expr*subscripts[MAXDIM];
5300-
intsubscriptvals[MAXDIM];
5301-
Datumoldarraydatum,
5302-
newarraydatum,
5303-
coerced_value;
5304-
boololdarrayisnull;
5305-
Oidparenttypoid;
5306-
int32parenttypmod;
5307-
SPITupleTable*save_eval_tuptable;
5308-
MemoryContextoldcontext;
5309-
5310-
/*
5311-
* We need to do subscript evaluation, which might require
5312-
* evaluating general expressions; and the caller might have
5313-
* done that too in order to prepare the input Datum. We have
5314-
* to save and restore the caller's SPI_execute result, if
5315-
* any.
5316-
*/
5317-
save_eval_tuptable=estate->eval_tuptable;
5318-
estate->eval_tuptable=NULL;
5319-
5320-
/*
5321-
* To handle constructs like x[1][2] := something, we have to
5322-
* be prepared to deal with a chain of arrayelem datums. Chase
5323-
* back to find the base array datum, and save the subscript
5324-
* expressions as we go. (We are scanning right to left here,
5325-
* but want to evaluate the subscripts left-to-right to
5326-
* minimize surprises.) Note that arrayelem is left pointing
5327-
* to the leftmost arrayelem datum, where we will cache the
5328-
* array element type data.
5329-
*/
5330-
nsubscripts=0;
5331-
do
5332-
{
5333-
arrayelem= (PLpgSQL_arrayelem*)target;
5334-
if (nsubscripts >=MAXDIM)
5335-
ereport(ERROR,
5336-
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
5337-
errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
5338-
nsubscripts+1,MAXDIM)));
5339-
subscripts[nsubscripts++]=arrayelem->subscript;
5340-
target=estate->datums[arrayelem->arrayparentno];
5341-
}while (target->dtype==PLPGSQL_DTYPE_ARRAYELEM);
5342-
5343-
/* Fetch current value of array datum */
5344-
exec_eval_datum(estate,target,
5345-
&parenttypoid,&parenttypmod,
5346-
&oldarraydatum,&oldarrayisnull);
5347-
5348-
/* Update cached type data if necessary */
5349-
if (arrayelem->parenttypoid!=parenttypoid||
5350-
arrayelem->parenttypmod!=parenttypmod)
5351-
{
5352-
Oidarraytypoid;
5353-
int32arraytypmod=parenttypmod;
5354-
int16arraytyplen;
5355-
Oidelemtypoid;
5356-
int16elemtyplen;
5357-
boolelemtypbyval;
5358-
charelemtypalign;
5359-
5360-
/* If target is domain over array, reduce to base type */
5361-
arraytypoid=getBaseTypeAndTypmod(parenttypoid,
5362-
&arraytypmod);
5363-
5364-
/* ... and identify the element type */
5365-
elemtypoid=get_element_type(arraytypoid);
5366-
if (!OidIsValid(elemtypoid))
5367-
ereport(ERROR,
5368-
(errcode(ERRCODE_DATATYPE_MISMATCH),
5369-
errmsg("subscripted object is not an array")));
5370-
5371-
/* Collect needed data about the types */
5372-
arraytyplen=get_typlen(arraytypoid);
5373-
5374-
get_typlenbyvalalign(elemtypoid,
5375-
&elemtyplen,
5376-
&elemtypbyval,
5377-
&elemtypalign);
5378-
5379-
/* Now safe to update the cached data */
5380-
arrayelem->parenttypoid=parenttypoid;
5381-
arrayelem->parenttypmod=parenttypmod;
5382-
arrayelem->arraytypoid=arraytypoid;
5383-
arrayelem->arraytypmod=arraytypmod;
5384-
arrayelem->arraytyplen=arraytyplen;
5385-
arrayelem->elemtypoid=elemtypoid;
5386-
arrayelem->elemtyplen=elemtyplen;
5387-
arrayelem->elemtypbyval=elemtypbyval;
5388-
arrayelem->elemtypalign=elemtypalign;
5389-
}
5390-
5391-
/*
5392-
* Evaluate the subscripts, switch into left-to-right order.
5393-
* Like the expression built by ExecInitSubscriptingRef(),
5394-
* complain if any subscript is null.
5395-
*/
5396-
for (i=0;i<nsubscripts;i++)
5397-
{
5398-
boolsubisnull;
5399-
5400-
subscriptvals[i]=
5401-
exec_eval_integer(estate,
5402-
subscripts[nsubscripts-1-i],
5403-
&subisnull);
5404-
if (subisnull)
5405-
ereport(ERROR,
5406-
(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
5407-
errmsg("array subscript in assignment must not be null")));
5408-
5409-
/*
5410-
* Clean up in case the subscript expression wasn't
5411-
* simple. We can't do exec_eval_cleanup, but we can do
5412-
* this much (which is safe because the integer subscript
5413-
* value is surely pass-by-value), and we must do it in
5414-
* case the next subscript expression isn't simple either.
5415-
*/
5416-
if (estate->eval_tuptable!=NULL)
5417-
SPI_freetuptable(estate->eval_tuptable);
5418-
estate->eval_tuptable=NULL;
5419-
}
5420-
5421-
/* Now we can restore caller's SPI_execute result if any. */
5422-
Assert(estate->eval_tuptable==NULL);
5423-
estate->eval_tuptable=save_eval_tuptable;
5424-
5425-
/* Coerce source value to match array element type. */
5426-
coerced_value=exec_cast_value(estate,
5427-
value,
5428-
&isNull,
5429-
valtype,
5430-
valtypmod,
5431-
arrayelem->elemtypoid,
5432-
arrayelem->arraytypmod);
5433-
5434-
/*
5435-
* If the original array is null, cons up an empty array so
5436-
* that the assignment can proceed; we'll end with a
5437-
* one-element array containing just the assigned-to
5438-
* subscript. This only works for varlena arrays, though; for
5439-
* fixed-length array types we skip the assignment. We can't
5440-
* support assignment of a null entry into a fixed-length
5441-
* array, either, so that's a no-op too. This is all ugly but
5442-
* corresponds to the current behavior of execExpr*.c.
5443-
*/
5444-
if (arrayelem->arraytyplen>0&&/* fixed-length array? */
5445-
(oldarrayisnull||isNull))
5446-
return;
5447-
5448-
/* empty array, if any, and newarraydatum are short-lived */
5449-
oldcontext=MemoryContextSwitchTo(get_eval_mcontext(estate));
5450-
5451-
if (oldarrayisnull)
5452-
oldarraydatum=PointerGetDatum(construct_empty_array(arrayelem->elemtypoid));
5453-
5454-
/*
5455-
* Build the modified array value.
5456-
*/
5457-
newarraydatum=array_set_element(oldarraydatum,
5458-
nsubscripts,
5459-
subscriptvals,
5460-
coerced_value,
5461-
isNull,
5462-
arrayelem->arraytyplen,
5463-
arrayelem->elemtyplen,
5464-
arrayelem->elemtypbyval,
5465-
arrayelem->elemtypalign);
5466-
5467-
MemoryContextSwitchTo(oldcontext);
5468-
5469-
/*
5470-
* Assign the new array to the base variable. It's never NULL
5471-
* at this point. Note that if the target is a domain,
5472-
* coercing the base array type back up to the domain will
5473-
* happen within exec_assign_value.
5474-
*/
5475-
exec_assign_value(estate,target,
5476-
newarraydatum,
5477-
false,
5478-
arrayelem->arraytypoid,
5479-
arrayelem->arraytypmod);
5480-
break;
5481-
}
5482-
54835287
default:
54845288
elog(ERROR,"unrecognized dtype: %d",target->dtype);
54855289
}
@@ -5490,8 +5294,8 @@ exec_assign_value(PLpgSQL_execstate *estate,
54905294
*
54915295
* The type oid, typmod, value in Datum format, and null flag are returned.
54925296
*
5493-
* At present this doesn't handle PLpgSQL_expror PLpgSQL_arrayelemdatums;
5494-
*that's not neededbecause we never pass references to such datums to SPI.
5297+
* At present this doesn't handle PLpgSQL_expr datums; that's not needed
5298+
* because we never pass references to such datums to SPI.
54955299
*
54965300
* NOTE: the returned Datum points right at the stored value in the case of
54975301
* pass-by-reference datatypes. Generally callers should take care not to

‎src/pl/plpgsql/src/pl_funcs.c

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -768,9 +768,6 @@ plpgsql_free_function_memory(PLpgSQL_function *func)
768768
break;
769769
casePLPGSQL_DTYPE_RECFIELD:
770770
break;
771-
casePLPGSQL_DTYPE_ARRAYELEM:
772-
free_expr(((PLpgSQL_arrayelem*)d)->subscript);
773-
break;
774771
default:
775772
elog(ERROR,"unrecognized data type: %d",d->dtype);
776773
}
@@ -1704,12 +1701,6 @@ plpgsql_dumptree(PLpgSQL_function *func)
17041701
((PLpgSQL_recfield*)d)->fieldname,
17051702
((PLpgSQL_recfield*)d)->recparentno);
17061703
break;
1707-
casePLPGSQL_DTYPE_ARRAYELEM:
1708-
printf("ARRAYELEM of VAR %d subscript ",
1709-
((PLpgSQL_arrayelem*)d)->arrayparentno);
1710-
dump_expr(((PLpgSQL_arrayelem*)d)->subscript);
1711-
printf("\n");
1712-
break;
17131704
default:
17141705
printf("??? unknown data type %d\n",d->dtype);
17151706
}

‎src/pl/plpgsql/src/pl_gram.y

Lines changed: 13 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -177,11 +177,10 @@ staticvoidcheck_raise_parameters(PLpgSQL_stmt_raise *stmt);
177177
%type<list>decl_cursor_arglist
178178
%type<nsitem>decl_aliasitem
179179

180-
%type<expr>expr_until_semiexpr_until_rightbracket
180+
%type<expr>expr_until_semi
181181
%type<expr>expr_until_thenexpr_until_loopopt_expr_until_when
182182
%type<expr>opt_exitcond
183183

184-
%type<datum>assign_var
185184
%type<var>cursor_variable
186185
%type<datum>decl_cursor_arg
187186
%type<forvariable>for_variable
@@ -1155,16 +1154,23 @@ getdiag_item :
11551154
}
11561155
;
11571156

1158-
getdiag_target:assign_var
1157+
getdiag_target:T_DATUM
11591158
{
1160-
if ($1->dtype == PLPGSQL_DTYPE_ROW ||
1161-
$1->dtype == PLPGSQL_DTYPE_REC)
1159+
/*
1160+
* In principle we should support a getdiag_target
1161+
* that is an array element, but for now we don't, so
1162+
* just throw an error if next token is '['.
1163+
*/
1164+
if ($1.datum->dtype == PLPGSQL_DTYPE_ROW ||
1165+
$1.datum->dtype == PLPGSQL_DTYPE_REC ||
1166+
plpgsql_peek() =='[')
11621167
ereport(ERROR,
11631168
(errcode(ERRCODE_SYNTAX_ERROR),
11641169
errmsg("\"%s\" is not a scalar variable",
1165-
((PLpgSQL_variable *)$1)->refname),
1170+
NameOfDatum(&($1))),
11661171
parser_errposition(@1)));
1167-
$$ = $1;
1172+
check_assignable($1.datum, @1);
1173+
$$ = $1.datum;
11681174
}
11691175
| T_WORD
11701176
{
@@ -1178,29 +1184,6 @@ getdiag_target: assign_var
11781184
}
11791185
;
11801186

1181-
1182-
assign_var: T_DATUM
1183-
{
1184-
check_assignable($1.datum, @1);
1185-
$$ = $1.datum;
1186-
}
1187-
| assign_var'[' expr_until_rightbracket
1188-
{
1189-
PLpgSQL_arrayelem*new;
1190-
1191-
new =palloc0(sizeof(PLpgSQL_arrayelem));
1192-
new->dtype= PLPGSQL_DTYPE_ARRAYELEM;
1193-
new->subscript= $3;
1194-
new->arrayparentno = $1->dno;
1195-
/* initialize cached type data to "not valid"*/
1196-
new->parenttypoid = InvalidOid;
1197-
1198-
plpgsql_adddatum((PLpgSQL_datum *)new);
1199-
1200-
$$ = (PLpgSQL_datum *)new;
1201-
}
1202-
;
1203-
12041187
stmt_if: K_IF expr_until_then proc_sect stmt_elsifs stmt_else K_END K_IF';'
12051188
{
12061189
PLpgSQL_stmt_if *new;
@@ -2471,10 +2454,6 @@ expr_until_semi :
24712454
{ $$ =read_sql_expression(';',";"); }
24722455
;
24732456

2474-
expr_until_rightbracket :
2475-
{ $$ =read_sql_expression(']',"]"); }
2476-
;
2477-
24782457
expr_until_then :
24792458
{ $$ =read_sql_expression(K_THEN,"THEN"); }
24802459
;
@@ -3493,11 +3472,6 @@ check_assignable(PLpgSQL_datum *datum, int location)
34933472
check_assignable(plpgsql_Datums[((PLpgSQL_recfield *) datum)->recparentno],
34943473
location);
34953474
break;
3496-
case PLPGSQL_DTYPE_ARRAYELEM:
3497-
/* assignable if parent array is*/
3498-
check_assignable(plpgsql_Datums[((PLpgSQL_arrayelem *) datum)->arrayparentno],
3499-
location);
3500-
break;
35013475
default:
35023476
elog(ERROR,"unrecognized dtype: %d",datum->dtype);
35033477
break;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp