@@ -896,31 +896,30 @@ static HeapTuple
896896PLy_modify_tuple (PLyProcedure * proc , PyObject * pltd , TriggerData * tdata ,
897897 HeapTuple otup )
898898{
899+ HeapTuple rtup ;
899900 PyObject * volatile plntup ;
900901 PyObject * volatile plkeys ;
901902 PyObject * volatile plval ;
902- HeapTuple rtup ;
903- int natts ,
904- i ,
905- attn ,
906- atti ;
907- int * volatile modattrs ;
908903 Datum * volatile modvalues ;
909- char * volatile modnulls ;
910- TupleDesc tupdesc ;
904+ bool * volatile modnulls ;
905+ bool * volatile modrepls ;
911906 ErrorContextCallback plerrcontext ;
912907
913908 plerrcontext .callback = plpython_trigger_error_callback ;
914909 plerrcontext .previous = error_context_stack ;
915910 error_context_stack = & plerrcontext ;
916911
917912 plntup = plkeys = plval = NULL ;
918- modattrs = NULL ;
919913 modvalues = NULL ;
920914 modnulls = NULL ;
915+ modrepls = NULL ;
921916
922917 PG_TRY ();
923918 {
919+ TupleDesc tupdesc ;
920+ int nkeys ,
921+ i ;
922+
924923 if ((plntup = PyDict_GetItemString (pltd , "new" )) == NULL )
925924 ereport (ERROR ,
926925 (errcode (ERRCODE_UNDEFINED_OBJECT ),
@@ -932,18 +931,20 @@ PLy_modify_tuple(PLyProcedure *proc, PyObject *pltd, TriggerData *tdata,
932931 errmsg ("TD[\"new\"] is not a dictionary" )));
933932
934933 plkeys = PyDict_Keys (plntup );
935- natts = PyList_Size (plkeys );
936-
937- modattrs = (int * ) palloc (natts * sizeof (int ));
938- modvalues = (Datum * ) palloc (natts * sizeof (Datum ));
939- modnulls = (char * ) palloc (natts * sizeof (char ));
934+ nkeys = PyList_Size (plkeys );
940935
941936 tupdesc = tdata -> tg_relation -> rd_att ;
942937
943- for (i = 0 ; i < natts ; i ++ )
938+ modvalues = (Datum * ) palloc0 (tupdesc -> natts * sizeof (Datum ));
939+ modnulls = (bool * ) palloc0 (tupdesc -> natts * sizeof (bool ));
940+ modrepls = (bool * ) palloc0 (tupdesc -> natts * sizeof (bool ));
941+
942+ for (i = 0 ; i < nkeys ; i ++ )
944943 {
945944 PyObject * platt ;
946945 char * plattstr ;
946+ int attn ;
947+ PLyObToDatum * att ;
947948
948949 platt = PyList_GetItem (plkeys , i );
949950 if (PyString_Check (platt ))
@@ -963,62 +964,57 @@ PLy_modify_tuple(PLyProcedure *proc, PyObject *pltd, TriggerData *tdata,
963964 (errcode (ERRCODE_UNDEFINED_COLUMN ),
964965 errmsg ("key \"%s\" found in TD[\"new\"] does not exist as a column in the triggering row" ,
965966 plattstr )));
966- atti = attn - 1 ;
967+ if (attn <= 0 )
968+ ereport (ERROR ,
969+ (errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
970+ errmsg ("cannot set system attribute \"%s\"" ,
971+ plattstr )));
972+ att = & proc -> result .out .r .atts [attn - 1 ];
967973
968974 plval = PyDict_GetItem (plntup , platt );
969975 if (plval == NULL )
970976 elog (FATAL , "Python interpreter is probably corrupted" );
971977
972978 Py_INCREF (plval );
973979
974- modattrs [i ] = attn ;
975-
976- if (tupdesc -> attrs [atti ]-> attisdropped )
977- {
978- modvalues [i ] = (Datum ) 0 ;
979- modnulls [i ] = 'n' ;
980- }
981- else if (plval != Py_None )
980+ if (plval != Py_None )
982981 {
983- PLyObToDatum * att = & proc -> result .out .r .atts [atti ];
984-
985- modvalues [i ] = (att -> func ) (att ,
986- tupdesc -> attrs [atti ]-> atttypmod ,
987- plval ,
988- false);
989- modnulls [i ] = ' ' ;
982+ modvalues [attn - 1 ] =
983+ (att -> func ) (att ,
984+ tupdesc -> attrs [attn - 1 ]-> atttypmod ,
985+ plval ,
986+ false);
987+ modnulls [attn - 1 ] = false;
990988 }
991989 else
992990 {
993- modvalues [i ] =
994- InputFunctionCall (& proc -> result . out . r . atts [ atti ]. typfunc ,
991+ modvalues [attn - 1 ] =
992+ InputFunctionCall (& att -> typfunc ,
995993 NULL ,
996- proc -> result . out . r . atts [ atti ]. typioparam ,
997- tupdesc -> attrs [atti ]-> atttypmod );
998- modnulls [i ] = 'n' ;
994+ att -> typioparam ,
995+ tupdesc -> attrs [attn - 1 ]-> atttypmod );
996+ modnulls [attn - 1 ] = true ;
999997 }
998+ modrepls [attn - 1 ] = true;
1000999
10011000 Py_DECREF (plval );
10021001 plval = NULL ;
10031002 }
10041003
1005- rtup = SPI_modifytuple (tdata -> tg_relation , otup , natts ,
1006- modattrs , modvalues , modnulls );
1007- if (rtup == NULL )
1008- elog (ERROR , "SPI_modifytuple failed: error %d" , SPI_result );
1004+ rtup = heap_modify_tuple (otup , tupdesc , modvalues , modnulls , modrepls );
10091005 }
10101006 PG_CATCH ();
10111007 {
10121008 Py_XDECREF (plntup );
10131009 Py_XDECREF (plkeys );
10141010 Py_XDECREF (plval );
10151011
1016- if (modnulls )
1017- pfree (modnulls );
10181012 if (modvalues )
10191013 pfree (modvalues );
1020- if (modattrs )
1021- pfree (modattrs );
1014+ if (modnulls )
1015+ pfree (modnulls );
1016+ if (modrepls )
1017+ pfree (modrepls );
10221018
10231019 PG_RE_THROW ();
10241020 }
@@ -1027,9 +1023,9 @@ PLy_modify_tuple(PLyProcedure *proc, PyObject *pltd, TriggerData *tdata,
10271023 Py_DECREF (plntup );
10281024 Py_DECREF (plkeys );
10291025
1030- pfree (modattrs );
10311026 pfree (modvalues );
10321027 pfree (modnulls );
1028+ pfree (modrepls );
10331029
10341030 error_context_stack = plerrcontext .previous ;
10351031
0 commit comments