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

Commit2178cbf

Browse files
committed
Modernize result-tuple construction in pltcl_trigger_handler().
Use Tcl_ListObjGetElements instead of Tcl_SplitList. Aside from beingpossibly more efficient in its own right, this means we are no longerresponsible for freeing a malloc'd result array, so we can get rid ofa PG_TRY/PG_CATCH block.Use heap_form_tuple instead of SPI_modifytuple. We don't need theextra generality of the latter, since we're always replacing allcolumns. Nor do we need its memory-context-munging, since at thispoint we're already out of the SPI environment.Per comparison of this code to tuple-building code submitted by Jim Nasby.I've abandoned the thought of merging the two cases into a single routine,but we may as well make the older code simpler and faster where we can.
1 parentfd2664d commit2178cbf

File tree

1 file changed

+73
-94
lines changed

1 file changed

+73
-94
lines changed

‎src/pl/tcl/pltcl.c

Lines changed: 73 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -870,12 +870,11 @@ pltcl_trigger_handler(PG_FUNCTION_ARGS, bool pltrusted)
870870
Tcl_Obj*tcl_newtup;
871871
inttcl_rc;
872872
inti;
873-
int*modattrs;
874-
Datum*modvalues;
875-
char*modnulls;
876-
intret_numvals;
877873
constchar*result;
878-
constchar**ret_values;
874+
intresult_Objc;
875+
Tcl_Obj**result_Objv;
876+
Datum*values;
877+
bool*nulls;
879878

880879
/* Connect to SPI manager */
881880
if (SPI_connect()!=SPI_OK_CONNECT)
@@ -1065,13 +1064,16 @@ pltcl_trigger_handler(PG_FUNCTION_ARGS, bool pltrusted)
10651064
throw_tcl_error(interp,prodesc->user_proname);
10661065

10671066
/************************************************************
1068-
* The return value from the procedure might be one of
1069-
* the magic strings OK or SKIP or a list from array get.
1070-
* We can check for OK or SKIP without worrying about encoding.
1067+
* Exit SPI environment.
10711068
************************************************************/
10721069
if (SPI_finish()!=SPI_OK_FINISH)
10731070
elog(ERROR,"SPI_finish() failed");
10741071

1072+
/************************************************************
1073+
* The return value from the procedure might be one of
1074+
* the magic strings OK or SKIP, or a list from array get.
1075+
* We can check for OK or SKIP without worrying about encoding.
1076+
************************************************************/
10751077
result=Tcl_GetStringResult(interp);
10761078

10771079
if (strcmp(result,"OK")==0)
@@ -1080,108 +1082,85 @@ pltcl_trigger_handler(PG_FUNCTION_ARGS, bool pltrusted)
10801082
return (HeapTuple)NULL;
10811083

10821084
/************************************************************
1083-
*Convert theresult valuefrom the Tcl interpreter
1084-
*and setup structures for SPI_modifytuple();
1085+
*Otherwise, thereturn valueshould be a column name/value list
1086+
*specifying the modified tuple to return.
10851087
************************************************************/
1086-
if (Tcl_SplitList(interp,result,
1087-
&ret_numvals,&ret_values)!=TCL_OK)
1088+
if (Tcl_ListObjGetElements(interp,Tcl_GetObjResult(interp),
1089+
&result_Objc,&result_Objv)!=TCL_OK)
10881090
ereport(ERROR,
10891091
(errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
10901092
errmsg("could not split return value from trigger: %s",
10911093
utf_u2e(Tcl_GetStringResult(interp)))));
10921094

1093-
/* Use a TRY to ensure ret_values will get freed */
1094-
PG_TRY();
1095-
{
1096-
if (ret_numvals %2!=0)
1097-
ereport(ERROR,
1098-
(errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
1099-
errmsg("trigger's return list must have even number of elements")));
1095+
if (result_Objc %2!=0)
1096+
ereport(ERROR,
1097+
(errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
1098+
errmsg("trigger's return list must have even number of elements")));
11001099

1101-
modattrs= (int*)palloc(tupdesc->natts*sizeof(int));
1102-
modvalues= (Datum*)palloc(tupdesc->natts*sizeof(Datum));
1103-
for (i=0;i<tupdesc->natts;i++)
1104-
{
1105-
modattrs[i]=i+1;
1106-
modvalues[i]= (Datum)NULL;
1107-
}
1100+
values= (Datum*)palloc0(tupdesc->natts*sizeof(Datum));
1101+
nulls= (bool*)palloc(tupdesc->natts*sizeof(bool));
1102+
memset(nulls, true,tupdesc->natts*sizeof(bool));
11081103

1109-
modnulls=palloc(tupdesc->natts);
1110-
memset(modnulls,'n',tupdesc->natts);
1104+
for (i=0;i<result_Objc;i+=2)
1105+
{
1106+
char*ret_name=utf_u2e(Tcl_GetString(result_Objv[i]));
1107+
char*ret_value=utf_u2e(Tcl_GetString(result_Objv[i+1]));
1108+
intattnum;
1109+
Oidtypinput;
1110+
Oidtypioparam;
1111+
FmgrInfofinfo;
11111112

1112-
for (i=0;i<ret_numvals;i+=2)
1113+
/************************************************************
1114+
* Get the attribute number
1115+
*
1116+
* We silently ignore ".tupno", if it's present but doesn't match
1117+
* any actual output column. This allows direct use of a row
1118+
* returned by pltcl_set_tuple_values().
1119+
************************************************************/
1120+
attnum=SPI_fnumber(tupdesc,ret_name);
1121+
if (attnum==SPI_ERROR_NOATTRIBUTE)
11131122
{
1114-
char*ret_name=utf_u2e(ret_values[i]);
1115-
char*ret_value=utf_u2e(ret_values[i+1]);
1116-
intattnum;
1117-
Oidtypinput;
1118-
Oidtypioparam;
1119-
FmgrInfofinfo;
1120-
1121-
/************************************************************
1122-
* Get the attribute number
1123-
*
1124-
* We silently ignore ".tupno", if it's present but doesn't match
1125-
* any actual output column. This allows direct use of a row
1126-
* returned by pltcl_set_tuple_values().
1127-
************************************************************/
1128-
attnum=SPI_fnumber(tupdesc,ret_name);
1129-
if (attnum==SPI_ERROR_NOATTRIBUTE)
1130-
{
1131-
if (strcmp(ret_name,".tupno")==0)
1132-
continue;
1133-
ereport(ERROR,
1134-
(errcode(ERRCODE_UNDEFINED_COLUMN),
1135-
errmsg("unrecognized attribute \"%s\"",
1136-
ret_name)));
1137-
}
1138-
if (attnum <=0)
1139-
ereport(ERROR,
1140-
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1141-
errmsg("cannot set system attribute \"%s\"",
1142-
ret_name)));
1143-
1144-
/************************************************************
1145-
* Ignore dropped columns
1146-
************************************************************/
1147-
if (tupdesc->attrs[attnum-1]->attisdropped)
1123+
if (strcmp(ret_name,".tupno")==0)
11481124
continue;
1149-
1150-
/************************************************************
1151-
* Lookup the attribute type in the syscache
1152-
* for the input function
1153-
************************************************************/
1154-
getTypeInputInfo(tupdesc->attrs[attnum-1]->atttypid,
1155-
&typinput,&typioparam);
1156-
fmgr_info(typinput,&finfo);
1157-
1158-
/************************************************************
1159-
* Set the attribute to NOT NULL and convert the contents
1160-
************************************************************/
1161-
modvalues[attnum-1]=InputFunctionCall(&finfo,
1162-
ret_value,
1163-
typioparam,
1164-
tupdesc->attrs[attnum-1]->atttypmod);
1165-
modnulls[attnum-1]=' ';
1125+
ereport(ERROR,
1126+
(errcode(ERRCODE_UNDEFINED_COLUMN),
1127+
errmsg("unrecognized attribute \"%s\"",
1128+
ret_name)));
11661129
}
1130+
if (attnum <=0)
1131+
ereport(ERROR,
1132+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1133+
errmsg("cannot set system attribute \"%s\"",
1134+
ret_name)));
11671135

1168-
rettup=SPI_modifytuple(trigdata->tg_relation,rettup,tupdesc->natts,
1169-
modattrs,modvalues,modnulls);
1136+
/************************************************************
1137+
* Ignore dropped columns
1138+
************************************************************/
1139+
if (tupdesc->attrs[attnum-1]->attisdropped)
1140+
continue;
11701141

1171-
pfree(modattrs);
1172-
pfree(modvalues);
1173-
pfree(modnulls);
1142+
/************************************************************
1143+
* Lookup the attribute type's input function
1144+
************************************************************/
1145+
getTypeInputInfo(tupdesc->attrs[attnum-1]->atttypid,
1146+
&typinput,&typioparam);
1147+
fmgr_info(typinput,&finfo);
11741148

1175-
if (rettup==NULL)
1176-
elog(ERROR,"SPI_modifytuple() failed - RC = %d",SPI_result);
1177-
}
1178-
PG_CATCH();
1179-
{
1180-
ckfree((char*)ret_values);
1181-
PG_RE_THROW();
1149+
/************************************************************
1150+
* Set the attribute to NOT NULL and convert the contents
1151+
************************************************************/
1152+
values[attnum-1]=InputFunctionCall(&finfo,
1153+
ret_value,
1154+
typioparam,
1155+
tupdesc->attrs[attnum-1]->atttypmod);
1156+
nulls[attnum-1]= false;
11821157
}
1183-
PG_END_TRY();
1184-
ckfree((char*)ret_values);
1158+
1159+
/* Build the modified tuple to return */
1160+
rettup=heap_form_tuple(tupdesc,values,nulls);
1161+
1162+
pfree(values);
1163+
pfree(nulls);
11851164

11861165
returnrettup;
11871166
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp