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

Commit ce1c202

Browse files
committed
I have attached 5 patches (split up for ease of review) to plperl.c.
1. Two minor cleanups: - We don't need to call hv_exists+hv_fetch; we should just check the return value of hv_fetch. - newSVpv("undef",0) is the string "undef", not a real undef. 2. This should fix the bug Andrew Dunstan described in a recent -hackers post. It replaces three bogus "eval_pv(key, 0)" calls with newSVpv, and eliminates another redundant hv_exists+hv_fetch pair. 3. plperl_build_tuple_argument builds up a string of Perl code to create a hash representing the tuple. This patch creates the hash directly. 4. Another minor cleanup: replace a couple of av_store()s with av_push. 5. Analogous to #3 for plperl_trigger_build_args. This patch removes the static sv_add_tuple_value function, which does much the same as two other utility functions defined later, and merges the functionality into plperl_hash_from_tuple. I have tested the patches to the best of my limited ability, but I would appreciate it very much if someone else could review and test them too. (Thanks to Andrew and David Fetter for their help with some testing.) Abhijit Menon-Sen
1 parent bdb8b39 commit ce1c202

File tree

1 file changed

+93
-129
lines changed

1 file changed

+93
-129
lines changed

src/pl/plperl/plperl.c

+93-129
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
* ENHANCEMENTS, OR MODIFICATIONS.
3434
*
3535
* 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 $
3737
*
3838
**********************************************************************/
3939

@@ -276,33 +276,30 @@ plperl_safe_init(void)
276276
plperl_safe_init_done = true;
277277
}
278278

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, "{ ");
290279

280+
static HV *
281+
plperl_hash_from_tuple(HeapTuple tuple, TupleDesc tupdesc)
282+
{
283+
int i;
284+
HV *hv = newHV();
291285
for (i = 0; i < tupdesc->natts; i++)
292286
{
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);
297294
else
298-
sv_catpvf(rv, "%s => undef", key);
299-
if (i != tupdesc->natts - 1)
300-
sv_catpvf(rv, ", ");
301-
}
295+
value = newSV(0);
302296

303-
sv_catpvf(rv, " }");
297+
hv_store(hv, key, strlen(key), value, 0);
298+
}
299+
return hv;
304300
}
305301

302+
306303
/**********************************************************************
307304
* set up arguments for a trigger call
308305
**********************************************************************/
@@ -312,76 +309,89 @@ plperl_trigger_build_args(FunctionCallInfo fcinfo)
312309
TriggerData *tdata;
313310
TupleDesc tupdesc;
314311
int i = 0;
315-
SV *rv;
312+
char *level;
313+
char *event;
314+
char *relid;
315+
char *when;
316+
HV *hv;
316317

317-
rv = newSVpv("{ ", 0);
318+
hv = newHV();
318319

319320
tdata = (TriggerData *) fcinfo->context;
320-
321321
tupdesc = tdata->tg_relation->rd_att;
322322

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);
325331

326332
if (TRIGGER_FIRED_BY_INSERT(tdata->tg_event))
327333
{
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);
331339
}
332340
else if (TRIGGER_FIRED_BY_DELETE(tdata->tg_event))
333341
{
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);
337347
}
338348
else if (TRIGGER_FIRED_BY_UPDATE(tdata->tg_event))
339349
{
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";
347362
}
348-
else
349-
sv_catpvf(rv, ", event => 'UNKNOWN'");
350363

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);
352366

353367
if (tdata->tg_trigger->tgnargs != 0)
354368
{
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);
363373
}
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);
365377

366378
if (TRIGGER_FIRED_BEFORE(tdata->tg_event))
367-
sv_catpvf(rv, ", when => 'BEFORE'");
379+
when = "BEFORE";
368380
else if (TRIGGER_FIRED_AFTER(tdata->tg_event))
369-
sv_catpvf(rv, ", when => 'AFTER'");
381+
when = "AFTER";
370382
else
371-
sv_catpvf(rv, ", when => 'UNKNOWN'");
383+
when = "UNKNOWN";
384+
hv_store(hv, "when", 4, newSVpv(when, 0), 0);
372385

373386
if (TRIGGER_FIRED_FOR_ROW(tdata->tg_event))
374-
sv_catpvf(rv, ", level => 'ROW'");
387+
level = "ROW";
375388
else if (TRIGGER_FIRED_FOR_STATEMENT(tdata->tg_event))
376-
sv_catpvf(rv, ", level => 'STATEMENT'");
389+
level = "STATEMENT";
377390
else
378-
sv_catpvf(rv, ", level => 'UNKNOWN'");
391+
level = "UNKNOWN";
392+
hv_store(hv, "level", 5, newSVpv(level, 0), 0);
379393

380-
sv_catpvf(rv, " }");
381-
382-
rv = perl_eval_pv(SvPV(rv, PL_na), TRUE);
383-
384-
return rv;
394+
return newRV((SV*)hv);
385395
}
386396

387397

@@ -440,21 +450,17 @@ static AV *
440450
plperl_get_keys(HV *hv)
441451
{
442452
AV *ret;
443-
int key_count;
444453
SV *val;
445454
char *key;
446455
I32 klen;
447456

448-
key_count = 0;
449457
ret = newAV();
450458

451459
hv_iterinit(hv);
452460
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));
457462
hv_iterinit(hv);
463+
458464
return ret;
459465
}
460466

@@ -484,11 +490,8 @@ plperl_get_key(AV *keys, int index)
484490
static char *
485491
plperl_get_elem(HV *hash, char *key)
486492
{
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)
492495
{
493496
elog(ERROR, "plperl: key '%s' not found", key);
494497
return NULL;
@@ -998,7 +1001,8 @@ plperl_func_handler(PG_FUNCTION_ARGS)
9981001
g_attr_num = tupdesc->natts;
9991002

10001003
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));
10021006

10031007
slot = TupleDescGetSlot(tupdesc);
10041008
funcctx->slot = slot;
@@ -1269,6 +1273,7 @@ compile_plperl_function(Oid fn_oid, bool is_trigger)
12691273
int proname_len;
12701274
plperl_proc_desc *prodesc = NULL;
12711275
int i;
1276+
SV **svp;
12721277

12731278
/* We'll need the pg_proc tuple in any case... */
12741279
procTup = SearchSysCache(PROCOID,
@@ -1291,12 +1296,12 @@ compile_plperl_function(Oid fn_oid, bool is_trigger)
12911296
/************************************************************
12921297
* Lookup the internal proc name in the hashtable
12931298
************************************************************/
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)
12951301
{
12961302
bool uptodate;
12971303

1298-
prodesc = (plperl_proc_desc *) SvIV(*hv_fetch(plperl_proc_hash,
1299-
internal_proname, proname_len, 0));
1304+
prodesc = (plperl_proc_desc *) SvIV(*svp);
13001305

13011306
/************************************************************
13021307
* If it's present, must check whether it's still up to date.
@@ -1519,39 +1524,30 @@ static SV *
15191524
plperl_build_tuple_argument(HeapTuple tuple, TupleDesc tupdesc)
15201525
{
15211526
int i;
1522-
SV *output;
1527+
HV *hv;
15231528
Datum attr;
15241529
bool isnull;
15251530
char *attname;
15261531
char *outputstr;
15271532
HeapTuple typeTup;
15281533
Oid typoutput;
15291534
Oid typioparam;
1535+
int namelen;
15301536

1531-
output = sv_2mortal(newSVpv("{", 0));
1537+
hv = newHV();
15321538

15331539
for (i = 0; i < tupdesc->natts; i++)
15341540
{
1535-
/* ignore dropped attributes */
15361541
if (tupdesc->attrs[i]->attisdropped)
15371542
continue;
15381543

1539-
/************************************************************
1540-
* Get the attribute name
1541-
************************************************************/
15421544
attname = tupdesc->attrs[i]->attname.data;
1543-
1544-
/************************************************************
1545-
* Get the attributes value
1546-
************************************************************/
1545+
namelen = strlen(attname);
15471546
attr = heap_getattr(tuple, i + 1, tupdesc, &isnull);
15481547

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);
15551551
continue;
15561552
}
15571553

@@ -1577,13 +1573,11 @@ plperl_build_tuple_argument(HeapTuple tuple, TupleDesc tupdesc)
15771573
attr,
15781574
ObjectIdGetDatum(typioparam),
15791575
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);
15821578
}
15831579

1584-
sv_catpv(output, "}");
1585-
output = perl_eval_pv(SvPV(output, PL_na), TRUE);
1586-
return output;
1580+
return sv_2mortal(newRV((SV *)hv));
15871581
}
15881582

15891583

@@ -1599,36 +1593,6 @@ plperl_spi_exec(char *query, int limit)
15991593
return ret_hv;
16001594
}
16011595

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-
16321596
static HV *
16331597
plperl_spi_execute_fetch_result(SPITupleTable *tuptable, int processed, int status)
16341598
{
@@ -1653,7 +1617,7 @@ plperl_spi_execute_fetch_result(SPITupleTable *tuptable, int processed, int stat
16531617
for (i = 0; i < processed; i++)
16541618
{
16551619
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));
16571621
}
16581622
hv_store(result, "rows", strlen("rows"),
16591623
newRV_noinc((SV *) rows), 0);

0 commit comments

Comments
 (0)