mirror of
https://git.postgresql.org/git/postgresql.git
synced 2025-02-11 19:20:40 +08:00
Add pg_identify_object_as_address
This function returns object type and objname/objargs arrays, which can be passed to pg_get_object_address. This is especially useful because the textual representation can be copied to a remote server in order to obtain the corresponding OID-based address. In essence, this function is the inverse of recently added pg_get_object_address(). Catalog version bumped due to the addition of the new function. Also add docs to pg_get_object_address.
This commit is contained in:
parent
5b447ad3a9
commit
a676201490
@ -15307,14 +15307,6 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
|
||||
<primary>format_type</primary>
|
||||
</indexterm>
|
||||
|
||||
<indexterm>
|
||||
<primary>pg_describe_object</primary>
|
||||
</indexterm>
|
||||
|
||||
<indexterm>
|
||||
<primary>pg_identify_object</primary>
|
||||
</indexterm>
|
||||
|
||||
<indexterm>
|
||||
<primary>pg_get_constraintdef</primary>
|
||||
</indexterm>
|
||||
@ -15429,16 +15421,6 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
|
||||
<entry><type>text</type></entry>
|
||||
<entry>get SQL name of a data type</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><literal><function>pg_describe_object(<parameter>catalog_id</parameter>, <parameter>object_id</parameter>, <parameter>object_sub_id</parameter>)</function></literal></entry>
|
||||
<entry><type>text</type></entry>
|
||||
<entry>get description of a database object</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><literal><function>pg_identify_object(<parameter>catalog_id</parameter> <type>oid</>, <parameter>object_id</parameter> <type>oid</>, <parameter>object_sub_id</parameter> <type>integer</>)</function></literal></entry>
|
||||
<entry><parameter>type</> <type>text</>, <parameter>schema</> <type>text</>, <parameter>name</> <type>text</>, <parameter>identity</> <type>text</></entry>
|
||||
<entry>get identity of a database object</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><literal><function>pg_get_constraintdef(<parameter>constraint_oid</parameter>)</function></literal></entry>
|
||||
<entry><type>text</type></entry>
|
||||
@ -15707,31 +15689,6 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
|
||||
<structname>pg_class</> catalogs.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<function>pg_describe_object</function> returns a textual description of a database
|
||||
object specified by catalog OID, object OID and a (possibly zero) sub-object ID.
|
||||
This description is intended to be human-readable, and might be translated,
|
||||
depending on server configuration.
|
||||
This is useful to determine the identity of an object as stored in the
|
||||
<structname>pg_depend</structname> catalog.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<function>pg_identify_object</function> returns a row containing enough information
|
||||
to uniquely identify the database object specified by catalog OID, object OID and a
|
||||
(possibly zero) sub-object ID. This information is intended to be machine-readable,
|
||||
and is never translated.
|
||||
<parameter>type</> identifies the type of database object;
|
||||
<parameter>schema</> is the schema name that the object belongs in, or
|
||||
<literal>NULL</> for object types that do not belong to schemas;
|
||||
<parameter>name</> is the name of the object, quoted if necessary, only
|
||||
present if it can be used (alongside schema name, if pertinent) as a unique
|
||||
identifier of the object, otherwise <literal>NULL</>;
|
||||
<parameter>identity</> is the complete object identity, with the precise format
|
||||
depending on object type, and each part within the format being
|
||||
schema-qualified and quoted as necessary.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<function>pg_typeof</function> returns the OID of the data type of the
|
||||
value that is passed to it. This can be helpful for troubleshooting or
|
||||
@ -15790,6 +15747,112 @@ SELECT collation for ('foo' COLLATE "de_DE");
|
||||
the given name matches multiple objects).
|
||||
</para>
|
||||
|
||||
<indexterm>
|
||||
<primary>pg_describe_object</primary>
|
||||
</indexterm>
|
||||
|
||||
<indexterm>
|
||||
<primary>pg_identify_object</primary>
|
||||
</indexterm>
|
||||
|
||||
<indexterm>
|
||||
<primary>pg_identify_object_as_address</primary>
|
||||
</indexterm>
|
||||
|
||||
<indexterm>
|
||||
<primary>pg_get_object_address</primary>
|
||||
</indexterm>
|
||||
|
||||
<para>
|
||||
<xref linkend="functions-info-object-table"> lists functions related to
|
||||
database object identification and addressing.
|
||||
</para>
|
||||
|
||||
<table id="functions-info-object-table">
|
||||
<title>Object Information and Addressing Functions</title>
|
||||
<tgroup cols="3">
|
||||
<thead>
|
||||
<row><entry>Name</entry> <entry>Return Type</entry> <entry>Description</entry></row>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<row>
|
||||
<entry><literal><function>pg_describe_object(<parameter>catalog_id</parameter>, <parameter>object_id</parameter>, <parameter>object_sub_id</parameter>)</function></literal></entry>
|
||||
<entry><type>text</type></entry>
|
||||
<entry>get description of a database object</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><literal><function>pg_identify_object(<parameter>catalog_id</parameter> <type>oid</>, <parameter>object_id</parameter> <type>oid</>, <parameter>object_sub_id</parameter> <type>integer</>)</function></literal></entry>
|
||||
<entry><parameter>type</> <type>text</>, <parameter>schema</> <type>text</>, <parameter>name</> <type>text</>, <parameter>identity</> <type>text</></entry>
|
||||
<entry>get identity of a database object</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><literal><function>pg_identify_object_as_address(<parameter>catalog_id</parameter> <type>oid</>, <parameter>object_id</parameter> <type>oid</>, <parameter>object_sub_id</parameter> <type>integer</>)</function></literal></entry>
|
||||
<entry><parameter>type</> <type>text</>, <parameter>name</> <type>text[]</>, <parameter>args</> <type>text[]</></entry>
|
||||
<entry>get external representation of a database object's address</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><literal><function>pg_get_object_address(<parameter>type</parameter> <type>text</>, <parameter>name</parameter> <type>text[]</>, <parameter>args</parameter> <type>text[]</>)</function></literal></entry>
|
||||
<entry><parameter>catalog_id</> <type>oid</>, <parameter>object_id</> <type>oid</>, <parameter>object_sub_id</> <type>int32</></entry>
|
||||
<entry>get address of a database object, from its external representation</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
|
||||
<para>
|
||||
<function>pg_describe_object</function> returns a textual description of a database
|
||||
object specified by catalog OID, object OID and a (possibly zero) sub-object ID.
|
||||
This description is intended to be human-readable, and might be translated,
|
||||
depending on server configuration.
|
||||
This is useful to determine the identity of an object as stored in the
|
||||
<structname>pg_depend</structname> catalog.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<function>pg_identify_object</function> returns a row containing enough information
|
||||
to uniquely identify the database object specified by catalog OID, object OID and a
|
||||
(possibly zero) sub-object ID. This information is intended to be machine-readable,
|
||||
and is never translated.
|
||||
<parameter>type</> identifies the type of database object;
|
||||
<parameter>schema</> is the schema name that the object belongs in, or
|
||||
<literal>NULL</> for object types that do not belong to schemas;
|
||||
<parameter>name</> is the name of the object, quoted if necessary, only
|
||||
present if it can be used (alongside schema name, if pertinent) as a unique
|
||||
identifier of the object, otherwise <literal>NULL</>;
|
||||
<parameter>identity</> is the complete object identity, with the precise format
|
||||
depending on object type, and each part within the format being
|
||||
schema-qualified and quoted as necessary.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<function>pg_identify_object_as_address</function> returns a row containing
|
||||
enough information to uniquely identify the database object specified by
|
||||
catalog OID, object OID and a (possibly zero) sub-object ID. The returned
|
||||
information is independent of the current server, that is, it could be used
|
||||
to identify an identically named object in another server.
|
||||
<parameter>type</> identifies the type of database object;
|
||||
<parameter>name</> and <parameter>args</> are text arrays that together
|
||||
form a reference to the object. These three columns can be passed to
|
||||
<function>pg_get_object_address</> to obtain the internal address
|
||||
of the object.
|
||||
This function is the inverse of <function>pg_get_object_address</function>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<function>pg_get_object_address</function> returns a row containing enough
|
||||
information to uniquely identify the database object specified by its
|
||||
type and object name and argument arrays. The returned values are the
|
||||
ones that would be used in system catalogs such as <structname>pg_depend</>
|
||||
and can be passed to other system functions such as
|
||||
<function>pg_identify_object</> or <function>pg_describe_object</>.
|
||||
<parameter>catalog_id</> is the OID of the system catalog containing the
|
||||
object;
|
||||
<parameter>object_id</> is the OID of the object itself, and
|
||||
<parameter>object_sub_id</> is the object sub-ID, or zero if none.
|
||||
This function is the inverse of <function>pg_identify_object_as_address</function>.
|
||||
</para>
|
||||
|
||||
<indexterm>
|
||||
<primary>col_description</primary>
|
||||
</indexterm>
|
||||
|
@ -74,6 +74,7 @@
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/fmgroids.h"
|
||||
#include "utils/lsyscache.h"
|
||||
#include "utils/memutils.h"
|
||||
#include "utils/syscache.h"
|
||||
#include "utils/tqual.h"
|
||||
|
||||
@ -556,8 +557,9 @@ static void getRelationTypeDescription(StringInfo buffer, Oid relid,
|
||||
int32 objectSubId);
|
||||
static void getProcedureTypeDescription(StringInfo buffer, Oid procid);
|
||||
static void getConstraintTypeDescription(StringInfo buffer, Oid constroid);
|
||||
static void getOpFamilyIdentity(StringInfo buffer, Oid opfid);
|
||||
static void getRelationIdentity(StringInfo buffer, Oid relid);
|
||||
static void getOpFamilyIdentity(StringInfo buffer, Oid opfid, List **objname,
|
||||
List **objargs);
|
||||
static void getRelationIdentity(StringInfo buffer, Oid relid, List **objname);
|
||||
|
||||
/*
|
||||
* Translate an object name and arguments (as passed by the parser) to an
|
||||
@ -2931,6 +2933,66 @@ pg_identify_object(PG_FUNCTION_ARGS)
|
||||
PG_RETURN_DATUM(HeapTupleGetDatum(htup));
|
||||
}
|
||||
|
||||
/*
|
||||
* SQL-level callable function to obtain object type + identity
|
||||
*/
|
||||
Datum
|
||||
pg_identify_object_as_address(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Oid classid = PG_GETARG_OID(0);
|
||||
Oid objid = PG_GETARG_OID(1);
|
||||
int32 subobjid = PG_GETARG_INT32(2);
|
||||
ObjectAddress address;
|
||||
char *identity;
|
||||
List *names;
|
||||
List *args;
|
||||
Datum values[3];
|
||||
bool nulls[3];
|
||||
TupleDesc tupdesc;
|
||||
HeapTuple htup;
|
||||
|
||||
address.classId = classid;
|
||||
address.objectId = objid;
|
||||
address.objectSubId = subobjid;
|
||||
|
||||
/*
|
||||
* Construct a tuple descriptor for the result row. This must match this
|
||||
* function's pg_proc entry!
|
||||
*/
|
||||
tupdesc = CreateTemplateTupleDesc(3, false);
|
||||
TupleDescInitEntry(tupdesc, (AttrNumber) 1, "type",
|
||||
TEXTOID, -1, 0);
|
||||
TupleDescInitEntry(tupdesc, (AttrNumber) 2, "object_names",
|
||||
TEXTARRAYOID, -1, 0);
|
||||
TupleDescInitEntry(tupdesc, (AttrNumber) 3, "object_args",
|
||||
TEXTARRAYOID, -1, 0);
|
||||
|
||||
tupdesc = BlessTupleDesc(tupdesc);
|
||||
|
||||
/* object type */
|
||||
values[0] = CStringGetTextDatum(getObjectTypeDescription(&address));
|
||||
nulls[0] = false;
|
||||
|
||||
/* object identity */
|
||||
identity = getObjectIdentityParts(&address, &names, &args);
|
||||
pfree(identity);
|
||||
|
||||
/* object_names */
|
||||
values[1] = PointerGetDatum(strlist_to_textarray(names));
|
||||
nulls[1] = false;
|
||||
|
||||
/* object_args */
|
||||
if (args)
|
||||
values[2] = PointerGetDatum(strlist_to_textarray(args));
|
||||
else
|
||||
values[2] = PointerGetDatum(construct_empty_array(TEXTOID));
|
||||
nulls[2] = false;
|
||||
|
||||
htup = heap_form_tuple(tupdesc, values, nulls);
|
||||
|
||||
PG_RETURN_DATUM(HeapTupleGetDatum(htup));
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a palloc'ed string that describes the type of object that the
|
||||
* passed address is for.
|
||||
@ -3187,22 +3249,50 @@ getProcedureTypeDescription(StringInfo buffer, Oid procid)
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a palloc'ed string that identifies an object.
|
||||
* Obtain a given object's identity, as a palloc'ed string.
|
||||
*
|
||||
* This is for machine consumption, so it's not translated. All elements are
|
||||
* schema-qualified when appropriate.
|
||||
*/
|
||||
char *
|
||||
getObjectIdentity(const ObjectAddress *object)
|
||||
{
|
||||
return getObjectIdentityParts(object, NULL, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* As above, but more detailed.
|
||||
*
|
||||
* There are two sets of return values: the identity itself as a palloc'd
|
||||
* string is returned. objname and objargs, if not NULL, are output parameters
|
||||
* that receive lists of C-strings that are useful to give back to
|
||||
* get_object_address() to reconstruct the ObjectAddress.
|
||||
*/
|
||||
char *
|
||||
getObjectIdentityParts(const ObjectAddress *object,
|
||||
List **objname, List **objargs)
|
||||
{
|
||||
StringInfoData buffer;
|
||||
|
||||
initStringInfo(&buffer);
|
||||
|
||||
/*
|
||||
* Make sure that both objname and objargs were passed, or none was; and
|
||||
* initialize them to empty lists. For objname this is useless because it
|
||||
* will be initialized in all cases inside the switch; but we do it anyway
|
||||
* so that we can test below that no branch leaves it unset.
|
||||
*/
|
||||
Assert(PointerIsValid(objname) == PointerIsValid(objargs));
|
||||
if (objname)
|
||||
{
|
||||
*objname = NIL;
|
||||
*objargs = NIL;
|
||||
}
|
||||
|
||||
switch (getObjectClass(object))
|
||||
{
|
||||
case OCLASS_CLASS:
|
||||
getRelationIdentity(&buffer, object->objectId);
|
||||
getRelationIdentity(&buffer, object->objectId, objname);
|
||||
if (object->objectSubId != 0)
|
||||
{
|
||||
char *attr;
|
||||
@ -3210,17 +3300,27 @@ getObjectIdentity(const ObjectAddress *object)
|
||||
attr = get_relid_attribute_name(object->objectId,
|
||||
object->objectSubId);
|
||||
appendStringInfo(&buffer, ".%s", quote_identifier(attr));
|
||||
if (objname)
|
||||
*objname = lappend(*objname, attr);
|
||||
}
|
||||
break;
|
||||
|
||||
case OCLASS_PROC:
|
||||
appendStringInfoString(&buffer,
|
||||
format_procedure_qualified(object->objectId));
|
||||
if (objname)
|
||||
format_procedure_parts(object->objectId, objname, objargs);
|
||||
break;
|
||||
|
||||
case OCLASS_TYPE:
|
||||
appendStringInfoString(&buffer,
|
||||
format_type_be_qualified(object->objectId));
|
||||
{
|
||||
char *typeout;
|
||||
|
||||
typeout = format_type_be_qualified(object->objectId);
|
||||
appendStringInfoString(&buffer, typeout);
|
||||
if (objname)
|
||||
*objname = list_make1(typeout);
|
||||
}
|
||||
break;
|
||||
|
||||
case OCLASS_CAST:
|
||||
@ -3243,6 +3343,12 @@ getObjectIdentity(const ObjectAddress *object)
|
||||
format_type_be_qualified(castForm->castsource),
|
||||
format_type_be_qualified(castForm->casttarget));
|
||||
|
||||
if (objname)
|
||||
{
|
||||
*objname = list_make1(format_type_be_qualified(castForm->castsource));
|
||||
*objargs = list_make1(format_type_be_qualified(castForm->casttarget));
|
||||
}
|
||||
|
||||
heap_close(castRel, AccessShareLock);
|
||||
break;
|
||||
}
|
||||
@ -3263,6 +3369,8 @@ getObjectIdentity(const ObjectAddress *object)
|
||||
appendStringInfoString(&buffer,
|
||||
quote_qualified_identifier(schema,
|
||||
NameStr(coll->collname)));
|
||||
if (objname)
|
||||
*objname = list_make2(schema, NameStr(coll->collname));
|
||||
ReleaseSysCache(collTup);
|
||||
break;
|
||||
}
|
||||
@ -3283,19 +3391,25 @@ getObjectIdentity(const ObjectAddress *object)
|
||||
{
|
||||
appendStringInfo(&buffer, "%s on ",
|
||||
quote_identifier(NameStr(con->conname)));
|
||||
getRelationIdentity(&buffer, con->conrelid);
|
||||
getRelationIdentity(&buffer, con->conrelid, objname);
|
||||
if (objname)
|
||||
*objname = lappend(*objname, pstrdup(NameStr(con->conname)));
|
||||
}
|
||||
else
|
||||
{
|
||||
ObjectAddress domain;
|
||||
|
||||
Assert(OidIsValid(con->contypid));
|
||||
domain.classId = TypeRelationId;
|
||||
domain.objectId = con->contypid;
|
||||
domain.objectSubId = 0;
|
||||
|
||||
appendStringInfo(&buffer, "%s on %s",
|
||||
quote_identifier(NameStr(con->conname)),
|
||||
getObjectIdentity(&domain));
|
||||
getObjectIdentityParts(&domain, objname, objargs));
|
||||
|
||||
if (objname)
|
||||
*objargs = lappend(*objargs, pstrdup(NameStr(con->conname)));
|
||||
}
|
||||
|
||||
ReleaseSysCache(conTup);
|
||||
@ -3315,6 +3429,8 @@ getObjectIdentity(const ObjectAddress *object)
|
||||
conForm = (Form_pg_conversion) GETSTRUCT(conTup);
|
||||
appendStringInfoString(&buffer,
|
||||
quote_identifier(NameStr(conForm->conname)));
|
||||
if (objname)
|
||||
*objname = list_make1(pstrdup(NameStr(conForm->conname)));
|
||||
ReleaseSysCache(conTup);
|
||||
break;
|
||||
}
|
||||
@ -3352,7 +3468,8 @@ getObjectIdentity(const ObjectAddress *object)
|
||||
colobject.objectSubId = attrdef->adnum;
|
||||
|
||||
appendStringInfo(&buffer, "for %s",
|
||||
getObjectIdentity(&colobject));
|
||||
getObjectIdentityParts(&colobject,
|
||||
objname, objargs));
|
||||
|
||||
systable_endscan(adscan);
|
||||
heap_close(attrdefDesc, AccessShareLock);
|
||||
@ -3372,17 +3489,23 @@ getObjectIdentity(const ObjectAddress *object)
|
||||
langForm = (Form_pg_language) GETSTRUCT(langTup);
|
||||
appendStringInfoString(&buffer,
|
||||
quote_identifier(NameStr(langForm->lanname)));
|
||||
if (objname)
|
||||
*objname = list_make1(pstrdup(NameStr(langForm->lanname)));
|
||||
ReleaseSysCache(langTup);
|
||||
break;
|
||||
}
|
||||
case OCLASS_LARGEOBJECT:
|
||||
appendStringInfo(&buffer, "%u",
|
||||
object->objectId);
|
||||
if (objname)
|
||||
*objname = list_make1(psprintf("%u", object->objectId));
|
||||
break;
|
||||
|
||||
case OCLASS_OPERATOR:
|
||||
appendStringInfoString(&buffer,
|
||||
format_operator_qualified(object->objectId));
|
||||
if (objname)
|
||||
format_operator_parts(object->objectId, objname, objargs);
|
||||
break;
|
||||
|
||||
case OCLASS_OPCLASS:
|
||||
@ -3413,14 +3536,19 @@ getObjectIdentity(const ObjectAddress *object)
|
||||
NameStr(opcForm->opcname)));
|
||||
appendStringInfo(&buffer, " for %s",
|
||||
quote_identifier(NameStr(amForm->amname)));
|
||||
|
||||
if (objname)
|
||||
{
|
||||
*objname = list_make2(pstrdup(schema),
|
||||
pstrdup(NameStr(opcForm->opcname)));
|
||||
*objargs = list_make1(pstrdup(NameStr(amForm->amname)));
|
||||
}
|
||||
ReleaseSysCache(amTup);
|
||||
ReleaseSysCache(opcTup);
|
||||
break;
|
||||
}
|
||||
|
||||
case OCLASS_OPFAMILY:
|
||||
getOpFamilyIdentity(&buffer, object->objectId);
|
||||
getOpFamilyIdentity(&buffer, object->objectId, objname, objargs);
|
||||
break;
|
||||
|
||||
case OCLASS_AMOP:
|
||||
@ -3432,6 +3560,10 @@ getObjectIdentity(const ObjectAddress *object)
|
||||
Form_pg_amop amopForm;
|
||||
StringInfoData opfam;
|
||||
|
||||
/* no objname support here */
|
||||
if (objname)
|
||||
*objname = NIL;
|
||||
|
||||
amopDesc = heap_open(AccessMethodOperatorRelationId,
|
||||
AccessShareLock);
|
||||
|
||||
@ -3452,7 +3584,7 @@ getObjectIdentity(const ObjectAddress *object)
|
||||
amopForm = (Form_pg_amop) GETSTRUCT(tup);
|
||||
|
||||
initStringInfo(&opfam);
|
||||
getOpFamilyIdentity(&opfam, amopForm->amopfamily);
|
||||
getOpFamilyIdentity(&opfam, amopForm->amopfamily, NULL, NULL);
|
||||
|
||||
appendStringInfo(&buffer, "operator %d (%s, %s) of %s",
|
||||
amopForm->amopstrategy,
|
||||
@ -3476,6 +3608,10 @@ getObjectIdentity(const ObjectAddress *object)
|
||||
Form_pg_amproc amprocForm;
|
||||
StringInfoData opfam;
|
||||
|
||||
/* no objname support here */
|
||||
if (objname)
|
||||
*objname = NIL;
|
||||
|
||||
amprocDesc = heap_open(AccessMethodProcedureRelationId,
|
||||
AccessShareLock);
|
||||
|
||||
@ -3496,7 +3632,7 @@ getObjectIdentity(const ObjectAddress *object)
|
||||
amprocForm = (Form_pg_amproc) GETSTRUCT(tup);
|
||||
|
||||
initStringInfo(&opfam);
|
||||
getOpFamilyIdentity(&opfam, amprocForm->amprocfamily);
|
||||
getOpFamilyIdentity(&opfam, amprocForm->amprocfamily, NULL, NULL);
|
||||
|
||||
appendStringInfo(&buffer, "function %d (%s, %s) of %s",
|
||||
amprocForm->amprocnum,
|
||||
@ -3529,7 +3665,9 @@ getObjectIdentity(const ObjectAddress *object)
|
||||
|
||||
appendStringInfo(&buffer, "%s on ",
|
||||
quote_identifier(NameStr(rule->rulename)));
|
||||
getRelationIdentity(&buffer, rule->ev_class);
|
||||
getRelationIdentity(&buffer, rule->ev_class, objname);
|
||||
if (objname)
|
||||
*objname = lappend(*objname, NameStr(rule->rulename));
|
||||
|
||||
heap_close(ruleDesc, AccessShareLock);
|
||||
break;
|
||||
@ -3553,7 +3691,9 @@ getObjectIdentity(const ObjectAddress *object)
|
||||
|
||||
appendStringInfo(&buffer, "%s on ",
|
||||
quote_identifier(NameStr(trig->tgname)));
|
||||
getRelationIdentity(&buffer, trig->tgrelid);
|
||||
getRelationIdentity(&buffer, trig->tgrelid, objname);
|
||||
if (objname)
|
||||
*objname = lappend(*objname, NameStr(trig->tgname));
|
||||
|
||||
heap_close(trigDesc, AccessShareLock);
|
||||
break;
|
||||
@ -3577,7 +3717,9 @@ getObjectIdentity(const ObjectAddress *object)
|
||||
|
||||
appendStringInfo(&buffer, "%s on ",
|
||||
quote_identifier(NameStr(policy->polname)));
|
||||
getRelationIdentity(&buffer, policy->polrelid);
|
||||
getRelationIdentity(&buffer, policy->polrelid, objname);
|
||||
if (objname)
|
||||
*objname = lappend(*objname, NameStr(policy->polname));
|
||||
|
||||
heap_close(polDesc, AccessShareLock);
|
||||
break;
|
||||
@ -3593,6 +3735,8 @@ getObjectIdentity(const ObjectAddress *object)
|
||||
object->objectId);
|
||||
appendStringInfoString(&buffer,
|
||||
quote_identifier(nspname));
|
||||
if (objname)
|
||||
*objname = list_make1(nspname);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -3612,6 +3756,9 @@ getObjectIdentity(const ObjectAddress *object)
|
||||
appendStringInfoString(&buffer,
|
||||
quote_qualified_identifier(schema,
|
||||
NameStr(formParser->prsname)));
|
||||
if (objname)
|
||||
*objname = list_make2(schema,
|
||||
pstrdup(NameStr(formParser->prsname)));
|
||||
ReleaseSysCache(tup);
|
||||
break;
|
||||
}
|
||||
@ -3632,6 +3779,9 @@ getObjectIdentity(const ObjectAddress *object)
|
||||
appendStringInfoString(&buffer,
|
||||
quote_qualified_identifier(schema,
|
||||
NameStr(formDict->dictname)));
|
||||
if (objname)
|
||||
*objname = list_make2(schema,
|
||||
pstrdup(NameStr(formDict->dictname)));
|
||||
ReleaseSysCache(tup);
|
||||
break;
|
||||
}
|
||||
@ -3652,7 +3802,9 @@ getObjectIdentity(const ObjectAddress *object)
|
||||
appendStringInfoString(&buffer,
|
||||
quote_qualified_identifier(schema,
|
||||
NameStr(formTmpl->tmplname)));
|
||||
pfree(schema);
|
||||
if (objname)
|
||||
*objname = list_make2(schema,
|
||||
pstrdup(NameStr(formTmpl->tmplname)));
|
||||
ReleaseSysCache(tup);
|
||||
break;
|
||||
}
|
||||
@ -3673,6 +3825,9 @@ getObjectIdentity(const ObjectAddress *object)
|
||||
appendStringInfoString(&buffer,
|
||||
quote_qualified_identifier(schema,
|
||||
NameStr(formCfg->cfgname)));
|
||||
if (objname)
|
||||
*objname = list_make2(schema,
|
||||
pstrdup(NameStr(formCfg->cfgname)));
|
||||
ReleaseSysCache(tup);
|
||||
break;
|
||||
}
|
||||
@ -3682,6 +3837,8 @@ getObjectIdentity(const ObjectAddress *object)
|
||||
char *username;
|
||||
|
||||
username = GetUserNameFromId(object->objectId);
|
||||
if (objname)
|
||||
*objname = list_make1(username);
|
||||
appendStringInfoString(&buffer,
|
||||
quote_identifier(username));
|
||||
break;
|
||||
@ -3695,6 +3852,8 @@ getObjectIdentity(const ObjectAddress *object)
|
||||
if (!datname)
|
||||
elog(ERROR, "cache lookup failed for database %u",
|
||||
object->objectId);
|
||||
if (objname)
|
||||
*objname = list_make1(datname);
|
||||
appendStringInfoString(&buffer,
|
||||
quote_identifier(datname));
|
||||
break;
|
||||
@ -3708,6 +3867,8 @@ getObjectIdentity(const ObjectAddress *object)
|
||||
if (!tblspace)
|
||||
elog(ERROR, "cache lookup failed for tablespace %u",
|
||||
object->objectId);
|
||||
if (objname)
|
||||
*objname = list_make1(tblspace);
|
||||
appendStringInfoString(&buffer,
|
||||
quote_identifier(tblspace));
|
||||
break;
|
||||
@ -3719,6 +3880,8 @@ getObjectIdentity(const ObjectAddress *object)
|
||||
|
||||
fdw = GetForeignDataWrapper(object->objectId);
|
||||
appendStringInfoString(&buffer, quote_identifier(fdw->fdwname));
|
||||
if (objname)
|
||||
*objname = list_make1(pstrdup(fdw->fdwname));
|
||||
break;
|
||||
}
|
||||
|
||||
@ -3729,6 +3892,8 @@ getObjectIdentity(const ObjectAddress *object)
|
||||
srv = GetForeignServer(object->objectId);
|
||||
appendStringInfoString(&buffer,
|
||||
quote_identifier(srv->servername));
|
||||
if (objname)
|
||||
*objname = list_make1(pstrdup(srv->servername));
|
||||
break;
|
||||
}
|
||||
|
||||
@ -3738,6 +3903,10 @@ getObjectIdentity(const ObjectAddress *object)
|
||||
Oid useid;
|
||||
const char *usename;
|
||||
|
||||
/* no objname support */
|
||||
if (objname)
|
||||
*objname = NIL;
|
||||
|
||||
tup = SearchSysCache1(USERMAPPINGOID,
|
||||
ObjectIdGetDatum(object->objectId));
|
||||
if (!HeapTupleIsValid(tup))
|
||||
@ -3762,10 +3931,13 @@ getObjectIdentity(const ObjectAddress *object)
|
||||
Relation defaclrel;
|
||||
ScanKeyData skey[1];
|
||||
SysScanDesc rcscan;
|
||||
|
||||
HeapTuple tup;
|
||||
Form_pg_default_acl defacl;
|
||||
|
||||
/* no objname support */
|
||||
if (objname)
|
||||
*objname = NIL;
|
||||
|
||||
defaclrel = heap_open(DefaultAclRelationId, AccessShareLock);
|
||||
|
||||
ScanKeyInit(&skey[0],
|
||||
@ -3832,6 +4004,8 @@ getObjectIdentity(const ObjectAddress *object)
|
||||
elog(ERROR, "cache lookup failed for extension %u",
|
||||
object->objectId);
|
||||
appendStringInfoString(&buffer, quote_identifier(extname));
|
||||
if (objname)
|
||||
*objname = list_make1(extname);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -3840,6 +4014,10 @@ getObjectIdentity(const ObjectAddress *object)
|
||||
HeapTuple tup;
|
||||
Form_pg_event_trigger trigForm;
|
||||
|
||||
/* no objname support here */
|
||||
if (objname)
|
||||
*objname = NIL;
|
||||
|
||||
tup = SearchSysCache1(EVENTTRIGGEROID,
|
||||
ObjectIdGetDatum(object->objectId));
|
||||
if (!HeapTupleIsValid(tup))
|
||||
@ -3860,11 +4038,21 @@ getObjectIdentity(const ObjectAddress *object)
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* If a get_object_address representation was requested, make sure we are
|
||||
* providing one. We don't check for objargs, because many of the cases
|
||||
* above leave it as NIL.
|
||||
*/
|
||||
if (objname && *objname == NIL)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("requested object address for object type that cannot support it")));
|
||||
|
||||
return buffer.data;
|
||||
}
|
||||
|
||||
static void
|
||||
getOpFamilyIdentity(StringInfo buffer, Oid opfid)
|
||||
getOpFamilyIdentity(StringInfo buffer, Oid opfid, List **objname, List **objargs)
|
||||
{
|
||||
HeapTuple opfTup;
|
||||
Form_pg_opfamily opfForm;
|
||||
@ -3889,6 +4077,13 @@ getOpFamilyIdentity(StringInfo buffer, Oid opfid)
|
||||
NameStr(opfForm->opfname)),
|
||||
NameStr(amForm->amname));
|
||||
|
||||
if (objname)
|
||||
{
|
||||
*objname = list_make2(pstrdup(schema),
|
||||
pstrdup(NameStr(opfForm->opfname)));
|
||||
*objargs = list_make1(pstrdup(NameStr(amForm->amname)));
|
||||
}
|
||||
|
||||
ReleaseSysCache(amTup);
|
||||
ReleaseSysCache(opfTup);
|
||||
}
|
||||
@ -3898,7 +4093,7 @@ getOpFamilyIdentity(StringInfo buffer, Oid opfid)
|
||||
* StringInfo.
|
||||
*/
|
||||
static void
|
||||
getRelationIdentity(StringInfo buffer, Oid relid)
|
||||
getRelationIdentity(StringInfo buffer, Oid relid, List **objname)
|
||||
{
|
||||
HeapTuple relTup;
|
||||
Form_pg_class relForm;
|
||||
@ -3914,6 +4109,45 @@ getRelationIdentity(StringInfo buffer, Oid relid)
|
||||
appendStringInfoString(buffer,
|
||||
quote_qualified_identifier(schema,
|
||||
NameStr(relForm->relname)));
|
||||
if (objname)
|
||||
*objname = list_make2(schema, pstrdup(NameStr(relForm->relname)));
|
||||
|
||||
ReleaseSysCache(relTup);
|
||||
}
|
||||
|
||||
/*
|
||||
* Auxiliary function to return a TEXT array out of a list of C-strings.
|
||||
*/
|
||||
ArrayType *
|
||||
strlist_to_textarray(List *list)
|
||||
{
|
||||
ArrayType *arr;
|
||||
Datum *datums;
|
||||
int j = 0;
|
||||
ListCell *cell;
|
||||
MemoryContext memcxt;
|
||||
MemoryContext oldcxt;
|
||||
|
||||
memcxt = AllocSetContextCreate(CurrentMemoryContext,
|
||||
"strlist to array",
|
||||
ALLOCSET_DEFAULT_MINSIZE,
|
||||
ALLOCSET_DEFAULT_INITSIZE,
|
||||
ALLOCSET_DEFAULT_MAXSIZE);
|
||||
oldcxt = MemoryContextSwitchTo(memcxt);
|
||||
|
||||
datums = palloc(sizeof(text *) * list_length(list));
|
||||
foreach(cell, list)
|
||||
{
|
||||
char *name = lfirst(cell);
|
||||
|
||||
datums[j++] = CStringGetTextDatum(name);
|
||||
}
|
||||
|
||||
MemoryContextSwitchTo(oldcxt);
|
||||
|
||||
arr = construct_array(datums, list_length(list),
|
||||
TEXTOID, -1, false, 'i');
|
||||
MemoryContextDelete(memcxt);
|
||||
|
||||
return arr;
|
||||
}
|
||||
|
@ -438,6 +438,41 @@ format_procedure_internal(Oid procedure_oid, bool force_qualify)
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Output a objname/objargs representation for the procedure with the
|
||||
* given OID. If it doesn't exist, an error is thrown.
|
||||
*
|
||||
* This can be used to feed get_object_address.
|
||||
*/
|
||||
void
|
||||
format_procedure_parts(Oid procedure_oid, List **objnames, List **objargs)
|
||||
{
|
||||
HeapTuple proctup;
|
||||
Form_pg_proc procform;
|
||||
int nargs;
|
||||
int i;
|
||||
|
||||
proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(procedure_oid));
|
||||
|
||||
if (!HeapTupleIsValid(proctup))
|
||||
elog(ERROR, "cache lookup failed for procedure with OID %u", procedure_oid);
|
||||
|
||||
procform = (Form_pg_proc) GETSTRUCT(proctup);
|
||||
nargs = procform->pronargs;
|
||||
|
||||
*objnames = list_make2(get_namespace_name(procform->pronamespace),
|
||||
pstrdup(NameStr(procform->proname)));
|
||||
*objargs = NIL;
|
||||
for (i = 0; i < nargs; i++)
|
||||
{
|
||||
Oid thisargtype = procform->proargtypes.values[i];
|
||||
|
||||
*objargs = lappend(*objargs, format_type_be_qualified(thisargtype));
|
||||
}
|
||||
|
||||
ReleaseSysCache(proctup);
|
||||
}
|
||||
|
||||
/*
|
||||
* regprocedureout - converts proc OID to "pro_name(args)"
|
||||
*/
|
||||
@ -875,6 +910,31 @@ format_operator_qualified(Oid operator_oid)
|
||||
return format_operator_internal(operator_oid, true);
|
||||
}
|
||||
|
||||
void
|
||||
format_operator_parts(Oid operator_oid, List **objnames, List **objargs)
|
||||
{
|
||||
HeapTuple opertup;
|
||||
Form_pg_operator oprForm;
|
||||
|
||||
opertup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operator_oid));
|
||||
if (!HeapTupleIsValid(opertup))
|
||||
elog(ERROR, "cache lookup failed for operator with OID %u",
|
||||
operator_oid);
|
||||
|
||||
oprForm = (Form_pg_operator) GETSTRUCT(opertup);
|
||||
*objnames = list_make2(get_namespace_name(oprForm->oprnamespace),
|
||||
pstrdup(NameStr(oprForm->oprname)));
|
||||
*objargs = NIL;
|
||||
if (oprForm->oprleft)
|
||||
*objargs = lappend(*objargs,
|
||||
format_type_be_qualified(oprForm->oprleft));
|
||||
if (oprForm->oprright)
|
||||
*objargs = lappend(*objargs,
|
||||
format_type_be_qualified(oprForm->oprright));
|
||||
|
||||
ReleaseSysCache(opertup);
|
||||
}
|
||||
|
||||
/*
|
||||
* regoperatorout - converts operator OID to "opr_name(args)"
|
||||
*/
|
||||
|
@ -53,6 +53,6 @@
|
||||
*/
|
||||
|
||||
/* yyyymmddN */
|
||||
#define CATALOG_VERSION_NO 201412234
|
||||
#define CATALOG_VERSION_NO 201412301
|
||||
|
||||
#endif
|
||||
|
@ -58,5 +58,8 @@ extern char *getObjectDescriptionOids(Oid classid, Oid objid);
|
||||
extern int read_objtype_from_string(const char *objtype);
|
||||
extern char *getObjectTypeDescription(const ObjectAddress *object);
|
||||
extern char *getObjectIdentity(const ObjectAddress *address);
|
||||
extern char *getObjectIdentityParts(const ObjectAddress *address,
|
||||
List **objname, List **objargs);
|
||||
extern ArrayType *strlist_to_textarray(List *list);
|
||||
|
||||
#endif /* OBJECTADDRESS_H */
|
||||
|
@ -3036,6 +3036,9 @@ DESCR("get identification of SQL object");
|
||||
DATA(insert OID = 3839 ( pg_identify_object PGNSP PGUID 12 1 0 0 0 f f f f t f s 3 0 2249 "26 26 23" "{26,26,23,25,25,25,25}" "{i,i,i,o,o,o,o}" "{classid,objid,subobjid,type,schema,name,identity}" _null_ pg_identify_object _null_ _null_ _null_ ));
|
||||
DESCR("get machine-parseable identification of SQL object");
|
||||
|
||||
DATA(insert OID = 3382 ( pg_identify_object_as_address PGNSP PGUID 12 1 0 0 0 f f f f t f s 3 0 2249 "26 26 23" "{26,26,23,25,1009,1009}" "{i,i,i,o,o,o}" "{classid,objid,subobjid,type,object_names,object_args}" _null_ pg_identify_object_as_address _null_ _null_ _null_ ));
|
||||
DESCR("get identification of SQL object for pg_get_object_address()");
|
||||
|
||||
DATA(insert OID = 3954 ( pg_get_object_address PGNSP PGUID 12 1 0 0 0 f f f f t f s 3 0 2249 "25 1009 1009" "{25,1009,1009,26,26,23}" "{i,i,i,o,o,o}" "{type,name,args,classid,objid,subobjid}" _null_ pg_get_object_address _null_ _null_ _null_ ));
|
||||
DESCR("get OID-based object address from name/args arrays");
|
||||
|
||||
|
@ -642,8 +642,12 @@ extern Datum text_regclass(PG_FUNCTION_ARGS);
|
||||
extern List *stringToQualifiedNameList(const char *string);
|
||||
extern char *format_procedure(Oid procedure_oid);
|
||||
extern char *format_procedure_qualified(Oid procedure_oid);
|
||||
extern void format_procedure_parts(Oid operator_oid, List **objnames,
|
||||
List **objargs);
|
||||
extern char *format_operator(Oid operator_oid);
|
||||
extern char *format_operator_qualified(Oid operator_oid);
|
||||
extern void format_operator_parts(Oid operator_oid, List **objnames,
|
||||
List **objargs);
|
||||
|
||||
/* rowtypes.c */
|
||||
extern Datum record_in(PG_FUNCTION_ARGS);
|
||||
@ -1194,6 +1198,7 @@ extern Datum pg_last_committed_xact(PG_FUNCTION_ARGS);
|
||||
/* catalogs/dependency.c */
|
||||
extern Datum pg_describe_object(PG_FUNCTION_ARGS);
|
||||
extern Datum pg_identify_object(PG_FUNCTION_ARGS);
|
||||
extern Datum pg_identify_object_as_address(PG_FUNCTION_ARGS);
|
||||
|
||||
/* catalog/objectaddress.c */
|
||||
extern Datum pg_get_object_address(PG_FUNCTION_ARGS);
|
||||
|
@ -339,46 +339,51 @@ WITH objects (type, name, args) AS (VALUES
|
||||
-- event trigger
|
||||
('policy', '{addr_nsp, gentable, genpol}', '{}')
|
||||
)
|
||||
SELECT (pg_identify_object(classid, objid, subobjid)).*
|
||||
FROM objects, pg_get_object_address(type, name, args)
|
||||
ORDER BY classid, objid;
|
||||
type | schema | name | identity
|
||||
---------------------------+------------+-------------------+----------------------------------------------------------------------
|
||||
type | pg_catalog | _int4 | integer[]
|
||||
type | addr_nsp | gencomptype | addr_nsp.gencomptype
|
||||
type | addr_nsp | genenum | addr_nsp.genenum
|
||||
type | addr_nsp | gendomain | addr_nsp.gendomain
|
||||
function | pg_catalog | | pg_catalog.pg_identify_object(pg_catalog.oid,pg_catalog.oid,integer)
|
||||
aggregate | addr_nsp | | addr_nsp.genaggr(integer)
|
||||
sequence | addr_nsp | gentable_a_seq | addr_nsp.gentable_a_seq
|
||||
table | addr_nsp | gentable | addr_nsp.gentable
|
||||
table column | addr_nsp | gentable | addr_nsp.gentable.b
|
||||
index | addr_nsp | gentable_pkey | addr_nsp.gentable_pkey
|
||||
view | addr_nsp | genview | addr_nsp.genview
|
||||
materialized view | addr_nsp | genmatview | addr_nsp.genmatview
|
||||
foreign table column | addr_nsp | genftable | addr_nsp.genftable.a
|
||||
foreign table | addr_nsp | genftable | addr_nsp.genftable
|
||||
role | | regtest_addr_user | regtest_addr_user
|
||||
server | | addr_fserv | addr_fserv
|
||||
foreign-data wrapper | | addr_fdw | addr_fdw
|
||||
default value | | | for addr_nsp.gentable.b
|
||||
cast | | | (bigint AS integer)
|
||||
table constraint | addr_nsp | | a_chk on addr_nsp.gentable
|
||||
domain constraint | addr_nsp | | domconstr on addr_nsp.gendomain
|
||||
conversion | pg_catalog | ascii_to_mic | ascii_to_mic
|
||||
language | | plpgsql | plpgsql
|
||||
schema | | addr_nsp | addr_nsp
|
||||
operator class | pg_catalog | int4_ops | pg_catalog.int4_ops for btree
|
||||
operator | pg_catalog | | pg_catalog.+(integer,integer)
|
||||
rule | | | "_RETURN" on addr_nsp.genview
|
||||
trigger | | | t on addr_nsp.gentable
|
||||
operator family | pg_catalog | integer_ops | pg_catalog.integer_ops for btree
|
||||
policy | | | genpol on addr_nsp.gentable
|
||||
collation | pg_catalog | "default" | pg_catalog."default"
|
||||
text search dictionary | addr_nsp | addr_ts_dict | addr_nsp.addr_ts_dict
|
||||
text search parser | addr_nsp | addr_ts_prs | addr_nsp.addr_ts_prs
|
||||
text search configuration | addr_nsp | addr_ts_conf | addr_nsp.addr_ts_conf
|
||||
text search template | addr_nsp | addr_ts_temp | addr_nsp.addr_ts_temp
|
||||
SELECT (pg_identify_object(addr1.classid, addr1.objid, addr1.subobjid)).*,
|
||||
-- test roundtrip through pg_identify_object_as_address
|
||||
ROW(pg_identify_object(addr1.classid, addr1.objid, addr1.subobjid)) =
|
||||
ROW(pg_identify_object(addr2.classid, addr2.objid, addr2.subobjid))
|
||||
FROM objects, pg_get_object_address(type, name, args) addr1,
|
||||
pg_identify_object_as_address(classid, objid, subobjid) ioa(typ,nms,args),
|
||||
pg_get_object_address(typ, nms, ioa.args) as addr2
|
||||
ORDER BY addr1.classid, addr1.objid;
|
||||
type | schema | name | identity | ?column?
|
||||
---------------------------+------------+-------------------+----------------------------------------------------------------------+----------
|
||||
type | pg_catalog | _int4 | integer[] | t
|
||||
type | addr_nsp | gencomptype | addr_nsp.gencomptype | t
|
||||
type | addr_nsp | genenum | addr_nsp.genenum | t
|
||||
type | addr_nsp | gendomain | addr_nsp.gendomain | t
|
||||
function | pg_catalog | | pg_catalog.pg_identify_object(pg_catalog.oid,pg_catalog.oid,integer) | t
|
||||
aggregate | addr_nsp | | addr_nsp.genaggr(integer) | t
|
||||
sequence | addr_nsp | gentable_a_seq | addr_nsp.gentable_a_seq | t
|
||||
table | addr_nsp | gentable | addr_nsp.gentable | t
|
||||
table column | addr_nsp | gentable | addr_nsp.gentable.b | t
|
||||
index | addr_nsp | gentable_pkey | addr_nsp.gentable_pkey | t
|
||||
view | addr_nsp | genview | addr_nsp.genview | t
|
||||
materialized view | addr_nsp | genmatview | addr_nsp.genmatview | t
|
||||
foreign table column | addr_nsp | genftable | addr_nsp.genftable.a | t
|
||||
foreign table | addr_nsp | genftable | addr_nsp.genftable | t
|
||||
role | | regtest_addr_user | regtest_addr_user | t
|
||||
server | | addr_fserv | addr_fserv | t
|
||||
foreign-data wrapper | | addr_fdw | addr_fdw | t
|
||||
default value | | | for addr_nsp.gentable.b | t
|
||||
cast | | | (bigint AS integer) | t
|
||||
table constraint | addr_nsp | | a_chk on addr_nsp.gentable | t
|
||||
domain constraint | addr_nsp | | domconstr on addr_nsp.gendomain | t
|
||||
conversion | pg_catalog | ascii_to_mic | ascii_to_mic | t
|
||||
language | | plpgsql | plpgsql | t
|
||||
schema | | addr_nsp | addr_nsp | t
|
||||
operator class | pg_catalog | int4_ops | pg_catalog.int4_ops for btree | t
|
||||
operator | pg_catalog | | pg_catalog.+(integer,integer) | t
|
||||
rule | | | "_RETURN" on addr_nsp.genview | t
|
||||
trigger | | | t on addr_nsp.gentable | t
|
||||
operator family | pg_catalog | integer_ops | pg_catalog.integer_ops for btree | t
|
||||
policy | | | genpol on addr_nsp.gentable | t
|
||||
collation | pg_catalog | "default" | pg_catalog."default" | t
|
||||
text search dictionary | addr_nsp | addr_ts_dict | addr_nsp.addr_ts_dict | t
|
||||
text search parser | addr_nsp | addr_ts_prs | addr_nsp.addr_ts_prs | t
|
||||
text search configuration | addr_nsp | addr_ts_conf | addr_nsp.addr_ts_conf | t
|
||||
text search template | addr_nsp | addr_ts_temp | addr_nsp.addr_ts_temp | t
|
||||
(35 rows)
|
||||
|
||||
---
|
||||
|
@ -159,9 +159,14 @@ WITH objects (type, name, args) AS (VALUES
|
||||
-- event trigger
|
||||
('policy', '{addr_nsp, gentable, genpol}', '{}')
|
||||
)
|
||||
SELECT (pg_identify_object(classid, objid, subobjid)).*
|
||||
FROM objects, pg_get_object_address(type, name, args)
|
||||
ORDER BY classid, objid;
|
||||
SELECT (pg_identify_object(addr1.classid, addr1.objid, addr1.subobjid)).*,
|
||||
-- test roundtrip through pg_identify_object_as_address
|
||||
ROW(pg_identify_object(addr1.classid, addr1.objid, addr1.subobjid)) =
|
||||
ROW(pg_identify_object(addr2.classid, addr2.objid, addr2.subobjid))
|
||||
FROM objects, pg_get_object_address(type, name, args) addr1,
|
||||
pg_identify_object_as_address(classid, objid, subobjid) ioa(typ,nms,args),
|
||||
pg_get_object_address(typ, nms, ioa.args) as addr2
|
||||
ORDER BY addr1.classid, addr1.objid;
|
||||
|
||||
---
|
||||
--- Cleanup resources
|
||||
|
Loading…
Reference in New Issue
Block a user