Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 4587547

Browse files
committed
Added: SPI_copytuple() & SPI_modifytuple()
1 parent a40a546 commit 4587547

File tree

2 files changed

+108
-7
lines changed

2 files changed

+108
-7
lines changed

src/backend/executor/spi.c

Lines changed: 103 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ static void _SPI_fetch(FetchStmt * stmt);
4848
#endif
4949
static 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

201201
int
202-
SPI_execp(void *plan, Datum *Values, char *Nulls, int tcount)
202+
SPI_execp(void *plan, Datum * Values, char *Nulls, int tcount)
203203
{
204204
int 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+
281378
int
282379
SPI_fnumber(TupleDesc tupdesc, char *fname)
283380
{
284381
int res;
285-
382+
286383
for (res = 0; res < tupdesc->natts; res++)
287384
{
288385
if (strcasecmp(tupdesc->attrs[res]->attname.data, fname) == 0)
@@ -333,7 +430,7 @@ SPI_getvalue(HeapTuple tuple, TupleDesc tupdesc, int fnumber)
333430
Datum
334431
SPI_getbinval(HeapTuple tuple, TupleDesc tupdesc, int fnumber, bool * isnull)
335432
{
336-
Datum val;
433+
Datum val;
337434

338435
*isnull = true;
339436
SPI_result = 0;
@@ -539,7 +636,7 @@ _SPI_execute(char *src, int tcount, _SPI_plan * plan)
539636
}
540637

541638
static 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
{
544641
QueryTreeList *queryTree_list = plan->qtlist;
545642
List *planTree_list = plan->ptlist;
@@ -591,7 +688,7 @@ _SPI_execute_plan(_SPI_plan * plan, Datum *Values, char *Nulls, int tcount)
591688
{
592689
paramLI->kind = PARAM_NUM;
593690
paramLI->id = k + 1;
594-
paramLI->isnull = (Nulls != NULL && Nulls[k] != 'n');
691+
paramLI->isnull = (Nulls && Nulls[k] == 'n');
595692
paramLI->value = Values[k];
596693
}
597694
paramLI->kind = PARAM_INVALID;

src/include/executor/spi.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,10 +73,14 @@ extern int SPI_result;
7373
extern int SPI_connect(void);
7474
extern int SPI_finish(void);
7575
extern int SPI_exec(char *src, int tcount);
76-
extern int SPI_execp(void *plan, Datum *values, char *Nulls, int tcount);
76+
extern int SPI_execp(void *plan, Datum * values, char *Nulls, int tcount);
7777
extern void *SPI_prepare(char *src, int nargs, Oid * argtypes);
7878
extern void *SPI_saveplan(void *plan);
7979

80+
extern HeapTuple SPI_copytuple(HeapTuple tuple);
81+
extern HeapTuple
82+
SPI_modifytuple(Relation rel, HeapTuple tuple, int natts,
83+
int *attnum, Datum * Values, char *Nulls);
8084
extern int SPI_fnumber(TupleDesc tupdesc, char *fname);
8185
extern char *SPI_fname(TupleDesc tupdesc, int fnumber);
8286
extern char *SPI_getvalue(HeapTuple tuple, TupleDesc tupdesc, int fnumber);

0 commit comments

Comments
 (0)