>From 92562fa5cd116e1a11cc93d275ff6079639d4cf4 Mon Sep 17 00:00:00 2001
From: Alvaro Herrera <alvherre@alvh.no-ip.org>
Date: Wed, 15 Oct 2014 18:02:45 -0300
Subject: [PATCH 2/5] add support for OBJECT_DEFAULT in get_object_address

---
 src/backend/catalog/objectaddress.c  | 91 ++++++++++++++++++++++++++++++++++++
 src/backend/commands/event_trigger.c |  1 +
 src/include/nodes/parsenodes.h       |  1 +
 3 files changed, 93 insertions(+)

diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c
index 297deb5..7a0b24b 100644
--- a/src/backend/catalog/objectaddress.c
+++ b/src/backend/catalog/objectaddress.c
@@ -441,6 +441,9 @@ static ObjectAddress get_object_address_relobject(ObjectType objtype,
 static ObjectAddress get_object_address_attribute(ObjectType objtype,
 							 List *objname, Relation *relp,
 							 LOCKMODE lockmode, bool missing_ok);
+static ObjectAddress get_object_address_attrdef(ObjectType objtype,
+						   List *objname, Relation *relp, LOCKMODE lockmode,
+						   bool missing_ok);
 static ObjectAddress get_object_address_type(ObjectType objtype,
 						List *objname, bool missing_ok);
 static ObjectAddress get_object_address_opcf(ObjectType objtype, List *objname,
@@ -528,6 +531,12 @@ get_object_address(ObjectType objtype, List *objname, List *objargs,
 												 &relation, lockmode,
 												 missing_ok);
 				break;
+			case OBJECT_DEFAULT:
+				address =
+					get_object_address_attrdef(objtype, objname,
+											   &relation, lockmode,
+											   missing_ok);
+				break;
 			case OBJECT_RULE:
 			case OBJECT_TRIGGER:
 			case OBJECT_TABCONSTRAINT:
@@ -1097,6 +1106,88 @@ get_object_address_attribute(ObjectType objtype, List *objname,
 }
 
 /*
+ * Find the ObjectAddress for an attribute's default value.
+ */
+static ObjectAddress
+get_object_address_attrdef(ObjectType objtype, List *objname,
+						   Relation *relp, LOCKMODE lockmode,
+						   bool missing_ok)
+{
+	ObjectAddress address;
+	List	   *relname;
+	Oid			reloid;
+	Relation	relation;
+	const char *attname;
+	AttrNumber	attnum;
+	TupleDesc	tupdesc;
+	Oid			defoid;
+
+	/* Extract relation name and open relation. */
+	if (list_length(objname) < 2)
+		ereport(ERROR,
+				(errcode(ERRCODE_SYNTAX_ERROR),
+				 errmsg("column name must be qualified")));
+	attname = strVal(llast(objname));
+	relname = list_truncate(list_copy(objname), list_length(objname) - 1);
+	/* XXX no missing_ok support here */
+	relation = relation_openrv(makeRangeVarFromNameList(relname), lockmode);
+	reloid = RelationGetRelid(relation);
+
+	tupdesc = RelationGetDescr(relation);
+
+	/* Look up attribute number and scan pg_attrdef to find its tuple */
+	attnum = get_attnum(reloid, attname);
+	defoid = InvalidOid;
+	if (attnum != InvalidAttrNumber && tupdesc->constr != NULL)
+	{
+		Relation	attrdef;
+		ScanKeyData	keys[2];
+		SysScanDesc	scan;
+		HeapTuple	tup;
+
+		attrdef = relation_open(AttrDefaultRelationId, AccessShareLock);
+		ScanKeyInit(&keys[0],
+					Anum_pg_attrdef_adrelid,
+					BTEqualStrategyNumber,
+					F_OIDEQ,
+					ObjectIdGetDatum(reloid));
+		ScanKeyInit(&keys[1],
+					Anum_pg_attrdef_adnum,
+					BTEqualStrategyNumber,
+					F_INT2EQ,
+					Int16GetDatum(attnum));
+		scan = systable_beginscan(attrdef, AttrDefaultIndexId, true,
+								  NULL, 2, keys);
+		if (HeapTupleIsValid(tup = systable_getnext(scan)))
+			defoid = HeapTupleGetOid(tup);
+
+		systable_endscan(scan);
+		relation_close(attrdef, AccessShareLock);
+	}
+	if (!OidIsValid(defoid))
+	{
+		if (!missing_ok)
+			ereport(ERROR,
+					(errcode(ERRCODE_UNDEFINED_COLUMN),
+					 errmsg("default value for column \"%s\" of relation \"%s\" does not exist",
+							attname, NameListToString(relname))));
+
+		address.classId = AttrDefaultRelationId;
+		address.objectId = InvalidOid;
+		address.objectSubId = InvalidAttrNumber;
+		relation_close(relation, lockmode);
+		return address;
+	}
+
+	address.classId = AttrDefaultRelationId;
+	address.objectId = defoid;
+	address.objectSubId = 0;
+
+	*relp = relation;
+	return address;
+}
+
+/*
  * Find the ObjectAddress for a type or domain
  */
 static ObjectAddress
diff --git a/src/backend/commands/event_trigger.c b/src/backend/commands/event_trigger.c
index 6bdb774..34dd3c0 100644
--- a/src/backend/commands/event_trigger.c
+++ b/src/backend/commands/event_trigger.c
@@ -1055,6 +1055,7 @@ EventTriggerSupportsObjectType(ObjectType obtype)
 		case OBJECT_COLUMN:
 		case OBJECT_COLLATION:
 		case OBJECT_CONVERSION:
+		case OBJECT_DEFAULT:
 		case OBJECT_DOMAIN:
 		case OBJECT_DOMCONSTRAINT:
 		case OBJECT_EXTENSION:
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 64508f0..35e7b28 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -1211,6 +1211,7 @@ typedef enum ObjectType
 	OBJECT_COLLATION,
 	OBJECT_CONVERSION,
 	OBJECT_DATABASE,
+	OBJECT_DEFAULT,
 	OBJECT_DOMAIN,
 	OBJECT_DOMCONSTRAINT,
 	OBJECT_EVENT_TRIGGER,
-- 
2.1.3

