Fix coredump in pg_get_triggerdef, ensure function name is schema-
qualified when necessary, simplify argument-printing code.
This commit is contained in:
parent
dc554458ad
commit
0b5b3e9e65
@ -3,7 +3,7 @@
|
|||||||
* back to source text
|
* back to source text
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.139 2003/04/24 21:16:43 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.140 2003/05/20 20:35:10 tgl Exp $
|
||||||
*
|
*
|
||||||
* This software is copyrighted by Jan Wieck - Hamburg.
|
* This software is copyrighted by Jan Wieck - Hamburg.
|
||||||
*
|
*
|
||||||
@ -49,10 +49,10 @@
|
|||||||
#include "catalog/pg_cast.h"
|
#include "catalog/pg_cast.h"
|
||||||
#include "catalog/pg_constraint.h"
|
#include "catalog/pg_constraint.h"
|
||||||
#include "catalog/pg_index.h"
|
#include "catalog/pg_index.h"
|
||||||
#include "catalog/pg_trigger.h"
|
|
||||||
#include "catalog/pg_opclass.h"
|
#include "catalog/pg_opclass.h"
|
||||||
#include "catalog/pg_operator.h"
|
#include "catalog/pg_operator.h"
|
||||||
#include "catalog/pg_shadow.h"
|
#include "catalog/pg_shadow.h"
|
||||||
|
#include "catalog/pg_trigger.h"
|
||||||
#include "executor/spi.h"
|
#include "executor/spi.h"
|
||||||
#include "lib/stringinfo.h"
|
#include "lib/stringinfo.h"
|
||||||
#include "nodes/makefuncs.h"
|
#include "nodes/makefuncs.h"
|
||||||
@ -380,7 +380,6 @@ pg_get_triggerdef(PG_FUNCTION_ARGS)
|
|||||||
Oid trigid = PG_GETARG_OID(0);
|
Oid trigid = PG_GETARG_OID(0);
|
||||||
text *trigdef;
|
text *trigdef;
|
||||||
HeapTuple ht_trig;
|
HeapTuple ht_trig;
|
||||||
HeapTuple ht_proc;
|
|
||||||
Form_pg_trigger trigrec;
|
Form_pg_trigger trigrec;
|
||||||
int len;
|
int len;
|
||||||
StringInfoData buf;
|
StringInfoData buf;
|
||||||
@ -388,9 +387,6 @@ pg_get_triggerdef(PG_FUNCTION_ARGS)
|
|||||||
ScanKeyData skey[1];
|
ScanKeyData skey[1];
|
||||||
SysScanDesc tgscan;
|
SysScanDesc tgscan;
|
||||||
int findx = 0;
|
int findx = 0;
|
||||||
const char *tgargs;
|
|
||||||
const char *p;
|
|
||||||
char *tgfname;
|
|
||||||
char *tgname;
|
char *tgname;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -398,9 +394,6 @@ pg_get_triggerdef(PG_FUNCTION_ARGS)
|
|||||||
*/
|
*/
|
||||||
tgrel = heap_openr(TriggerRelationName, AccessShareLock);
|
tgrel = heap_openr(TriggerRelationName, AccessShareLock);
|
||||||
|
|
||||||
/*
|
|
||||||
* Find the trigger
|
|
||||||
*/
|
|
||||||
ScanKeyEntryInitialize(&skey[0], 0x0,
|
ScanKeyEntryInitialize(&skey[0], 0x0,
|
||||||
ObjectIdAttributeNumber, F_OIDEQ,
|
ObjectIdAttributeNumber, F_OIDEQ,
|
||||||
ObjectIdGetDatum(trigid));
|
ObjectIdGetDatum(trigid));
|
||||||
@ -415,18 +408,6 @@ pg_get_triggerdef(PG_FUNCTION_ARGS)
|
|||||||
trigid);
|
trigid);
|
||||||
|
|
||||||
trigrec = (Form_pg_trigger) GETSTRUCT(ht_trig);
|
trigrec = (Form_pg_trigger) GETSTRUCT(ht_trig);
|
||||||
systable_endscan(tgscan);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Fetch the pg_proc tuple of the trigger's function
|
|
||||||
*/
|
|
||||||
ht_proc = SearchSysCache(PROCOID,
|
|
||||||
ObjectIdGetDatum(trigrec->tgfoid),
|
|
||||||
0, 0, 0);
|
|
||||||
if (!HeapTupleIsValid(ht_proc))
|
|
||||||
elog(ERROR, "syscache lookup for function %u failed", trigrec->tgfoid);
|
|
||||||
|
|
||||||
tgfname = NameStr(((Form_pg_proc) GETSTRUCT(ht_proc))->proname);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Start the trigger definition. Note that the trigger's name should
|
* Start the trigger definition. Note that the trigger's name should
|
||||||
@ -466,14 +447,11 @@ pg_get_triggerdef(PG_FUNCTION_ARGS)
|
|||||||
appendStringInfo(&buf, " ON %s ",
|
appendStringInfo(&buf, " ON %s ",
|
||||||
generate_relation_name(trigrec->tgrelid));
|
generate_relation_name(trigrec->tgrelid));
|
||||||
|
|
||||||
|
|
||||||
if (trigrec->tgisconstraint)
|
if (trigrec->tgisconstraint)
|
||||||
{
|
{
|
||||||
if (trigrec->tgconstrrelid != 0)
|
if (trigrec->tgconstrrelid != InvalidOid)
|
||||||
{
|
|
||||||
appendStringInfo(&buf, "FROM %s ",
|
appendStringInfo(&buf, "FROM %s ",
|
||||||
generate_relation_name(trigrec->tgconstrrelid));
|
generate_relation_name(trigrec->tgconstrrelid));
|
||||||
}
|
|
||||||
if (!trigrec->tgdeferrable)
|
if (!trigrec->tgdeferrable)
|
||||||
appendStringInfo(&buf, "NOT ");
|
appendStringInfo(&buf, "NOT ");
|
||||||
appendStringInfo(&buf, "DEFERRABLE INITIALLY ");
|
appendStringInfo(&buf, "DEFERRABLE INITIALLY ");
|
||||||
@ -490,50 +468,39 @@ pg_get_triggerdef(PG_FUNCTION_ARGS)
|
|||||||
appendStringInfo(&buf, "FOR EACH STATEMENT ");
|
appendStringInfo(&buf, "FOR EACH STATEMENT ");
|
||||||
|
|
||||||
appendStringInfo(&buf, "EXECUTE PROCEDURE %s(",
|
appendStringInfo(&buf, "EXECUTE PROCEDURE %s(",
|
||||||
quote_identifier(tgfname));
|
generate_function_name(trigrec->tgfoid, 0, NULL));
|
||||||
|
|
||||||
/* Get args string */
|
if (trigrec->tgnargs > 0)
|
||||||
tgargs = DatumGetCString(DirectFunctionCall1(byteaout,
|
{
|
||||||
PointerGetDatum(&trigrec->tgargs)));
|
bytea *val;
|
||||||
/* If it's NULL, fail */
|
bool isnull;
|
||||||
if (tgargs == NULL)
|
char *p;
|
||||||
elog(ERROR, "pg_get_triggerdef: tgargs is NULL");
|
int i;
|
||||||
|
|
||||||
for (findx = 0; findx < trigrec->tgnargs; findx++)
|
val = (bytea *) fastgetattr(ht_trig,
|
||||||
|
Anum_pg_trigger_tgargs,
|
||||||
|
tgrel->rd_att, &isnull);
|
||||||
|
if (isnull)
|
||||||
|
elog(ERROR, "tgargs is null for trigger %u", trigid);
|
||||||
|
p = (char *) VARDATA(val);
|
||||||
|
for (i = 0; i < trigrec->tgnargs; i++)
|
||||||
{
|
{
|
||||||
const char *s;
|
if (i > 0)
|
||||||
|
appendStringInfo(&buf, ", ");
|
||||||
for (p = tgargs;;)
|
|
||||||
{
|
|
||||||
p = strchr(p, '\\');
|
|
||||||
if (p == NULL)
|
|
||||||
{
|
|
||||||
elog(ERROR, "pg_get_triggerdef: bad argument string for trigger");
|
|
||||||
}
|
|
||||||
p++;
|
|
||||||
if (*p == '\\')
|
|
||||||
{
|
|
||||||
p++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (p[0] == '0' && p[1] == '0' && p[2] == '0')
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
p--;
|
|
||||||
appendStringInfoChar(&buf, '\'');
|
appendStringInfoChar(&buf, '\'');
|
||||||
for (s = tgargs; s < p;)
|
while (*p)
|
||||||
{
|
{
|
||||||
/* If character is an apostrophe, escape it */
|
/* escape quotes and backslashes */
|
||||||
if (*s == '\'')
|
if (*p == '\'' || *p == '\\')
|
||||||
appendStringInfoChar(&buf, '\\');
|
appendStringInfoChar(&buf, '\\');
|
||||||
appendStringInfoChar(&buf, *s++);
|
appendStringInfoChar(&buf, *p++);
|
||||||
}
|
}
|
||||||
|
p++;
|
||||||
appendStringInfoChar(&buf, '\'');
|
appendStringInfoChar(&buf, '\'');
|
||||||
appendStringInfo(&buf, (findx < trigrec->tgnargs - 1) ? ", " : "");
|
}
|
||||||
tgargs = p + 4;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Deliberately omit semi-colon */
|
/* We deliberately do not put semi-colon at end */
|
||||||
appendStringInfo(&buf, ")");
|
appendStringInfo(&buf, ")");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -546,8 +513,8 @@ pg_get_triggerdef(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
pfree(buf.data);
|
pfree(buf.data);
|
||||||
|
|
||||||
ReleaseSysCache(ht_trig);
|
systable_endscan(tgscan);
|
||||||
ReleaseSysCache(ht_proc);
|
|
||||||
heap_close(tgrel, AccessShareLock);
|
heap_close(tgrel, AccessShareLock);
|
||||||
|
|
||||||
PG_RETURN_TEXT_P(trigdef);
|
PG_RETURN_TEXT_P(trigdef);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user