From dbd35a972fabba2ed723ac9ab4c4236ab2bd271d Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Wed, 12 Oct 2011 15:45:03 -0400 Subject: Throw a useful error message if an extension script file is fed to psql. We have seen one too many reports of people trying to use 9.1 extension files in the old-fashioned way of sourcing them in psql. Not only does that usually not work (due to failure to substitute for MODULE_PATHNAME and/or @extschema@), but if it did work they'd get a collection of loose objects not an extension. To prevent this, insert an \echo ... \quit line that prints a suitable error message into each extension script file, and teach commands/extension.c to ignore lines starting with \echo. That should not only prevent any adverse consequences of loading a script file the wrong way, but make it crystal clear to users that they need to do it differently now. Tom Lane, following an idea of Andrew Dunstan's. Back-patch into 9.1 ... there is not going to be much value in this if we wait till 9.2. --- src/backend/commands/extension.c | 49 ++++++++++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 17 deletions(-) (limited to 'src/backend/commands/extension.c') diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c index e5ea12e9200..024d4c8a009 100644 --- a/src/backend/commands/extension.c +++ b/src/backend/commands/extension.c @@ -33,6 +33,7 @@ #include "catalog/indexing.h" #include "catalog/namespace.h" #include "catalog/objectaccess.h" +#include "catalog/pg_collation.h" #include "catalog/pg_depend.h" #include "catalog/pg_extension.h" #include "catalog/pg_namespace.h" @@ -857,26 +858,39 @@ execute_extension_script(Oid extensionOid, ExtensionControlFile *control, CurrentExtensionObject = extensionOid; PG_TRY(); { - char *sql = read_extension_script_file(control, filename); + char *c_sql = read_extension_script_file(control, filename); + Datum t_sql; + + /* We use various functions that want to operate on text datums */ + t_sql = CStringGetTextDatum(c_sql); + + /* + * Reduce any lines beginning with "\echo" to empty. This allows + * scripts to contain messages telling people not to run them via + * psql, which has been found to be necessary due to old habits. + */ + t_sql = DirectFunctionCall4Coll(textregexreplace, + C_COLLATION_OID, + t_sql, + CStringGetTextDatum("^\\\\echo.*$"), + CStringGetTextDatum(""), + CStringGetTextDatum("ng")); /* * If it's not relocatable, substitute the target schema name for * occcurrences of @extschema@. * - * For a relocatable extension, we just run the script as-is. There - * cannot be any need for @extschema@, else it wouldn't be - * relocatable. + * For a relocatable extension, we needn't do this. There cannot be + * any need for @extschema@, else it wouldn't be relocatable. */ if (!control->relocatable) { const char *qSchemaName = quote_identifier(schemaName); - sql = text_to_cstring( - DatumGetTextPP( - DirectFunctionCall3(replace_text, - CStringGetTextDatum(sql), - CStringGetTextDatum("@extschema@"), - CStringGetTextDatum(qSchemaName)))); + t_sql = DirectFunctionCall3(replace_text, + t_sql, + CStringGetTextDatum("@extschema@"), + CStringGetTextDatum(qSchemaName)); } /* @@ -885,15 +899,16 @@ execute_extension_script(Oid extensionOid, ExtensionControlFile *control, */ if (control->module_pathname) { - sql = text_to_cstring( - DatumGetTextPP( - DirectFunctionCall3(replace_text, - CStringGetTextDatum(sql), - CStringGetTextDatum("MODULE_PATHNAME"), - CStringGetTextDatum(control->module_pathname)))); + t_sql = DirectFunctionCall3(replace_text, + t_sql, + CStringGetTextDatum("MODULE_PATHNAME"), + CStringGetTextDatum(control->module_pathname)); } - execute_sql_string(sql, filename); + /* And now back to C string */ + c_sql = text_to_cstring(DatumGetTextPP(t_sql)); + + execute_sql_string(c_sql, filename); } PG_CATCH(); { -- cgit v1.2.3