@@ -48,7 +48,7 @@ static void _SPI_fetch(FetchStmt * stmt);
4848#endif
4949static int
5050_SPI_execute_plan (_SPI_plan * plan ,
51- Datum * Values ,char * Nulls ,int tcount );
51+ Datum * Values ,char * Nulls ,int tcount );
5252
5353#define _SPI_CPLAN_CURCXT 0
5454#define _SPI_CPLAN_PROCXT 1
@@ -199,7 +199,7 @@ SPI_exec(char *src, int tcount)
199199}
200200
201201int
202- SPI_execp (void * plan ,Datum * Values ,char * Nulls ,int tcount )
202+ SPI_execp (void * plan ,Datum * Values ,char * Nulls ,int tcount )
203203{
204204int res ;
205205
@@ -278,11 +278,108 @@ SPI_saveplan(void *plan)
278278
279279}
280280
281+ HeapTuple
282+ SPI_copytuple (HeapTuple tuple )
283+ {
284+ MemoryContext oldcxt = NULL ;
285+ HeapTuple ctuple ;
286+
287+ if (tuple == NULL )
288+ {
289+ SPI_result = SPI_ERROR_ARGUMENT ;
290+ return (NULL );
291+ }
292+
293+ if (_SPI_curid + 1 == _SPI_connected )/* connected */
294+ {
295+ if (_SPI_current != & (_SPI_stack [_SPI_curid + 1 ]))
296+ elog (FATAL ,"SPI: stack corrupted" );
297+ oldcxt = MemoryContextSwitchTo (_SPI_current -> savedcxt );
298+ }
299+
300+ ctuple = heap_copytuple (tuple );
301+
302+ if (oldcxt )
303+ MemoryContextSwitchTo (oldcxt );
304+
305+ return (ctuple );
306+ }
307+
308+ HeapTuple
309+ SPI_modifytuple (Relation rel ,HeapTuple tuple ,int natts ,int * attnum ,
310+ Datum * Values ,char * Nulls )
311+ {
312+ MemoryContext oldcxt = NULL ;
313+ HeapTuple mtuple ;
314+ int numberOfAttributes ;
315+ uint8 infomask ;
316+ Datum * v ;
317+ char * n ;
318+ bool isnull ;
319+ int i ;
320+
321+ if (rel == NULL || tuple == NULL || natts <=0 || attnum == NULL || Values == NULL )
322+ {
323+ SPI_result = SPI_ERROR_ARGUMENT ;
324+ return (NULL );
325+ }
326+
327+ if (_SPI_curid + 1 == _SPI_connected )/* connected */
328+ {
329+ if (_SPI_current != & (_SPI_stack [_SPI_curid + 1 ]))
330+ elog (FATAL ,"SPI: stack corrupted" );
331+ oldcxt = MemoryContextSwitchTo (_SPI_current -> savedcxt );
332+ }
333+ SPI_result = 0 ;
334+ numberOfAttributes = rel -> rd_att -> natts ;
335+ v = (Datum * )palloc (numberOfAttributes * sizeof (Datum ));
336+ n = (char * )palloc (numberOfAttributes * sizeof (char ));
337+
338+ /* fetch old values and nulls */
339+ for (i = 0 ;i < numberOfAttributes ;i ++ )
340+ {
341+ v [i ]= heap_getattr (tuple ,InvalidBuffer ,i + 1 ,rel -> rd_att ,& isnull );
342+ n [i ]= (isnull ) ?'n' :' ' ;
343+ }
344+
345+ /* replace values and nulls */
346+ for (i = 0 ;i < natts ;i ++ )
347+ {
348+ if (attnum [i ] <=0 || attnum [i ]> numberOfAttributes )
349+ break ;
350+ v [attnum [i ]- 1 ]= Values [i ];
351+ n [attnum [i ]- 1 ]= (Nulls && Nulls [i ]== 'n' ) ?'n' :' ' ;
352+ }
353+
354+ if (i == natts )/* no errors in attnum[] */
355+ {
356+ mtuple = heap_formtuple (rel -> rd_att ,v ,n );
357+ infomask = mtuple -> t_infomask ;
358+ memmove (& (mtuple -> t_ctid ),& (tuple -> t_ctid ),
359+ ((char * )& (tuple -> t_hoff )- (char * )& (tuple -> t_ctid )));
360+ mtuple -> t_infomask = infomask ;
361+ mtuple -> t_natts = numberOfAttributes ;
362+ }
363+ else
364+ {
365+ mtuple = NULL ;
366+ SPI_result = SPI_ERROR_NOATTRIBUTE ;
367+ }
368+
369+ pfree (v );
370+ pfree (n );
371+
372+ if (oldcxt )
373+ MemoryContextSwitchTo (oldcxt );
374+
375+ return (mtuple );
376+ }
377+
281378int
282379SPI_fnumber (TupleDesc tupdesc ,char * fname )
283380{
284381int res ;
285-
382+
286383for (res = 0 ;res < tupdesc -> natts ;res ++ )
287384{
288385if (strcasecmp (tupdesc -> attrs [res ]-> attname .data ,fname )== 0 )
@@ -333,7 +430,7 @@ SPI_getvalue(HeapTuple tuple, TupleDesc tupdesc, int fnumber)
333430Datum
334431SPI_getbinval (HeapTuple tuple ,TupleDesc tupdesc ,int fnumber ,bool * isnull )
335432{
336- Datum val ;
433+ Datum val ;
337434
338435* isnull = true;
339436SPI_result = 0 ;
@@ -539,7 +636,7 @@ _SPI_execute(char *src, int tcount, _SPI_plan * plan)
539636}
540637
541638static int
542- _SPI_execute_plan (_SPI_plan * plan ,Datum * Values ,char * Nulls ,int tcount )
639+ _SPI_execute_plan (_SPI_plan * plan ,Datum * Values ,char * Nulls ,int tcount )
543640{
544641QueryTreeList * queryTree_list = plan -> qtlist ;
545642List * planTree_list = plan -> ptlist ;
@@ -591,7 +688,7 @@ _SPI_execute_plan(_SPI_plan * plan, Datum *Values, char *Nulls, int tcount)
591688{
592689paramLI -> kind = PARAM_NUM ;
593690paramLI -> id = k + 1 ;
594- paramLI -> isnull = (Nulls != NULL && Nulls [k ]! ='n' );
691+ paramLI -> isnull = (Nulls && Nulls [k ]= ='n' );
595692paramLI -> value = Values [k ];
596693}
597694paramLI -> kind = PARAM_INVALID ;