@ -90,6 +90,8 @@ typedef struct ExtensionControlFile
bool trusted ; /* allow becoming superuser on the fly? */
bool trusted ; /* allow becoming superuser on the fly? */
int encoding ; /* encoding of the script file, or -1 */
int encoding ; /* encoding of the script file, or -1 */
List * requires ; /* names of prerequisite extensions */
List * requires ; /* names of prerequisite extensions */
List * no_relocate ; /* names of prerequisite extensions that
* should not be relocated */
} ExtensionControlFile ;
} ExtensionControlFile ;
/*
/*
@ -606,6 +608,21 @@ parse_extension_control_file(ExtensionControlFile *control,
item - > name ) ) ) ;
item - > name ) ) ) ;
}
}
}
}
else if ( strcmp ( item - > name , " no_relocate " ) = = 0 )
{
/* Need a modifiable copy of string */
char * rawnames = pstrdup ( item - > value ) ;
/* Parse string into list of identifiers */
if ( ! SplitIdentifierString ( rawnames , ' , ' , & control - > no_relocate ) )
{
/* syntax error in name list */
ereport ( ERROR ,
( errcode ( ERRCODE_INVALID_PARAMETER_VALUE ) ,
errmsg ( " parameter \" %s \" must be a list of extension names " ,
item - > name ) ) ) ;
}
}
else
else
ereport ( ERROR ,
ereport ( ERROR ,
( errcode ( ERRCODE_SYNTAX_ERROR ) ,
( errcode ( ERRCODE_SYNTAX_ERROR ) ,
@ -845,6 +862,8 @@ extension_is_trusted(ExtensionControlFile *control)
* Execute the appropriate script file for installing or updating the extension
* Execute the appropriate script file for installing or updating the extension
*
*
* If from_version isn ' t NULL , it ' s an update
* If from_version isn ' t NULL , it ' s an update
*
* Note : requiredSchemas must be one - for - one with the control - > requires list
*/
*/
static void
static void
execute_extension_script ( Oid extensionOid , ExtensionControlFile * control ,
execute_extension_script ( Oid extensionOid , ExtensionControlFile * control ,
@ -860,6 +879,7 @@ execute_extension_script(Oid extensionOid, ExtensionControlFile *control,
int save_nestlevel ;
int save_nestlevel ;
StringInfoData pathbuf ;
StringInfoData pathbuf ;
ListCell * lc ;
ListCell * lc ;
ListCell * lc2 ;
/*
/*
* Enforce superuser - ness if appropriate . We postpone these checks until
* Enforce superuser - ness if appropriate . We postpone these checks until
@ -1030,6 +1050,27 @@ execute_extension_script(Oid extensionOid, ExtensionControlFile *control,
CStringGetTextDatum ( qSchemaName ) ) ;
CStringGetTextDatum ( qSchemaName ) ) ;
}
}
/*
* Likewise , substitute required extensions ' schema names for
* occurrences of @ extschema : extension_name @ .
*/
Assert ( list_length ( control - > requires ) = = list_length ( requiredSchemas ) ) ;
forboth ( lc , control - > requires , lc2 , requiredSchemas )
{
char * reqextname = ( char * ) lfirst ( lc ) ;
Oid reqschema = lfirst_oid ( lc2 ) ;
char * schemaName = get_namespace_name ( reqschema ) ;
const char * qSchemaName = quote_identifier ( schemaName ) ;
char * repltoken ;
repltoken = psprintf ( " @extschema:%s@ " , reqextname ) ;
t_sql = DirectFunctionCall3Coll ( replace_text ,
C_COLLATION_OID ,
t_sql ,
CStringGetTextDatum ( repltoken ) ,
CStringGetTextDatum ( qSchemaName ) ) ;
}
/*
/*
* If module_pathname was set in the control file , substitute its
* If module_pathname was set in the control file , substitute its
* value for occurrences of MODULE_PATHNAME .
* value for occurrences of MODULE_PATHNAME .
@ -2817,9 +2858,43 @@ AlterExtensionNamespace(const char *extensionName, const char *newschema, Oid *o
Oid dep_oldNspOid ;
Oid dep_oldNspOid ;
/*
/*
* Ignore non - membership dependencies . ( Currently , the only other
* If a dependent extension has a no_relocate request for this
* case we could see here is a normal dependency from another
* extension , disallow SET SCHEMA . ( XXX it ' s a bit ugly to do this in
* extension . )
* the same loop that ' s actually executing the renames : we may detect
* the error condition only after having expended a fair amount of
* work . However , the alternative is to do two scans of pg_depend ,
* which seems like optimizing for failure cases . The rename work
* will all roll back cleanly enough if we do fail here . )
*/
if ( pg_depend - > deptype = = DEPENDENCY_NORMAL & &
pg_depend - > classid = = ExtensionRelationId )
{
char * depextname = get_extension_name ( pg_depend - > objid ) ;
ExtensionControlFile * dcontrol ;
ListCell * lc ;
dcontrol = read_extension_control_file ( depextname ) ;
foreach ( lc , dcontrol - > no_relocate )
{
char * nrextname = ( char * ) lfirst ( lc ) ;
if ( strcmp ( nrextname , NameStr ( extForm - > extname ) ) = = 0 )
{
ereport ( ERROR ,
( errcode ( ERRCODE_FEATURE_NOT_SUPPORTED ) ,
errmsg ( " cannot SET SCHEMA of extension \" %s \" because other extensions prevent it " ,
NameStr ( extForm - > extname ) ) ,
errdetail ( " Extension \" %s \" requests no relocation of extension \" %s \" . " ,
depextname ,
NameStr ( extForm - > extname ) ) ) ) ;
}
}
}
/*
* Otherwise , ignore non - membership dependencies . ( Currently , the
* only other case we could see here is a normal dependency from
* another extension . )
*/
*/
if ( pg_depend - > deptype ! = DEPENDENCY_EXTENSION )
if ( pg_depend - > deptype ! = DEPENDENCY_EXTENSION )
continue ;
continue ;