Skip to content

Commit 0b5b3e9

Browse files
committed
Fix coredump in pg_get_triggerdef, ensure function name is schema-
qualified when necessary, simplify argument-printing code.
1 parent dc55445 commit 0b5b3e9

File tree

1 file changed

+47
-80
lines changed

1 file changed

+47
-80
lines changed

src/backend/utils/adt/ruleutils.c

Lines changed: 47 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* back to source text
44
*
55
* IDENTIFICATION
6-
* $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.139 2003/04/24 21:16:43 tgl Exp $
6+
* $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.140 2003/05/20 20:35:10 tgl Exp $
77
*
88
* This software is copyrighted by Jan Wieck - Hamburg.
99
*
@@ -49,10 +49,10 @@
4949
#include "catalog/pg_cast.h"
5050
#include "catalog/pg_constraint.h"
5151
#include "catalog/pg_index.h"
52-
#include "catalog/pg_trigger.h"
5352
#include "catalog/pg_opclass.h"
5453
#include "catalog/pg_operator.h"
5554
#include "catalog/pg_shadow.h"
55+
#include "catalog/pg_trigger.h"
5656
#include "executor/spi.h"
5757
#include "lib/stringinfo.h"
5858
#include "nodes/makefuncs.h"
@@ -380,53 +380,34 @@ pg_get_triggerdef(PG_FUNCTION_ARGS)
380380
Oid trigid = PG_GETARG_OID(0);
381381
text *trigdef;
382382
HeapTuple ht_trig;
383-
HeapTuple ht_proc;
384383
Form_pg_trigger trigrec;
385384
int len;
386385
StringInfoData buf;
387-
Relation tgrel;
388-
ScanKeyData skey[1];
389-
SysScanDesc tgscan;
390-
int findx = 0;
391-
const char *tgargs;
392-
const char *p;
393-
char *tgfname;
386+
Relation tgrel;
387+
ScanKeyData skey[1];
388+
SysScanDesc tgscan;
389+
int findx = 0;
394390
char *tgname;
395391

396392
/*
397393
* Fetch the pg_trigger tuple by the Oid of the trigger
398394
*/
399-
tgrel = heap_openr(TriggerRelationName, AccessShareLock);
395+
tgrel = heap_openr(TriggerRelationName, AccessShareLock);
400396

401-
/*
402-
* Find the trigger
403-
*/
404-
ScanKeyEntryInitialize(&skey[0], 0x0,
405-
ObjectIdAttributeNumber, F_OIDEQ,
406-
ObjectIdGetDatum(trigid));
397+
ScanKeyEntryInitialize(&skey[0], 0x0,
398+
ObjectIdAttributeNumber, F_OIDEQ,
399+
ObjectIdGetDatum(trigid));
407400

408-
tgscan = systable_beginscan(tgrel, TriggerOidIndex, true,
409-
SnapshotNow, 1, skey);
401+
tgscan = systable_beginscan(tgrel, TriggerOidIndex, true,
402+
SnapshotNow, 1, skey);
410403

411-
ht_trig = systable_getnext(tgscan);
404+
ht_trig = systable_getnext(tgscan);
412405

413-
if (!HeapTupleIsValid(ht_trig))
414-
elog(ERROR, "pg_get_triggerdef: there is no trigger with oid %u",
415-
trigid);
406+
if (!HeapTupleIsValid(ht_trig))
407+
elog(ERROR, "pg_get_triggerdef: there is no trigger with oid %u",
408+
trigid);
416409

417410
trigrec = (Form_pg_trigger) GETSTRUCT(ht_trig);
418-
systable_endscan(tgscan);
419-
420-
/*
421-
* Fetch the pg_proc tuple of the trigger's function
422-
*/
423-
ht_proc = SearchSysCache(PROCOID,
424-
ObjectIdGetDatum(trigrec->tgfoid),
425-
0, 0, 0);
426-
if (!HeapTupleIsValid(ht_proc))
427-
elog(ERROR, "syscache lookup for function %u failed", trigrec->tgfoid);
428-
429-
tgfname = NameStr(((Form_pg_proc) GETSTRUCT(ht_proc))->proname);
430411

431412
/*
432413
* Start the trigger definition. Note that the trigger's name should
@@ -464,16 +445,13 @@ pg_get_triggerdef(PG_FUNCTION_ARGS)
464445
appendStringInfo(&buf, " UPDATE");
465446
}
466447
appendStringInfo(&buf, " ON %s ",
467-
generate_relation_name(trigrec->tgrelid));
468-
448+
generate_relation_name(trigrec->tgrelid));
469449

470450
if (trigrec->tgisconstraint)
471451
{
472-
if (trigrec->tgconstrrelid != 0)
473-
{
452+
if (trigrec->tgconstrrelid != InvalidOid)
474453
appendStringInfo(&buf, "FROM %s ",
475-
generate_relation_name(trigrec->tgconstrrelid));
476-
}
454+
generate_relation_name(trigrec->tgconstrrelid));
477455
if (!trigrec->tgdeferrable)
478456
appendStringInfo(&buf, "NOT ");
479457
appendStringInfo(&buf, "DEFERRABLE INITIALLY ");
@@ -490,50 +468,39 @@ pg_get_triggerdef(PG_FUNCTION_ARGS)
490468
appendStringInfo(&buf, "FOR EACH STATEMENT ");
491469

492470
appendStringInfo(&buf, "EXECUTE PROCEDURE %s(",
493-
quote_identifier(tgfname));
494-
495-
/* Get args string */
496-
tgargs = DatumGetCString(DirectFunctionCall1(byteaout,
497-
PointerGetDatum(&trigrec->tgargs)));
498-
/* If it's NULL, fail */
499-
if (tgargs == NULL)
500-
elog(ERROR, "pg_get_triggerdef: tgargs is NULL");
501-
502-
for (findx = 0; findx < trigrec->tgnargs; findx++)
503-
{
504-
const char *s;
505-
506-
for (p = tgargs;;)
471+
generate_function_name(trigrec->tgfoid, 0, NULL));
472+
473+
if (trigrec->tgnargs > 0)
474+
{
475+
bytea *val;
476+
bool isnull;
477+
char *p;
478+
int i;
479+
480+
val = (bytea *) fastgetattr(ht_trig,
481+
Anum_pg_trigger_tgargs,
482+
tgrel->rd_att, &isnull);
483+
if (isnull)
484+
elog(ERROR, "tgargs is null for trigger %u", trigid);
485+
p = (char *) VARDATA(val);
486+
for (i = 0; i < trigrec->tgnargs; i++)
507487
{
508-
p = strchr(p, '\\');
509-
if (p == NULL)
488+
if (i > 0)
489+
appendStringInfo(&buf, ", ");
490+
appendStringInfoChar(&buf, '\'');
491+
while (*p)
510492
{
511-
elog(ERROR, "pg_get_triggerdef: bad argument string for trigger");
493+
/* escape quotes and backslashes */
494+
if (*p == '\'' || *p == '\\')
495+
appendStringInfoChar(&buf, '\\');
496+
appendStringInfoChar(&buf, *p++);
512497
}
513498
p++;
514-
if (*p == '\\')
515-
{
516-
p++;
517-
continue;
518-
}
519-
if (p[0] == '0' && p[1] == '0' && p[2] == '0')
520-
break;
521-
}
522-
p--;
523-
appendStringInfoChar(&buf, '\'');
524-
for (s = tgargs; s < p;)
525-
{
526-
/* If character is an apostrophe, escape it */
527-
if (*s == '\'')
528-
appendStringInfoChar(&buf, '\\');
529-
appendStringInfoChar(&buf, *s++);
499+
appendStringInfoChar(&buf, '\'');
530500
}
531-
appendStringInfoChar(&buf, '\'');
532-
appendStringInfo(&buf, (findx < trigrec->tgnargs - 1) ? ", " : "");
533-
tgargs = p + 4;
534501
}
535502

536-
/* Deliberately omit semi-colon */
503+
/* We deliberately do not put semi-colon at end */
537504
appendStringInfo(&buf, ")");
538505

539506
/*
@@ -546,8 +513,8 @@ pg_get_triggerdef(PG_FUNCTION_ARGS)
546513

547514
pfree(buf.data);
548515

549-
ReleaseSysCache(ht_trig);
550-
ReleaseSysCache(ht_proc);
516+
systable_endscan(tgscan);
517+
551518
heap_close(tgrel, AccessShareLock);
552519

553520
PG_RETURN_TEXT_P(trigdef);

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy