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

Commitde5fed0

Browse files
committed
Merge two copies of tuple-building code in pltcl.c.
Make pltcl_trigger_handler() construct modified tuples usingpltcl_build_tuple_result(), rather than its own copy of essentiallythe same logic. This results in slightly different message wording forthe error cases, and in one case a different SQLSTATE, but it seemsunlikely that any existing applications are depending on any of thosedetails.While at it, fix a typo in commit26abb50: pltcl_build_tuple_result wasapplying encoding conversion in the wrong direction. That would be aback-patchable bug fix, except the code hasn't shipped yet.Jim Nasby, reviewed by meDiscussion:https://postgr.es/m/d2c6425a-d9e0-f034-f774-4a872c234d89@BlueTreble.com
1 parentd74ecbc commitde5fed0

File tree

1 file changed

+39
-74
lines changed

1 file changed

+39
-74
lines changed

‎src/pl/tcl/pltcl.c

Lines changed: 39 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,9 @@ typedef struct pltcl_call_state
202202
/* Call info struct, or NULL in a trigger */
203203
FunctionCallInfofcinfo;
204204

205+
/* Trigger data, if we're in a normal (not event) trigger; else NULL */
206+
TriggerData*trigdata;
207+
205208
/* Function we're executing (NULL if not yet identified) */
206209
pltcl_proc_desc*prodesc;
207210

@@ -1000,8 +1003,8 @@ pltcl_trigger_handler(PG_FUNCTION_ARGS, pltcl_call_state *call_state,
10001003
constchar*result;
10011004
intresult_Objc;
10021005
Tcl_Obj**result_Objv;
1003-
Datum*values;
1004-
bool*nulls;
1006+
1007+
call_state->trigdata=trigdata;
10051008

10061009
/* Connect to SPI manager */
10071010
if (SPI_connect()!=SPI_OK_CONNECT)
@@ -1018,7 +1021,7 @@ pltcl_trigger_handler(PG_FUNCTION_ARGS, pltcl_call_state *call_state,
10181021

10191022
interp=prodesc->interp_desc->interp;
10201023

1021-
tupdesc=trigdata->tg_relation->rd_att;
1024+
tupdesc=RelationGetDescr(trigdata->tg_relation);
10221025

10231026
/************************************************************
10241027
* Create the tcl command to call the internal
@@ -1219,69 +1222,9 @@ pltcl_trigger_handler(PG_FUNCTION_ARGS, pltcl_call_state *call_state,
12191222
errmsg("could not split return value from trigger: %s",
12201223
utf_u2e(Tcl_GetStringResult(interp)))));
12211224

1222-
if (result_Objc %2!=0)
1223-
ereport(ERROR,
1224-
(errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
1225-
errmsg("trigger's return list must have even number of elements")));
1226-
1227-
values= (Datum*)palloc0(tupdesc->natts*sizeof(Datum));
1228-
nulls= (bool*)palloc(tupdesc->natts*sizeof(bool));
1229-
memset(nulls, true,tupdesc->natts*sizeof(bool));
1230-
1231-
for (i=0;i<result_Objc;i+=2)
1232-
{
1233-
char*ret_name=utf_u2e(Tcl_GetString(result_Objv[i]));
1234-
char*ret_value=utf_u2e(Tcl_GetString(result_Objv[i+1]));
1235-
intattnum;
1236-
Oidtypinput;
1237-
Oidtypioparam;
1238-
FmgrInfofinfo;
1239-
1240-
/************************************************************
1241-
* Get the attribute number
1242-
*
1243-
* We silently ignore ".tupno", if it's present but doesn't match
1244-
* any actual output column. This allows direct use of a row
1245-
* returned by pltcl_set_tuple_values().
1246-
************************************************************/
1247-
attnum=SPI_fnumber(tupdesc,ret_name);
1248-
if (attnum==SPI_ERROR_NOATTRIBUTE)
1249-
{
1250-
if (strcmp(ret_name,".tupno")==0)
1251-
continue;
1252-
ereport(ERROR,
1253-
(errcode(ERRCODE_UNDEFINED_COLUMN),
1254-
errmsg("unrecognized attribute \"%s\"",
1255-
ret_name)));
1256-
}
1257-
if (attnum <=0)
1258-
ereport(ERROR,
1259-
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1260-
errmsg("cannot set system attribute \"%s\"",
1261-
ret_name)));
1262-
1263-
/************************************************************
1264-
* Lookup the attribute type's input function
1265-
************************************************************/
1266-
getTypeInputInfo(tupdesc->attrs[attnum-1]->atttypid,
1267-
&typinput,&typioparam);
1268-
fmgr_info(typinput,&finfo);
1269-
1270-
/************************************************************
1271-
* Set the attribute to NOT NULL and convert the contents
1272-
************************************************************/
1273-
values[attnum-1]=InputFunctionCall(&finfo,
1274-
ret_value,
1275-
typioparam,
1276-
tupdesc->attrs[attnum-1]->atttypmod);
1277-
nulls[attnum-1]= false;
1278-
}
1279-
1280-
/* Build the modified tuple to return */
1281-
rettup=heap_form_tuple(tupdesc,values,nulls);
1282-
1283-
pfree(values);
1284-
pfree(nulls);
1225+
/* Convert function result to tuple */
1226+
rettup=pltcl_build_tuple_result(interp,result_Objv,result_Objc,
1227+
call_state);
12851228

12861229
returnrettup;
12871230
}
@@ -3014,6 +2957,8 @@ pltcl_build_tuple_argument(HeapTuple tuple, TupleDesc tupdesc)
30142957
* pltcl_build_tuple_result() - Build a tuple of function's result rowtype
30152958
* from a Tcl list of column names and values
30162959
*
2960+
* In a trigger function, we build a tuple of the trigger table's rowtype.
2961+
*
30172962
* Note: this function leaks memory. Even if we made it clean up its own
30182963
* mess, there's no way to prevent the datatype input functions it calls
30192964
* from leaking. Run it in a short-lived context, unless we're about to
@@ -3023,24 +2968,44 @@ static HeapTuple
30232968
pltcl_build_tuple_result(Tcl_Interp*interp,Tcl_Obj**kvObjv,intkvObjc,
30242969
pltcl_call_state*call_state)
30252970
{
2971+
TupleDesctupdesc;
2972+
AttInMetadata*attinmeta;
30262973
char**values;
30272974
inti;
30282975

2976+
if (call_state->ret_tupdesc)
2977+
{
2978+
tupdesc=call_state->ret_tupdesc;
2979+
attinmeta=call_state->attinmeta;
2980+
}
2981+
elseif (call_state->trigdata)
2982+
{
2983+
tupdesc=RelationGetDescr(call_state->trigdata->tg_relation);
2984+
attinmeta=TupleDescGetAttInMetadata(tupdesc);
2985+
}
2986+
else
2987+
{
2988+
elog(ERROR,"PL/Tcl function does not return a tuple");
2989+
tupdesc=NULL;/* keep compiler quiet */
2990+
attinmeta=NULL;
2991+
}
2992+
2993+
values= (char**)palloc0(tupdesc->natts*sizeof(char*));
2994+
30292995
if (kvObjc %2!=0)
30302996
ereport(ERROR,
30312997
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
30322998
errmsg("column name/value list must have even number of elements")));
30332999

3034-
values= (char**)palloc0(call_state->ret_tupdesc->natts*sizeof(char*));
3035-
30363000
for (i=0;i<kvObjc;i+=2)
30373001
{
3038-
char*fieldName=utf_e2u(Tcl_GetString(kvObjv[i]));
3039-
intattn=SPI_fnumber(call_state->ret_tupdesc,fieldName);
3002+
char*fieldName=utf_u2e(Tcl_GetString(kvObjv[i]));
3003+
intattn=SPI_fnumber(tupdesc,fieldName);
30403004

30413005
/*
3042-
* As in pltcl_trigger_handler, silently ignore ".tupno" if it's in
3043-
* the list but doesn't match any column name.
3006+
* We silently ignore ".tupno", if it's present but doesn't match any
3007+
* actual output column. This allows direct use of a row returned by
3008+
* pltcl_set_tuple_values().
30443009
*/
30453010
if (attn==SPI_ERROR_NOATTRIBUTE)
30463011
{
@@ -3058,10 +3023,10 @@ pltcl_build_tuple_result(Tcl_Interp *interp, Tcl_Obj **kvObjv, int kvObjc,
30583023
errmsg("cannot set system attribute \"%s\"",
30593024
fieldName)));
30603025

3061-
values[attn-1]=utf_e2u(Tcl_GetString(kvObjv[i+1]));
3026+
values[attn-1]=utf_u2e(Tcl_GetString(kvObjv[i+1]));
30623027
}
30633028

3064-
returnBuildTupleFromCStrings(call_state->attinmeta,values);
3029+
returnBuildTupleFromCStrings(attinmeta,values);
30653030
}
30663031

30673032
/**********************************************************************

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp