3
3
* procedural language
4
4
*
5
5
* IDENTIFICATION
6
- * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.76 2002/12/17 15:45:01 tgl Exp $
6
+ * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.77 2003/01/21 22:06:12 tgl Exp $
7
7
*
8
8
* This software is copyrighted by Jan Wieck - Hamburg.
9
9
*
@@ -1356,15 +1356,15 @@ exec_stmt_fors(PLpgSQL_execstate * estate, PLpgSQL_stmt_fors * stmt)
1356
1356
exec_run_select (estate , stmt -> query , 0 , & portal );
1357
1357
1358
1358
SPI_cursor_fetch (portal , true, 10 );
1359
- n = SPI_processed ;
1360
1359
tuptab = SPI_tuptable ;
1360
+ n = SPI_processed ;
1361
1361
1362
1362
/*
1363
1363
* If the query didn't return any rows, set the target to NULL and
1364
1364
* return with FOUND = false.
1365
1365
*/
1366
1366
if (n == 0 )
1367
- exec_move_row (estate , rec , row , NULL , NULL );
1367
+ exec_move_row (estate , rec , row , NULL , tuptab -> tupdesc );
1368
1368
else
1369
1369
found = true; /* processed at least one tuple */
1370
1370
@@ -1478,6 +1478,7 @@ exec_stmt_select(PLpgSQL_execstate * estate, PLpgSQL_stmt_select * stmt)
1478
1478
* Run the query
1479
1479
*/
1480
1480
exec_run_select (estate , stmt -> query , 1 , NULL );
1481
+ tuptab = estate -> eval_tuptable ;
1481
1482
n = estate -> eval_processed ;
1482
1483
1483
1484
/*
@@ -1486,15 +1487,14 @@ exec_stmt_select(PLpgSQL_execstate * estate, PLpgSQL_stmt_select * stmt)
1486
1487
*/
1487
1488
if (n == 0 )
1488
1489
{
1489
- exec_move_row (estate , rec , row , NULL , NULL );
1490
+ exec_move_row (estate , rec , row , NULL , tuptab -> tupdesc );
1490
1491
exec_eval_cleanup (estate );
1491
1492
return PLPGSQL_RC_OK ;
1492
1493
}
1493
1494
1494
1495
/*
1495
1496
* Put the result into the target and set found to true
1496
1497
*/
1497
- tuptab = estate -> eval_tuptable ;
1498
1498
exec_move_row (estate , rec , row , tuptab -> vals [0 ], tuptab -> tupdesc );
1499
1499
exec_set_found (estate , true);
1500
1500
@@ -1627,6 +1627,8 @@ exec_stmt_return_next(PLpgSQL_execstate * estate,
1627
1627
{
1628
1628
PLpgSQL_rec * rec = (PLpgSQL_rec * ) (estate -> datums [stmt -> rec -> recno ]);
1629
1629
1630
+ if (!HeapTupleIsValid (rec -> tup ))
1631
+ elog (ERROR , "record \"%s\" is unassigned yet" , rec -> refname );
1630
1632
if (!compatible_tupdesc (tupdesc , rec -> tupdesc ))
1631
1633
elog (ERROR , "Wrong record type supplied in RETURN NEXT" );
1632
1634
tuple = rec -> tup ;
@@ -2369,15 +2371,15 @@ exec_stmt_dynfors(PLpgSQL_execstate * estate, PLpgSQL_stmt_dynfors * stmt)
2369
2371
* Fetch the initial 10 tuples
2370
2372
*/
2371
2373
SPI_cursor_fetch (portal , true, 10 );
2372
- n = SPI_processed ;
2373
2374
tuptab = SPI_tuptable ;
2375
+ n = SPI_processed ;
2374
2376
2375
2377
/*
2376
2378
* If the query didn't return any rows, set the target to NULL and
2377
2379
* return with FOUND = false.
2378
2380
*/
2379
2381
if (n == 0 )
2380
- exec_move_row (estate , rec , row , NULL , NULL );
2382
+ exec_move_row (estate , rec , row , NULL , tuptab -> tupdesc );
2381
2383
else
2382
2384
found = true;
2383
2385
@@ -2776,8 +2778,8 @@ exec_stmt_fetch(PLpgSQL_execstate * estate, PLpgSQL_stmt_fetch * stmt)
2776
2778
* ----------
2777
2779
*/
2778
2780
SPI_cursor_fetch (portal , true, 1 );
2779
- n = SPI_processed ;
2780
2781
tuptab = SPI_tuptable ;
2782
+ n = SPI_processed ;
2781
2783
2782
2784
/* ----------
2783
2785
* If the FETCH didn't return a row, set the target
@@ -2786,7 +2788,7 @@ exec_stmt_fetch(PLpgSQL_execstate * estate, PLpgSQL_stmt_fetch * stmt)
2786
2788
*/
2787
2789
if (n == 0 )
2788
2790
{
2789
- exec_move_row (estate , rec , row , NULL , NULL );
2791
+ exec_move_row (estate , rec , row , NULL , tuptab -> tupdesc );
2790
2792
return PLPGSQL_RC_OK ;
2791
2793
}
2792
2794
@@ -3353,8 +3355,8 @@ exec_move_row(PLpgSQL_execstate * estate,
3353
3355
HeapTuple tup , TupleDesc tupdesc )
3354
3356
{
3355
3357
/*
3356
- * Record is simple - just put the tuple and its descriptor into the
3357
- * record
3358
+ * Record is simple - just copy the tuple and its descriptor into the
3359
+ * record variable
3358
3360
*/
3359
3361
if (rec != NULL )
3360
3362
{
@@ -3372,13 +3374,34 @@ exec_move_row(PLpgSQL_execstate * estate,
3372
3374
if (HeapTupleIsValid (tup ))
3373
3375
{
3374
3376
rec -> tup = heap_copytuple (tup );
3375
- rec -> tupdesc = CreateTupleDescCopy (tupdesc );
3376
3377
rec -> freetup = true;
3377
- rec -> freetupdesc = true;
3378
+ }
3379
+ else if (tupdesc )
3380
+ {
3381
+ /* If we have a tupdesc but no data, form an all-nulls tuple */
3382
+ char * nulls ;
3383
+
3384
+ /* +1 to avoid possible palloc(0) if no attributes */
3385
+ nulls = (char * ) palloc (tupdesc -> natts * sizeof (char ) + 1 );
3386
+ memset (nulls , 'n' , tupdesc -> natts * sizeof (char ));
3387
+
3388
+ rec -> tup = heap_formtuple (tupdesc , NULL , nulls );
3389
+ rec -> freetup = true;
3390
+
3391
+ pfree (nulls );
3378
3392
}
3379
3393
else
3380
3394
{
3381
3395
rec -> tup = NULL ;
3396
+ }
3397
+
3398
+ if (tupdesc )
3399
+ {
3400
+ rec -> tupdesc = CreateTupleDescCopy (tupdesc );
3401
+ rec -> freetupdesc = true;
3402
+ }
3403
+ else
3404
+ {
3382
3405
rec -> tupdesc = NULL ;
3383
3406
}
3384
3407
@@ -3395,6 +3418,9 @@ exec_move_row(PLpgSQL_execstate * estate,
3395
3418
* table, or it might have fewer if the table has had columns added by
3396
3419
* ALTER TABLE. Ignore extra columns and assume NULL for missing
3397
3420
* columns, the same as heap_getattr would do.
3421
+ *
3422
+ * If we have no tuple data at all, we'll assign NULL to all columns
3423
+ * of the row variable.
3398
3424
*/
3399
3425
if (row != NULL )
3400
3426
{
0 commit comments