diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c
index fa861e6..4d82527 100644
*** a/src/backend/commands/extension.c
--- b/src/backend/commands/extension.c
*************** typedef struct ExtensionVersionInfo
*** 100,105 ****
--- 100,106 ----
  static List *find_update_path(List *evi_list,
  				 ExtensionVersionInfo *evi_start,
  				 ExtensionVersionInfo *evi_target,
+ 				 bool reject_indirect,
  				 bool reinitialize);
  static void get_available_versions_for_extension(ExtensionControlFile *pcontrol,
  									 Tuplestorestate *tupstore,
*************** identify_update_path(ExtensionControlFil
*** 1071,1077 ****
  	evi_target = get_ext_ver_info(newVersion, &evi_list);
  
  	/* Find shortest path */
! 	result = find_update_path(evi_list, evi_start, evi_target, false);
  
  	if (result == NIL)
  		ereport(ERROR,
--- 1072,1078 ----
  	evi_target = get_ext_ver_info(newVersion, &evi_list);
  
  	/* Find shortest path */
! 	result = find_update_path(evi_list, evi_start, evi_target, false, false);
  
  	if (result == NIL)
  		ereport(ERROR,
*************** identify_update_path(ExtensionControlFil
*** 1086,1091 ****
--- 1087,1095 ----
   * Apply Dijkstra's algorithm to find the shortest path from evi_start to
   * evi_target.
   *
+  * If reject_indirect is true, ignore paths that go through installable
+  * versions (presumably, caller will consider starting from such versions).
+  *
   * If reinitialize is false, assume the ExtensionVersionInfo list has not
   * been used for this before, and the initialization done by get_ext_ver_info
   * is still good.
*************** static List *
*** 1097,1102 ****
--- 1101,1107 ----
  find_update_path(List *evi_list,
  				 ExtensionVersionInfo *evi_start,
  				 ExtensionVersionInfo *evi_target,
+ 				 bool reject_indirect,
  				 bool reinitialize)
  {
  	List	   *result;
*************** find_update_path(List *evi_list,
*** 1105,1110 ****
--- 1110,1117 ----
  
  	/* Caller error if start == target */
  	Assert(evi_start != evi_target);
+ 	/* Caller error if reject_indirect and target is installable */
+ 	Assert(!(reject_indirect && evi_target->installable));
  
  	if (reinitialize)
  	{
*************** find_update_path(List *evi_list,
*** 1131,1136 ****
--- 1138,1146 ----
  			ExtensionVersionInfo *evi2 = (ExtensionVersionInfo *) lfirst(lc);
  			int			newdist;
  
+ 			/* if reject_indirect, treat installable versions as unreachable */
+ 			if (reject_indirect && evi2->installable)
+ 				continue;
  			newdist = evi->distance + 1;
  			if (newdist < evi2->distance)
  			{
*************** find_update_path(List *evi_list,
*** 1167,1172 ****
--- 1177,1239 ----
  }
  
  /*
+  * Given a target version that is not directly installable, find the
+  * best installation sequence starting from a directly-installable version.
+  *
+  * evi_list: previously-collected version update graph
+  * evi_target: member of that list that we want to reach
+  *
+  * Returns the best starting-point version, or NULL if there is none.
+  * On success, *best_path is set to the path from the start point.
+  *
+  * If there's more than one possible start point, prefer shorter update paths,
+  * and break any ties arbitrarily on the basis of strcmp'ing the starting
+  * versions' names.
+  */
+ static ExtensionVersionInfo *
+ find_install_path(List *evi_list, ExtensionVersionInfo *evi_target,
+ 				  List **best_path)
+ {
+ 	ExtensionVersionInfo *evi_start = NULL;
+ 	ListCell   *lc;
+ 
+ 	/* Target should not be installable */
+ 	Assert(!evi_target->installable);
+ 
+ 	*best_path = NIL;
+ 
+ 	/* Consider all installable versions as start points */
+ 	foreach(lc, evi_list)
+ 	{
+ 		ExtensionVersionInfo *evi1 = (ExtensionVersionInfo *) lfirst(lc);
+ 		List	   *path;
+ 
+ 		if (!evi1->installable)
+ 			continue;
+ 
+ 		/*
+ 		 * Find shortest path from evi1 to evi_target; but no need to consider
+ 		 * paths going through other installable versions.
+ 		 */
+ 		path = find_update_path(evi_list, evi1, evi_target, true, true);
+ 		if (path == NIL)
+ 			continue;
+ 
+ 		/* Remember best path */
+ 		if (evi_start == NULL ||
+ 			list_length(path) < list_length(*best_path) ||
+ 			(list_length(path) == list_length(*best_path) &&
+ 			 strcmp(evi_start->name, evi1->name) < 0))
+ 		{
+ 			evi_start = evi1;
+ 			*best_path = path;
+ 		}
+ 	}
+ 
+ 	return evi_start;
+ }
+ 
+ /*
   * CREATE EXTENSION worker
   *
   * When CASCADE is specified, CreateExtensionInternal() recurses if required
*************** CreateExtensionInternal(CreateExtensionS
*** 1264,1274 ****
  	check_valid_version_name(versionName);
  
  	/*
! 	 * Determine the (unpackaged) version to update from, if any, and then
! 	 * figure out what sequence of update scripts we need to apply.
  	 */
  	if (d_old_version && d_old_version->arg)
  	{
  		oldVersionName = strVal(d_old_version->arg);
  		check_valid_version_name(oldVersionName);
  
--- 1331,1348 ----
  	check_valid_version_name(versionName);
  
  	/*
! 	 * Figure out which script(s) we need to run to install the desired
! 	 * version of the extension.  If we do not have a script that directly
! 	 * does what is needed, we try to find a sequence of update scripts that
! 	 * will get us there.
  	 */
  	if (d_old_version && d_old_version->arg)
  	{
+ 		/*
+ 		 * "FROM old_version" was specified, indicating that we're trying to
+ 		 * update from some unpackaged version of the extension.  Locate a
+ 		 * series of update scripts that will do it.
+ 		 */
  		oldVersionName = strVal(d_old_version->arg);
  		check_valid_version_name(oldVersionName);
  
*************** CreateExtensionInternal(CreateExtensionS
*** 1304,1311 ****
  	}
  	else
  	{
  		oldVersionName = NULL;
! 		updateVersions = NIL;
  	}
  
  	/*
--- 1378,1438 ----
  	}
  	else
  	{
+ 		/*
+ 		 * No FROM, so we're installing from scratch.  If there is an install
+ 		 * script for the desired version, we only need to run that one.
+ 		 */
+ 		char	   *filename;
+ 		struct stat fst;
+ 
  		oldVersionName = NULL;
! 
! 		filename = get_extension_script_filename(pcontrol, NULL, versionName);
! 		if (stat(filename, &fst) == 0)
! 		{
! 			/* Easy, no extra scripts */
! 			updateVersions = NIL;
! 		}
! 		else
! 		{
! 			/* Look for best way to install this version */
! 			List	   *evi_list;
! 			ExtensionVersionInfo *evi_target;
! 
! 			/* Extract the version update graph from the script directory */
! 			evi_list = get_ext_ver_list(pcontrol);
! 
! 			/* Identify the target version */
! 			evi_target = get_ext_ver_info(versionName, &evi_list);
! 
! 			/*
! 			 * We don't expect it to be installable, but maybe somebody added
! 			 * a suitable script right after our stat() test.
! 			 */
! 			if (evi_target->installable)
! 			{
! 				/* Easy, no extra scripts */
! 				updateVersions = NIL;
! 			}
! 			else
! 			{
! 				/* Identify best path to reach target */
! 				ExtensionVersionInfo *evi_start;
! 
! 				evi_start = find_install_path(evi_list, evi_target,
! 											  &updateVersions);
! 
! 				/* Fail if no path ... */
! 				if (evi_start == NULL)
! 					ereport(ERROR,
! 							(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
! 							 errmsg("extension \"%s\" has no installation script for version \"%s\"",
! 									pcontrol->name, versionName)));
! 
! 				/* Otherwise, install best starting point and then upgrade */
! 				versionName = evi_start->name;
! 			}
! 		}
  	}
  
  	/*
*************** get_available_versions_for_extension(Ext
*** 1910,1952 ****
  									 Tuplestorestate *tupstore,
  									 TupleDesc tupdesc)
  {
! 	int			extnamelen = strlen(pcontrol->name);
! 	char	   *location;
! 	DIR		   *dir;
! 	struct dirent *de;
  
! 	location = get_extension_script_directory(pcontrol);
! 	dir = AllocateDir(location);
! 	/* Note this will fail if script directory doesn't exist */
! 	while ((de = ReadDir(dir, location)) != NULL)
  	{
  		ExtensionControlFile *control;
- 		char	   *vername;
  		Datum		values[7];
  		bool		nulls[7];
  
! 		/* must be a .sql file ... */
! 		if (!is_extension_script_filename(de->d_name))
! 			continue;
! 
! 		/* ... matching extension name followed by separator */
! 		if (strncmp(de->d_name, pcontrol->name, extnamelen) != 0 ||
! 			de->d_name[extnamelen] != '-' ||
! 			de->d_name[extnamelen + 1] != '-')
! 			continue;
! 
! 		/* extract version name from 'extname--something.sql' filename */
! 		vername = pstrdup(de->d_name + extnamelen + 2);
! 		*strrchr(vername, '.') = '\0';
! 
! 		/* ignore it if it's an update script */
! 		if (strstr(vername, "--"))
  			continue;
  
  		/*
  		 * Fetch parameters for specific version (pcontrol is not changed)
  		 */
! 		control = read_extension_aux_control_file(pcontrol, vername);
  
  		memset(values, 0, sizeof(values));
  		memset(nulls, 0, sizeof(nulls));
--- 2037,2064 ----
  									 Tuplestorestate *tupstore,
  									 TupleDesc tupdesc)
  {
! 	List	   *evi_list;
! 	ListCell   *lc;
  
! 	/* Extract the version update graph from the script directory */
! 	evi_list = get_ext_ver_list(pcontrol);
! 
! 	/* For each installable version ... */
! 	foreach(lc, evi_list)
  	{
+ 		ExtensionVersionInfo *evi = (ExtensionVersionInfo *) lfirst(lc);
  		ExtensionControlFile *control;
  		Datum		values[7];
  		bool		nulls[7];
+ 		ListCell   *lc2;
  
! 		if (!evi->installable)
  			continue;
  
  		/*
  		 * Fetch parameters for specific version (pcontrol is not changed)
  		 */
! 		control = read_extension_aux_control_file(pcontrol, evi->name);
  
  		memset(values, 0, sizeof(values));
  		memset(nulls, 0, sizeof(nulls));
*************** get_available_versions_for_extension(Ext
*** 1955,1961 ****
  		values[0] = DirectFunctionCall1(namein,
  										CStringGetDatum(control->name));
  		/* version */
! 		values[1] = CStringGetTextDatum(vername);
  		/* superuser */
  		values[2] = BoolGetDatum(control->superuser);
  		/* relocatable */
--- 2067,2073 ----
  		values[0] = DirectFunctionCall1(namein,
  										CStringGetDatum(control->name));
  		/* version */
! 		values[1] = CStringGetTextDatum(evi->name);
  		/* superuser */
  		values[2] = BoolGetDatum(control->superuser);
  		/* relocatable */
*************** get_available_versions_for_extension(Ext
*** 1998,2006 ****
  			values[6] = CStringGetTextDatum(control->comment);
  
  		tuplestore_putvalues(tupstore, tupdesc, values, nulls);
- 	}
  
! 	FreeDir(dir);
  }
  
  /*
--- 2110,2137 ----
  			values[6] = CStringGetTextDatum(control->comment);
  
  		tuplestore_putvalues(tupstore, tupdesc, values, nulls);
  
! 		/*
! 		 * Find all non-directly-installable versions that would be installed
! 		 * starting from this version, and report them with the same
! 		 * control-file parameters.
! 		 */
! 		foreach(lc2, evi_list)
! 		{
! 			ExtensionVersionInfo *evi2 = (ExtensionVersionInfo *) lfirst(lc2);
! 			List	   *best_path;
! 
! 			if (evi2->installable)
! 				continue;
! 			if (find_install_path(evi_list, evi2, &best_path) == evi)
! 			{
! 				/* replace only the version column */
! 				values[1] = CStringGetTextDatum(evi2->name);
! 
! 				tuplestore_putvalues(tupstore, tupdesc, values, nulls);
! 			}
! 		}
! 	}
  }
  
  /*
*************** pg_extension_update_paths(PG_FUNCTION_AR
*** 2072,2078 ****
  				continue;
  
  			/* Find shortest path from evi1 to evi2 */
! 			path = find_update_path(evi_list, evi1, evi2, true);
  
  			/* Emit result row */
  			memset(values, 0, sizeof(values));
--- 2203,2209 ----
  				continue;
  
  			/* Find shortest path from evi1 to evi2 */
! 			path = find_update_path(evi_list, evi1, evi2, false, true);
  
  			/* Emit result row */
  			memset(values, 0, sizeof(values));
