33
33
* ENHANCEMENTS, OR MODIFICATIONS.
34
34
*
35
35
* IDENTIFICATION
36
- * $PostgreSQL: pgsql/src/pl/plperl/plperl.c,v 1.54 2004/10/07 19:01:09 momjian Exp $
36
+ * $PostgreSQL: pgsql/src/pl/plperl/plperl.c,v 1.55 2004/10/15 17:08:26 momjian Exp $
37
37
*
38
38
**********************************************************************/
39
39
@@ -276,33 +276,30 @@ plperl_safe_init(void)
276
276
plperl_safe_init_done = true;
277
277
}
278
278
279
- /**********************************************************************
280
- * turn a tuple into a hash expression and add it to a list
281
- **********************************************************************/
282
- static void
283
- plperl_sv_add_tuple_value (SV * rv , HeapTuple tuple , TupleDesc tupdesc )
284
- {
285
- int i ;
286
- char * value ;
287
- char * key ;
288
-
289
- sv_catpvf (rv , "{ " );
290
279
280
+ static HV *
281
+ plperl_hash_from_tuple (HeapTuple tuple , TupleDesc tupdesc )
282
+ {
283
+ int i ;
284
+ HV * hv = newHV ();
291
285
for (i = 0 ; i < tupdesc -> natts ; i ++ )
292
286
{
293
- key = SPI_fname (tupdesc , i + 1 );
294
- value = SPI_getvalue (tuple , tupdesc , i + 1 );
295
- if (value )
296
- sv_catpvf (rv , "%s => '%s'" , key , value );
287
+ SV * value ;
288
+
289
+ char * key = SPI_fname (tupdesc , i + 1 );
290
+ char * val = SPI_getvalue (tuple , tupdesc , i + 1 );
291
+
292
+ if (val )
293
+ value = newSVpv (val , 0 );
297
294
else
298
- sv_catpvf (rv , "%s => undef" , key );
299
- if (i != tupdesc -> natts - 1 )
300
- sv_catpvf (rv , ", " );
301
- }
295
+ value = newSV (0 );
302
296
303
- sv_catpvf (rv , " }" );
297
+ hv_store (hv , key , strlen (key ), value , 0 );
298
+ }
299
+ return hv ;
304
300
}
305
301
302
+
306
303
/**********************************************************************
307
304
* set up arguments for a trigger call
308
305
**********************************************************************/
@@ -312,76 +309,89 @@ plperl_trigger_build_args(FunctionCallInfo fcinfo)
312
309
TriggerData * tdata ;
313
310
TupleDesc tupdesc ;
314
311
int i = 0 ;
315
- SV * rv ;
312
+ char * level ;
313
+ char * event ;
314
+ char * relid ;
315
+ char * when ;
316
+ HV * hv ;
316
317
317
- rv = newSVpv ( "{ " , 0 );
318
+ hv = newHV ( );
318
319
319
320
tdata = (TriggerData * ) fcinfo -> context ;
320
-
321
321
tupdesc = tdata -> tg_relation -> rd_att ;
322
322
323
- sv_catpvf (rv , "name => '%s'" , tdata -> tg_trigger -> tgname );
324
- sv_catpvf (rv , ", relid => '%s'" , DatumGetCString (DirectFunctionCall1 (oidout , ObjectIdGetDatum (tdata -> tg_relation -> rd_id ))));
323
+ relid = DatumGetCString (
324
+ DirectFunctionCall1 (
325
+ oidout , ObjectIdGetDatum (tdata -> tg_relation -> rd_id )
326
+ )
327
+ );
328
+
329
+ hv_store (hv , "name" , 4 , newSVpv (tdata -> tg_trigger -> tgname , 0 ), 0 );
330
+ hv_store (hv , "relid" , 5 , newSVpv (relid , 0 ), 0 );
325
331
326
332
if (TRIGGER_FIRED_BY_INSERT (tdata -> tg_event ))
327
333
{
328
- sv_catpvf (rv , ", event => 'INSERT'" );
329
- sv_catpvf (rv , ", new =>" );
330
- plperl_sv_add_tuple_value (rv , tdata -> tg_trigtuple , tupdesc );
334
+ event = "INSERT" ;
335
+ hv_store (hv , "new" , 3 ,
336
+ newRV ((SV * )plperl_hash_from_tuple (tdata -> tg_trigtuple ,
337
+ tupdesc )),
338
+ 0 );
331
339
}
332
340
else if (TRIGGER_FIRED_BY_DELETE (tdata -> tg_event ))
333
341
{
334
- sv_catpvf (rv , ", event => 'DELETE'" );
335
- sv_catpvf (rv , ", old => " );
336
- plperl_sv_add_tuple_value (rv , tdata -> tg_trigtuple , tupdesc );
342
+ event = "DELETE" ;
343
+ hv_store (hv , "old" , 3 ,
344
+ newRV ((SV * )plperl_hash_from_tuple (tdata -> tg_trigtuple ,
345
+ tupdesc )),
346
+ 0 );
337
347
}
338
348
else if (TRIGGER_FIRED_BY_UPDATE (tdata -> tg_event ))
339
349
{
340
- sv_catpvf (rv , ", event => 'UPDATE'" );
341
-
342
- sv_catpvf (rv , ", new =>" );
343
- plperl_sv_add_tuple_value (rv , tdata -> tg_newtuple , tupdesc );
344
-
345
- sv_catpvf (rv , ", old => " );
346
- plperl_sv_add_tuple_value (rv , tdata -> tg_trigtuple , tupdesc );
350
+ event = "UPDATE" ;
351
+ hv_store (hv , "old" , 3 ,
352
+ newRV ((SV * )plperl_hash_from_tuple (tdata -> tg_trigtuple ,
353
+ tupdesc )),
354
+ 0 );
355
+ hv_store (hv , "new" , 3 ,
356
+ newRV ((SV * )plperl_hash_from_tuple (tdata -> tg_newtuple ,
357
+ tupdesc )),
358
+ 0 );
359
+ }
360
+ else {
361
+ event = "UNKNOWN" ;
347
362
}
348
- else
349
- sv_catpvf (rv , ", event => 'UNKNOWN'" );
350
363
351
- sv_catpvf (rv , ", argc => %d" , tdata -> tg_trigger -> tgnargs );
364
+ hv_store (hv , "event" , 5 , newSVpv (event , 0 ), 0 );
365
+ hv_store (hv , "argc" , 4 , newSViv (tdata -> tg_trigger -> tgnargs ), 0 );
352
366
353
367
if (tdata -> tg_trigger -> tgnargs != 0 )
354
368
{
355
- sv_catpvf (rv , ", args => [ " );
356
- for (i = 0 ; i < tdata -> tg_trigger -> tgnargs ; i ++ )
357
- {
358
- sv_catpvf (rv , "%s" , tdata -> tg_trigger -> tgargs [i ]);
359
- if (i != tdata -> tg_trigger -> tgnargs - 1 )
360
- sv_catpvf (rv , ", " );
361
- }
362
- sv_catpvf (rv , " ]" );
369
+ AV * av = newAV ();
370
+ for (i = 0 ; i < tdata -> tg_trigger -> tgnargs ; i ++ )
371
+ av_push (av , newSVpv (tdata -> tg_trigger -> tgargs [i ], 0 ));
372
+ hv_store (hv , "args" , 4 , newRV ((SV * )av ), 0 );
363
373
}
364
- sv_catpvf (rv , ", relname => '%s'" , SPI_getrelname (tdata -> tg_relation ));
374
+
375
+ hv_store (hv , "relname" , 7 ,
376
+ newSVpv (SPI_getrelname (tdata -> tg_relation ), 0 ), 0 );
365
377
366
378
if (TRIGGER_FIRED_BEFORE (tdata -> tg_event ))
367
- sv_catpvf ( rv , ", when => ' BEFORE'" ) ;
379
+ when = " BEFORE" ;
368
380
else if (TRIGGER_FIRED_AFTER (tdata -> tg_event ))
369
- sv_catpvf ( rv , ", when => ' AFTER'" ) ;
381
+ when = " AFTER" ;
370
382
else
371
- sv_catpvf (rv , ", when => 'UNKNOWN'" );
383
+ when = "UNKNOWN" ;
384
+ hv_store (hv , "when" , 4 , newSVpv (when , 0 ), 0 );
372
385
373
386
if (TRIGGER_FIRED_FOR_ROW (tdata -> tg_event ))
374
- sv_catpvf ( rv , ", level => ' ROW'" ) ;
387
+ level = " ROW" ;
375
388
else if (TRIGGER_FIRED_FOR_STATEMENT (tdata -> tg_event ))
376
- sv_catpvf ( rv , ", level => ' STATEMENT'" ) ;
389
+ level = " STATEMENT" ;
377
390
else
378
- sv_catpvf (rv , ", level => 'UNKNOWN'" );
391
+ level = "UNKNOWN" ;
392
+ hv_store (hv , "level" , 5 , newSVpv (level , 0 ), 0 );
379
393
380
- sv_catpvf (rv , " }" );
381
-
382
- rv = perl_eval_pv (SvPV (rv , PL_na ), TRUE);
383
-
384
- return rv ;
394
+ return newRV ((SV * )hv );
385
395
}
386
396
387
397
@@ -440,21 +450,17 @@ static AV *
440
450
plperl_get_keys (HV * hv )
441
451
{
442
452
AV * ret ;
443
- int key_count ;
444
453
SV * val ;
445
454
char * key ;
446
455
I32 klen ;
447
456
448
- key_count = 0 ;
449
457
ret = newAV ();
450
458
451
459
hv_iterinit (hv );
452
460
while ((val = hv_iternextsv (hv , (char * * ) & key , & klen )))
453
- {
454
- av_store (ret , key_count , eval_pv (key , TRUE));
455
- key_count ++ ;
456
- }
461
+ av_push (ret , newSVpv (key , 0 ));
457
462
hv_iterinit (hv );
463
+
458
464
return ret ;
459
465
}
460
466
@@ -484,11 +490,8 @@ plperl_get_key(AV *keys, int index)
484
490
static char *
485
491
plperl_get_elem (HV * hash , char * key )
486
492
{
487
- SV * * svp ;
488
-
489
- if (hv_exists_ent (hash , eval_pv (key , TRUE), FALSE))
490
- svp = hv_fetch (hash , key , strlen (key ), FALSE);
491
- else
493
+ SV * * svp = hv_fetch (hash , key , strlen (key ), FALSE);
494
+ if (!svp )
492
495
{
493
496
elog (ERROR , "plperl: key '%s' not found" , key );
494
497
return NULL ;
@@ -998,7 +1001,8 @@ plperl_func_handler(PG_FUNCTION_ARGS)
998
1001
g_attr_num = tupdesc -> natts ;
999
1002
1000
1003
for (i = 0 ; i < tupdesc -> natts ; i ++ )
1001
- av_store (g_column_keys , i + 1 , eval_pv (SPI_fname (tupdesc , i + 1 ), TRUE));
1004
+ av_store (g_column_keys , i + 1 ,
1005
+ newSVpv (SPI_fname (tupdesc , i + 1 ), 0 ));
1002
1006
1003
1007
slot = TupleDescGetSlot (tupdesc );
1004
1008
funcctx -> slot = slot ;
@@ -1269,6 +1273,7 @@ compile_plperl_function(Oid fn_oid, bool is_trigger)
1269
1273
int proname_len ;
1270
1274
plperl_proc_desc * prodesc = NULL ;
1271
1275
int i ;
1276
+ SV * * svp ;
1272
1277
1273
1278
/* We'll need the pg_proc tuple in any case... */
1274
1279
procTup = SearchSysCache (PROCOID ,
@@ -1291,12 +1296,12 @@ compile_plperl_function(Oid fn_oid, bool is_trigger)
1291
1296
/************************************************************
1292
1297
* Lookup the internal proc name in the hashtable
1293
1298
************************************************************/
1294
- if (hv_exists (plperl_proc_hash , internal_proname , proname_len ))
1299
+ svp = hv_fetch (plperl_proc_hash , internal_proname , proname_len , FALSE);
1300
+ if (svp )
1295
1301
{
1296
1302
bool uptodate ;
1297
1303
1298
- prodesc = (plperl_proc_desc * ) SvIV (* hv_fetch (plperl_proc_hash ,
1299
- internal_proname , proname_len , 0 ));
1304
+ prodesc = (plperl_proc_desc * ) SvIV (* svp );
1300
1305
1301
1306
/************************************************************
1302
1307
* If it's present, must check whether it's still up to date.
@@ -1519,39 +1524,30 @@ static SV *
1519
1524
plperl_build_tuple_argument (HeapTuple tuple , TupleDesc tupdesc )
1520
1525
{
1521
1526
int i ;
1522
- SV * output ;
1527
+ HV * hv ;
1523
1528
Datum attr ;
1524
1529
bool isnull ;
1525
1530
char * attname ;
1526
1531
char * outputstr ;
1527
1532
HeapTuple typeTup ;
1528
1533
Oid typoutput ;
1529
1534
Oid typioparam ;
1535
+ int namelen ;
1530
1536
1531
- output = sv_2mortal ( newSVpv ( "{" , 0 ) );
1537
+ hv = newHV ( );
1532
1538
1533
1539
for (i = 0 ; i < tupdesc -> natts ; i ++ )
1534
1540
{
1535
- /* ignore dropped attributes */
1536
1541
if (tupdesc -> attrs [i ]-> attisdropped )
1537
1542
continue ;
1538
1543
1539
- /************************************************************
1540
- * Get the attribute name
1541
- ************************************************************/
1542
1544
attname = tupdesc -> attrs [i ]-> attname .data ;
1543
-
1544
- /************************************************************
1545
- * Get the attributes value
1546
- ************************************************************/
1545
+ namelen = strlen (attname );
1547
1546
attr = heap_getattr (tuple , i + 1 , tupdesc , & isnull );
1548
1547
1549
- /************************************************************
1550
- * If it is null it will be set to undef in the hash.
1551
- ************************************************************/
1552
- if (isnull )
1553
- {
1554
- sv_catpvf (output , "'%s' => undef," , attname );
1548
+ if (isnull ) {
1549
+ /* Store (attname => undef) and move on. */
1550
+ hv_store (hv , attname , namelen , newSV (0 ), 0 );
1555
1551
continue ;
1556
1552
}
1557
1553
@@ -1577,13 +1573,11 @@ plperl_build_tuple_argument(HeapTuple tuple, TupleDesc tupdesc)
1577
1573
attr ,
1578
1574
ObjectIdGetDatum (typioparam ),
1579
1575
Int32GetDatum (tupdesc -> attrs [i ]-> atttypmod )));
1580
- sv_catpvf ( output , "'%s' => '%s'," , attname , outputstr );
1581
- pfree ( outputstr );
1576
+
1577
+ hv_store ( hv , attname , namelen , newSVpv ( outputstr , 0 ), 0 );
1582
1578
}
1583
1579
1584
- sv_catpv (output , "}" );
1585
- output = perl_eval_pv (SvPV (output , PL_na ), TRUE);
1586
- return output ;
1580
+ return sv_2mortal (newRV ((SV * )hv ));
1587
1581
}
1588
1582
1589
1583
@@ -1599,36 +1593,6 @@ plperl_spi_exec(char *query, int limit)
1599
1593
return ret_hv ;
1600
1594
}
1601
1595
1602
- static HV *
1603
- plperl_hash_from_tuple (HeapTuple tuple , TupleDesc tupdesc )
1604
- {
1605
- int i ;
1606
- char * attname ;
1607
- char * attdata ;
1608
-
1609
- HV * array ;
1610
-
1611
- array = newHV ();
1612
-
1613
- for (i = 0 ; i < tupdesc -> natts ; i ++ )
1614
- {
1615
- /************************************************************
1616
- * Get the attribute name
1617
- ************************************************************/
1618
- attname = tupdesc -> attrs [i ]-> attname .data ;
1619
-
1620
- /************************************************************
1621
- * Get the attributes value
1622
- ************************************************************/
1623
- attdata = SPI_getvalue (tuple , tupdesc , i + 1 );
1624
- if (attdata )
1625
- hv_store (array , attname , strlen (attname ), newSVpv (attdata , 0 ), 0 );
1626
- else
1627
- hv_store (array , attname , strlen (attname ), newSVpv ("undef" , 0 ), 0 );
1628
- }
1629
- return array ;
1630
- }
1631
-
1632
1596
static HV *
1633
1597
plperl_spi_execute_fetch_result (SPITupleTable * tuptable , int processed , int status )
1634
1598
{
@@ -1653,7 +1617,7 @@ plperl_spi_execute_fetch_result(SPITupleTable *tuptable, int processed, int stat
1653
1617
for (i = 0 ; i < processed ; i ++ )
1654
1618
{
1655
1619
row = plperl_hash_from_tuple (tuptable -> vals [i ], tuptable -> tupdesc );
1656
- av_store (rows , i , newRV_noinc ((SV * ) row ));
1620
+ av_push (rows , newRV_noinc ((SV * )row ));
1657
1621
}
1658
1622
hv_store (result , "rows" , strlen ("rows" ),
1659
1623
newRV_noinc ((SV * ) rows ), 0 );
0 commit comments