diff --git a/contrib/adminpack/adminpack.control b/contrib/adminpack/adminpack.control
index 5f4331d..79562b0 100644
*** a/contrib/adminpack/adminpack.control
--- b/contrib/adminpack/adminpack.control
***************
*** 2,5 ****
  comment = 'Administrative functions for PostgreSQL'
  version = '9.1devel'
  relocatable = false
! schema = 'pg_catalog'
\ No newline at end of file
--- 2,5 ----
  comment = 'Administrative functions for PostgreSQL'
  version = '9.1devel'
  relocatable = false
! schema = 'pg_catalog'
diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c
index ec463d3..f4bb6db 100644
*** a/src/backend/catalog/dependency.c
--- b/src/backend/catalog/dependency.c
***************
*** 79,84 ****
--- 79,113 ----
  #include "utils/tqual.h"
  
  
+ /*
+  * Deletion processing requires additional state for each ObjectAddress that
+  * it's planning to delete.  For simplicity and code-sharing we make the
+  * ObjectAddresses code support arrays with or without this extra state.
+  */
+ typedef struct
+ {
+ 	int			flags;			/* bitmask, see bit definitions below */
+ 	ObjectAddress dependee;		/* object whose deletion forced this one */
+ } ObjectAddressExtra;
+ 
+ /* ObjectAddressExtra flag bits */
+ #define DEPFLAG_ORIGINAL	0x0001		/* an original deletion target */
+ #define DEPFLAG_NORMAL		0x0002		/* reached via normal dependency */
+ #define DEPFLAG_AUTO		0x0004		/* reached via auto dependency */
+ #define DEPFLAG_INTERNAL	0x0008		/* reached via internal dependency */
+ 
+ 
+ /* expansible list of ObjectAddresses */
+ struct ObjectAddresses
+ {
+ 	ObjectAddress *refs;		/* => palloc'd array */
+ 	ObjectAddressExtra *extras; /* => palloc'd array, or NULL if not used */
+ 	int			numrefs;		/* current number of references */
+ 	int			maxrefs;		/* current size of palloc'd array(s) */
+ };
+ 
+ /* typedef ObjectAddresses appears in dependency.h */
+ 
  /* threaded list of ObjectAddresses, for recursion detection */
  typedef struct ObjectAddressStack
  {
*************** findDependentObjects(const ObjectAddress
*** 525,530 ****
--- 554,560 ----
  				/* no problem */
  				break;
  			case DEPENDENCY_INTERNAL:
+ 
  				/*
  				 * This object is part of the internal implementation of
  				 * another object.	We have four cases:
diff --git a/src/backend/catalog/pg_depend.c b/src/backend/catalog/pg_depend.c
index 4be6490..1810a71 100644
*** a/src/backend/catalog/pg_depend.c
--- b/src/backend/catalog/pg_depend.c
*************** changeDependencyTypeFor(Oid objid,
*** 328,334 ****
  	return count;
  }
  
- 
  /*
   * isObjectPinned()
   *
--- 328,333 ----
diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c
index d7d99d2..40bc2cb 100644
*** a/src/backend/catalog/pg_proc.c
--- b/src/backend/catalog/pg_proc.c
*************** ProcedureCreate(const char *procedureNam
*** 626,632 ****
  	{
  		recordDependencyOn(&myself, &CreateExtensionAddress, DEPENDENCY_INTERNAL);
  	}
! 	else if(is_update && OidIsValid(extensionOid))
  	{
  		/* we have to recreate the dependency to the known extension */
  		ObjectAddress extension;
--- 626,632 ----
  	{
  		recordDependencyOn(&myself, &CreateExtensionAddress, DEPENDENCY_INTERNAL);
  	}
! 	else if (is_update && OidIsValid(extensionOid))
  	{
  		/* we have to recreate the dependency to the known extension */
  		ObjectAddress extension;
diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c
index aaa08b0..7b791bf 100644
*** a/src/backend/commands/extension.c
--- b/src/backend/commands/extension.c
***************
*** 17,23 ****
   * parameter, which is the name of the SQL script to run to install the
   * extension.
   *
!  * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
   * Portions Copyright (c) 1994, Regents of the University of California
   *
   *
--- 17,23 ----
   * parameter, which is the name of the SQL script to run to install the
   * extension.
   *
!  * Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
   * Portions Copyright (c) 1994, Regents of the University of California
   *
   *
***************
*** 29,43 ****
  #include "postgres.h"
  
  #include <unistd.h>
- #include <dirent.h>
- #include <sys/types.h>
- #include <sys/stat.h>
  
  #include "access/xact.h"
- #include "access/genam.h"
- #include "access/heapam.h"
  #include "access/sysattr.h"
- #include "catalog/dependency.h"
  #include "catalog/indexing.h"
  #include "catalog/namespace.h"
  #include "catalog/pg_depend.h"
--- 29,37 ----
***************
*** 51,66 ****
  #include "funcapi.h"
  #include "mb/pg_wchar.h"
  #include "miscadmin.h"
- #include "storage/fd.h"
- #include "utils/array.h"
  #include "utils/builtins.h"
  #include "utils/fmgroids.h"
- #include "utils/genfile.h"
  #include "utils/guc.h"
  #include "utils/lsyscache.h"
- #include "utils/memutils.h"
- #include "utils/rel.h"
- #include "utils/syscache.h"
  #include "utils/tqual.h"
  
  /*
--- 45,54 ----
***************
*** 68,74 ****
   */
  ObjectAddress CreateExtensionAddress;
  bool create_extension = false;
! bool create_extension_with_user_data = true;
  
  /*
   * Internal data structures, for control file parsing and listings.
--- 56,63 ----
   */
  ObjectAddress CreateExtensionAddress;
  bool create_extension = false;
! 
! static bool create_extension_with_user_data;
  
  /*
   * Internal data structures, for control file parsing and listings.
*************** typedef struct extension_fctx
*** 101,146 ****
  	ExtensionList *installed;
  } extension_fctx;
  
  /*
   * Utility functions to handle extension related paths
   */
  static bool
! filename_extension_control_p(const char *filename)
! {
! 	return ! ( strcmp(filename, ".") == 0
! 			   || strcmp(filename, "..") == 0
! 			   || strrchr(filename, '.') == NULL
! 			   || strcmp(strrchr(filename, '.'), ".control") != 0 );
! }
! 
! /*
!  * Given the 'name.control' filename, return the extension's name:
!  *
!  * `basename $filename .control`
!  */
! static char *
! get_extension_name_from_control_filename(const char *filename)
  {
! 	if (filename_extension_control_p(filename))
! 	{
! 		char  *extname;
! 		char *slash = strrchr(filename, '/');
! 		char *dot   = strrchr(filename, '.');
! 
! 		if (slash == NULL)
! 			/* relative filename... */
! 			slash = (char *)filename;
! 		else
! 			/* the file ends with .control and has a / before, that's safe */
! 			slash++;
  
! 		extname = palloc(MAXPGPATH);
! 		memset(extname, '\0', MAXPGPATH);
! 		strncpy(extname, slash, dot - slash);
! 		return extname;
! 	}
! 	else
! 		return NULL;
  }
  
  static char *
--- 90,106 ----
  	ExtensionList *installed;
  } extension_fctx;
  
+ static bool extension_is_relocatable(Oid ext_oid);
+ 
  /*
   * Utility functions to handle extension related paths
   */
  static bool
! is_extension_control_filename(const char *filename)
  {
! 	const char *extension = strrchr(filename, '.');
  
! 	return extension != NULL && strcmp(extension, ".control") == 0;
  }
  
  static char *
*************** get_extension_control_basepath(void)
*** 150,156 ****
  	char	   *result;
  
  	get_share_path(my_exec_path, sharepath);
! 	result = palloc(MAXPGPATH);
  	snprintf(result, MAXPGPATH, "%s/contrib", sharepath);
  
  	return result;
--- 110,116 ----
  	char	   *result;
  
  	get_share_path(my_exec_path, sharepath);
! 	result = (char *) palloc(MAXPGPATH);
  	snprintf(result, MAXPGPATH, "%s/contrib", sharepath);
  
  	return result;
*************** get_extension_control_filename(const cha
*** 163,169 ****
  	char	   *result;
  
  	get_share_path(my_exec_path, sharepath);
! 	result = palloc(MAXPGPATH);
  	snprintf(result, MAXPGPATH, "%s/contrib/%s.control", sharepath, extname);
  
  	return result;
--- 123,129 ----
  	char	   *result;
  
  	get_share_path(my_exec_path, sharepath);
! 	result = (char *) palloc(MAXPGPATH);
  	snprintf(result, MAXPGPATH, "%s/contrib/%s.control", sharepath, extname);
  
  	return result;
*************** get_extension_absolute_path(const char *
*** 183,189 ****
  		return (char *)filename;
  
  	get_share_path(my_exec_path, sharepath);
! 	result = palloc(MAXPGPATH);
      snprintf(result, MAXPGPATH, "%s/contrib/%s", sharepath, filename);
  
  	return result;
--- 143,149 ----
  		return (char *)filename;
  
  	get_share_path(my_exec_path, sharepath);
! 	result = (char *) palloc(MAXPGPATH);
      snprintf(result, MAXPGPATH, "%s/contrib/%s", sharepath, filename);
  
  	return result;
*************** parse_extension_control_file(const char 
*** 203,210 ****
  {
  	FILE	   *file;
  	bool		saw_relocatable = false;
! 	ExtensionControlFile *control =
! 		(ExtensionControlFile *)palloc(sizeof(ExtensionControlFile));
  	ConfigVariable *item,
  				   *head = NULL,
  				   *tail = NULL;
--- 163,169 ----
  {
  	FILE	   *file;
  	bool		saw_relocatable = false;
! 	ExtensionControlFile *control;
  	ConfigVariable *item,
  				   *head = NULL,
  				   *tail = NULL;
*************** parse_extension_control_file(const char 
*** 216,224 ****
  	 * default values, all string fields are NULL til parsed, except for the
  	 * name, which ain't parsed
  	 */
  	control->name = pstrdup(extname);
- 	control->script =
- 		control->version = control->comment = control->schema = NULL;
  	control->encoding = -1;
  
  	/*
--- 175,182 ----
  	 * default values, all string fields are NULL til parsed, except for the
  	 * name, which ain't parsed
  	 */
+ 	control = (ExtensionControlFile *) palloc0(sizeof(ExtensionControlFile));
  	control->name = pstrdup(extname);
  	control->encoding = -1;
  
  	/*
*************** parse_extension_control_file(const char 
*** 294,305 ****
  		/*
  		 * script defaults to ${extension-name}.sql
  		 */
! 		char  *script;
  
! 		script = palloc(MAXPGPATH);
! 		memset(script, '\0', MAXPGPATH);
! 		sprintf(script, "%s.sql", control->name);
! 		control->script = script;;
  	}
  
  	if (!saw_relocatable)
--- 252,261 ----
  		/*
  		 * script defaults to ${extension-name}.sql
  		 */
! 		char	script[MAXPGPATH];
  
! 		snprintf(script, MAXPGPATH, "%s.sql", control->name);
! 		control->script = pstrdup(script);
  	}
  
  	if (!saw_relocatable)
*************** read_extension_control_file(const char *
*** 319,335 ****
  {
      char *filename = get_extension_control_filename(extname);
  
! 	if (access(filename, R_OK) == 0)
! 	{
! 		return parse_extension_control_file(extname, filename);
! 	}
! 
! 	ereport(ERROR,
! 			(errmsg("could not read extension control file '%s' "
! 					"for extension %s", filename, extname)));
! 
! 	/* make compiler happy */
! 	return NULL;
  }
  
  /*
--- 275,281 ----
  {
      char *filename = get_extension_control_filename(extname);
  
! 	return parse_extension_control_file(extname, filename);
  }
  
  /*
*************** execute_extension_script(ExtensionContro
*** 413,430 ****
  						 const char *schema, bool user_data)
  {
  	char       *filename = get_extension_absolute_path(control->script);
! 	char       *old_cmsgs = NULL, *old_lmsgs = NULL; /* silence compiler */
! 	bool        reset_cmsgs = false, reset_lmsgs = false;
  	Oid         target_schema;
  	OverrideSearchPath *overridePath;
  
- 	/*
- 	 * Set create_extension and create_extension_with_user_data so that the
- 	 * function pg_extension_with_user_data() returns the right value.
- 	 */
- 	create_extension = true;
- 	create_extension_with_user_data = user_data;
- 
  	elog(DEBUG1,
  		 "Installing extension '%s' from '%s', in schema %s, %s user data",
  		 control->name,
--- 359,369 ----
  						 const char *schema, bool user_data)
  {
  	char       *filename = get_extension_absolute_path(control->script);
! 	char	   *save_client_min_messages = NULL,
! 			   *save_log_min_messages = NULL;
  	Oid         target_schema;
  	OverrideSearchPath *overridePath;
  
  	elog(DEBUG1,
  		 "Installing extension '%s' from '%s', in schema %s, %s user data",
  		 control->name,
*************** execute_extension_script(ExtensionContro
*** 441,458 ****
  	 *
  	 * We want to avoid dumping the full script for each of those.
  	 */
! 	reset_cmsgs = client_min_messages < WARNING;
! 	reset_lmsgs = log_min_messages < WARNING;
! 
! 	if (reset_cmsgs)
  	{
! 		old_cmsgs = pstrdup((char *)GetConfigOption("client_min_messages", false));
! 		SetConfigOption("client_min_messages", "warning", PGC_SUSET, PGC_S_SESSION);
  	}
! 	if (reset_lmsgs)
  	{
! 		old_lmsgs = pstrdup((char *)GetConfigOption("log_min_messages", false));
! 		SetConfigOption("log_min_messages", "warning", PGC_SUSET, PGC_S_SESSION);
  	}
  
  	target_schema = LookupCreationNamespace(schema);
--- 380,399 ----
  	 *
  	 * We want to avoid dumping the full script for each of those.
  	 */
! 	if (client_min_messages < WARNING)
  	{
! 		save_client_min_messages =
! 			pstrdup(GetConfigOption("client_min_messages", false));
! 		SetConfigOption("client_min_messages", "warning",
! 						PGC_SUSET, PGC_S_SESSION);
  	}
! 
! 	if (log_min_messages < WARNING)
  	{
! 		save_log_min_messages =
! 			pstrdup(GetConfigOption("log_min_messages", false));
! 		SetConfigOption("log_min_messages", "warning",
! 						PGC_SUSET, PGC_S_SESSION);
  	}
  
  	target_schema = LookupCreationNamespace(schema);
*************** execute_extension_script(ExtensionContro
*** 468,475 ****
--- 409,420 ----
  	PushOverrideSearchPath(overridePath);
  
  	/*
+ 	 * Set create_extension and create_extension_with_user_data so that
+ 	 * the function pg_extension_with_user_data() returns the right value.
  	 * On failure, ensure that create_extension does not remain set.
  	 */
+ 	create_extension = true;
+ 	create_extension_with_user_data = user_data;
  	PG_TRY();
  	{
  		char *sql = read_extension_script_file(control);
*************** execute_extension_script(ExtensionContro
*** 542,559 ****
  	}
  	PG_END_TRY();
  
- 	/* Reset search path to normal state */
- 	PopOverrideSearchPath();
- 
- 	if (reset_cmsgs)
- 		SetConfigOption("client_min_messages",
- 						old_cmsgs, PGC_SUSET, PGC_S_SESSION);
- 	if (reset_lmsgs)
- 		SetConfigOption("log_min_messages",
- 						old_lmsgs, PGC_SUSET, PGC_S_SESSION);
- 
  	/* reset the current_extension dependency tracker */
  	create_extension = false;
  }
  
  /*
--- 487,504 ----
  	}
  	PG_END_TRY();
  
  	/* reset the current_extension dependency tracker */
  	create_extension = false;
+ 
+ 	/* Reset search path and GUC variables to normal state */
+ 	PopOverrideSearchPath();
+ 
+ 	if (save_client_min_messages != NULL)
+ 		SetConfigOption("client_min_messages", save_client_min_messages,
+ 						PGC_SUSET, PGC_S_SESSION);
+ 	if (save_log_min_messages != NULL)
+ 		SetConfigOption("log_min_messages", save_log_min_messages,
+ 						PGC_SUSET, PGC_S_SESSION);
  }
  
  /*
*************** execute_extension_script(ExtensionContro
*** 564,570 ****
  void
  CreateExtension(CreateExtensionStmt *stmt)
  {
- 
  	ListCell   *option;
  	DefElem    *d_user_data = NULL;
  	DefElem    *d_schema = NULL;
--- 509,514 ----
*************** CreateExtension(CreateExtensionStmt *stm
*** 594,605 ****
  	 * pg_extension catalog to forbid having two backends concurrently
  	 * creating the same extension.
  	 */
! 	if( InvalidOid != get_extension_oid(stmt->extname, true) )
! 	{
  		ereport(ERROR,
  				(errcode(ERRCODE_DUPLICATE_OBJECT),
  				 errmsg("extension \"%s\" already exists", stmt->extname)));
- 	}
  
  	/*
  	 * The control file does not contain any text given to the backend
--- 538,547 ----
  	 * pg_extension catalog to forbid having two backends concurrently
  	 * creating the same extension.
  	 */
! 	if (get_extension_oid(stmt->extname, true) != InvalidOid)
  		ereport(ERROR,
  				(errcode(ERRCODE_DUPLICATE_OBJECT),
  				 errmsg("extension \"%s\" already exists", stmt->extname)));
  
  	/*
  	 * The control file does not contain any text given to the backend
*************** CreateExtension(CreateExtensionStmt *stm
*** 650,662 ****
  		 */
  		schema = strVal(d_schema->arg);
  
! 		if (!control->relocatable && control->schema != NULL)
  		{
! 			if (strcmp(control->schema, schema) != 0)
! 				ereport(ERROR,
! 						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
! 						 errmsg("this extension has to be installed in schema \"%s\"",
! 								control->schema)));
  		}
  
  		/* If the user is giving us the schema name, it must exists already */
--- 592,604 ----
  		 */
  		schema = strVal(d_schema->arg);
  
! 		if (!control->relocatable && control->schema != NULL &&
! 			strcmp(control->schema, schema) != 0)
  		{
! 			ereport(ERROR,
! 					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
! 					 errmsg("this extension has to be installed in schema \"%s\"",
! 							control->schema)));
  		}
  
  		/* If the user is giving us the schema name, it must exists already */
*************** CreateExtension(CreateExtensionStmt *stm
*** 725,739 ****
  	 * pg_extension catalog to forbid having two backends concurrently
  	 * creating the same extension.
  	 */
! 	if( InvalidOid != get_extension_oid(stmt->extname, true) )
! 	{
  		ereport(ERROR,
  				(errcode(ERRCODE_DUPLICATE_OBJECT),
  				 errmsg("extension \"%s\" already exists", stmt->extname)));
- 	}
  
  	memset(values, 0, sizeof(values));
! 	MemSet(nulls, false, sizeof(nulls));
  
  	values[Anum_pg_extension_extname - 1] =
  		DirectFunctionCall1(namein, CStringGetDatum(control->name));
--- 667,679 ----
  	 * pg_extension catalog to forbid having two backends concurrently
  	 * creating the same extension.
  	 */
! 	if (get_extension_oid(stmt->extname, true) != InvalidOid)
  		ereport(ERROR,
  				(errcode(ERRCODE_DUPLICATE_OBJECT),
  				 errmsg("extension \"%s\" already exists", stmt->extname)));
  
  	memset(values, 0, sizeof(values));
! 	memset(nulls, 0, sizeof(nulls));
  
  	values[Anum_pg_extension_extname - 1] =
  		DirectFunctionCall1(namein, CStringGetDatum(control->name));
*************** CreateExtension(CreateExtensionStmt *stm
*** 743,749 ****
  	values[Anum_pg_extension_relocatable - 1] =
  		BoolGetDatum(control->relocatable);
  
! 	if( control->version == NULL )
  		nulls[Anum_pg_extension_extversion - 1] = true;
  	else
  		values[Anum_pg_extension_extversion - 1] =
--- 683,689 ----
  	values[Anum_pg_extension_relocatable - 1] =
  		BoolGetDatum(control->relocatable);
  
! 	if (control->version == NULL)
  		nulls[Anum_pg_extension_extversion - 1] = true;
  	else
  		values[Anum_pg_extension_extversion - 1] =
*************** CreateExtension(CreateExtensionStmt *stm
*** 759,765 ****
  	 * Comment on extension
  	 */
  	if (control->comment != NULL)
! 		CreateComments(extensionoid, ExtensionRelationId, 0,  control->comment);
  
  	/*
  	 * Set the globals create_extension and extension so that any object
--- 699,705 ----
  	 * Comment on extension
  	 */
  	if (control->comment != NULL)
! 		CreateComments(extensionoid, ExtensionRelationId, 0, control->comment);
  
  	/*
  	 * Set the globals create_extension and extension so that any object
*************** CreateExtension(CreateExtensionStmt *stm
*** 784,790 ****
  	}
  
  	execute_extension_script(control, schema, user_data);
- 	return;
  }
  
  /*
--- 724,729 ----
*************** DropExtension(DropExtensionStmt *stmt)
*** 852,859 ****
  	object.objectSubId = 0;
  
  	performDeletion(&object, stmt->behavior);
- 
- 	return;
  }
  
  /*
--- 791,796 ----
*************** get_extension_name(Oid ext_oid)
*** 939,950 ****
  }
  
  /*
!  * extension_relocatable_p
   *
   * Returns true when the extension is marked 'relocatable'
   */
! bool
! extension_relocatable_p(Oid ext_oid)
  {
  	bool	    relocatable;
  	Relation	rel;
--- 876,887 ----
  }
  
  /*
!  * extension_is_relocatable
   *
   * Returns true when the extension is marked 'relocatable'
   */
! static bool
! extension_is_relocatable(Oid ext_oid)
  {
  	bool	    relocatable;
  	Relation	rel;
*************** pg_extensions(PG_FUNCTION_ARGS)
*** 1192,1198 ****
  		/* Get an array of installed extensions, but only their names */
  		installed = extension_list_installed(true);
  
! 		fctx = palloc(sizeof(extension_fctx));
  		fctx->dir.location = get_extension_control_basepath();
  		fctx->dir.dirdesc  = AllocateDir(fctx->dir.location);
  		fctx->installed    = installed;
--- 1129,1135 ----
  		/* Get an array of installed extensions, but only their names */
  		installed = extension_list_installed(true);
  
! 		fctx = (extension_fctx *) palloc(sizeof(extension_fctx));
  		fctx->dir.location = get_extension_control_basepath();
  		fctx->dir.dirdesc  = AllocateDir(fctx->dir.location);
  		fctx->installed    = installed;
*************** pg_extensions(PG_FUNCTION_ARGS)
*** 1213,1243 ****
  	while ((de = ReadDir(fctx->dir.dirdesc, fctx->dir.location)) != NULL)
  	{
  		ExtensionControlFile *control;
  		Datum		values[5];
  		bool		nulls[5];
  		bool        is_installed = false;
  		int         i = 0;
  		HeapTuple	tuple;
  
! 		if (!filename_extension_control_p(de->d_name))
  			continue;
  
  		control = parse_extension_control_file(
! 			get_extension_name_from_control_filename(de->d_name),
! 			get_extension_absolute_path(de->d_name));
  
  		memset(values, 0, sizeof(values));
! 		MemSet(nulls, false, sizeof(nulls));
  
  		values[0] = DirectFunctionCall1(namein, CStringGetDatum(control->name));
  		values[2] = BoolGetDatum(control->relocatable);
  
! 		if( control->version == NULL )
  			nulls[1] = true;
  		else
  			values[1] = CStringGetTextDatum(control->version);
  
! 		if( control->comment == NULL )
  			nulls[3] = true;
  		else
  			values[3] = CStringGetTextDatum(control->comment);
--- 1150,1184 ----
  	while ((de = ReadDir(fctx->dir.dirdesc, fctx->dir.location)) != NULL)
  	{
  		ExtensionControlFile *control;
+ 		char	   *extname;
  		Datum		values[5];
  		bool		nulls[5];
  		bool        is_installed = false;
  		int         i = 0;
  		HeapTuple	tuple;
  
! 		if (!is_extension_control_filename(de->d_name))
  			continue;
  
+ 		/* extract extension name from 'name.control' filename */
+ 		extname = pstrdup(de->d_name);
+ 		*strrchr(extname, '.') = '\0';
+ 
  		control = parse_extension_control_file(
! 					extname, get_extension_absolute_path(de->d_name));
  
  		memset(values, 0, sizeof(values));
! 		memset(nulls, 0, sizeof(nulls));
  
  		values[0] = DirectFunctionCall1(namein, CStringGetDatum(control->name));
  		values[2] = BoolGetDatum(control->relocatable);
  
! 		if (control->version == NULL)
  			nulls[1] = true;
  		else
  			values[1] = CStringGetTextDatum(control->version);
  
! 		if (control->comment == NULL)
  			nulls[3] = true;
  		else
  			values[3] = CStringGetTextDatum(control->comment);
*************** pg_extensions(PG_FUNCTION_ARGS)
*** 1247,1253 ****
  		 * expect installations to typically have very few extensions
  		 * installed, we simple rescan the same array each time.
  		 */
! 		while( !is_installed && i < fctx->installed->numrefs )
  			is_installed = 0 == strcmp(fctx->installed->exts[i++].name,
  									   control->name);
  
--- 1188,1194 ----
  		 * expect installations to typically have very few extensions
  		 * installed, we simple rescan the same array each time.
  		 */
! 		while (!is_installed && i < fctx->installed->numrefs)
  			is_installed = 0 == strcmp(fctx->installed->exts[i++].name,
  									   control->name);
  
*************** AlterExtensionNamespace_oid(Oid extensio
*** 1289,1300 ****
  				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
  				 (errmsg("must be superuser to ALTER EXTENSION"))));
  
! 	if (!extension_relocatable_p(extensionOid))
  		ereport(ERROR,
  				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
  				 (errmsg("this extension does not support SET SCHEMA"))));
  
! 	object = (ObjectAddress *)palloc(sizeof(ObjectAddress));
  	object->classId = ExtensionRelationId;
  	object->objectId = extensionOid;
  	object->objectSubId = 0;
--- 1230,1241 ----
  				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
  				 (errmsg("must be superuser to ALTER EXTENSION"))));
  
! 	if (!extension_is_relocatable(extensionOid))
  		ereport(ERROR,
  				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
  				 (errmsg("this extension does not support SET SCHEMA"))));
  
! 	object = (ObjectAddress *) palloc(sizeof(ObjectAddress));
  	object->classId = ExtensionRelationId;
  	object->objectId = extensionOid;
  	object->objectSubId = 0;
*************** AlterExtensionNamespace_oid(Oid extensio
*** 1302,1308 ****
  	/*
  	 * We scan pg_depend to find objects that depend directly on the extension.
  	 */
! 	dep = (ObjectAddress *)palloc(sizeof(ObjectAddress));
  
  	depRel = heap_open(DependRelationId, AccessShareLock);
  
--- 1243,1249 ----
  	/*
  	 * We scan pg_depend to find objects that depend directly on the extension.
  	 */
! 	dep = (ObjectAddress *) palloc(sizeof(ObjectAddress));
  
  	depRel = heap_open(DependRelationId, AccessShareLock);
  
*************** AlterExtensionNamespace_oid(Oid extensio
*** 1375,1383 ****
  
  		if (HeapTupleIsValid(tup))
  		{
! 			values = palloc0(rel->rd_att->natts * sizeof(Datum));
! 			nulls = palloc0(rel->rd_att->natts * sizeof(bool));
! 			replaces = palloc0(rel->rd_att->natts * sizeof(bool));
  			values[Anum_pg_extension_extnamespace  - 1] = nspOid;
  			replaces[Anum_pg_extension_extnamespace  - 1] = true;
  			newtup = heap_modify_tuple(tup, rel->rd_att, values, nulls, replaces);
--- 1316,1324 ----
  
  		if (HeapTupleIsValid(tup))
  		{
! 			values = (Datum *) palloc0(rel->rd_att->natts * sizeof(Datum));
! 			nulls = (bool *) palloc0(rel->rd_att->natts * sizeof(bool));
! 			replaces = (bool *) palloc0(rel->rd_att->natts * sizeof(bool));
  			values[Anum_pg_extension_extnamespace  - 1] = nspOid;
  			replaces[Anum_pg_extension_extnamespace  - 1] = true;
  			newtup = heap_modify_tuple(tup, rel->rd_att, values, nulls, replaces);
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index 84c68a7..747fa52 100644
*** a/src/bin/psql/tab-complete.c
--- b/src/bin/psql/tab-complete.c
*************** static const SchemaQuery Query_for_list_
*** 578,583 ****
--- 578,593 ----
  "   FROM pg_catalog.pg_proc "\
  "  WHERE proname='%s'"
  
+ #define Query_for_list_of_extensions \
+ " SELECT pg_catalog.quote_ident(extname) "\
+ "   FROM pg_catalog.pg_extension "\
+ "  WHERE substring(pg_catalog.quote_ident(extname),1,%d)='%s'"
+ 
+ #define Query_for_list_of_available_extensions \
+ " SELECT pg_catalog.quote_ident(name) "\
+ "   FROM pg_catalog.pg_available_extensions "\
+ "  WHERE substring(pg_catalog.quote_ident(name),1,%d)='%s' AND NOT installed"
+ 
  /*
   * This is a list of all "things" in Pgsql, which can show up after CREATE or
   * DROP; and there is also a query to get a list of them.
*************** static const pgsql_thing_t words_after_c
*** 606,611 ****
--- 616,622 ----
  	{"DATABASE", Query_for_list_of_databases},
  	{"DICTIONARY", Query_for_list_of_ts_dictionaries, NULL, true},
  	{"DOMAIN", NULL, &Query_for_list_of_domains},
+ 	{"EXTENSION", Query_for_list_of_extensions},
  	{"FOREIGN DATA WRAPPER", NULL, NULL},
  	{"FOREIGN TABLE", NULL, NULL},
  	{"FUNCTION", NULL, &Query_for_list_of_functions},
*************** psql_completion(char *text, int start, i
*** 775,781 ****
  			 pg_strcasecmp(prev3_wd, "TABLE") != 0)
  	{
  		static const char *const list_ALTER[] =
! 		{"AGGREGATE", "CONVERSION", "DATABASE", "DEFAULT PRIVILEGES", "DOMAIN", "FOREIGN DATA WRAPPER", "FOREIGN TABLE", "FUNCTION",
  			"GROUP", "INDEX", "LANGUAGE", "LARGE OBJECT", "OPERATOR", "ROLE", "SCHEMA", "SERVER", "SEQUENCE", "TABLE",
  		"TABLESPACE", "TEXT SEARCH", "TRIGGER", "TYPE", "USER", "USER MAPPING FOR", "VIEW", NULL};
  
--- 786,793 ----
  			 pg_strcasecmp(prev3_wd, "TABLE") != 0)
  	{
  		static const char *const list_ALTER[] =
! 		{"AGGREGATE", "CONVERSION", "DATABASE", "DEFAULT PRIVILEGES", "DOMAIN",
! 			"EXTENSION", "FOREIGN DATA WRAPPER", "FOREIGN TABLE", "FUNCTION",
  			"GROUP", "INDEX", "LANGUAGE", "LARGE OBJECT", "OPERATOR", "ROLE", "SCHEMA", "SERVER", "SEQUENCE", "TABLE",
  		"TABLESPACE", "TEXT SEARCH", "TRIGGER", "TYPE", "USER", "USER MAPPING FOR", "VIEW", NULL};
  
*************** psql_completion(char *text, int start, i
*** 838,843 ****
--- 850,860 ----
  		COMPLETE_WITH_LIST(list_ALTERDATABASE);
  	}
  
+ 	/* ALTER EXTENSION <name> */
+ 	else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 &&
+ 			 pg_strcasecmp(prev2_wd, "EXTENSION") == 0)
+ 		COMPLETE_WITH_CONST("SET SCHEMA");
+ 
  	/* ALTER FOREIGN */
  	else if (pg_strcasecmp(prev2_wd, "ALTER") == 0 &&
  			 pg_strcasecmp(prev_wd, "FOREIGN") == 0)
*************** psql_completion(char *text, int start, i
*** 1579,1584 ****
--- 1596,1611 ----
  			 pg_strcasecmp(prev_wd, "TEMPLATE") == 0)
  		COMPLETE_WITH_QUERY(Query_for_list_of_template_databases);
  
+ /* CREATE EXTENSION */
+ 	/* Complete with available extensions rather than installed ones. */
+ 	else if (pg_strcasecmp(prev2_wd, "CREATE") == 0 &&
+ 			 pg_strcasecmp(prev_wd, "EXTENSION") == 0)
+ 		COMPLETE_WITH_QUERY(Query_for_list_of_available_extensions);
+ 	/* CREATE EXTENSION <name> */
+ 	else if (pg_strcasecmp(prev3_wd, "CREATE") == 0 &&
+ 			 pg_strcasecmp(prev2_wd, "EXTENSION") == 0)
+ 		COMPLETE_WITH_CONST("WITH SCHEMA");
+ 
  	/* CREATE FOREIGN */
  	else if (pg_strcasecmp(prev2_wd, "CREATE") == 0 &&
  			 pg_strcasecmp(prev_wd, "FOREIGN") == 0)
*************** psql_completion(char *text, int start, i
*** 1922,1927 ****
--- 1949,1955 ----
  	else if ((pg_strcasecmp(prev3_wd, "DROP") == 0 &&
  			  (pg_strcasecmp(prev2_wd, "CONVERSION") == 0 ||
  			   pg_strcasecmp(prev2_wd, "DOMAIN") == 0 ||
+ 			   pg_strcasecmp(prev2_wd, "EXTENSION") == 0 ||
  			   pg_strcasecmp(prev2_wd, "FUNCTION") == 0 ||
  			   pg_strcasecmp(prev2_wd, "INDEX") == 0 ||
  			   pg_strcasecmp(prev2_wd, "LANGUAGE") == 0 ||
diff --git a/src/include/catalog/dependency.h b/src/include/catalog/dependency.h
index 74ed40b..7607c06 100644
*** a/src/include/catalog/dependency.h
--- b/src/include/catalog/dependency.h
*************** typedef enum SharedDependencyType
*** 101,131 ****
  	SHARED_DEPENDENCY_INVALID = 0
  } SharedDependencyType;
  
! /*
!  * Deletion processing requires additional state for each ObjectAddress that
!  * it's planning to delete.  For simplicity and code-sharing we make the
!  * ObjectAddresses code support arrays with or without this extra state.
!  */
! typedef struct
! {
! 	int			flags;			/* bitmask, see bit definitions below */
! 	ObjectAddress dependee;		/* object whose deletion forced this one */
! } ObjectAddressExtra;
! 
! /* ObjectAddressExtra flag bits */
! #define DEPFLAG_ORIGINAL	0x0001		/* an original deletion target */
! #define DEPFLAG_NORMAL		0x0002		/* reached via normal dependency */
! #define DEPFLAG_AUTO		0x0004		/* reached via auto dependency */
! #define DEPFLAG_INTERNAL	0x0008		/* reached via internal dependency */
! 
! /* expansible list of ObjectAddresses (used in dependency.c and extension.c) */
! typedef struct
! {
! 	ObjectAddress *refs;		/* => palloc'd array */
! 	ObjectAddressExtra *extras; /* => palloc'd array, or NULL if not used */
! 	int			numrefs;		/* current number of references */
! 	int			maxrefs;		/* current size of palloc'd array(s) */
! } ObjectAddresses;
  
  /*
   * This enum covers all system catalogs whose OIDs can appear in
--- 101,108 ----
  	SHARED_DEPENDENCY_INVALID = 0
  } SharedDependencyType;
  
! /* expansible list of ObjectAddresses (private in dependency.c) */
! typedef struct ObjectAddresses ObjectAddresses;
  
  /*
   * This enum covers all system catalogs whose OIDs can appear in
diff --git a/src/include/catalog/pg_extension.h b/src/include/catalog/pg_extension.h
index 2ea24a6..32b3677 100644
*** a/src/include/catalog/pg_extension.h
--- b/src/include/catalog/pg_extension.h
***************
*** 3,9 ****
   * pg_extension.h
   *	  definition of the system "extension" relation (pg_extension)
   *
!  * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
   * Portions Copyright (c) 1994, Regents of the University of California
   *
   * src/include/catalog/pg_extension.h
--- 3,9 ----
   * pg_extension.h
   *	  definition of the system "extension" relation (pg_extension)
   *
!  * Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
   * Portions Copyright (c) 1994, Regents of the University of California
   *
   * src/include/catalog/pg_extension.h
*************** typedef FormData_pg_extension *Form_pg_e
*** 53,63 ****
  #define Anum_pg_extension_extversion		4
  
  /* ----------------
!  *		initial contents of pg_extension
   * ----------------
   */
  
- /* btree
- DATA(insert ("PostgreSQL" PG_VERSION _null_));
- */
  #endif   /* PG_EXTENSION_H */
--- 53,60 ----
  #define Anum_pg_extension_extversion		4
  
  /* ----------------
!  *		pg_extension has no initial contents
   * ----------------
   */
  
  #endif   /* PG_EXTENSION_H */
diff --git a/src/include/commands/extension.h b/src/include/commands/extension.h
index 11809b8..cc5e7ed 100644
*** a/src/include/commands/extension.h
--- b/src/include/commands/extension.h
***************
*** 4,10 ****
   *		Extension management commands (create/drop extension).
   *
   *
!  * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
   * Portions Copyright (c) 1994, Regents of the University of California
   *
   * src/include/commands/extension.h
--- 4,10 ----
   *		Extension management commands (create/drop extension).
   *
   *
!  * Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
   * Portions Copyright (c) 1994, Regents of the University of California
   *
   * src/include/commands/extension.h
***************
*** 30,46 ****
   */
  extern ObjectAddress CreateExtensionAddress;
  extern bool create_extension;
- extern bool create_extension_with_user_data;
  
  extern void CreateExtension(CreateExtensionStmt *stmt);
  extern void DropExtension(DropExtensionStmt *stmt);
  
  extern Oid get_extension_oid(const char *extname, bool missing_ok);
  extern char *get_extension_name(Oid ext_oid);
- extern bool extension_relocatable_p(Oid ext_oid);
  extern void RemoveExtensionById(Oid extId);
  extern void AlterExtensionNamespace(char *name, const char *newschema);
  extern void AlterExtensionNamespace_oid(Oid extensionOid, Oid nspOid);
  
- 
  #endif   /* EXTENSION_H */
--- 30,43 ----
