diff --git a/README.md b/README.md index 0b5e4e4..c8c5e64 100644 --- a/README.md +++ b/README.md @@ -169,18 +169,20 @@ This also works for updating and dropping privileged extensions. If you don't want to enable this functionality, simply leave `supautils.privileged_extensions` empty. Extensions **not** in `supautils.privileged_extensions` would behave normally, i.e. created using the current role. -supautils also lets you set custom scripts per privileged extension that gets run at certain events. Currently supported scripts are `before-create` and `after-create`. +### Extension Custom Scripts + +supautils also lets you set custom scripts per extension that gets run at certain events. Currently supported scripts are `before-create` and `after-create`. To make this work, configure the setting below: ``` -supautils.privileged_extensions_custom_scripts_path = '/opt/postgresql/privileged_extensions_custom_scripts' +supautils.extension_custom_scripts_path = '/some/path/extension-custom-scripts' ``` Then put the scripts inside the path, e.g.: ```sql --- /opt/postgresql/privileged_extensions_custom_scripts/hstore/after-create.sql +-- /some/path/extension-custom-scripts/hstore/after-create.sql grant all on type hstore to non_superuser_role; ``` diff --git a/src/extension_custom_scripts.c b/src/extension_custom_scripts.c new file mode 100644 index 0000000..6f07b55 --- /dev/null +++ b/src/extension_custom_scripts.c @@ -0,0 +1,157 @@ +#include "extension_custom_scripts.h" + +// Prevent recursively running custom scripts +static bool running_custom_script = false; + +// This produces a char surrounded by a triple single quote like '''x''' +// This is so when it gets interpreted by SQL it converts to a single quote surround: 'x' +// To see an example, do `select 'x';` vs `select '''x''';` on psql. +static char *sql_literal(const char *str){ + return str == NULL? + "'null'": // also handle the NULL cstr case + quote_literal_cstr(quote_literal_cstr(str)); +} + +static void run_custom_script(const char *filename, const char *extname, + const char *extschema, const char *extversion, + bool extcascade) { + if (running_custom_script) { + return; + } + running_custom_script = true; + + static const char sql_replace_template[] = "\ + do $_$\ + begin\ + execute replace(replace(replace(replace(\ + pg_read_file(%s)\ + , '@extname@', %s)\ + , '@extschema@', %s)\ + , '@extversion@', %s)\ + , '@extcascade@', %s);\ + exception\ + when undefined_file then\ + null;\ + end; $_$"; + + static const size_t max_sql_len + = sizeof (sql_replace_template) + + MAXPGPATH // max size of a file path + + 3 * (NAMEDATALEN + 6) // 3 *(identifier + 6 single quotes of the SQL literal, see sql_literal) + + sizeof ("false") // max size of a bool string value + ; + + char sql[max_sql_len]; + + snprintf(sql, + max_sql_len, + sql_replace_template, + quote_literal_cstr(filename), + sql_literal(extname), + sql_literal(extschema), + sql_literal(extversion), + extcascade?"'true'":"'false'"); + + PushActiveSnapshot(GetTransactionSnapshot()); + SPI_connect(); + + int rc = SPI_execute(sql, false, 0); + if (rc != SPI_OK_UTILITY) { + elog(ERROR, "SPI_execute failed with error code %d", rc); + } + SPI_finish(); + PopActiveSnapshot(); + running_custom_script = false; +} + +void run_global_before_create_script(char *extname, List *options, const char *privileged_extensions_custom_scripts_path){ + DefElem *d_schema = NULL, *d_new_version = NULL, *d_cascade = NULL; + char *extschema = NULL, *extversion = NULL; + bool extcascade = false; + char filename[MAXPGPATH]; + + ListCell *option_cell = NULL; + + foreach (option_cell, options) { + DefElem *defel = (DefElem *)lfirst(option_cell); + + if (strcmp(defel->defname, "schema") == 0) { + d_schema = defel; + extschema = defGetString(d_schema); + } else if (strcmp(defel->defname, "new_version") == 0) { + d_new_version = defel; + extversion = defGetString(d_new_version); + } else if (strcmp(defel->defname, "cascade") == 0) { + d_cascade = defel; + extcascade = defGetBoolean(d_cascade); + } + } + + snprintf(filename, MAXPGPATH, "%s/before-create.sql", + privileged_extensions_custom_scripts_path); + run_custom_script(filename, extname, extschema, extversion, + extcascade); +} + +void run_ext_before_create_script(char *extname, List *options, const char *privileged_extensions_custom_scripts_path){ + DefElem *d_schema = NULL; + DefElem *d_new_version = NULL; + DefElem *d_cascade = NULL; + char *extschema = NULL; + char *extversion = NULL; + bool extcascade = false; + ListCell *option_cell = NULL; + char filename[MAXPGPATH]; + + foreach (option_cell, options) { + DefElem *defel = (DefElem *)lfirst(option_cell); + + if (strcmp(defel->defname, "schema") == 0) { + d_schema = defel; + extschema = defGetString(d_schema); + } else if (strcmp(defel->defname, "new_version") == 0) { + d_new_version = defel; + extversion = defGetString(d_new_version); + } else if (strcmp(defel->defname, "cascade") == 0) { + d_cascade = defel; + extcascade = defGetBoolean(d_cascade); + } + } + + + snprintf(filename, MAXPGPATH, "%s/%s/before-create.sql", + privileged_extensions_custom_scripts_path, extname); + run_custom_script(filename, extname, extschema, extversion, + extcascade); +} + +void run_ext_after_create_script(char *extname, List *options, const char *privileged_extensions_custom_scripts_path){ + DefElem *d_schema = NULL; + DefElem *d_new_version = NULL; + DefElem *d_cascade = NULL; + char *extschema = NULL; + char *extversion = NULL; + bool extcascade = false; + ListCell *option_cell = NULL; + char filename[MAXPGPATH]; + + foreach (option_cell, options) { + DefElem *defel = (DefElem *)lfirst(option_cell); + + if (strcmp(defel->defname, "schema") == 0) { + d_schema = defel; + extschema = defGetString(d_schema); + } else if (strcmp(defel->defname, "new_version") == 0) { + d_new_version = defel; + extversion = defGetString(d_new_version); + } else if (strcmp(defel->defname, "cascade") == 0) { + d_cascade = defel; + extcascade = defGetBoolean(d_cascade); + } + } + + snprintf(filename, MAXPGPATH, "%s/%s/after-create.sql", + privileged_extensions_custom_scripts_path, extname); + run_custom_script(filename, extname, extschema, extversion, + extcascade); +} diff --git a/src/extension_custom_scripts.h b/src/extension_custom_scripts.h new file mode 100644 index 0000000..fea3c52 --- /dev/null +++ b/src/extension_custom_scripts.h @@ -0,0 +1,18 @@ +#ifndef EXTENSION_CUSTOM_SCRIPTS_H +#define EXTENSION_CUSTOM_SCRIPTS_H + +#include "pg_prelude.h" + +extern void run_global_before_create_script( + char *extname, List *options, + const char *privileged_extensions_custom_scripts_path); + +extern void run_ext_before_create_script( + char *extname, List *options, + const char *privileged_extensions_custom_scripts_path); + +extern void run_ext_after_create_script( + char *extname, List *options, + const char *privileged_extensions_custom_scripts_path); + +#endif diff --git a/src/extensions_parameter_overrides.c b/src/extensions_parameter_overrides.c index 060b04a..6afa880 100644 --- a/src/extensions_parameter_overrides.c +++ b/src/extensions_parameter_overrides.c @@ -128,3 +128,42 @@ parse_extensions_parameter_overrides(const char *str, return state; } + +void override_create_ext_statement(CreateExtensionStmt *stmt, + const size_t total_epos, + const extension_parameter_overrides *epos) { + for (size_t i = 0; i < total_epos; i++) { + if (strcmp(epos[i].name, stmt->extname) == 0) { + const extension_parameter_overrides *epo = &epos[i]; + DefElem *schema_option = NULL; + DefElem *schema_override_option = NULL; + ListCell *option_cell; + + if (epo->schema != NULL) { + Node *schema_node = (Node *)makeString(pstrdup(epo->schema)); + schema_override_option = makeDefElem("schema", schema_node, -1); + } + + foreach (option_cell, stmt->options) { + DefElem *defel = (DefElem *)lfirst(option_cell); + + if (strcmp(defel->defname, "schema") == 0) { + if (schema_option != NULL) { + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("conflicting or redundant options"))); + } + schema_option = defel; + } + } + + if (schema_override_option != NULL) { + if (schema_option != NULL) { + stmt->options = + list_delete_ptr(stmt->options, schema_option); + } + stmt->options = lappend(stmt->options, schema_override_option); + } + } + } +} diff --git a/src/extensions_parameter_overrides.h b/src/extensions_parameter_overrides.h index 4cda50f..a79c11f 100644 --- a/src/extensions_parameter_overrides.h +++ b/src/extensions_parameter_overrides.h @@ -1,6 +1,8 @@ #ifndef EXTENSIONS_PARAMETER_OVERRIDES_H #define EXTENSIONS_PARAMETER_OVERRIDES_H +#include "pg_prelude.h" + typedef struct { char *name; char *schema; @@ -29,4 +31,9 @@ extern json_extension_parameter_overrides_parse_state parse_extensions_parameter_overrides(const char *str, extension_parameter_overrides *epos); +extern void +override_create_ext_statement(CreateExtensionStmt *stmt, + const size_t total_epos, + const extension_parameter_overrides *epos); + #endif diff --git a/src/privileged_extensions.c b/src/privileged_extensions.c index ba18ebd..e328578 100644 --- a/src/privileged_extensions.c +++ b/src/privileged_extensions.c @@ -1,200 +1,4 @@ -#include "pg_prelude.h" -#include "extensions_parameter_overrides.h" #include "privileged_extensions.h" -#include "utils.h" - -// Prevent recursively running custom scripts -static bool running_custom_script = false; - -// This produces a char surrounded by a triple single quote like '''x''' -// This is so when it gets interpreted by SQL it converts to a single quote surround: 'x' -// To see an example, do `select 'x';` vs `select '''x''';` on psql. -static char *sql_literal(const char *str){ - return str == NULL? - "'null'": // also handle the NULL cstr case - quote_literal_cstr(quote_literal_cstr(str)); -} - -static void run_custom_script(const char *filename, const char *extname, - const char *extschema, const char *extversion, - bool extcascade) { - if (running_custom_script) { - return; - } - running_custom_script = true; - - static const char sql_replace_template[] = "\ - do $_$\ - begin\ - execute replace(replace(replace(replace(\ - pg_read_file(%s)\ - , '@extname@', %s)\ - , '@extschema@', %s)\ - , '@extversion@', %s)\ - , '@extcascade@', %s);\ - exception\ - when undefined_file then\ - null;\ - end; $_$"; - - static const size_t max_sql_len - = sizeof (sql_replace_template) - + MAXPGPATH // max size of a file path - + 3 * (NAMEDATALEN + 6) // 3 *(identifier + 6 single quotes of the SQL literal, see sql_literal) - + sizeof ("false") // max size of a bool string value - ; - - char sql[max_sql_len]; - - snprintf(sql, - max_sql_len, - sql_replace_template, - quote_literal_cstr(filename), - sql_literal(extname), - sql_literal(extschema), - sql_literal(extversion), - extcascade?"'true'":"'false'"); - - PushActiveSnapshot(GetTransactionSnapshot()); - SPI_connect(); - - int rc = SPI_execute(sql, false, 0); - if (rc != SPI_OK_UTILITY) { - elog(ERROR, "SPI_execute failed with error code %d", rc); - } - SPI_finish(); - PopActiveSnapshot(); - running_custom_script = false; -} - -void run_global_before_create_script(char *extname, List *options, const char *privileged_extensions_custom_scripts_path){ - DefElem *d_schema = NULL, *d_new_version = NULL, *d_cascade = NULL; - char *extschema = NULL, *extversion = NULL; - bool extcascade = false; - char filename[MAXPGPATH]; - - ListCell *option_cell = NULL; - - foreach (option_cell, options) { - DefElem *defel = (DefElem *)lfirst(option_cell); - - if (strcmp(defel->defname, "schema") == 0) { - d_schema = defel; - extschema = defGetString(d_schema); - } else if (strcmp(defel->defname, "new_version") == 0) { - d_new_version = defel; - extversion = defGetString(d_new_version); - } else if (strcmp(defel->defname, "cascade") == 0) { - d_cascade = defel; - extcascade = defGetBoolean(d_cascade); - } - } - - snprintf(filename, MAXPGPATH, "%s/before-create.sql", - privileged_extensions_custom_scripts_path); - run_custom_script(filename, extname, extschema, extversion, - extcascade); -} - -void run_ext_before_create_script(char *extname, List *options, const char *privileged_extensions_custom_scripts_path){ - DefElem *d_schema = NULL; - DefElem *d_new_version = NULL; - DefElem *d_cascade = NULL; - char *extschema = NULL; - char *extversion = NULL; - bool extcascade = false; - ListCell *option_cell = NULL; - char filename[MAXPGPATH]; - - foreach (option_cell, options) { - DefElem *defel = (DefElem *)lfirst(option_cell); - - if (strcmp(defel->defname, "schema") == 0) { - d_schema = defel; - extschema = defGetString(d_schema); - } else if (strcmp(defel->defname, "new_version") == 0) { - d_new_version = defel; - extversion = defGetString(d_new_version); - } else if (strcmp(defel->defname, "cascade") == 0) { - d_cascade = defel; - extcascade = defGetBoolean(d_cascade); - } - } - - - snprintf(filename, MAXPGPATH, "%s/%s/before-create.sql", - privileged_extensions_custom_scripts_path, extname); - run_custom_script(filename, extname, extschema, extversion, - extcascade); -} - -void run_ext_after_create_script(char *extname, List *options, const char *privileged_extensions_custom_scripts_path){ - DefElem *d_schema = NULL; - DefElem *d_new_version = NULL; - DefElem *d_cascade = NULL; - char *extschema = NULL; - char *extversion = NULL; - bool extcascade = false; - ListCell *option_cell = NULL; - char filename[MAXPGPATH]; - - foreach (option_cell, options) { - DefElem *defel = (DefElem *)lfirst(option_cell); - - if (strcmp(defel->defname, "schema") == 0) { - d_schema = defel; - extschema = defGetString(d_schema); - } else if (strcmp(defel->defname, "new_version") == 0) { - d_new_version = defel; - extversion = defGetString(d_new_version); - } else if (strcmp(defel->defname, "cascade") == 0) { - d_cascade = defel; - extcascade = defGetBoolean(d_cascade); - } - } - - snprintf(filename, MAXPGPATH, "%s/%s/after-create.sql", - privileged_extensions_custom_scripts_path, extname); - run_custom_script(filename, extname, extschema, extversion, - extcascade); -} - -void override_create_ext_statement(CreateExtensionStmt *stmt, const size_t total_epos, const extension_parameter_overrides *epos){ - for (size_t i = 0; i < total_epos; i++) { - if (strcmp(epos[i].name, stmt->extname) == 0) { - const extension_parameter_overrides *epo = &epos[i]; - DefElem *schema_option = NULL; - DefElem *schema_override_option = NULL; - ListCell *option_cell; - - if (epo->schema != NULL) { - Node *schema_node = (Node *)makeString(pstrdup(epo->schema)); - schema_override_option = makeDefElem("schema", schema_node, -1); - } - - foreach (option_cell, stmt->options) { - DefElem *defel = (DefElem *)lfirst(option_cell); - - if (strcmp(defel->defname, "schema") == 0) { - if (schema_option != NULL) { - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("conflicting or redundant options"))); - } - schema_option = defel; - } - } - - if (schema_override_option != NULL) { - if (schema_option != NULL) { - stmt->options = - list_delete_ptr(stmt->options, schema_option); - } - stmt->options = lappend(stmt->options, schema_override_option); - } - } - } -} bool all_extensions_are_privileged(List *objects, const char *privileged_extensions){ ListCell *lc; diff --git a/src/privileged_extensions.h b/src/privileged_extensions.h index 681422d..adf1d8e 100644 --- a/src/privileged_extensions.h +++ b/src/privileged_extensions.h @@ -1,19 +1,11 @@ #ifndef PRIVILEGED_EXTENSIONS_H #define PRIVILEGED_EXTENSIONS_H -#include "extensions_parameter_overrides.h" +#include "pg_prelude.h" #include "utils.h" -bool all_extensions_are_privileged(List *objects, const char *privileged_extensions); +extern bool all_extensions_are_privileged(List *objects, const char *privileged_extensions); -bool is_extension_privileged(const char *extname, const char *privileged_extensions); - -void run_global_before_create_script(char *extname, List *options, const char *privileged_extensions_custom_scripts_path); - -void run_ext_before_create_script(char *extname, List *options, const char *privileged_extensions_custom_scripts_path); - -void run_ext_after_create_script(char *extname, List *options, const char *privileged_extensions_custom_scripts_path); - -void override_create_ext_statement(CreateExtensionStmt *stmt, const size_t total_epos, const extension_parameter_overrides *epos); +extern bool is_extension_privileged(const char *extname, const char *privileged_extensions); #endif diff --git a/src/supautils.c b/src/supautils.c index a66cf76..028c57d 100644 --- a/src/supautils.c +++ b/src/supautils.c @@ -1,6 +1,7 @@ #include "pg_prelude.h" #include "constrained_extensions.h" #include "drop_trigger_grants.h" +#include "extension_custom_scripts.h" #include "extensions_parameter_overrides.h" #include "policy_grants.h" #include "privileged_extensions.h" @@ -39,7 +40,7 @@ static char *placeholders_disallowed_values = NULL; static char *empty_placeholder = NULL; static char *privileged_extensions = NULL; static char *supautils_superuser = NULL; -static char *privileged_extensions_custom_scripts_path = NULL; +static char *extension_custom_scripts_path = NULL; static char *privileged_role = NULL; // the privileged_role is a proxy role for the `supautils.superuser` role static char *privileged_role_allowed_configs = NULL; @@ -448,29 +449,36 @@ static void supautils_hook(PROCESS_UTILITY_PARAMS) { constrain_extension(stmt->extname, cexts, total_cexts); - if (is_extension_privileged(stmt->extname, privileged_extensions)) { - bool already_switched_to_superuser = false; + bool already_switched_to_superuser = false; - switch_to_superuser(supautils_superuser, &already_switched_to_superuser); + switch_to_superuser(supautils_superuser, &already_switched_to_superuser); - run_global_before_create_script(stmt->extname, stmt->options, privileged_extensions_custom_scripts_path); + run_global_before_create_script(stmt->extname, stmt->options, extension_custom_scripts_path); - run_ext_before_create_script(stmt->extname, stmt->options, privileged_extensions_custom_scripts_path); + run_ext_before_create_script(stmt->extname, stmt->options, extension_custom_scripts_path); - override_create_ext_statement(stmt, total_epos, epos); + override_create_ext_statement(stmt, total_epos, epos); - run_process_utility_hook(prev_hook); + if (is_extension_privileged(stmt->extname, privileged_extensions)) { + run_process_utility_hook(prev_hook); + } else { + if (!already_switched_to_superuser) { + switch_to_original_role(); + already_switched_to_superuser = false; + } - run_ext_after_create_script(stmt->extname, stmt->options, privileged_extensions_custom_scripts_path); + run_process_utility_hook(prev_hook); - if (!already_switched_to_superuser) { - switch_to_original_role(); - } + switch_to_superuser(supautils_superuser, &already_switched_to_superuser); + } - return; + run_ext_after_create_script(stmt->extname, stmt->options, extension_custom_scripts_path); + + if (!already_switched_to_superuser) { + switch_to_original_role(); } - break; + return; } /* @@ -1261,9 +1269,19 @@ void _PG_init(void) { NULL); DefineCustomStringVariable("supautils.privileged_extensions_custom_scripts_path", - "Path to load privileged extensions' custom scripts from", + "Path to load privileged extensions' custom scripts from. Deprecated: use supautils.extension_custom_scripts_path instead.", + NULL, + &extension_custom_scripts_path, + NULL, + PGC_SIGHUP, 0, + NULL, + NULL, + NULL); + + DefineCustomStringVariable("supautils.extension_custom_scripts_path", + "Path to load extension custom scripts from", NULL, - &privileged_extensions_custom_scripts_path, + &extension_custom_scripts_path, NULL, PGC_SIGHUP, 0, NULL, diff --git a/test/expected/extension_custom_scripts.out b/test/expected/extension_custom_scripts.out new file mode 100644 index 0000000..68dbfbf --- /dev/null +++ b/test/expected/extension_custom_scripts.out @@ -0,0 +1,38 @@ +set role extensions_role; +\echo + +-- per-extension custom scripts are run +create extension fuzzystrmatch; +drop extension fuzzystrmatch; +select * from t2; + column1 +--------- + 1 +(1 row) + +reset role; +drop table t2; +set role extensions_role; +\echo + +-- global extension custom scripts are run +create extension dict_xsyn; +NOTICE: extname: dict_xsyn, extschema: , extversion: , extcascade: f +create extension insert_username version "1.0" schema public cascade; +NOTICE: extname: insert_username, extschema: public, extversion: 1.0, extcascade: t +\echo + +-- custom scripts are run even for superusers +reset role; +create extension fuzzystrmatch; +drop extension fuzzystrmatch; +select * from t2; + column1 +--------- + 1 +(1 row) + +drop table t2; +set role extensions_role; +\echo + diff --git a/test/expected/privileged_extensions.out b/test/expected/privileged_extensions.out index fe8aa79..0ef8c0f 100644 --- a/test/expected/privileged_extensions.out +++ b/test/expected/privileged_extensions.out @@ -12,39 +12,6 @@ select '1=>2'::hstore; drop extension hstore; \echo --- per-extension custom scripts are run -select * from t2; - column1 ---------- - 1 -(1 row) - -reset role; -drop table t2; -set role extensions_role; -\echo - --- global extension custom scripts are run -create extension dict_xsyn; -NOTICE: extname: dict_xsyn, extschema: , extversion: , extcascade: f -create extension insert_username version "1.0" schema public cascade; -NOTICE: extname: insert_username, extschema: public, extversion: 1.0, extcascade: t -\echo - --- custom scripts are run even for superusers -reset role; -create extension hstore; -drop extension hstore; -select * from t2; - column1 ---------- - 1 -(1 row) - -drop table t2; -set role extensions_role; -\echo - -- cannot create other extensions create extension file_fdw; ERROR: permission denied to create extension "file_fdw" diff --git a/test/init.conf.in b/test/init.conf.in index 1dde758..d2488ad 100644 --- a/test/init.conf.in +++ b/test/init.conf.in @@ -6,7 +6,7 @@ wal_level=logical supautils.reserved_roles='supabase_storage_admin, anon, reserved_but_not_yet_created, authenticator*' supautils.reserved_memberships='pg_read_server_files,pg_write_server_files,pg_execute_server_program,role_with_reserved_membership' -supautils.privileged_extensions='autoinc, citext, hstore, sslinfo, insert_username, dict_xsyn, postgres_fdw, pageinspect' +supautils.privileged_extensions='autoinc, citext, hstore, sslinfo, insert_username, dict_xsyn, fuzzystrmatch, postgres_fdw, pageinspect' supautils.constrained_extensions='{"adminpack": { "cpu": 64}, "cube": { "mem": "17 GB"}, "lo": { "disk": "100 GB"}, "amcheck": { "cpu": 2, "mem": "100 MB", "disk": "100 MB"}}' supautils.privileged_role='privileged_role' supautils.privileged_role_allowed_configs='session_replication_role, pgrst.*, other.nested.*' @@ -15,4 +15,4 @@ supautils.placeholders_disallowed_values='"content-type","x-special-header",spec supautils.extensions_parameter_overrides='{"sslinfo":{"schema":"pg_catalog"}}' supautils.drop_trigger_grants='{"privileged_role":["allow_drop_triggers.my_table"]}' supautils.policy_grants='{"privileged_role":["allow_policies.my_table","allow_policies.nonexistent_table"]}' -supautils.privileged_extensions_custom_scripts_path='@TMPDIR@/privileged_extensions_custom_scripts' +supautils.extension_custom_scripts_path='@TMPDIR@/extension-custom-scripts' diff --git a/test/init.sh b/test/init.sh index ab70b76..c80646b 100644 --- a/test/init.sh +++ b/test/init.sh @@ -1,5 +1,5 @@ # print notice when creating an extension -mkdir -p "$TMPDIR/privileged_extensions_custom_scripts" +mkdir -p "$TMPDIR/extension-custom-scripts" echo "do \$\$ begin if not (@extname@ = ANY(ARRAY['dict_xsyn', 'insert_username'])) then @@ -8,12 +8,12 @@ echo "do \$\$ if exists (select from pg_available_extensions where name = @extname@) then raise notice 'extname: %, extschema: %, extversion: %, extcascade: %', @extname@, @extschema@, @extversion@, @extcascade@; end if; - end \$\$;" > "$TMPDIR/privileged_extensions_custom_scripts/before-create.sql" + end \$\$;" > "$TMPDIR/extension-custom-scripts/before-create.sql" -mkdir -p "$TMPDIR/privileged_extensions_custom_scripts/autoinc" -echo 'create extension citext;' > "$TMPDIR/privileged_extensions_custom_scripts/autoinc/after-create.sql" +mkdir -p "$TMPDIR/extension-custom-scripts/autoinc" +echo 'create extension citext;' > "$TMPDIR/extension-custom-scripts/autoinc/after-create.sql" # assert both before-create and after-create scripts are run -mkdir -p "$TMPDIR/privileged_extensions_custom_scripts/hstore" -echo 'create table t1();' > "$TMPDIR/privileged_extensions_custom_scripts/hstore/before-create.sql" -echo 'drop table t1; create table t2 as values (1);' > "$TMPDIR/privileged_extensions_custom_scripts/hstore/after-create.sql" +mkdir -p "$TMPDIR/extension-custom-scripts/fuzzystrmatch" +echo 'create table t1();' > "$TMPDIR/extension-custom-scripts/fuzzystrmatch/before-create.sql" +echo 'drop table t1; create table t2 as values (1);' > "$TMPDIR/extension-custom-scripts/fuzzystrmatch/after-create.sql" diff --git a/test/sql/extension_custom_scripts.sql b/test/sql/extension_custom_scripts.sql new file mode 100644 index 0000000..9885e92 --- /dev/null +++ b/test/sql/extension_custom_scripts.sql @@ -0,0 +1,27 @@ +set role extensions_role; +\echo + +-- per-extension custom scripts are run +create extension fuzzystrmatch; +drop extension fuzzystrmatch; +select * from t2; + +reset role; +drop table t2; +set role extensions_role; +\echo + +-- global extension custom scripts are run +create extension dict_xsyn; +create extension insert_username version "1.0" schema public cascade; +\echo + +-- custom scripts are run even for superusers +reset role; +create extension fuzzystrmatch; +drop extension fuzzystrmatch; +select * from t2; + +drop table t2; +set role extensions_role; +\echo diff --git a/test/sql/privileged_extensions.sql b/test/sql/privileged_extensions.sql index fb88e38..e56a77b 100644 --- a/test/sql/privileged_extensions.sql +++ b/test/sql/privileged_extensions.sql @@ -8,29 +8,6 @@ select '1=>2'::hstore; drop extension hstore; \echo --- per-extension custom scripts are run -select * from t2; - -reset role; -drop table t2; -set role extensions_role; -\echo - --- global extension custom scripts are run -create extension dict_xsyn; -create extension insert_username version "1.0" schema public cascade; -\echo - --- custom scripts are run even for superusers -reset role; -create extension hstore; -drop extension hstore; -select * from t2; - -drop table t2; -set role extensions_role; -\echo - -- cannot create other extensions create extension file_fdw; \echo