1 /*-------------------------------------------------------------------------
4 * Commands to manipulate extensions
6 * Extensions in PostgreSQL allow management of collections of SQL objects.
8 * All we need internally to manage an extension is an OID so that the
9 * dependent objects can be associated with it. An extension is created by
10 * populating the pg_extension catalog from a "control" file.
11 * The extension control file is parsed with the same parser we use for
12 * postgresql.conf. An extension also has an installation script file,
13 * containing SQL commands to create the extension's objects.
15 * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
16 * Portions Copyright (c) 1994, Regents of the University of California
20 * src/backend/commands/extension.c
22 *-------------------------------------------------------------------------
32 #include "access/genam.h"
33 #include "access/htup_details.h"
34 #include "access/relation.h"
35 #include "access/sysattr.h"
36 #include "access/table.h"
37 #include "access/xact.h"
38 #include "catalog/catalog.h"
39 #include "catalog/dependency.h"
40 #include "catalog/indexing.h"
41 #include "catalog/namespace.h"
42 #include "catalog/objectaccess.h"
43 #include "catalog/pg_collation.h"
44 #include "catalog/pg_depend.h"
45 #include "catalog/pg_extension.h"
46 #include "catalog/pg_namespace.h"
47 #include "catalog/pg_type.h"
48 #include "commands/alter.h"
49 #include "commands/comment.h"
50 #include "commands/defrem.h"
51 #include "commands/extension.h"
52 #include "commands/schemacmds.h"
54 #include "mb/pg_wchar.h"
55 #include "miscadmin.h"
56 #include "nodes/makefuncs.h"
57 #include "storage/fd.h"
58 #include "tcop/utility.h"
59 #include "utils/acl.h"
60 #include "utils/builtins.h"
61 #include "utils/fmgroids.h"
62 #include "utils/lsyscache.h"
63 #include "utils/memutils.h"
64 #include "utils/rel.h"
65 #include "utils/snapmgr.h"
66 #include "utils/varlena.h"
69 /* Globally visible state variables */
70 bool creating_extension = false;
71 Oid CurrentExtensionObject = InvalidOid;
74 * Internal data structure to hold the results of parsing a control file
76 typedef struct ExtensionControlFile
78 char *name; /* name of the extension */
79 char *directory; /* directory for script files */
80 char *default_version; /* default install target version, if any */
81 char *module_pathname; /* string to substitute for
83 char *comment; /* comment, if any */
84 char *schema; /* target schema (allowed if !relocatable) */
85 bool relocatable; /* is ALTER EXTENSION SET SCHEMA supported? */
86 bool superuser; /* must be superuser to install? */
87 int encoding; /* encoding of the script file, or -1 */
88 List *requires; /* names of prerequisite extensions */
89 } ExtensionControlFile;
92 * Internal data structure for update path information
94 typedef struct ExtensionVersionInfo
96 char *name; /* name of the starting version */
97 List *reachable; /* List of ExtensionVersionInfo's */
98 bool installable; /* does this version have an install script? */
99 /* working state for Dijkstra's algorithm: */
100 bool distance_known; /* is distance from start known yet? */
101 int distance; /* current worst-case distance estimate */
102 struct ExtensionVersionInfo *previous; /* current best predecessor */
103 } ExtensionVersionInfo;
105 /* Local functions */
106 static List *find_update_path(List *evi_list,
107 ExtensionVersionInfo *evi_start,
108 ExtensionVersionInfo *evi_target,
109 bool reject_indirect,
111 static Oid get_required_extension(char *reqExtensionName,
113 char *origSchemaName,
117 static void get_available_versions_for_extension(ExtensionControlFile *pcontrol,
118 Tuplestorestate *tupstore,
120 static Datum convert_requires_to_datum(List *requires);
121 static void ApplyExtensionUpdates(Oid extensionOid,
122 ExtensionControlFile *pcontrol,
123 const char *initialVersion,
124 List *updateVersions,
125 char *origSchemaName,
128 static char *read_whole_file(const char *filename, int *length);
132 * get_extension_oid - given an extension name, look up the OID
134 * If missing_ok is false, throw an error if extension name not found. If
135 * true, just return InvalidOid.
138 get_extension_oid(const char *extname, bool missing_ok)
142 SysScanDesc scandesc;
144 ScanKeyData entry[1];
146 rel = table_open(ExtensionRelationId, AccessShareLock);
148 ScanKeyInit(&entry[0],
149 Anum_pg_extension_extname,
150 BTEqualStrategyNumber, F_NAMEEQ,
151 CStringGetDatum(extname));
153 scandesc = systable_beginscan(rel, ExtensionNameIndexId, true,
156 tuple = systable_getnext(scandesc);
158 /* We assume that there can be at most one matching tuple */
159 if (HeapTupleIsValid(tuple))
160 result = ((Form_pg_extension) GETSTRUCT(tuple))->oid;
164 systable_endscan(scandesc);
166 table_close(rel, AccessShareLock);
168 if (!OidIsValid(result) && !missing_ok)
170 (errcode(ERRCODE_UNDEFINED_OBJECT),
171 errmsg("extension \"%s\" does not exist",
178 * get_extension_name - given an extension OID, look up the name
180 * Returns a palloc'd string, or NULL if no such extension.
183 get_extension_name(Oid ext_oid)
187 SysScanDesc scandesc;
189 ScanKeyData entry[1];
191 rel = table_open(ExtensionRelationId, AccessShareLock);
193 ScanKeyInit(&entry[0],
194 Anum_pg_extension_oid,
195 BTEqualStrategyNumber, F_OIDEQ,
196 ObjectIdGetDatum(ext_oid));
198 scandesc = systable_beginscan(rel, ExtensionOidIndexId, true,
201 tuple = systable_getnext(scandesc);
203 /* We assume that there can be at most one matching tuple */
204 if (HeapTupleIsValid(tuple))
205 result = pstrdup(NameStr(((Form_pg_extension) GETSTRUCT(tuple))->extname));
209 systable_endscan(scandesc);
211 table_close(rel, AccessShareLock);
217 * get_extension_schema - given an extension OID, fetch its extnamespace
219 * Returns InvalidOid if no such extension.
222 get_extension_schema(Oid ext_oid)
226 SysScanDesc scandesc;
228 ScanKeyData entry[1];
230 rel = table_open(ExtensionRelationId, AccessShareLock);
232 ScanKeyInit(&entry[0],
233 Anum_pg_extension_oid,
234 BTEqualStrategyNumber, F_OIDEQ,
235 ObjectIdGetDatum(ext_oid));
237 scandesc = systable_beginscan(rel, ExtensionOidIndexId, true,
240 tuple = systable_getnext(scandesc);
242 /* We assume that there can be at most one matching tuple */
243 if (HeapTupleIsValid(tuple))
244 result = ((Form_pg_extension) GETSTRUCT(tuple))->extnamespace;
248 systable_endscan(scandesc);
250 table_close(rel, AccessShareLock);
256 * Utility functions to check validity of extension and version names
259 check_valid_extension_name(const char *extensionname)
261 int namelen = strlen(extensionname);
264 * Disallow empty names (the parser rejects empty identifiers anyway, but
269 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
270 errmsg("invalid extension name: \"%s\"", extensionname),
271 errdetail("Extension names must not be empty.")));
274 * No double dashes, since that would make script filenames ambiguous.
276 if (strstr(extensionname, "--"))
278 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
279 errmsg("invalid extension name: \"%s\"", extensionname),
280 errdetail("Extension names must not contain \"--\".")));
283 * No leading or trailing dash either. (We could probably allow this, but
284 * it would require much care in filename parsing and would make filenames
285 * visually if not formally ambiguous. Since there's no real-world use
286 * case, let's just forbid it.)
288 if (extensionname[0] == '-' || extensionname[namelen - 1] == '-')
290 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
291 errmsg("invalid extension name: \"%s\"", extensionname),
292 errdetail("Extension names must not begin or end with \"-\".")));
295 * No directory separators either (this is sufficient to prevent ".."
298 if (first_dir_separator(extensionname) != NULL)
300 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
301 errmsg("invalid extension name: \"%s\"", extensionname),
302 errdetail("Extension names must not contain directory separator characters.")));
306 check_valid_version_name(const char *versionname)
308 int namelen = strlen(versionname);
311 * Disallow empty names (we could possibly allow this, but there seems
316 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
317 errmsg("invalid extension version name: \"%s\"", versionname),
318 errdetail("Version names must not be empty.")));
321 * No double dashes, since that would make script filenames ambiguous.
323 if (strstr(versionname, "--"))
325 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
326 errmsg("invalid extension version name: \"%s\"", versionname),
327 errdetail("Version names must not contain \"--\".")));
330 * No leading or trailing dash either.
332 if (versionname[0] == '-' || versionname[namelen - 1] == '-')
334 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
335 errmsg("invalid extension version name: \"%s\"", versionname),
336 errdetail("Version names must not begin or end with \"-\".")));
339 * No directory separators either (this is sufficient to prevent ".."
342 if (first_dir_separator(versionname) != NULL)
344 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
345 errmsg("invalid extension version name: \"%s\"", versionname),
346 errdetail("Version names must not contain directory separator characters.")));
350 * Utility functions to handle extension-related path names
353 is_extension_control_filename(const char *filename)
355 const char *extension = strrchr(filename, '.');
357 return (extension != NULL) && (strcmp(extension, ".control") == 0);
361 is_extension_script_filename(const char *filename)
363 const char *extension = strrchr(filename, '.');
365 return (extension != NULL) && (strcmp(extension, ".sql") == 0);
369 get_extension_control_directory(void)
371 char sharepath[MAXPGPATH];
374 get_share_path(my_exec_path, sharepath);
375 result = (char *) palloc(MAXPGPATH);
376 snprintf(result, MAXPGPATH, "%s/extension", sharepath);
382 get_extension_control_filename(const char *extname)
384 char sharepath[MAXPGPATH];
387 get_share_path(my_exec_path, sharepath);
388 result = (char *) palloc(MAXPGPATH);
389 snprintf(result, MAXPGPATH, "%s/extension/%s.control",
396 get_extension_script_directory(ExtensionControlFile *control)
398 char sharepath[MAXPGPATH];
402 * The directory parameter can be omitted, absolute, or relative to the
403 * installation's share directory.
405 if (!control->directory)
406 return get_extension_control_directory();
408 if (is_absolute_path(control->directory))
409 return pstrdup(control->directory);
411 get_share_path(my_exec_path, sharepath);
412 result = (char *) palloc(MAXPGPATH);
413 snprintf(result, MAXPGPATH, "%s/%s", sharepath, control->directory);
419 get_extension_aux_control_filename(ExtensionControlFile *control,
425 scriptdir = get_extension_script_directory(control);
427 result = (char *) palloc(MAXPGPATH);
428 snprintf(result, MAXPGPATH, "%s/%s--%s.control",
429 scriptdir, control->name, version);
437 get_extension_script_filename(ExtensionControlFile *control,
438 const char *from_version, const char *version)
443 scriptdir = get_extension_script_directory(control);
445 result = (char *) palloc(MAXPGPATH);
447 snprintf(result, MAXPGPATH, "%s/%s--%s--%s.sql",
448 scriptdir, control->name, from_version, version);
450 snprintf(result, MAXPGPATH, "%s/%s--%s.sql",
451 scriptdir, control->name, version);
460 * Parse contents of primary or auxiliary control file, and fill in
461 * fields of *control. We parse primary file if version == NULL,
462 * else the optional auxiliary file for that version.
464 * Control files are supposed to be very short, half a dozen lines,
465 * so we don't worry about memory allocation risks here. Also we don't
466 * worry about what encoding it's in; all values are expected to be ASCII.
469 parse_extension_control_file(ExtensionControlFile *control,
474 ConfigVariable *item,
479 * Locate the file to read. Auxiliary files are optional.
482 filename = get_extension_aux_control_filename(control, version);
484 filename = get_extension_control_filename(control->name);
486 if ((file = AllocateFile(filename, "r")) == NULL)
488 if (version && errno == ENOENT)
490 /* no auxiliary file for this version */
495 (errcode_for_file_access(),
496 errmsg("could not open extension control file \"%s\": %m",
501 * Parse the file content, using GUC's file parsing code. We need not
502 * check the return value since any errors will be thrown at ERROR level.
504 (void) ParseConfigFp(file, filename, 0, ERROR, &head, &tail);
509 * Convert the ConfigVariable list into ExtensionControlFile entries.
511 for (item = head; item != NULL; item = item->next)
513 if (strcmp(item->name, "directory") == 0)
517 (errcode(ERRCODE_SYNTAX_ERROR),
518 errmsg("parameter \"%s\" cannot be set in a secondary extension control file",
521 control->directory = pstrdup(item->value);
523 else if (strcmp(item->name, "default_version") == 0)
527 (errcode(ERRCODE_SYNTAX_ERROR),
528 errmsg("parameter \"%s\" cannot be set in a secondary extension control file",
531 control->default_version = pstrdup(item->value);
533 else if (strcmp(item->name, "module_pathname") == 0)
535 control->module_pathname = pstrdup(item->value);
537 else if (strcmp(item->name, "comment") == 0)
539 control->comment = pstrdup(item->value);
541 else if (strcmp(item->name, "schema") == 0)
543 control->schema = pstrdup(item->value);
545 else if (strcmp(item->name, "relocatable") == 0)
547 if (!parse_bool(item->value, &control->relocatable))
549 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
550 errmsg("parameter \"%s\" requires a Boolean value",
553 else if (strcmp(item->name, "superuser") == 0)
555 if (!parse_bool(item->value, &control->superuser))
557 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
558 errmsg("parameter \"%s\" requires a Boolean value",
561 else if (strcmp(item->name, "encoding") == 0)
563 control->encoding = pg_valid_server_encoding(item->value);
564 if (control->encoding < 0)
566 (errcode(ERRCODE_UNDEFINED_OBJECT),
567 errmsg("\"%s\" is not a valid encoding name",
570 else if (strcmp(item->name, "requires") == 0)
572 /* Need a modifiable copy of string */
573 char *rawnames = pstrdup(item->value);
575 /* Parse string into list of identifiers */
576 if (!SplitIdentifierString(rawnames, ',', &control->requires))
578 /* syntax error in name list */
580 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
581 errmsg("parameter \"%s\" must be a list of extension names",
587 (errcode(ERRCODE_SYNTAX_ERROR),
588 errmsg("unrecognized parameter \"%s\" in file \"%s\"",
589 item->name, filename)));
592 FreeConfigVariables(head);
594 if (control->relocatable && control->schema != NULL)
596 (errcode(ERRCODE_SYNTAX_ERROR),
597 errmsg("parameter \"schema\" cannot be specified when \"relocatable\" is true")));
603 * Read the primary control file for the specified extension.
605 static ExtensionControlFile *
606 read_extension_control_file(const char *extname)
608 ExtensionControlFile *control;
611 * Set up default values. Pointer fields are initially null.
613 control = (ExtensionControlFile *) palloc0(sizeof(ExtensionControlFile));
614 control->name = pstrdup(extname);
615 control->relocatable = false;
616 control->superuser = true;
617 control->encoding = -1;
620 * Parse the primary control file.
622 parse_extension_control_file(control, NULL);
628 * Read the auxiliary control file for the specified extension and version.
630 * Returns a new modified ExtensionControlFile struct; the original struct
631 * (reflecting just the primary control file) is not modified.
633 static ExtensionControlFile *
634 read_extension_aux_control_file(const ExtensionControlFile *pcontrol,
637 ExtensionControlFile *acontrol;
640 * Flat-copy the struct. Pointer fields share values with original.
642 acontrol = (ExtensionControlFile *) palloc(sizeof(ExtensionControlFile));
643 memcpy(acontrol, pcontrol, sizeof(ExtensionControlFile));
646 * Parse the auxiliary control file, overwriting struct fields
648 parse_extension_control_file(acontrol, version);
654 * Read an SQL script file into a string, and convert to database encoding
657 read_extension_script_file(const ExtensionControlFile *control,
658 const char *filename)
665 src_str = read_whole_file(filename, &len);
667 /* use database encoding if not given */
668 if (control->encoding < 0)
669 src_encoding = GetDatabaseEncoding();
671 src_encoding = control->encoding;
673 /* make sure that source string is valid in the expected encoding */
674 pg_verify_mbstr_len(src_encoding, src_str, len, false);
677 * Convert the encoding to the database encoding. read_whole_file
678 * null-terminated the string, so if no conversion happens the string is
681 dest_str = pg_any_to_server(src_str, len, src_encoding);
687 * Execute given SQL string.
689 * Note: it's tempting to just use SPI to execute the string, but that does
690 * not work very well. The really serious problem is that SPI will parse,
691 * analyze, and plan the whole string before executing any of it; of course
692 * this fails if there are any plannable statements referring to objects
693 * created earlier in the script. A lesser annoyance is that SPI insists
694 * on printing the whole string as errcontext in case of any error, and that
695 * could be very long.
698 execute_sql_string(const char *sql)
700 List *raw_parsetree_list;
705 * Parse the SQL string into a list of raw parse trees.
707 raw_parsetree_list = pg_parse_query(sql);
709 /* All output from SELECTs goes to the bit bucket */
710 dest = CreateDestReceiver(DestNone);
713 * Do parse analysis, rule rewrite, planning, and execution for each raw
714 * parsetree. We must fully execute each query before beginning parse
715 * analysis on the next one, since there may be interdependencies.
717 foreach(lc1, raw_parsetree_list)
719 RawStmt *parsetree = lfirst_node(RawStmt, lc1);
723 /* Be sure parser can see any DDL done so far */
724 CommandCounterIncrement();
726 stmt_list = pg_analyze_and_rewrite(parsetree,
731 stmt_list = pg_plan_queries(stmt_list, CURSOR_OPT_PARALLEL_OK, NULL);
733 foreach(lc2, stmt_list)
735 PlannedStmt *stmt = lfirst_node(PlannedStmt, lc2);
737 CommandCounterIncrement();
739 PushActiveSnapshot(GetTransactionSnapshot());
741 if (stmt->utilityStmt == NULL)
745 qdesc = CreateQueryDesc(stmt,
747 GetActiveSnapshot(), NULL,
748 dest, NULL, NULL, 0);
750 ExecutorStart(qdesc, 0);
751 ExecutorRun(qdesc, ForwardScanDirection, 0, true);
752 ExecutorFinish(qdesc);
755 FreeQueryDesc(qdesc);
759 if (IsA(stmt->utilityStmt, TransactionStmt))
761 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
762 errmsg("transaction control statements are not allowed within an extension script")));
766 PROCESS_UTILITY_QUERY,
777 /* Be sure to advance the command counter after the last script command */
778 CommandCounterIncrement();
782 * Execute the appropriate script file for installing or updating the extension
784 * If from_version isn't NULL, it's an update
787 execute_extension_script(Oid extensionOid, ExtensionControlFile *control,
788 const char *from_version,
790 List *requiredSchemas,
791 const char *schemaName, Oid schemaOid)
795 StringInfoData pathbuf;
799 * Enforce superuser-ness if appropriate. We postpone this check until
800 * here so that the flag is correctly associated with the right script(s)
801 * if it's set in secondary control files.
803 if (control->superuser && !superuser())
805 if (from_version == NULL)
807 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
808 errmsg("permission denied to create extension \"%s\"",
810 errhint("Must be superuser to create this extension.")));
813 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
814 errmsg("permission denied to update extension \"%s\"",
816 errhint("Must be superuser to update this extension.")));
819 filename = get_extension_script_filename(control, from_version, version);
822 * Force client_min_messages and log_min_messages to be at least WARNING,
823 * so that we won't spam the user with useless NOTICE messages from common
824 * script actions like creating shell types.
826 * We use the equivalent of a function SET option to allow the setting to
827 * persist for exactly the duration of the script execution. guc.c also
828 * takes care of undoing the setting on error.
830 save_nestlevel = NewGUCNestLevel();
832 if (client_min_messages < WARNING)
833 (void) set_config_option("client_min_messages", "warning",
834 PGC_USERSET, PGC_S_SESSION,
835 GUC_ACTION_SAVE, true, 0, false);
836 if (log_min_messages < WARNING)
837 (void) set_config_option("log_min_messages", "warning",
838 PGC_SUSET, PGC_S_SESSION,
839 GUC_ACTION_SAVE, true, 0, false);
842 * Set up the search path to contain the target schema, then the schemas
843 * of any prerequisite extensions, and nothing else. In particular this
844 * makes the target schema be the default creation target namespace.
846 * Note: it might look tempting to use PushOverrideSearchPath for this,
847 * but we cannot do that. We have to actually set the search_path GUC in
848 * case the extension script examines or changes it. In any case, the
849 * GUC_ACTION_SAVE method is just as convenient.
851 initStringInfo(&pathbuf);
852 appendStringInfoString(&pathbuf, quote_identifier(schemaName));
853 foreach(lc, requiredSchemas)
855 Oid reqschema = lfirst_oid(lc);
856 char *reqname = get_namespace_name(reqschema);
859 appendStringInfo(&pathbuf, ", %s", quote_identifier(reqname));
862 (void) set_config_option("search_path", pathbuf.data,
863 PGC_USERSET, PGC_S_SESSION,
864 GUC_ACTION_SAVE, true, 0, false);
867 * Set creating_extension and related variables so that
868 * recordDependencyOnCurrentExtension and other functions do the right
869 * things. On failure, ensure we reset these variables.
871 creating_extension = true;
872 CurrentExtensionObject = extensionOid;
875 char *c_sql = read_extension_script_file(control, filename);
878 /* We use various functions that want to operate on text datums */
879 t_sql = CStringGetTextDatum(c_sql);
882 * Reduce any lines beginning with "\echo" to empty. This allows
883 * scripts to contain messages telling people not to run them via
884 * psql, which has been found to be necessary due to old habits.
886 t_sql = DirectFunctionCall4Coll(textregexreplace,
889 CStringGetTextDatum("^\\\\echo.*$"),
890 CStringGetTextDatum(""),
891 CStringGetTextDatum("ng"));
894 * If it's not relocatable, substitute the target schema name for
895 * occurrences of @extschema@.
897 * For a relocatable extension, we needn't do this. There cannot be
898 * any need for @extschema@, else it wouldn't be relocatable.
900 if (!control->relocatable)
902 const char *qSchemaName = quote_identifier(schemaName);
904 t_sql = DirectFunctionCall3Coll(replace_text,
907 CStringGetTextDatum("@extschema@"),
908 CStringGetTextDatum(qSchemaName));
912 * If module_pathname was set in the control file, substitute its
913 * value for occurrences of MODULE_PATHNAME.
915 if (control->module_pathname)
917 t_sql = DirectFunctionCall3Coll(replace_text,
920 CStringGetTextDatum("MODULE_PATHNAME"),
921 CStringGetTextDatum(control->module_pathname));
924 /* And now back to C string */
925 c_sql = text_to_cstring(DatumGetTextPP(t_sql));
927 execute_sql_string(c_sql);
931 creating_extension = false;
932 CurrentExtensionObject = InvalidOid;
937 creating_extension = false;
938 CurrentExtensionObject = InvalidOid;
941 * Restore the GUC variables we set above.
943 AtEOXact_GUC(true, save_nestlevel);
947 * Find or create an ExtensionVersionInfo for the specified version name
949 * Currently, we just use a List of the ExtensionVersionInfo's. Searching
950 * for them therefore uses about O(N^2) time when there are N versions of
951 * the extension. We could change the data structure to a hash table if
952 * this ever becomes a bottleneck.
954 static ExtensionVersionInfo *
955 get_ext_ver_info(const char *versionname, List **evi_list)
957 ExtensionVersionInfo *evi;
960 foreach(lc, *evi_list)
962 evi = (ExtensionVersionInfo *) lfirst(lc);
963 if (strcmp(evi->name, versionname) == 0)
967 evi = (ExtensionVersionInfo *) palloc(sizeof(ExtensionVersionInfo));
968 evi->name = pstrdup(versionname);
969 evi->reachable = NIL;
970 evi->installable = false;
971 /* initialize for later application of Dijkstra's algorithm */
972 evi->distance_known = false;
973 evi->distance = INT_MAX;
974 evi->previous = NULL;
976 *evi_list = lappend(*evi_list, evi);
982 * Locate the nearest unprocessed ExtensionVersionInfo
984 * This part of the algorithm is also about O(N^2). A priority queue would
985 * make it much faster, but for now there's no need.
987 static ExtensionVersionInfo *
988 get_nearest_unprocessed_vertex(List *evi_list)
990 ExtensionVersionInfo *evi = NULL;
993 foreach(lc, evi_list)
995 ExtensionVersionInfo *evi2 = (ExtensionVersionInfo *) lfirst(lc);
997 /* only vertices whose distance is still uncertain are candidates */
998 if (evi2->distance_known)
1000 /* remember the closest such vertex */
1002 evi->distance > evi2->distance)
1010 * Obtain information about the set of update scripts available for the
1011 * specified extension. The result is a List of ExtensionVersionInfo
1012 * structs, each with a subsidiary list of the ExtensionVersionInfos for
1013 * the versions that can be reached in one step from that version.
1016 get_ext_ver_list(ExtensionControlFile *control)
1018 List *evi_list = NIL;
1019 int extnamelen = strlen(control->name);
1024 location = get_extension_script_directory(control);
1025 dir = AllocateDir(location);
1026 while ((de = ReadDir(dir, location)) != NULL)
1030 ExtensionVersionInfo *evi;
1031 ExtensionVersionInfo *evi2;
1033 /* must be a .sql file ... */
1034 if (!is_extension_script_filename(de->d_name))
1037 /* ... matching extension name followed by separator */
1038 if (strncmp(de->d_name, control->name, extnamelen) != 0 ||
1039 de->d_name[extnamelen] != '-' ||
1040 de->d_name[extnamelen + 1] != '-')
1043 /* extract version name(s) from 'extname--something.sql' filename */
1044 vername = pstrdup(de->d_name + extnamelen + 2);
1045 *strrchr(vername, '.') = '\0';
1046 vername2 = strstr(vername, "--");
1049 /* It's an install, not update, script; record its version name */
1050 evi = get_ext_ver_info(vername, &evi_list);
1051 evi->installable = true;
1054 *vername2 = '\0'; /* terminate first version */
1055 vername2 += 2; /* and point to second */
1057 /* if there's a third --, it's bogus, ignore it */
1058 if (strstr(vername2, "--"))
1061 /* Create ExtensionVersionInfos and link them together */
1062 evi = get_ext_ver_info(vername, &evi_list);
1063 evi2 = get_ext_ver_info(vername2, &evi_list);
1064 evi->reachable = lappend(evi->reachable, evi2);
1072 * Given an initial and final version name, identify the sequence of update
1073 * scripts that have to be applied to perform that update.
1075 * Result is a List of names of versions to transition through (the initial
1076 * version is *not* included).
1079 identify_update_path(ExtensionControlFile *control,
1080 const char *oldVersion, const char *newVersion)
1084 ExtensionVersionInfo *evi_start;
1085 ExtensionVersionInfo *evi_target;
1087 /* Extract the version update graph from the script directory */
1088 evi_list = get_ext_ver_list(control);
1090 /* Initialize start and end vertices */
1091 evi_start = get_ext_ver_info(oldVersion, &evi_list);
1092 evi_target = get_ext_ver_info(newVersion, &evi_list);
1094 /* Find shortest path */
1095 result = find_update_path(evi_list, evi_start, evi_target, false, false);
1099 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1100 errmsg("extension \"%s\" has no update path from version \"%s\" to version \"%s\"",
1101 control->name, oldVersion, newVersion)));
1107 * Apply Dijkstra's algorithm to find the shortest path from evi_start to
1110 * If reject_indirect is true, ignore paths that go through installable
1111 * versions. This saves work when the caller will consider starting from
1112 * all installable versions anyway.
1114 * If reinitialize is false, assume the ExtensionVersionInfo list has not
1115 * been used for this before, and the initialization done by get_ext_ver_info
1116 * is still good. Otherwise, reinitialize all transient fields used here.
1118 * Result is a List of names of versions to transition through (the initial
1119 * version is *not* included). Returns NIL if no such path.
1122 find_update_path(List *evi_list,
1123 ExtensionVersionInfo *evi_start,
1124 ExtensionVersionInfo *evi_target,
1125 bool reject_indirect,
1129 ExtensionVersionInfo *evi;
1132 /* Caller error if start == target */
1133 Assert(evi_start != evi_target);
1134 /* Caller error if reject_indirect and target is installable */
1135 Assert(!(reject_indirect && evi_target->installable));
1139 foreach(lc, evi_list)
1141 evi = (ExtensionVersionInfo *) lfirst(lc);
1142 evi->distance_known = false;
1143 evi->distance = INT_MAX;
1144 evi->previous = NULL;
1148 evi_start->distance = 0;
1150 while ((evi = get_nearest_unprocessed_vertex(evi_list)) != NULL)
1152 if (evi->distance == INT_MAX)
1153 break; /* all remaining vertices are unreachable */
1154 evi->distance_known = true;
1155 if (evi == evi_target)
1156 break; /* found shortest path to target */
1157 foreach(lc, evi->reachable)
1159 ExtensionVersionInfo *evi2 = (ExtensionVersionInfo *) lfirst(lc);
1162 /* if reject_indirect, treat installable versions as unreachable */
1163 if (reject_indirect && evi2->installable)
1165 newdist = evi->distance + 1;
1166 if (newdist < evi2->distance)
1168 evi2->distance = newdist;
1169 evi2->previous = evi;
1171 else if (newdist == evi2->distance &&
1172 evi2->previous != NULL &&
1173 strcmp(evi->name, evi2->previous->name) < 0)
1176 * Break ties in favor of the version name that comes first
1177 * according to strcmp(). This behavior is undocumented and
1178 * users shouldn't rely on it. We do it just to ensure that
1179 * if there is a tie, the update path that is chosen does not
1180 * depend on random factors like the order in which directory
1181 * entries get visited.
1183 evi2->previous = evi;
1188 /* Return NIL if target is not reachable from start */
1189 if (!evi_target->distance_known)
1192 /* Build and return list of version names representing the update path */
1194 for (evi = evi_target; evi != evi_start; evi = evi->previous)
1195 result = lcons(evi->name, result);
1201 * Given a target version that is not directly installable, find the
1202 * best installation sequence starting from a directly-installable version.
1204 * evi_list: previously-collected version update graph
1205 * evi_target: member of that list that we want to reach
1207 * Returns the best starting-point version, or NULL if there is none.
1208 * On success, *best_path is set to the path from the start point.
1210 * If there's more than one possible start point, prefer shorter update paths,
1211 * and break any ties arbitrarily on the basis of strcmp'ing the starting
1214 static ExtensionVersionInfo *
1215 find_install_path(List *evi_list, ExtensionVersionInfo *evi_target,
1218 ExtensionVersionInfo *evi_start = NULL;
1224 * We don't expect to be called for an installable target, but if we are,
1225 * the answer is easy: just start from there, with an empty update path.
1227 if (evi_target->installable)
1230 /* Consider all installable versions as start points */
1231 foreach(lc, evi_list)
1233 ExtensionVersionInfo *evi1 = (ExtensionVersionInfo *) lfirst(lc);
1236 if (!evi1->installable)
1240 * Find shortest path from evi1 to evi_target; but no need to consider
1241 * paths going through other installable versions.
1243 path = find_update_path(evi_list, evi1, evi_target, true, true);
1247 /* Remember best path */
1248 if (evi_start == NULL ||
1249 list_length(path) < list_length(*best_path) ||
1250 (list_length(path) == list_length(*best_path) &&
1251 strcmp(evi_start->name, evi1->name) < 0))
1262 * CREATE EXTENSION worker
1264 * When CASCADE is specified, CreateExtensionInternal() recurses if required
1265 * extensions need to be installed. To sanely handle cyclic dependencies,
1266 * the "parents" list contains a list of names of extensions already being
1267 * installed, allowing us to error out if we recurse to one of those.
1269 static ObjectAddress
1270 CreateExtensionInternal(char *extensionName,
1272 const char *versionName,
1273 const char *oldVersionName,
1278 char *origSchemaName = schemaName;
1279 Oid schemaOid = InvalidOid;
1280 Oid extowner = GetUserId();
1281 ExtensionControlFile *pcontrol;
1282 ExtensionControlFile *control;
1283 List *updateVersions;
1284 List *requiredExtensions;
1285 List *requiredSchemas;
1287 ObjectAddress address;
1291 * Read the primary control file. Note we assume that it does not contain
1292 * any non-ASCII data, so there is no need to worry about encoding at this
1295 pcontrol = read_extension_control_file(extensionName);
1298 * Determine the version to install
1300 if (versionName == NULL)
1302 if (pcontrol->default_version)
1303 versionName = pcontrol->default_version;
1306 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1307 errmsg("version to install must be specified")));
1309 check_valid_version_name(versionName);
1312 * Figure out which script(s) we need to run to install the desired
1313 * version of the extension. If we do not have a script that directly
1314 * does what is needed, we try to find a sequence of update scripts that
1315 * will get us there.
1320 * "FROM old_version" was specified, indicating that we're trying to
1321 * update from some unpackaged version of the extension. Locate a
1322 * series of update scripts that will do it.
1324 check_valid_version_name(oldVersionName);
1326 if (strcmp(oldVersionName, versionName) == 0)
1328 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1329 errmsg("FROM version must be different from installation target version \"%s\"",
1332 updateVersions = identify_update_path(pcontrol,
1336 if (list_length(updateVersions) == 1)
1339 * Simple case where there's just one update script to run. We
1340 * will not need any follow-on update steps.
1342 Assert(strcmp((char *) linitial(updateVersions), versionName) == 0);
1343 updateVersions = NIL;
1348 * Multi-step sequence. We treat this as installing the version
1349 * that is the target of the first script, followed by successive
1350 * updates to the later versions.
1352 versionName = (char *) linitial(updateVersions);
1353 updateVersions = list_delete_first(updateVersions);
1359 * No FROM, so we're installing from scratch. If there is an install
1360 * script for the desired version, we only need to run that one.
1365 oldVersionName = NULL;
1367 filename = get_extension_script_filename(pcontrol, NULL, versionName);
1368 if (stat(filename, &fst) == 0)
1370 /* Easy, no extra scripts */
1371 updateVersions = NIL;
1375 /* Look for best way to install this version */
1377 ExtensionVersionInfo *evi_start;
1378 ExtensionVersionInfo *evi_target;
1380 /* Extract the version update graph from the script directory */
1381 evi_list = get_ext_ver_list(pcontrol);
1383 /* Identify the target version */
1384 evi_target = get_ext_ver_info(versionName, &evi_list);
1386 /* Identify best path to reach target */
1387 evi_start = find_install_path(evi_list, evi_target,
1390 /* Fail if no path ... */
1391 if (evi_start == NULL)
1393 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1394 errmsg("extension \"%s\" has no installation script nor update path for version \"%s\"",
1395 pcontrol->name, versionName)));
1397 /* Otherwise, install best starting point and then upgrade */
1398 versionName = evi_start->name;
1403 * Fetch control parameters for installation target version
1405 control = read_extension_aux_control_file(pcontrol, versionName);
1408 * Determine the target schema to install the extension into
1412 /* If the user is giving us the schema name, it must exist already. */
1413 schemaOid = get_namespace_oid(schemaName, false);
1416 if (control->schema != NULL)
1419 * The extension is not relocatable and the author gave us a schema
1422 * Unless CASCADE parameter was given, it's an error to give a schema
1423 * different from control->schema if control->schema is specified.
1425 if (schemaName && strcmp(control->schema, schemaName) != 0 &&
1428 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1429 errmsg("extension \"%s\" must be installed in schema \"%s\"",
1433 /* Always use the schema from control file for current extension. */
1434 schemaName = control->schema;
1436 /* Find or create the schema in case it does not exist. */
1437 schemaOid = get_namespace_oid(schemaName, true);
1439 if (!OidIsValid(schemaOid))
1441 CreateSchemaStmt *csstmt = makeNode(CreateSchemaStmt);
1443 csstmt->schemaname = schemaName;
1444 csstmt->authrole = NULL; /* will be created by current user */
1445 csstmt->schemaElts = NIL;
1446 csstmt->if_not_exists = false;
1447 CreateSchemaCommand(csstmt, "(generated CREATE SCHEMA command)",
1451 * CreateSchemaCommand includes CommandCounterIncrement, so new
1452 * schema is now visible.
1454 schemaOid = get_namespace_oid(schemaName, false);
1457 else if (!OidIsValid(schemaOid))
1460 * Neither user nor author of the extension specified schema; use the
1461 * current default creation namespace, which is the first explicit
1462 * entry in the search_path.
1464 List *search_path = fetch_search_path(false);
1466 if (search_path == NIL) /* nothing valid in search_path? */
1468 (errcode(ERRCODE_UNDEFINED_SCHEMA),
1469 errmsg("no schema has been selected to create in")));
1470 schemaOid = linitial_oid(search_path);
1471 schemaName = get_namespace_name(schemaOid);
1472 if (schemaName == NULL) /* recently-deleted namespace? */
1474 (errcode(ERRCODE_UNDEFINED_SCHEMA),
1475 errmsg("no schema has been selected to create in")));
1477 list_free(search_path);
1481 * Make note if a temporary namespace has been accessed in this
1484 if (isTempNamespace(schemaOid))
1485 MyXactFlags |= XACT_FLAGS_ACCESSEDTEMPNAMESPACE;
1488 * We don't check creation rights on the target namespace here. If the
1489 * extension script actually creates any objects there, it will fail if
1490 * the user doesn't have such permissions. But there are cases such as
1491 * procedural languages where it's convenient to set schema = pg_catalog
1492 * yet we don't want to restrict the command to users with ACL_CREATE for
1497 * Look up the prerequisite extensions, install them if necessary, and
1498 * build lists of their OIDs and the OIDs of their target schemas.
1500 requiredExtensions = NIL;
1501 requiredSchemas = NIL;
1502 foreach(lc, control->requires)
1504 char *curreq = (char *) lfirst(lc);
1508 reqext = get_required_extension(curreq,
1514 reqschema = get_extension_schema(reqext);
1515 requiredExtensions = lappend_oid(requiredExtensions, reqext);
1516 requiredSchemas = lappend_oid(requiredSchemas, reqschema);
1520 * Insert new tuple into pg_extension, and create dependency entries.
1522 address = InsertExtensionTuple(control->name, extowner,
1523 schemaOid, control->relocatable,
1525 PointerGetDatum(NULL),
1526 PointerGetDatum(NULL),
1527 requiredExtensions);
1528 extensionOid = address.objectId;
1531 * Apply any control-file comment on extension
1533 if (control->comment != NULL)
1534 CreateComments(extensionOid, ExtensionRelationId, 0, control->comment);
1537 * Execute the installation script file
1539 execute_extension_script(extensionOid, control,
1540 oldVersionName, versionName,
1542 schemaName, schemaOid);
1545 * If additional update scripts have to be executed, apply the updates as
1546 * though a series of ALTER EXTENSION UPDATE commands were given
1548 ApplyExtensionUpdates(extensionOid, pcontrol,
1549 versionName, updateVersions,
1550 origSchemaName, cascade, is_create);
1556 * Get the OID of an extension listed in "requires", possibly creating it.
1559 get_required_extension(char *reqExtensionName,
1560 char *extensionName,
1561 char *origSchemaName,
1566 Oid reqExtensionOid;
1568 reqExtensionOid = get_extension_oid(reqExtensionName, true);
1569 if (!OidIsValid(reqExtensionOid))
1573 /* Must install it. */
1575 List *cascade_parents;
1578 /* Check extension name validity before trying to cascade. */
1579 check_valid_extension_name(reqExtensionName);
1581 /* Check for cyclic dependency between extensions. */
1582 foreach(lc, parents)
1584 char *pname = (char *) lfirst(lc);
1586 if (strcmp(pname, reqExtensionName) == 0)
1588 (errcode(ERRCODE_INVALID_RECURSION),
1589 errmsg("cyclic dependency detected between extensions \"%s\" and \"%s\"",
1590 reqExtensionName, extensionName)));
1594 (errmsg("installing required extension \"%s\"",
1595 reqExtensionName)));
1597 /* Add current extension to list of parents to pass down. */
1598 cascade_parents = lappend(list_copy(parents), extensionName);
1601 * Create the required extension. We propagate the SCHEMA option
1602 * if any, and CASCADE, but no other options.
1604 addr = CreateExtensionInternal(reqExtensionName,
1612 /* Get its newly-assigned OID. */
1613 reqExtensionOid = addr.objectId;
1617 (errcode(ERRCODE_UNDEFINED_OBJECT),
1618 errmsg("required extension \"%s\" is not installed",
1621 errhint("Use CREATE EXTENSION ... CASCADE to install required extensions too.") : 0));
1624 return reqExtensionOid;
1631 CreateExtension(ParseState *pstate, CreateExtensionStmt *stmt)
1633 DefElem *d_schema = NULL;
1634 DefElem *d_new_version = NULL;
1635 DefElem *d_old_version = NULL;
1636 DefElem *d_cascade = NULL;
1637 char *schemaName = NULL;
1638 char *versionName = NULL;
1639 char *oldVersionName = NULL;
1640 bool cascade = false;
1643 /* Check extension name validity before any filesystem access */
1644 check_valid_extension_name(stmt->extname);
1647 * Check for duplicate extension name. The unique index on
1648 * pg_extension.extname would catch this anyway, and serves as a backstop
1649 * in case of race conditions; but this is a friendlier error message, and
1650 * besides we need a check to support IF NOT EXISTS.
1652 if (get_extension_oid(stmt->extname, true) != InvalidOid)
1654 if (stmt->if_not_exists)
1657 (errcode(ERRCODE_DUPLICATE_OBJECT),
1658 errmsg("extension \"%s\" already exists, skipping",
1660 return InvalidObjectAddress;
1664 (errcode(ERRCODE_DUPLICATE_OBJECT),
1665 errmsg("extension \"%s\" already exists",
1670 * We use global variables to track the extension being created, so we can
1671 * create only one extension at the same time.
1673 if (creating_extension)
1675 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1676 errmsg("nested CREATE EXTENSION is not supported")));
1678 /* Deconstruct the statement option list */
1679 foreach(lc, stmt->options)
1681 DefElem *defel = (DefElem *) lfirst(lc);
1683 if (strcmp(defel->defname, "schema") == 0)
1687 (errcode(ERRCODE_SYNTAX_ERROR),
1688 errmsg("conflicting or redundant options"),
1689 parser_errposition(pstate, defel->location)));
1691 schemaName = defGetString(d_schema);
1693 else if (strcmp(defel->defname, "new_version") == 0)
1697 (errcode(ERRCODE_SYNTAX_ERROR),
1698 errmsg("conflicting or redundant options"),
1699 parser_errposition(pstate, defel->location)));
1700 d_new_version = defel;
1701 versionName = defGetString(d_new_version);
1703 else if (strcmp(defel->defname, "old_version") == 0)
1707 (errcode(ERRCODE_SYNTAX_ERROR),
1708 errmsg("conflicting or redundant options"),
1709 parser_errposition(pstate, defel->location)));
1710 d_old_version = defel;
1711 oldVersionName = defGetString(d_old_version);
1713 else if (strcmp(defel->defname, "cascade") == 0)
1717 (errcode(ERRCODE_SYNTAX_ERROR),
1718 errmsg("conflicting or redundant options"),
1719 parser_errposition(pstate, defel->location)));
1721 cascade = defGetBoolean(d_cascade);
1724 elog(ERROR, "unrecognized option: %s", defel->defname);
1727 /* Call CreateExtensionInternal to do the real work. */
1728 return CreateExtensionInternal(stmt->extname,
1738 * InsertExtensionTuple
1740 * Insert the new pg_extension row, and create extension's dependency entries.
1741 * Return the OID assigned to the new row.
1743 * This is exported for the benefit of pg_upgrade, which has to create a
1744 * pg_extension entry (and the extension-level dependencies) without
1745 * actually running the extension's script.
1747 * extConfig and extCondition should be arrays or PointerGetDatum(NULL).
1748 * We declare them as plain Datum to avoid needing array.h in extension.h.
1751 InsertExtensionTuple(const char *extName, Oid extOwner,
1752 Oid schemaOid, bool relocatable, const char *extVersion,
1753 Datum extConfig, Datum extCondition,
1754 List *requiredExtensions)
1758 Datum values[Natts_pg_extension];
1759 bool nulls[Natts_pg_extension];
1761 ObjectAddress myself;
1766 * Build and insert the pg_extension tuple
1768 rel = table_open(ExtensionRelationId, RowExclusiveLock);
1770 memset(values, 0, sizeof(values));
1771 memset(nulls, 0, sizeof(nulls));
1773 extensionOid = GetNewOidWithIndex(rel, ExtensionOidIndexId,
1774 Anum_pg_extension_oid);
1775 values[Anum_pg_extension_oid - 1] = ObjectIdGetDatum(extensionOid);
1776 values[Anum_pg_extension_extname - 1] =
1777 DirectFunctionCall1(namein, CStringGetDatum(extName));
1778 values[Anum_pg_extension_extowner - 1] = ObjectIdGetDatum(extOwner);
1779 values[Anum_pg_extension_extnamespace - 1] = ObjectIdGetDatum(schemaOid);
1780 values[Anum_pg_extension_extrelocatable - 1] = BoolGetDatum(relocatable);
1781 values[Anum_pg_extension_extversion - 1] = CStringGetTextDatum(extVersion);
1783 if (extConfig == PointerGetDatum(NULL))
1784 nulls[Anum_pg_extension_extconfig - 1] = true;
1786 values[Anum_pg_extension_extconfig - 1] = extConfig;
1788 if (extCondition == PointerGetDatum(NULL))
1789 nulls[Anum_pg_extension_extcondition - 1] = true;
1791 values[Anum_pg_extension_extcondition - 1] = extCondition;
1793 tuple = heap_form_tuple(rel->rd_att, values, nulls);
1795 CatalogTupleInsert(rel, tuple);
1797 heap_freetuple(tuple);
1798 table_close(rel, RowExclusiveLock);
1801 * Record dependencies on owner, schema, and prerequisite extensions
1803 recordDependencyOnOwner(ExtensionRelationId, extensionOid, extOwner);
1805 myself.classId = ExtensionRelationId;
1806 myself.objectId = extensionOid;
1807 myself.objectSubId = 0;
1809 nsp.classId = NamespaceRelationId;
1810 nsp.objectId = schemaOid;
1811 nsp.objectSubId = 0;
1813 recordDependencyOn(&myself, &nsp, DEPENDENCY_NORMAL);
1815 foreach(lc, requiredExtensions)
1817 Oid reqext = lfirst_oid(lc);
1818 ObjectAddress otherext;
1820 otherext.classId = ExtensionRelationId;
1821 otherext.objectId = reqext;
1822 otherext.objectSubId = 0;
1824 recordDependencyOn(&myself, &otherext, DEPENDENCY_NORMAL);
1826 /* Post creation hook for new extension */
1827 InvokeObjectPostCreateHook(ExtensionRelationId, extensionOid, 0);
1833 * Guts of extension deletion.
1835 * All we need do here is remove the pg_extension tuple itself. Everything
1836 * else is taken care of by the dependency infrastructure.
1839 RemoveExtensionById(Oid extId)
1842 SysScanDesc scandesc;
1844 ScanKeyData entry[1];
1847 * Disallow deletion of any extension that's currently open for insertion;
1848 * else subsequent executions of recordDependencyOnCurrentExtension()
1849 * could create dangling pg_depend records that refer to a no-longer-valid
1850 * pg_extension OID. This is needed not so much because we think people
1851 * might write "DROP EXTENSION foo" in foo's own script files, as because
1852 * errors in dependency management in extension script files could give
1853 * rise to cases where an extension is dropped as a result of recursing
1854 * from some contained object. Because of that, we must test for the case
1855 * here, not at some higher level of the DROP EXTENSION command.
1857 if (extId == CurrentExtensionObject)
1859 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1860 errmsg("cannot drop extension \"%s\" because it is being modified",
1861 get_extension_name(extId))));
1863 rel = table_open(ExtensionRelationId, RowExclusiveLock);
1865 ScanKeyInit(&entry[0],
1866 Anum_pg_extension_oid,
1867 BTEqualStrategyNumber, F_OIDEQ,
1868 ObjectIdGetDatum(extId));
1869 scandesc = systable_beginscan(rel, ExtensionOidIndexId, true,
1872 tuple = systable_getnext(scandesc);
1874 /* We assume that there can be at most one matching tuple */
1875 if (HeapTupleIsValid(tuple))
1876 CatalogTupleDelete(rel, &tuple->t_self);
1878 systable_endscan(scandesc);
1880 table_close(rel, RowExclusiveLock);
1884 * This function lists the available extensions (one row per primary control
1885 * file in the control directory). We parse each control file and report the
1886 * interesting fields.
1888 * The system view pg_available_extensions provides a user interface to this
1889 * SRF, adding information about whether the extensions are installed in the
1893 pg_available_extensions(PG_FUNCTION_ARGS)
1895 ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
1897 Tuplestorestate *tupstore;
1898 MemoryContext per_query_ctx;
1899 MemoryContext oldcontext;
1904 /* check to see if caller supports us returning a tuplestore */
1905 if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo))
1907 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1908 errmsg("set-valued function called in context that cannot accept a set")));
1909 if (!(rsinfo->allowedModes & SFRM_Materialize))
1911 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1912 errmsg("materialize mode required, but it is not " \
1913 "allowed in this context")));
1915 /* Build a tuple descriptor for our result type */
1916 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
1917 elog(ERROR, "return type must be a row type");
1919 /* Build tuplestore to hold the result rows */
1920 per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
1921 oldcontext = MemoryContextSwitchTo(per_query_ctx);
1923 tupstore = tuplestore_begin_heap(true, false, work_mem);
1924 rsinfo->returnMode = SFRM_Materialize;
1925 rsinfo->setResult = tupstore;
1926 rsinfo->setDesc = tupdesc;
1928 MemoryContextSwitchTo(oldcontext);
1930 location = get_extension_control_directory();
1931 dir = AllocateDir(location);
1934 * If the control directory doesn't exist, we want to silently return an
1935 * empty set. Any other error will be reported by ReadDir.
1937 if (dir == NULL && errno == ENOENT)
1943 while ((de = ReadDir(dir, location)) != NULL)
1945 ExtensionControlFile *control;
1950 if (!is_extension_control_filename(de->d_name))
1953 /* extract extension name from 'name.control' filename */
1954 extname = pstrdup(de->d_name);
1955 *strrchr(extname, '.') = '\0';
1957 /* ignore it if it's an auxiliary control file */
1958 if (strstr(extname, "--"))
1961 control = read_extension_control_file(extname);
1963 memset(values, 0, sizeof(values));
1964 memset(nulls, 0, sizeof(nulls));
1967 values[0] = DirectFunctionCall1(namein,
1968 CStringGetDatum(control->name));
1969 /* default_version */
1970 if (control->default_version == NULL)
1973 values[1] = CStringGetTextDatum(control->default_version);
1975 if (control->comment == NULL)
1978 values[2] = CStringGetTextDatum(control->comment);
1980 tuplestore_putvalues(tupstore, tupdesc, values, nulls);
1986 /* clean up and return the tuplestore */
1987 tuplestore_donestoring(tupstore);
1993 * This function lists the available extension versions (one row per
1994 * extension installation script). For each version, we parse the related
1995 * control file(s) and report the interesting fields.
1997 * The system view pg_available_extension_versions provides a user interface
1998 * to this SRF, adding information about which versions are installed in the
2002 pg_available_extension_versions(PG_FUNCTION_ARGS)
2004 ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
2006 Tuplestorestate *tupstore;
2007 MemoryContext per_query_ctx;
2008 MemoryContext oldcontext;
2013 /* check to see if caller supports us returning a tuplestore */
2014 if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo))
2016 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2017 errmsg("set-valued function called in context that cannot accept a set")));
2018 if (!(rsinfo->allowedModes & SFRM_Materialize))
2020 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2021 errmsg("materialize mode required, but it is not " \
2022 "allowed in this context")));
2024 /* Build a tuple descriptor for our result type */
2025 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
2026 elog(ERROR, "return type must be a row type");
2028 /* Build tuplestore to hold the result rows */
2029 per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
2030 oldcontext = MemoryContextSwitchTo(per_query_ctx);
2032 tupstore = tuplestore_begin_heap(true, false, work_mem);
2033 rsinfo->returnMode = SFRM_Materialize;
2034 rsinfo->setResult = tupstore;
2035 rsinfo->setDesc = tupdesc;
2037 MemoryContextSwitchTo(oldcontext);
2039 location = get_extension_control_directory();
2040 dir = AllocateDir(location);
2043 * If the control directory doesn't exist, we want to silently return an
2044 * empty set. Any other error will be reported by ReadDir.
2046 if (dir == NULL && errno == ENOENT)
2052 while ((de = ReadDir(dir, location)) != NULL)
2054 ExtensionControlFile *control;
2057 if (!is_extension_control_filename(de->d_name))
2060 /* extract extension name from 'name.control' filename */
2061 extname = pstrdup(de->d_name);
2062 *strrchr(extname, '.') = '\0';
2064 /* ignore it if it's an auxiliary control file */
2065 if (strstr(extname, "--"))
2068 /* read the control file */
2069 control = read_extension_control_file(extname);
2071 /* scan extension's script directory for install scripts */
2072 get_available_versions_for_extension(control, tupstore, tupdesc);
2078 /* clean up and return the tuplestore */
2079 tuplestore_donestoring(tupstore);
2085 * Inner loop for pg_available_extension_versions:
2086 * read versions of one extension, add rows to tupstore
2089 get_available_versions_for_extension(ExtensionControlFile *pcontrol,
2090 Tuplestorestate *tupstore,
2096 /* Extract the version update graph from the script directory */
2097 evi_list = get_ext_ver_list(pcontrol);
2099 /* For each installable version ... */
2100 foreach(lc, evi_list)
2102 ExtensionVersionInfo *evi = (ExtensionVersionInfo *) lfirst(lc);
2103 ExtensionControlFile *control;
2108 if (!evi->installable)
2112 * Fetch parameters for specific version (pcontrol is not changed)
2114 control = read_extension_aux_control_file(pcontrol, evi->name);
2116 memset(values, 0, sizeof(values));
2117 memset(nulls, 0, sizeof(nulls));
2120 values[0] = DirectFunctionCall1(namein,
2121 CStringGetDatum(control->name));
2123 values[1] = CStringGetTextDatum(evi->name);
2125 values[2] = BoolGetDatum(control->superuser);
2127 values[3] = BoolGetDatum(control->relocatable);
2129 if (control->schema == NULL)
2132 values[4] = DirectFunctionCall1(namein,
2133 CStringGetDatum(control->schema));
2135 if (control->requires == NIL)
2138 values[5] = convert_requires_to_datum(control->requires);
2140 if (control->comment == NULL)
2143 values[6] = CStringGetTextDatum(control->comment);
2145 tuplestore_putvalues(tupstore, tupdesc, values, nulls);
2148 * Find all non-directly-installable versions that would be installed
2149 * starting from this version, and report them, inheriting the
2150 * parameters that aren't changed in updates from this version.
2152 foreach(lc2, evi_list)
2154 ExtensionVersionInfo *evi2 = (ExtensionVersionInfo *) lfirst(lc2);
2157 if (evi2->installable)
2159 if (find_install_path(evi_list, evi2, &best_path) == evi)
2162 * Fetch parameters for this version (pcontrol is not changed)
2164 control = read_extension_aux_control_file(pcontrol, evi2->name);
2166 /* name stays the same */
2168 values[1] = CStringGetTextDatum(evi2->name);
2170 values[2] = BoolGetDatum(control->superuser);
2172 values[3] = BoolGetDatum(control->relocatable);
2173 /* schema stays the same */
2175 if (control->requires == NIL)
2179 values[5] = convert_requires_to_datum(control->requires);
2182 /* comment stays the same */
2184 tuplestore_putvalues(tupstore, tupdesc, values, nulls);
2191 * Convert a list of extension names to a name[] Datum
2194 convert_requires_to_datum(List *requires)
2201 ndatums = list_length(requires);
2202 datums = (Datum *) palloc(ndatums * sizeof(Datum));
2204 foreach(lc, requires)
2206 char *curreq = (char *) lfirst(lc);
2209 DirectFunctionCall1(namein, CStringGetDatum(curreq));
2211 a = construct_array(datums, ndatums,
2213 NAMEDATALEN, false, 'c');
2214 return PointerGetDatum(a);
2218 * This function reports the version update paths that exist for the
2219 * specified extension.
2222 pg_extension_update_paths(PG_FUNCTION_ARGS)
2224 Name extname = PG_GETARG_NAME(0);
2225 ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
2227 Tuplestorestate *tupstore;
2228 MemoryContext per_query_ctx;
2229 MemoryContext oldcontext;
2231 ExtensionControlFile *control;
2234 /* Check extension name validity before any filesystem access */
2235 check_valid_extension_name(NameStr(*extname));
2237 /* check to see if caller supports us returning a tuplestore */
2238 if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo))
2240 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2241 errmsg("set-valued function called in context that cannot accept a set")));
2242 if (!(rsinfo->allowedModes & SFRM_Materialize))
2244 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2245 errmsg("materialize mode required, but it is not " \
2246 "allowed in this context")));
2248 /* Build a tuple descriptor for our result type */
2249 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
2250 elog(ERROR, "return type must be a row type");
2252 /* Build tuplestore to hold the result rows */
2253 per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
2254 oldcontext = MemoryContextSwitchTo(per_query_ctx);
2256 tupstore = tuplestore_begin_heap(true, false, work_mem);
2257 rsinfo->returnMode = SFRM_Materialize;
2258 rsinfo->setResult = tupstore;
2259 rsinfo->setDesc = tupdesc;
2261 MemoryContextSwitchTo(oldcontext);
2263 /* Read the extension's control file */
2264 control = read_extension_control_file(NameStr(*extname));
2266 /* Extract the version update graph from the script directory */
2267 evi_list = get_ext_ver_list(control);
2269 /* Iterate over all pairs of versions */
2270 foreach(lc1, evi_list)
2272 ExtensionVersionInfo *evi1 = (ExtensionVersionInfo *) lfirst(lc1);
2275 foreach(lc2, evi_list)
2277 ExtensionVersionInfo *evi2 = (ExtensionVersionInfo *) lfirst(lc2);
2285 /* Find shortest path from evi1 to evi2 */
2286 path = find_update_path(evi_list, evi1, evi2, false, true);
2288 /* Emit result row */
2289 memset(values, 0, sizeof(values));
2290 memset(nulls, 0, sizeof(nulls));
2293 values[0] = CStringGetTextDatum(evi1->name);
2295 values[1] = CStringGetTextDatum(evi2->name);
2301 StringInfoData pathbuf;
2304 initStringInfo(&pathbuf);
2305 /* The path doesn't include start vertex, but show it */
2306 appendStringInfoString(&pathbuf, evi1->name);
2309 char *versionName = (char *) lfirst(lcv);
2311 appendStringInfoString(&pathbuf, "--");
2312 appendStringInfoString(&pathbuf, versionName);
2314 values[2] = CStringGetTextDatum(pathbuf.data);
2315 pfree(pathbuf.data);
2318 tuplestore_putvalues(tupstore, tupdesc, values, nulls);
2322 /* clean up and return the tuplestore */
2323 tuplestore_donestoring(tupstore);
2329 * pg_extension_config_dump
2331 * Record information about a configuration table that belongs to an
2332 * extension being created, but whose contents should be dumped in whole
2333 * or in part during pg_dump.
2336 pg_extension_config_dump(PG_FUNCTION_ARGS)
2338 Oid tableoid = PG_GETARG_OID(0);
2339 text *wherecond = PG_GETARG_TEXT_PP(1);
2343 SysScanDesc extScan;
2350 Datum repl_val[Natts_pg_extension];
2351 bool repl_null[Natts_pg_extension];
2352 bool repl_repl[Natts_pg_extension];
2356 * We only allow this to be called from an extension's SQL script. We
2357 * shouldn't need any permissions check beyond that.
2359 if (!creating_extension)
2361 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2362 errmsg("%s can only be called from an SQL script executed by CREATE EXTENSION",
2363 "pg_extension_config_dump()")));
2366 * Check that the table exists and is a member of the extension being
2367 * created. This ensures that we don't need to register an additional
2368 * dependency to protect the extconfig entry.
2370 tablename = get_rel_name(tableoid);
2371 if (tablename == NULL)
2373 (errcode(ERRCODE_UNDEFINED_TABLE),
2374 errmsg("OID %u does not refer to a table", tableoid)));
2375 if (getExtensionOfObject(RelationRelationId, tableoid) !=
2376 CurrentExtensionObject)
2378 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
2379 errmsg("table \"%s\" is not a member of the extension being created",
2383 * Add the table OID and WHERE condition to the extension's extconfig and
2384 * extcondition arrays.
2386 * If the table is already in extconfig, treat this as an update of the
2390 /* Find the pg_extension tuple */
2391 extRel = table_open(ExtensionRelationId, RowExclusiveLock);
2393 ScanKeyInit(&key[0],
2394 Anum_pg_extension_oid,
2395 BTEqualStrategyNumber, F_OIDEQ,
2396 ObjectIdGetDatum(CurrentExtensionObject));
2398 extScan = systable_beginscan(extRel, ExtensionOidIndexId, true,
2401 extTup = systable_getnext(extScan);
2403 if (!HeapTupleIsValid(extTup)) /* should not happen */
2404 elog(ERROR, "could not find tuple for extension %u",
2405 CurrentExtensionObject);
2407 memset(repl_val, 0, sizeof(repl_val));
2408 memset(repl_null, false, sizeof(repl_null));
2409 memset(repl_repl, false, sizeof(repl_repl));
2411 /* Build or modify the extconfig value */
2412 elementDatum = ObjectIdGetDatum(tableoid);
2414 arrayDatum = heap_getattr(extTup, Anum_pg_extension_extconfig,
2415 RelationGetDescr(extRel), &isnull);
2418 /* Previously empty extconfig, so build 1-element array */
2422 a = construct_array(&elementDatum, 1,
2424 sizeof(Oid), true, 'i');
2428 /* Modify or extend existing extconfig array */
2432 a = DatumGetArrayTypeP(arrayDatum);
2434 arrayLength = ARR_DIMS(a)[0];
2435 if (ARR_NDIM(a) != 1 ||
2436 ARR_LBOUND(a)[0] != 1 ||
2439 ARR_ELEMTYPE(a) != OIDOID)
2440 elog(ERROR, "extconfig is not a 1-D Oid array");
2441 arrayData = (Oid *) ARR_DATA_PTR(a);
2443 arrayIndex = arrayLength + 1; /* set up to add after end */
2445 for (i = 0; i < arrayLength; i++)
2447 if (arrayData[i] == tableoid)
2449 arrayIndex = i + 1; /* replace this element instead */
2454 a = array_set(a, 1, &arrayIndex,
2457 -1 /* varlena array */ ,
2458 sizeof(Oid) /* OID's typlen */ ,
2459 true /* OID's typbyval */ ,
2460 'i' /* OID's typalign */ );
2462 repl_val[Anum_pg_extension_extconfig - 1] = PointerGetDatum(a);
2463 repl_repl[Anum_pg_extension_extconfig - 1] = true;
2465 /* Build or modify the extcondition value */
2466 elementDatum = PointerGetDatum(wherecond);
2468 arrayDatum = heap_getattr(extTup, Anum_pg_extension_extcondition,
2469 RelationGetDescr(extRel), &isnull);
2472 if (arrayLength != 0)
2473 elog(ERROR, "extconfig and extcondition arrays do not match");
2475 a = construct_array(&elementDatum, 1,
2481 a = DatumGetArrayTypeP(arrayDatum);
2483 if (ARR_NDIM(a) != 1 ||
2484 ARR_LBOUND(a)[0] != 1 ||
2486 ARR_ELEMTYPE(a) != TEXTOID)
2487 elog(ERROR, "extcondition is not a 1-D text array");
2488 if (ARR_DIMS(a)[0] != arrayLength)
2489 elog(ERROR, "extconfig and extcondition arrays do not match");
2491 /* Add or replace at same index as in extconfig */
2492 a = array_set(a, 1, &arrayIndex,
2495 -1 /* varlena array */ ,
2496 -1 /* TEXT's typlen */ ,
2497 false /* TEXT's typbyval */ ,
2498 'i' /* TEXT's typalign */ );
2500 repl_val[Anum_pg_extension_extcondition - 1] = PointerGetDatum(a);
2501 repl_repl[Anum_pg_extension_extcondition - 1] = true;
2503 extTup = heap_modify_tuple(extTup, RelationGetDescr(extRel),
2504 repl_val, repl_null, repl_repl);
2506 CatalogTupleUpdate(extRel, &extTup->t_self, extTup);
2508 systable_endscan(extScan);
2510 table_close(extRel, RowExclusiveLock);
2516 * extension_config_remove
2518 * Remove the specified table OID from extension's extconfig, if present.
2519 * This is not currently exposed as a function, but it could be;
2520 * for now, we just invoke it from ALTER EXTENSION DROP.
2523 extension_config_remove(Oid extensionoid, Oid tableoid)
2527 SysScanDesc extScan;
2533 Datum repl_val[Natts_pg_extension];
2534 bool repl_null[Natts_pg_extension];
2535 bool repl_repl[Natts_pg_extension];
2538 /* Find the pg_extension tuple */
2539 extRel = table_open(ExtensionRelationId, RowExclusiveLock);
2541 ScanKeyInit(&key[0],
2542 Anum_pg_extension_oid,
2543 BTEqualStrategyNumber, F_OIDEQ,
2544 ObjectIdGetDatum(extensionoid));
2546 extScan = systable_beginscan(extRel, ExtensionOidIndexId, true,
2549 extTup = systable_getnext(extScan);
2551 if (!HeapTupleIsValid(extTup)) /* should not happen */
2552 elog(ERROR, "could not find tuple for extension %u",
2555 /* Search extconfig for the tableoid */
2556 arrayDatum = heap_getattr(extTup, Anum_pg_extension_extconfig,
2557 RelationGetDescr(extRel), &isnull);
2570 a = DatumGetArrayTypeP(arrayDatum);
2572 arrayLength = ARR_DIMS(a)[0];
2573 if (ARR_NDIM(a) != 1 ||
2574 ARR_LBOUND(a)[0] != 1 ||
2577 ARR_ELEMTYPE(a) != OIDOID)
2578 elog(ERROR, "extconfig is not a 1-D Oid array");
2579 arrayData = (Oid *) ARR_DATA_PTR(a);
2581 arrayIndex = -1; /* flag for no deletion needed */
2583 for (i = 0; i < arrayLength; i++)
2585 if (arrayData[i] == tableoid)
2587 arrayIndex = i; /* index to remove */
2593 /* If tableoid is not in extconfig, nothing to do */
2596 systable_endscan(extScan);
2597 table_close(extRel, RowExclusiveLock);
2601 /* Modify or delete the extconfig value */
2602 memset(repl_val, 0, sizeof(repl_val));
2603 memset(repl_null, false, sizeof(repl_null));
2604 memset(repl_repl, false, sizeof(repl_repl));
2606 if (arrayLength <= 1)
2608 /* removing only element, just set array to null */
2609 repl_null[Anum_pg_extension_extconfig - 1] = true;
2613 /* squeeze out the target element */
2618 /* We already checked there are no nulls */
2619 deconstruct_array(a, OIDOID, sizeof(Oid), true, 'i',
2620 &dvalues, NULL, &nelems);
2622 for (i = arrayIndex; i < arrayLength - 1; i++)
2623 dvalues[i] = dvalues[i + 1];
2625 a = construct_array(dvalues, arrayLength - 1,
2626 OIDOID, sizeof(Oid), true, 'i');
2628 repl_val[Anum_pg_extension_extconfig - 1] = PointerGetDatum(a);
2630 repl_repl[Anum_pg_extension_extconfig - 1] = true;
2632 /* Modify or delete the extcondition value */
2633 arrayDatum = heap_getattr(extTup, Anum_pg_extension_extcondition,
2634 RelationGetDescr(extRel), &isnull);
2637 elog(ERROR, "extconfig and extcondition arrays do not match");
2641 a = DatumGetArrayTypeP(arrayDatum);
2643 if (ARR_NDIM(a) != 1 ||
2644 ARR_LBOUND(a)[0] != 1 ||
2646 ARR_ELEMTYPE(a) != TEXTOID)
2647 elog(ERROR, "extcondition is not a 1-D text array");
2648 if (ARR_DIMS(a)[0] != arrayLength)
2649 elog(ERROR, "extconfig and extcondition arrays do not match");
2652 if (arrayLength <= 1)
2654 /* removing only element, just set array to null */
2655 repl_null[Anum_pg_extension_extcondition - 1] = true;
2659 /* squeeze out the target element */
2664 /* We already checked there are no nulls */
2665 deconstruct_array(a, TEXTOID, -1, false, 'i',
2666 &dvalues, NULL, &nelems);
2668 for (i = arrayIndex; i < arrayLength - 1; i++)
2669 dvalues[i] = dvalues[i + 1];
2671 a = construct_array(dvalues, arrayLength - 1,
2672 TEXTOID, -1, false, 'i');
2674 repl_val[Anum_pg_extension_extcondition - 1] = PointerGetDatum(a);
2676 repl_repl[Anum_pg_extension_extcondition - 1] = true;
2678 extTup = heap_modify_tuple(extTup, RelationGetDescr(extRel),
2679 repl_val, repl_null, repl_repl);
2681 CatalogTupleUpdate(extRel, &extTup->t_self, extTup);
2683 systable_endscan(extScan);
2685 table_close(extRel, RowExclusiveLock);
2689 * Execute ALTER EXTENSION SET SCHEMA
2692 AlterExtensionNamespace(const char *extensionName, const char *newschema, Oid *oldschema)
2696 Oid oldNspOid = InvalidOid;
2697 AclResult aclresult;
2700 SysScanDesc extScan;
2702 Form_pg_extension extForm;
2704 SysScanDesc depScan;
2706 ObjectAddresses *objsMoved;
2707 ObjectAddress extAddr;
2709 extensionOid = get_extension_oid(extensionName, false);
2711 nspOid = LookupCreationNamespace(newschema);
2714 * Permission check: must own extension. Note that we don't bother to
2715 * check ownership of the individual member objects ...
2717 if (!pg_extension_ownercheck(extensionOid, GetUserId()))
2718 aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_EXTENSION,
2721 /* Permission check: must have creation rights in target namespace */
2722 aclresult = pg_namespace_aclcheck(nspOid, GetUserId(), ACL_CREATE);
2723 if (aclresult != ACLCHECK_OK)
2724 aclcheck_error(aclresult, OBJECT_SCHEMA, newschema);
2727 * If the schema is currently a member of the extension, disallow moving
2728 * the extension into the schema. That would create a dependency loop.
2730 if (getExtensionOfObject(NamespaceRelationId, nspOid) == extensionOid)
2732 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
2733 errmsg("cannot move extension \"%s\" into schema \"%s\" "
2734 "because the extension contains the schema",
2735 extensionName, newschema)));
2737 /* Locate the pg_extension tuple */
2738 extRel = table_open(ExtensionRelationId, RowExclusiveLock);
2740 ScanKeyInit(&key[0],
2741 Anum_pg_extension_oid,
2742 BTEqualStrategyNumber, F_OIDEQ,
2743 ObjectIdGetDatum(extensionOid));
2745 extScan = systable_beginscan(extRel, ExtensionOidIndexId, true,
2748 extTup = systable_getnext(extScan);
2750 if (!HeapTupleIsValid(extTup)) /* should not happen */
2751 elog(ERROR, "could not find tuple for extension %u",
2754 /* Copy tuple so we can modify it below */
2755 extTup = heap_copytuple(extTup);
2756 extForm = (Form_pg_extension) GETSTRUCT(extTup);
2758 systable_endscan(extScan);
2761 * If the extension is already in the target schema, just silently do
2764 if (extForm->extnamespace == nspOid)
2766 table_close(extRel, RowExclusiveLock);
2767 return InvalidObjectAddress;
2770 /* Check extension is supposed to be relocatable */
2771 if (!extForm->extrelocatable)
2773 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2774 errmsg("extension \"%s\" does not support SET SCHEMA",
2775 NameStr(extForm->extname))));
2777 objsMoved = new_object_addresses();
2780 * Scan pg_depend to find objects that depend directly on the extension,
2781 * and alter each one's schema.
2783 depRel = table_open(DependRelationId, AccessShareLock);
2785 ScanKeyInit(&key[0],
2786 Anum_pg_depend_refclassid,
2787 BTEqualStrategyNumber, F_OIDEQ,
2788 ObjectIdGetDatum(ExtensionRelationId));
2789 ScanKeyInit(&key[1],
2790 Anum_pg_depend_refobjid,
2791 BTEqualStrategyNumber, F_OIDEQ,
2792 ObjectIdGetDatum(extensionOid));
2794 depScan = systable_beginscan(depRel, DependReferenceIndexId, true,
2797 while (HeapTupleIsValid(depTup = systable_getnext(depScan)))
2799 Form_pg_depend pg_depend = (Form_pg_depend) GETSTRUCT(depTup);
2804 * Ignore non-membership dependencies. (Currently, the only other
2805 * case we could see here is a normal dependency from another
2808 if (pg_depend->deptype != DEPENDENCY_EXTENSION)
2811 dep.classId = pg_depend->classid;
2812 dep.objectId = pg_depend->objid;
2813 dep.objectSubId = pg_depend->objsubid;
2815 if (dep.objectSubId != 0) /* should not happen */
2816 elog(ERROR, "extension should not have a sub-object dependency");
2818 /* Relocate the object */
2819 dep_oldNspOid = AlterObjectNamespace_oid(dep.classId,
2825 * Remember previous namespace of first object that has one
2827 if (oldNspOid == InvalidOid && dep_oldNspOid != InvalidOid)
2828 oldNspOid = dep_oldNspOid;
2831 * If not all the objects had the same old namespace (ignoring any
2832 * that are not in namespaces), complain.
2834 if (dep_oldNspOid != InvalidOid && dep_oldNspOid != oldNspOid)
2836 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2837 errmsg("extension \"%s\" does not support SET SCHEMA",
2838 NameStr(extForm->extname)),
2839 errdetail("%s is not in the extension's schema \"%s\"",
2840 getObjectDescription(&dep),
2841 get_namespace_name(oldNspOid))));
2844 /* report old schema, if caller wants it */
2846 *oldschema = oldNspOid;
2848 systable_endscan(depScan);
2850 relation_close(depRel, AccessShareLock);
2852 /* Now adjust pg_extension.extnamespace */
2853 extForm->extnamespace = nspOid;
2855 CatalogTupleUpdate(extRel, &extTup->t_self, extTup);
2857 table_close(extRel, RowExclusiveLock);
2859 /* update dependencies to point to the new schema */
2860 changeDependencyFor(ExtensionRelationId, extensionOid,
2861 NamespaceRelationId, oldNspOid, nspOid);
2863 InvokeObjectPostAlterHook(ExtensionRelationId, extensionOid, 0);
2865 ObjectAddressSet(extAddr, ExtensionRelationId, extensionOid);
2871 * Execute ALTER EXTENSION UPDATE
2874 ExecAlterExtensionStmt(ParseState *pstate, AlterExtensionStmt *stmt)
2876 DefElem *d_new_version = NULL;
2878 char *oldVersionName;
2879 ExtensionControlFile *control;
2883 SysScanDesc extScan;
2885 List *updateVersions;
2889 ObjectAddress address;
2892 * We use global variables to track the extension being created, so we can
2893 * create/update only one extension at the same time.
2895 if (creating_extension)
2897 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2898 errmsg("nested ALTER EXTENSION is not supported")));
2901 * Look up the extension --- it must already exist in pg_extension
2903 extRel = table_open(ExtensionRelationId, AccessShareLock);
2905 ScanKeyInit(&key[0],
2906 Anum_pg_extension_extname,
2907 BTEqualStrategyNumber, F_NAMEEQ,
2908 CStringGetDatum(stmt->extname));
2910 extScan = systable_beginscan(extRel, ExtensionNameIndexId, true,
2913 extTup = systable_getnext(extScan);
2915 if (!HeapTupleIsValid(extTup))
2917 (errcode(ERRCODE_UNDEFINED_OBJECT),
2918 errmsg("extension \"%s\" does not exist",
2921 extensionOid = ((Form_pg_extension) GETSTRUCT(extTup))->oid;
2924 * Determine the existing version we are updating from
2926 datum = heap_getattr(extTup, Anum_pg_extension_extversion,
2927 RelationGetDescr(extRel), &isnull);
2929 elog(ERROR, "extversion is null");
2930 oldVersionName = text_to_cstring(DatumGetTextPP(datum));
2932 systable_endscan(extScan);
2934 table_close(extRel, AccessShareLock);
2936 /* Permission check: must own extension */
2937 if (!pg_extension_ownercheck(extensionOid, GetUserId()))
2938 aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_EXTENSION,
2942 * Read the primary control file. Note we assume that it does not contain
2943 * any non-ASCII data, so there is no need to worry about encoding at this
2946 control = read_extension_control_file(stmt->extname);
2949 * Read the statement option list
2951 foreach(lc, stmt->options)
2953 DefElem *defel = (DefElem *) lfirst(lc);
2955 if (strcmp(defel->defname, "new_version") == 0)
2959 (errcode(ERRCODE_SYNTAX_ERROR),
2960 errmsg("conflicting or redundant options"),
2961 parser_errposition(pstate, defel->location)));
2962 d_new_version = defel;
2965 elog(ERROR, "unrecognized option: %s", defel->defname);
2969 * Determine the version to update to
2971 if (d_new_version && d_new_version->arg)
2972 versionName = strVal(d_new_version->arg);
2973 else if (control->default_version)
2974 versionName = control->default_version;
2978 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2979 errmsg("version to install must be specified")));
2980 versionName = NULL; /* keep compiler quiet */
2982 check_valid_version_name(versionName);
2985 * If we're already at that version, just say so
2987 if (strcmp(oldVersionName, versionName) == 0)
2990 (errmsg("version \"%s\" of extension \"%s\" is already installed",
2991 versionName, stmt->extname)));
2992 return InvalidObjectAddress;
2996 * Identify the series of update script files we need to execute
2998 updateVersions = identify_update_path(control,
3003 * Update the pg_extension row and execute the update scripts, one at a
3006 ApplyExtensionUpdates(extensionOid, control,
3007 oldVersionName, updateVersions,
3008 NULL, false, false);
3010 ObjectAddressSet(address, ExtensionRelationId, extensionOid);
3016 * Apply a series of update scripts as though individual ALTER EXTENSION
3017 * UPDATE commands had been given, including altering the pg_extension row
3018 * and dependencies each time.
3020 * This might be more work than necessary, but it ensures that old update
3021 * scripts don't break if newer versions have different control parameters.
3024 ApplyExtensionUpdates(Oid extensionOid,
3025 ExtensionControlFile *pcontrol,
3026 const char *initialVersion,
3027 List *updateVersions,
3028 char *origSchemaName,
3032 const char *oldVersionName = initialVersion;
3035 foreach(lcv, updateVersions)
3037 char *versionName = (char *) lfirst(lcv);
3038 ExtensionControlFile *control;
3041 List *requiredExtensions;
3042 List *requiredSchemas;
3045 SysScanDesc extScan;
3047 Form_pg_extension extForm;
3048 Datum values[Natts_pg_extension];
3049 bool nulls[Natts_pg_extension];
3050 bool repl[Natts_pg_extension];
3051 ObjectAddress myself;
3055 * Fetch parameters for specific version (pcontrol is not changed)
3057 control = read_extension_aux_control_file(pcontrol, versionName);
3059 /* Find the pg_extension tuple */
3060 extRel = table_open(ExtensionRelationId, RowExclusiveLock);
3062 ScanKeyInit(&key[0],
3063 Anum_pg_extension_oid,
3064 BTEqualStrategyNumber, F_OIDEQ,
3065 ObjectIdGetDatum(extensionOid));
3067 extScan = systable_beginscan(extRel, ExtensionOidIndexId, true,
3070 extTup = systable_getnext(extScan);
3072 if (!HeapTupleIsValid(extTup)) /* should not happen */
3073 elog(ERROR, "could not find tuple for extension %u",
3076 extForm = (Form_pg_extension) GETSTRUCT(extTup);
3079 * Determine the target schema (set by original install)
3081 schemaOid = extForm->extnamespace;
3082 schemaName = get_namespace_name(schemaOid);
3085 * Modify extrelocatable and extversion in the pg_extension tuple
3087 memset(values, 0, sizeof(values));
3088 memset(nulls, 0, sizeof(nulls));
3089 memset(repl, 0, sizeof(repl));
3091 values[Anum_pg_extension_extrelocatable - 1] =
3092 BoolGetDatum(control->relocatable);
3093 repl[Anum_pg_extension_extrelocatable - 1] = true;
3094 values[Anum_pg_extension_extversion - 1] =
3095 CStringGetTextDatum(versionName);
3096 repl[Anum_pg_extension_extversion - 1] = true;
3098 extTup = heap_modify_tuple(extTup, RelationGetDescr(extRel),
3099 values, nulls, repl);
3101 CatalogTupleUpdate(extRel, &extTup->t_self, extTup);
3103 systable_endscan(extScan);
3105 table_close(extRel, RowExclusiveLock);
3108 * Look up the prerequisite extensions for this version, install them
3109 * if necessary, and build lists of their OIDs and the OIDs of their
3112 requiredExtensions = NIL;
3113 requiredSchemas = NIL;
3114 foreach(lc, control->requires)
3116 char *curreq = (char *) lfirst(lc);
3120 reqext = get_required_extension(curreq,
3126 reqschema = get_extension_schema(reqext);
3127 requiredExtensions = lappend_oid(requiredExtensions, reqext);
3128 requiredSchemas = lappend_oid(requiredSchemas, reqschema);
3132 * Remove and recreate dependencies on prerequisite extensions
3134 deleteDependencyRecordsForClass(ExtensionRelationId, extensionOid,
3135 ExtensionRelationId,
3138 myself.classId = ExtensionRelationId;
3139 myself.objectId = extensionOid;
3140 myself.objectSubId = 0;
3142 foreach(lc, requiredExtensions)
3144 Oid reqext = lfirst_oid(lc);
3145 ObjectAddress otherext;
3147 otherext.classId = ExtensionRelationId;
3148 otherext.objectId = reqext;
3149 otherext.objectSubId = 0;
3151 recordDependencyOn(&myself, &otherext, DEPENDENCY_NORMAL);
3154 InvokeObjectPostAlterHook(ExtensionRelationId, extensionOid, 0);
3157 * Finally, execute the update script file
3159 execute_extension_script(extensionOid, control,
3160 oldVersionName, versionName,
3162 schemaName, schemaOid);
3165 * Update prior-version name and loop around. Since
3166 * execute_sql_string did a final CommandCounterIncrement, we can
3167 * update the pg_extension row again.
3169 oldVersionName = versionName;
3174 * Execute ALTER EXTENSION ADD/DROP
3176 * Return value is the address of the altered extension.
3178 * objAddr is an output argument which, if not NULL, is set to the address of
3179 * the added/dropped object.
3182 ExecAlterExtensionContentsStmt(AlterExtensionContentsStmt *stmt,
3183 ObjectAddress *objAddr)
3185 ObjectAddress extension;
3186 ObjectAddress object;
3190 extension.classId = ExtensionRelationId;
3191 extension.objectId = get_extension_oid(stmt->extname, false);
3192 extension.objectSubId = 0;
3194 /* Permission check: must own extension */
3195 if (!pg_extension_ownercheck(extension.objectId, GetUserId()))
3196 aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_EXTENSION,
3200 * Translate the parser representation that identifies the object into an
3201 * ObjectAddress. get_object_address() will throw an error if the object
3202 * does not exist, and will also acquire a lock on the object to guard
3203 * against concurrent DROP and ALTER EXTENSION ADD/DROP operations.
3205 object = get_object_address(stmt->objtype, stmt->object,
3206 &relation, ShareUpdateExclusiveLock, false);
3208 Assert(object.objectSubId == 0);
3212 /* Permission check: must own target object, too */
3213 check_object_ownership(GetUserId(), stmt->objtype, object,
3214 stmt->object, relation);
3217 * Check existing extension membership.
3219 oldExtension = getExtensionOfObject(object.classId, object.objectId);
3221 if (stmt->action > 0)
3224 * ADD, so complain if object is already attached to some extension.
3226 if (OidIsValid(oldExtension))
3228 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
3229 errmsg("%s is already a member of extension \"%s\"",
3230 getObjectDescription(&object),
3231 get_extension_name(oldExtension))));
3234 * Prevent a schema from being added to an extension if the schema
3235 * contains the extension. That would create a dependency loop.
3237 if (object.classId == NamespaceRelationId &&
3238 object.objectId == get_extension_schema(extension.objectId))
3240 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
3241 errmsg("cannot add schema \"%s\" to extension \"%s\" "
3242 "because the schema contains the extension",
3243 get_namespace_name(object.objectId),
3247 * OK, add the dependency.
3249 recordDependencyOn(&object, &extension, DEPENDENCY_EXTENSION);
3252 * Also record the initial ACL on the object, if any.
3254 * Note that this will handle the object's ACLs, as well as any ACLs
3255 * on object subIds. (In other words, when the object is a table,
3256 * this will record the table's ACL and the ACLs for the columns on
3257 * the table, if any).
3259 recordExtObjInitPriv(object.objectId, object.classId);
3264 * DROP, so complain if it's not a member.
3266 if (oldExtension != extension.objectId)
3268 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
3269 errmsg("%s is not a member of extension \"%s\"",
3270 getObjectDescription(&object),
3274 * OK, drop the dependency.
3276 if (deleteDependencyRecordsForClass(object.classId, object.objectId,
3277 ExtensionRelationId,
3278 DEPENDENCY_EXTENSION) != 1)
3279 elog(ERROR, "unexpected number of extension dependency records");
3282 * If it's a relation, it might have an entry in the extension's
3283 * extconfig array, which we must remove.
3285 if (object.classId == RelationRelationId)
3286 extension_config_remove(extension.objectId, object.objectId);
3289 * Remove all the initial ACLs, if any.
3291 * Note that this will remove the object's ACLs, as well as any ACLs
3292 * on object subIds. (In other words, when the object is a table,
3293 * this will remove the table's ACL and the ACLs for the columns on
3294 * the table, if any).
3296 removeExtObjInitPriv(object.objectId, object.classId);
3299 InvokeObjectPostAlterHook(ExtensionRelationId, extension.objectId, 0);
3302 * If get_object_address() opened the relation for us, we close it to keep
3303 * the reference count correct - but we retain any locks acquired by
3304 * get_object_address() until commit time, to guard against concurrent
3307 if (relation != NULL)
3308 relation_close(relation, NoLock);
3314 * Read the whole of file into memory.
3316 * The file contents are returned as a single palloc'd chunk. For convenience
3317 * of the callers, an extra \0 byte is added to the end.
3320 read_whole_file(const char *filename, int *length)
3324 size_t bytes_to_read;
3327 if (stat(filename, &fst) < 0)
3329 (errcode_for_file_access(),
3330 errmsg("could not stat file \"%s\": %m", filename)));
3332 if (fst.st_size > (MaxAllocSize - 1))
3334 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
3335 errmsg("file \"%s\" is too large", filename)));
3336 bytes_to_read = (size_t) fst.st_size;
3338 if ((file = AllocateFile(filename, PG_BINARY_R)) == NULL)
3340 (errcode_for_file_access(),
3341 errmsg("could not open file \"%s\" for reading: %m",
3344 buf = (char *) palloc(bytes_to_read + 1);
3346 *length = fread(buf, 1, bytes_to_read, file);
3350 (errcode_for_file_access(),
3351 errmsg("could not read file \"%s\": %m", filename)));
3355 buf[*length] = '\0';