Stephen Frost <sfr...@snowman.net> writes:
> Yeah, default_version was the other one that looked like it might be
> possible to include, but folks might decide to try and use 'comment' in
> that way too.  Basically, there's a chance that they'd want to use any
> string in there.

Actually, I think that $default_value is the only other serious enough
candidate that we should support, and I think we should support it both
from the directory and module_pathname parameters.

Also, it seems to me that while the $directory macro should still be
found only at the beginning of the module_pathname value, the
$default_value should be substituted from wherever it is found.

Please find attached a v1 version of the patch implementing that.

 doc/src/sgml/extend.sgml         | 18 ++++++++
 src/backend/commands/extension.c | 79 +++++++++++++++++++++++++++++---
 2 files changed, 91 insertions(+), 6 deletions(-)

Regards,
-- 
Dimitri Fontaine
http://2ndQuadrant.fr     PostgreSQL : Expertise, Formation et Support

*** a/doc/src/sgml/extend.sgml
--- b/doc/src/sgml/extend.sgml
***************
*** 412,417 ****
--- 412,423 ----
          default behavior is equivalent to specifying
          <literal>directory = 'extension'</>.
         </para>
+        <para>
+         The macro <literal>$default_value</literal> is supported for this
+         parameter. When used <literal>$default_value</literal> is then
+         substituted with the <literal>default_value</literal> control
+         parameter value.
+        </para>
        </listitem>
       </varlistentry>
  
***************
*** 462,467 ****
--- 468,485 ----
          FUNCTION</> commands for C-language functions, so that the script
          files do not need to hard-wire the name of the shared library.
         </para>
+        <para>
+         The macro <literal>$default_value</literal> is supported for this
+         parameter. When used <literal>$default_value</literal> is then
+         substituted with the <literal>default_value</literal> control
+         parameter value.
+        </para>
+        <para>
+         The macro <literal>$directory</literal> is also supported for this
+         parameter, only when found at the very start of the value for this
+         parameter. When used <literal>$directory</literal> is then substituted
+         with the <literal>directory</literal> control parameter value.
+        </para>
        </listitem>
       </varlistentry>
  
*** a/src/backend/commands/extension.c
--- b/src/backend/commands/extension.c
***************
*** 369,374 **** get_extension_control_filename(const char *extname)
--- 369,377 ----
  	return result;
  }
  
+ /*
+  * In the control file, the directory entry supports $default_version macro.
+  */
  static char *
  get_extension_script_directory(ExtensionControlFile *control)
  {
***************
*** 383,393 **** get_extension_script_directory(ExtensionControlFile *control)
  		return get_extension_control_directory();
  
  	if (is_absolute_path(control->directory))
! 		return pstrdup(control->directory);
  
! 	get_share_path(my_exec_path, sharepath);
! 	result = (char *) palloc(MAXPGPATH);
! 	snprintf(result, MAXPGPATH, "%s/%s", sharepath, control->directory);
  
  	return result;
  }
--- 386,406 ----
  		return get_extension_control_directory();
  
  	if (is_absolute_path(control->directory))
! 		result = pstrdup(control->directory);
! 	else
! 	{
! 		get_share_path(my_exec_path, sharepath);
! 		result = (char *) palloc(MAXPGPATH);
! 		snprintf(result, MAXPGPATH, "%s/%s", sharepath, control->directory);
! 	}
  
! 	/* see about replacing the $default_version macro if present. */
! 	result = text_to_cstring(
! 		DatumGetTextPP(
! 			DirectFunctionCall3(replace_text,
! 								CStringGetTextDatum(result),
! 								CStringGetTextDatum("$default_version"),
! 								CStringGetTextDatum(control->default_version))));
  
  	return result;
  }
***************
*** 432,437 **** get_extension_script_filename(ExtensionControlFile *control,
--- 445,499 ----
  	return result;
  }
  
+ /*
+  * Substitute for any macros appearing in the given string.
+  * Result is always freshly palloc'd.
+  *
+  * Supported macros are:
+  *  - $directory
+  *  - $default_version
+  *
+  * The $directory macro must be used at the very start of the module_pathname.
+  */
+ static char *
+ substitute_module_macros(const char *module_pathname,
+ 						 const char *directory,
+ 						 const char *default_version)
+ {
+ 	Datum t_result;
+ 	const char *sep_ptr;
+ 
+ 	if (module_pathname == NULL)
+ 		return NULL;
+ 
+ 	/* Currently, we only recognize $directory at the start of the string */
+ 	if (module_pathname[0] != '$')
+ 		return pstrdup(module_pathname);
+ 
+ 	if ((sep_ptr = first_dir_separator(module_pathname)) == NULL)
+ 		sep_ptr = module_pathname + strlen(module_pathname);
+ 
+ 	/* Accept $libdir, just return module_pathname as is then */
+ 	if (strlen("$libdir") == sep_ptr - module_pathname &&
+ 		strncmp(module_pathname, "$libdir", strlen("$libdir")) == 0)
+ 		return pstrdup(module_pathname);
+ 
+ 	if (strlen("$directory") != sep_ptr - module_pathname ||
+ 		strncmp(module_pathname, "$directory", strlen("$directory")) != 0)
+ 		ereport(ERROR,
+ 				(errcode(ERRCODE_INVALID_NAME),
+ 				 errmsg("invalid macro module_pathname in: %s",
+ 						module_pathname)));
+ 
+ 	t_result = CStringGetTextDatum(psprintf("%s%s", directory, sep_ptr));
+ 	t_result = DirectFunctionCall3(replace_text,
+ 								   t_result,
+ 								   CStringGetTextDatum("$default_version"),
+ 								   CStringGetTextDatum(default_version));
+ 
+ 	return text_to_cstring(DatumGetTextPP(t_result));
+ }
+ 
  
  /*
   * Parse contents of primary or auxiliary control file, and fill in
***************
*** 895,904 **** execute_extension_script(Oid extensionOid, ExtensionControlFile *control,
  		 */
  		if (control->module_pathname)
  		{
  			t_sql = DirectFunctionCall3(replace_text,
  										t_sql,
! 									  CStringGetTextDatum("MODULE_PATHNAME"),
! 							  CStringGetTextDatum(control->module_pathname));
  		}
  
  		/* And now back to C string */
--- 957,971 ----
  		 */
  		if (control->module_pathname)
  		{
+ 			char *directory = get_extension_script_directory(control);
+ 			char *module_pathname =
+ 				substitute_module_macros(control->module_pathname,
+ 										 directory, control->default_version);
+ 
  			t_sql = DirectFunctionCall3(replace_text,
  										t_sql,
! 										CStringGetTextDatum("MODULE_PATHNAME"),
! 										CStringGetTextDatum(module_pathname));
  		}
  
  		/* And now back to C string */
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to