]> granicus.if.org Git - postgresql/blob - src/backend/commands/extension.c
Update copyright for 2016
[postgresql] / src / backend / commands / extension.c
1 /*-------------------------------------------------------------------------
2  *
3  * extension.c
4  *        Commands to manipulate extensions
5  *
6  * Extensions in PostgreSQL allow management of collections of SQL objects.
7  *
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 and recovery.conf.  An extension also has an installation
13  * script file, containing SQL commands to create the extension's objects.
14  *
15  * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
16  * Portions Copyright (c) 1994, Regents of the University of California
17  *
18  *
19  * IDENTIFICATION
20  *        src/backend/commands/extension.c
21  *
22  *-------------------------------------------------------------------------
23  */
24 #include "postgres.h"
25
26 #include <dirent.h>
27 #include <limits.h>
28 #include <sys/file.h>
29 #include <sys/stat.h>
30 #include <unistd.h>
31
32 #include "access/htup_details.h"
33 #include "access/sysattr.h"
34 #include "access/xact.h"
35 #include "catalog/dependency.h"
36 #include "catalog/indexing.h"
37 #include "catalog/namespace.h"
38 #include "catalog/objectaccess.h"
39 #include "catalog/pg_collation.h"
40 #include "catalog/pg_depend.h"
41 #include "catalog/pg_extension.h"
42 #include "catalog/pg_namespace.h"
43 #include "catalog/pg_type.h"
44 #include "commands/alter.h"
45 #include "commands/comment.h"
46 #include "commands/defrem.h"
47 #include "commands/extension.h"
48 #include "commands/schemacmds.h"
49 #include "funcapi.h"
50 #include "mb/pg_wchar.h"
51 #include "miscadmin.h"
52 #include "nodes/makefuncs.h"
53 #include "storage/fd.h"
54 #include "tcop/utility.h"
55 #include "utils/builtins.h"
56 #include "utils/fmgroids.h"
57 #include "utils/lsyscache.h"
58 #include "utils/memutils.h"
59 #include "utils/rel.h"
60 #include "utils/snapmgr.h"
61 #include "utils/tqual.h"
62
63
64 /* Globally visible state variables */
65 bool            creating_extension = false;
66 Oid                     CurrentExtensionObject = InvalidOid;
67
68 /*
69  * Internal data structure to hold the results of parsing a control file
70  */
71 typedef struct ExtensionControlFile
72 {
73         char       *name;                       /* name of the extension */
74         char       *directory;          /* directory for script files */
75         char       *default_version;    /* default install target version, if any */
76         char       *module_pathname;    /* string to substitute for MODULE_PATHNAME */
77         char       *comment;            /* comment, if any */
78         char       *schema;                     /* target schema (allowed if !relocatable) */
79         bool            relocatable;    /* is ALTER EXTENSION SET SCHEMA supported? */
80         bool            superuser;              /* must be superuser to install? */
81         int                     encoding;               /* encoding of the script file, or -1 */
82         List       *requires;           /* names of prerequisite extensions */
83 } ExtensionControlFile;
84
85 /*
86  * Internal data structure for update path information
87  */
88 typedef struct ExtensionVersionInfo
89 {
90         char       *name;                       /* name of the starting version */
91         List       *reachable;          /* List of ExtensionVersionInfo's */
92         bool            installable;    /* does this version have an install script? */
93         /* working state for Dijkstra's algorithm: */
94         bool            distance_known; /* is distance from start known yet? */
95         int                     distance;               /* current worst-case distance estimate */
96         struct ExtensionVersionInfo *previous;          /* current best predecessor */
97 } ExtensionVersionInfo;
98
99 /* Local functions */
100 static List *find_update_path(List *evi_list,
101                                  ExtensionVersionInfo *evi_start,
102                                  ExtensionVersionInfo *evi_target,
103                                  bool reinitialize);
104 static void get_available_versions_for_extension(ExtensionControlFile *pcontrol,
105                                                                          Tuplestorestate *tupstore,
106                                                                          TupleDesc tupdesc);
107 static void ApplyExtensionUpdates(Oid extensionOid,
108                                           ExtensionControlFile *pcontrol,
109                                           const char *initialVersion,
110                                           List *updateVersions);
111 static char *read_whole_file(const char *filename, int *length);
112
113
114 /*
115  * get_extension_oid - given an extension name, look up the OID
116  *
117  * If missing_ok is false, throw an error if extension name not found.  If
118  * true, just return InvalidOid.
119  */
120 Oid
121 get_extension_oid(const char *extname, bool missing_ok)
122 {
123         Oid                     result;
124         Relation        rel;
125         SysScanDesc scandesc;
126         HeapTuple       tuple;
127         ScanKeyData entry[1];
128
129         rel = heap_open(ExtensionRelationId, AccessShareLock);
130
131         ScanKeyInit(&entry[0],
132                                 Anum_pg_extension_extname,
133                                 BTEqualStrategyNumber, F_NAMEEQ,
134                                 CStringGetDatum(extname));
135
136         scandesc = systable_beginscan(rel, ExtensionNameIndexId, true,
137                                                                   NULL, 1, entry);
138
139         tuple = systable_getnext(scandesc);
140
141         /* We assume that there can be at most one matching tuple */
142         if (HeapTupleIsValid(tuple))
143                 result = HeapTupleGetOid(tuple);
144         else
145                 result = InvalidOid;
146
147         systable_endscan(scandesc);
148
149         heap_close(rel, AccessShareLock);
150
151         if (!OidIsValid(result) && !missing_ok)
152                 ereport(ERROR,
153                                 (errcode(ERRCODE_UNDEFINED_OBJECT),
154                                  errmsg("extension \"%s\" does not exist",
155                                                 extname)));
156
157         return result;
158 }
159
160 /*
161  * get_extension_name - given an extension OID, look up the name
162  *
163  * Returns a palloc'd string, or NULL if no such extension.
164  */
165 char *
166 get_extension_name(Oid ext_oid)
167 {
168         char       *result;
169         Relation        rel;
170         SysScanDesc scandesc;
171         HeapTuple       tuple;
172         ScanKeyData entry[1];
173
174         rel = heap_open(ExtensionRelationId, AccessShareLock);
175
176         ScanKeyInit(&entry[0],
177                                 ObjectIdAttributeNumber,
178                                 BTEqualStrategyNumber, F_OIDEQ,
179                                 ObjectIdGetDatum(ext_oid));
180
181         scandesc = systable_beginscan(rel, ExtensionOidIndexId, true,
182                                                                   NULL, 1, entry);
183
184         tuple = systable_getnext(scandesc);
185
186         /* We assume that there can be at most one matching tuple */
187         if (HeapTupleIsValid(tuple))
188                 result = pstrdup(NameStr(((Form_pg_extension) GETSTRUCT(tuple))->extname));
189         else
190                 result = NULL;
191
192         systable_endscan(scandesc);
193
194         heap_close(rel, AccessShareLock);
195
196         return result;
197 }
198
199 /*
200  * get_extension_schema - given an extension OID, fetch its extnamespace
201  *
202  * Returns InvalidOid if no such extension.
203  */
204 static Oid
205 get_extension_schema(Oid ext_oid)
206 {
207         Oid                     result;
208         Relation        rel;
209         SysScanDesc scandesc;
210         HeapTuple       tuple;
211         ScanKeyData entry[1];
212
213         rel = heap_open(ExtensionRelationId, AccessShareLock);
214
215         ScanKeyInit(&entry[0],
216                                 ObjectIdAttributeNumber,
217                                 BTEqualStrategyNumber, F_OIDEQ,
218                                 ObjectIdGetDatum(ext_oid));
219
220         scandesc = systable_beginscan(rel, ExtensionOidIndexId, true,
221                                                                   NULL, 1, entry);
222
223         tuple = systable_getnext(scandesc);
224
225         /* We assume that there can be at most one matching tuple */
226         if (HeapTupleIsValid(tuple))
227                 result = ((Form_pg_extension) GETSTRUCT(tuple))->extnamespace;
228         else
229                 result = InvalidOid;
230
231         systable_endscan(scandesc);
232
233         heap_close(rel, AccessShareLock);
234
235         return result;
236 }
237
238 /*
239  * Utility functions to check validity of extension and version names
240  */
241 static void
242 check_valid_extension_name(const char *extensionname)
243 {
244         int                     namelen = strlen(extensionname);
245
246         /*
247          * Disallow empty names (the parser rejects empty identifiers anyway, but
248          * let's check).
249          */
250         if (namelen == 0)
251                 ereport(ERROR,
252                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
253                                  errmsg("invalid extension name: \"%s\"", extensionname),
254                                  errdetail("Extension names must not be empty.")));
255
256         /*
257          * No double dashes, since that would make script filenames ambiguous.
258          */
259         if (strstr(extensionname, "--"))
260                 ereport(ERROR,
261                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
262                                  errmsg("invalid extension name: \"%s\"", extensionname),
263                                  errdetail("Extension names must not contain \"--\".")));
264
265         /*
266          * No leading or trailing dash either.  (We could probably allow this, but
267          * it would require much care in filename parsing and would make filenames
268          * visually if not formally ambiguous.  Since there's no real-world use
269          * case, let's just forbid it.)
270          */
271         if (extensionname[0] == '-' || extensionname[namelen - 1] == '-')
272                 ereport(ERROR,
273                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
274                                  errmsg("invalid extension name: \"%s\"", extensionname),
275                         errdetail("Extension names must not begin or end with \"-\".")));
276
277         /*
278          * No directory separators either (this is sufficient to prevent ".."
279          * style attacks).
280          */
281         if (first_dir_separator(extensionname) != NULL)
282                 ereport(ERROR,
283                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
284                                  errmsg("invalid extension name: \"%s\"", extensionname),
285                                  errdetail("Extension names must not contain directory separator characters.")));
286 }
287
288 static void
289 check_valid_version_name(const char *versionname)
290 {
291         int                     namelen = strlen(versionname);
292
293         /*
294          * Disallow empty names (we could possibly allow this, but there seems
295          * little point).
296          */
297         if (namelen == 0)
298                 ereport(ERROR,
299                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
300                            errmsg("invalid extension version name: \"%s\"", versionname),
301                                  errdetail("Version names must not be empty.")));
302
303         /*
304          * No double dashes, since that would make script filenames ambiguous.
305          */
306         if (strstr(versionname, "--"))
307                 ereport(ERROR,
308                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
309                            errmsg("invalid extension version name: \"%s\"", versionname),
310                                  errdetail("Version names must not contain \"--\".")));
311
312         /*
313          * No leading or trailing dash either.
314          */
315         if (versionname[0] == '-' || versionname[namelen - 1] == '-')
316                 ereport(ERROR,
317                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
318                            errmsg("invalid extension version name: \"%s\"", versionname),
319                           errdetail("Version names must not begin or end with \"-\".")));
320
321         /*
322          * No directory separators either (this is sufficient to prevent ".."
323          * style attacks).
324          */
325         if (first_dir_separator(versionname) != NULL)
326                 ereport(ERROR,
327                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
328                            errmsg("invalid extension version name: \"%s\"", versionname),
329                                  errdetail("Version names must not contain directory separator characters.")));
330 }
331
332 /*
333  * Utility functions to handle extension-related path names
334  */
335 static bool
336 is_extension_control_filename(const char *filename)
337 {
338         const char *extension = strrchr(filename, '.');
339
340         return (extension != NULL) && (strcmp(extension, ".control") == 0);
341 }
342
343 static bool
344 is_extension_script_filename(const char *filename)
345 {
346         const char *extension = strrchr(filename, '.');
347
348         return (extension != NULL) && (strcmp(extension, ".sql") == 0);
349 }
350
351 static char *
352 get_extension_control_directory(void)
353 {
354         char            sharepath[MAXPGPATH];
355         char       *result;
356
357         get_share_path(my_exec_path, sharepath);
358         result = (char *) palloc(MAXPGPATH);
359         snprintf(result, MAXPGPATH, "%s/extension", sharepath);
360
361         return result;
362 }
363
364 static char *
365 get_extension_control_filename(const char *extname)
366 {
367         char            sharepath[MAXPGPATH];
368         char       *result;
369
370         get_share_path(my_exec_path, sharepath);
371         result = (char *) palloc(MAXPGPATH);
372         snprintf(result, MAXPGPATH, "%s/extension/%s.control",
373                          sharepath, extname);
374
375         return result;
376 }
377
378 static char *
379 get_extension_script_directory(ExtensionControlFile *control)
380 {
381         char            sharepath[MAXPGPATH];
382         char       *result;
383
384         /*
385          * The directory parameter can be omitted, absolute, or relative to the
386          * installation's share directory.
387          */
388         if (!control->directory)
389                 return get_extension_control_directory();
390
391         if (is_absolute_path(control->directory))
392                 return pstrdup(control->directory);
393
394         get_share_path(my_exec_path, sharepath);
395         result = (char *) palloc(MAXPGPATH);
396         snprintf(result, MAXPGPATH, "%s/%s", sharepath, control->directory);
397
398         return result;
399 }
400
401 static char *
402 get_extension_aux_control_filename(ExtensionControlFile *control,
403                                                                    const char *version)
404 {
405         char       *result;
406         char       *scriptdir;
407
408         scriptdir = get_extension_script_directory(control);
409
410         result = (char *) palloc(MAXPGPATH);
411         snprintf(result, MAXPGPATH, "%s/%s--%s.control",
412                          scriptdir, control->name, version);
413
414         pfree(scriptdir);
415
416         return result;
417 }
418
419 static char *
420 get_extension_script_filename(ExtensionControlFile *control,
421                                                           const char *from_version, const char *version)
422 {
423         char       *result;
424         char       *scriptdir;
425
426         scriptdir = get_extension_script_directory(control);
427
428         result = (char *) palloc(MAXPGPATH);
429         if (from_version)
430                 snprintf(result, MAXPGPATH, "%s/%s--%s--%s.sql",
431                                  scriptdir, control->name, from_version, version);
432         else
433                 snprintf(result, MAXPGPATH, "%s/%s--%s.sql",
434                                  scriptdir, control->name, version);
435
436         pfree(scriptdir);
437
438         return result;
439 }
440
441
442 /*
443  * Parse contents of primary or auxiliary control file, and fill in
444  * fields of *control.  We parse primary file if version == NULL,
445  * else the optional auxiliary file for that version.
446  *
447  * Control files are supposed to be very short, half a dozen lines,
448  * so we don't worry about memory allocation risks here.  Also we don't
449  * worry about what encoding it's in; all values are expected to be ASCII.
450  */
451 static void
452 parse_extension_control_file(ExtensionControlFile *control,
453                                                          const char *version)
454 {
455         char       *filename;
456         FILE       *file;
457         ConfigVariable *item,
458                            *head = NULL,
459                            *tail = NULL;
460
461         /*
462          * Locate the file to read.  Auxiliary files are optional.
463          */
464         if (version)
465                 filename = get_extension_aux_control_filename(control, version);
466         else
467                 filename = get_extension_control_filename(control->name);
468
469         if ((file = AllocateFile(filename, "r")) == NULL)
470         {
471                 if (version && errno == ENOENT)
472                 {
473                         /* no auxiliary file for this version */
474                         pfree(filename);
475                         return;
476                 }
477                 ereport(ERROR,
478                                 (errcode_for_file_access(),
479                                  errmsg("could not open extension control file \"%s\": %m",
480                                                 filename)));
481         }
482
483         /*
484          * Parse the file content, using GUC's file parsing code.  We need not
485          * check the return value since any errors will be thrown at ERROR level.
486          */
487         (void) ParseConfigFp(file, filename, 0, ERROR, &head, &tail);
488
489         FreeFile(file);
490
491         /*
492          * Convert the ConfigVariable list into ExtensionControlFile entries.
493          */
494         for (item = head; item != NULL; item = item->next)
495         {
496                 if (strcmp(item->name, "directory") == 0)
497                 {
498                         if (version)
499                                 ereport(ERROR,
500                                                 (errcode(ERRCODE_SYNTAX_ERROR),
501                                                  errmsg("parameter \"%s\" cannot be set in a secondary extension control file",
502                                                                 item->name)));
503
504                         control->directory = pstrdup(item->value);
505                 }
506                 else if (strcmp(item->name, "default_version") == 0)
507                 {
508                         if (version)
509                                 ereport(ERROR,
510                                                 (errcode(ERRCODE_SYNTAX_ERROR),
511                                                  errmsg("parameter \"%s\" cannot be set in a secondary extension control file",
512                                                                 item->name)));
513
514                         control->default_version = pstrdup(item->value);
515                 }
516                 else if (strcmp(item->name, "module_pathname") == 0)
517                 {
518                         control->module_pathname = pstrdup(item->value);
519                 }
520                 else if (strcmp(item->name, "comment") == 0)
521                 {
522                         control->comment = pstrdup(item->value);
523                 }
524                 else if (strcmp(item->name, "schema") == 0)
525                 {
526                         control->schema = pstrdup(item->value);
527                 }
528                 else if (strcmp(item->name, "relocatable") == 0)
529                 {
530                         if (!parse_bool(item->value, &control->relocatable))
531                                 ereport(ERROR,
532                                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
533                                                  errmsg("parameter \"%s\" requires a Boolean value",
534                                                                 item->name)));
535                 }
536                 else if (strcmp(item->name, "superuser") == 0)
537                 {
538                         if (!parse_bool(item->value, &control->superuser))
539                                 ereport(ERROR,
540                                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
541                                                  errmsg("parameter \"%s\" requires a Boolean value",
542                                                                 item->name)));
543                 }
544                 else if (strcmp(item->name, "encoding") == 0)
545                 {
546                         control->encoding = pg_valid_server_encoding(item->value);
547                         if (control->encoding < 0)
548                                 ereport(ERROR,
549                                                 (errcode(ERRCODE_UNDEFINED_OBJECT),
550                                                  errmsg("\"%s\" is not a valid encoding name",
551                                                                 item->value)));
552                 }
553                 else if (strcmp(item->name, "requires") == 0)
554                 {
555                         /* Need a modifiable copy of string */
556                         char       *rawnames = pstrdup(item->value);
557
558                         /* Parse string into list of identifiers */
559                         if (!SplitIdentifierString(rawnames, ',', &control->requires))
560                         {
561                                 /* syntax error in name list */
562                                 ereport(ERROR,
563                                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
564                                  errmsg("parameter \"%s\" must be a list of extension names",
565                                                 item->name)));
566                         }
567                 }
568                 else
569                         ereport(ERROR,
570                                         (errcode(ERRCODE_SYNTAX_ERROR),
571                                          errmsg("unrecognized parameter \"%s\" in file \"%s\"",
572                                                         item->name, filename)));
573         }
574
575         FreeConfigVariables(head);
576
577         if (control->relocatable && control->schema != NULL)
578                 ereport(ERROR,
579                                 (errcode(ERRCODE_SYNTAX_ERROR),
580                                  errmsg("parameter \"schema\" cannot be specified when \"relocatable\" is true")));
581
582         pfree(filename);
583 }
584
585 /*
586  * Read the primary control file for the specified extension.
587  */
588 static ExtensionControlFile *
589 read_extension_control_file(const char *extname)
590 {
591         ExtensionControlFile *control;
592
593         /*
594          * Set up default values.  Pointer fields are initially null.
595          */
596         control = (ExtensionControlFile *) palloc0(sizeof(ExtensionControlFile));
597         control->name = pstrdup(extname);
598         control->relocatable = false;
599         control->superuser = true;
600         control->encoding = -1;
601
602         /*
603          * Parse the primary control file.
604          */
605         parse_extension_control_file(control, NULL);
606
607         return control;
608 }
609
610 /*
611  * Read the auxiliary control file for the specified extension and version.
612  *
613  * Returns a new modified ExtensionControlFile struct; the original struct
614  * (reflecting just the primary control file) is not modified.
615  */
616 static ExtensionControlFile *
617 read_extension_aux_control_file(const ExtensionControlFile *pcontrol,
618                                                                 const char *version)
619 {
620         ExtensionControlFile *acontrol;
621
622         /*
623          * Flat-copy the struct.  Pointer fields share values with original.
624          */
625         acontrol = (ExtensionControlFile *) palloc(sizeof(ExtensionControlFile));
626         memcpy(acontrol, pcontrol, sizeof(ExtensionControlFile));
627
628         /*
629          * Parse the auxiliary control file, overwriting struct fields
630          */
631         parse_extension_control_file(acontrol, version);
632
633         return acontrol;
634 }
635
636 /*
637  * Read an SQL script file into a string, and convert to database encoding
638  */
639 static char *
640 read_extension_script_file(const ExtensionControlFile *control,
641                                                    const char *filename)
642 {
643         int                     src_encoding;
644         char       *src_str;
645         char       *dest_str;
646         int                     len;
647
648         src_str = read_whole_file(filename, &len);
649
650         /* use database encoding if not given */
651         if (control->encoding < 0)
652                 src_encoding = GetDatabaseEncoding();
653         else
654                 src_encoding = control->encoding;
655
656         /* make sure that source string is valid in the expected encoding */
657         pg_verify_mbstr_len(src_encoding, src_str, len, false);
658
659         /*
660          * Convert the encoding to the database encoding. read_whole_file
661          * null-terminated the string, so if no conversion happens the string is
662          * valid as is.
663          */
664         dest_str = pg_any_to_server(src_str, len, src_encoding);
665
666         return dest_str;
667 }
668
669 /*
670  * Execute given SQL string.
671  *
672  * filename is used only to report errors.
673  *
674  * Note: it's tempting to just use SPI to execute the string, but that does
675  * not work very well.  The really serious problem is that SPI will parse,
676  * analyze, and plan the whole string before executing any of it; of course
677  * this fails if there are any plannable statements referring to objects
678  * created earlier in the script.  A lesser annoyance is that SPI insists
679  * on printing the whole string as errcontext in case of any error, and that
680  * could be very long.
681  */
682 static void
683 execute_sql_string(const char *sql, const char *filename)
684 {
685         List       *raw_parsetree_list;
686         DestReceiver *dest;
687         ListCell   *lc1;
688
689         /*
690          * Parse the SQL string into a list of raw parse trees.
691          */
692         raw_parsetree_list = pg_parse_query(sql);
693
694         /* All output from SELECTs goes to the bit bucket */
695         dest = CreateDestReceiver(DestNone);
696
697         /*
698          * Do parse analysis, rule rewrite, planning, and execution for each raw
699          * parsetree.  We must fully execute each query before beginning parse
700          * analysis on the next one, since there may be interdependencies.
701          */
702         foreach(lc1, raw_parsetree_list)
703         {
704                 Node       *parsetree = (Node *) lfirst(lc1);
705                 List       *stmt_list;
706                 ListCell   *lc2;
707
708                 stmt_list = pg_analyze_and_rewrite(parsetree,
709                                                                                    sql,
710                                                                                    NULL,
711                                                                                    0);
712                 stmt_list = pg_plan_queries(stmt_list, CURSOR_OPT_PARALLEL_OK, NULL);
713
714                 foreach(lc2, stmt_list)
715                 {
716                         Node       *stmt = (Node *) lfirst(lc2);
717
718                         if (IsA(stmt, TransactionStmt))
719                                 ereport(ERROR,
720                                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
721                                                  errmsg("transaction control statements are not allowed within an extension script")));
722
723                         CommandCounterIncrement();
724
725                         PushActiveSnapshot(GetTransactionSnapshot());
726
727                         if (IsA(stmt, PlannedStmt) &&
728                                 ((PlannedStmt *) stmt)->utilityStmt == NULL)
729                         {
730                                 QueryDesc  *qdesc;
731
732                                 qdesc = CreateQueryDesc((PlannedStmt *) stmt,
733                                                                                 sql,
734                                                                                 GetActiveSnapshot(), NULL,
735                                                                                 dest, NULL, 0);
736
737                                 ExecutorStart(qdesc, 0);
738                                 ExecutorRun(qdesc, ForwardScanDirection, 0);
739                                 ExecutorFinish(qdesc);
740                                 ExecutorEnd(qdesc);
741
742                                 FreeQueryDesc(qdesc);
743                         }
744                         else
745                         {
746                                 ProcessUtility(stmt,
747                                                            sql,
748                                                            PROCESS_UTILITY_QUERY,
749                                                            NULL,
750                                                            dest,
751                                                            NULL);
752                         }
753
754                         PopActiveSnapshot();
755                 }
756         }
757
758         /* Be sure to advance the command counter after the last script command */
759         CommandCounterIncrement();
760 }
761
762 /*
763  * Execute the appropriate script file for installing or updating the extension
764  *
765  * If from_version isn't NULL, it's an update
766  */
767 static void
768 execute_extension_script(Oid extensionOid, ExtensionControlFile *control,
769                                                  const char *from_version,
770                                                  const char *version,
771                                                  List *requiredSchemas,
772                                                  const char *schemaName, Oid schemaOid)
773 {
774         char       *filename;
775         int                     save_nestlevel;
776         StringInfoData pathbuf;
777         ListCell   *lc;
778
779         /*
780          * Enforce superuser-ness if appropriate.  We postpone this check until
781          * here so that the flag is correctly associated with the right script(s)
782          * if it's set in secondary control files.
783          */
784         if (control->superuser && !superuser())
785         {
786                 if (from_version == NULL)
787                         ereport(ERROR,
788                                         (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
789                                          errmsg("permission denied to create extension \"%s\"",
790                                                         control->name),
791                                          errhint("Must be superuser to create this extension.")));
792                 else
793                         ereport(ERROR,
794                                         (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
795                                          errmsg("permission denied to update extension \"%s\"",
796                                                         control->name),
797                                          errhint("Must be superuser to update this extension.")));
798         }
799
800         filename = get_extension_script_filename(control, from_version, version);
801
802         /*
803          * Force client_min_messages and log_min_messages to be at least WARNING,
804          * so that we won't spam the user with useless NOTICE messages from common
805          * script actions like creating shell types.
806          *
807          * We use the equivalent of a function SET option to allow the setting to
808          * persist for exactly the duration of the script execution.  guc.c also
809          * takes care of undoing the setting on error.
810          */
811         save_nestlevel = NewGUCNestLevel();
812
813         if (client_min_messages < WARNING)
814                 (void) set_config_option("client_min_messages", "warning",
815                                                                  PGC_USERSET, PGC_S_SESSION,
816                                                                  GUC_ACTION_SAVE, true, 0, false);
817         if (log_min_messages < WARNING)
818                 (void) set_config_option("log_min_messages", "warning",
819                                                                  PGC_SUSET, PGC_S_SESSION,
820                                                                  GUC_ACTION_SAVE, true, 0, false);
821
822         /*
823          * Set up the search path to contain the target schema, then the schemas
824          * of any prerequisite extensions, and nothing else.  In particular this
825          * makes the target schema be the default creation target namespace.
826          *
827          * Note: it might look tempting to use PushOverrideSearchPath for this,
828          * but we cannot do that.  We have to actually set the search_path GUC in
829          * case the extension script examines or changes it.  In any case, the
830          * GUC_ACTION_SAVE method is just as convenient.
831          */
832         initStringInfo(&pathbuf);
833         appendStringInfoString(&pathbuf, quote_identifier(schemaName));
834         foreach(lc, requiredSchemas)
835         {
836                 Oid                     reqschema = lfirst_oid(lc);
837                 char       *reqname = get_namespace_name(reqschema);
838
839                 if (reqname)
840                         appendStringInfo(&pathbuf, ", %s", quote_identifier(reqname));
841         }
842
843         (void) set_config_option("search_path", pathbuf.data,
844                                                          PGC_USERSET, PGC_S_SESSION,
845                                                          GUC_ACTION_SAVE, true, 0, false);
846
847         /*
848          * Set creating_extension and related variables so that
849          * recordDependencyOnCurrentExtension and other functions do the right
850          * things.  On failure, ensure we reset these variables.
851          */
852         creating_extension = true;
853         CurrentExtensionObject = extensionOid;
854         PG_TRY();
855         {
856                 char       *c_sql = read_extension_script_file(control, filename);
857                 Datum           t_sql;
858
859                 /* We use various functions that want to operate on text datums */
860                 t_sql = CStringGetTextDatum(c_sql);
861
862                 /*
863                  * Reduce any lines beginning with "\echo" to empty.  This allows
864                  * scripts to contain messages telling people not to run them via
865                  * psql, which has been found to be necessary due to old habits.
866                  */
867                 t_sql = DirectFunctionCall4Coll(textregexreplace,
868                                                                                 C_COLLATION_OID,
869                                                                                 t_sql,
870                                                                                 CStringGetTextDatum("^\\\\echo.*$"),
871                                                                                 CStringGetTextDatum(""),
872                                                                                 CStringGetTextDatum("ng"));
873
874                 /*
875                  * If it's not relocatable, substitute the target schema name for
876                  * occurrences of @extschema@.
877                  *
878                  * For a relocatable extension, we needn't do this.  There cannot be
879                  * any need for @extschema@, else it wouldn't be relocatable.
880                  */
881                 if (!control->relocatable)
882                 {
883                         const char *qSchemaName = quote_identifier(schemaName);
884
885                         t_sql = DirectFunctionCall3(replace_text,
886                                                                                 t_sql,
887                                                                                 CStringGetTextDatum("@extschema@"),
888                                                                                 CStringGetTextDatum(qSchemaName));
889                 }
890
891                 /*
892                  * If module_pathname was set in the control file, substitute its
893                  * value for occurrences of MODULE_PATHNAME.
894                  */
895                 if (control->module_pathname)
896                 {
897                         t_sql = DirectFunctionCall3(replace_text,
898                                                                                 t_sql,
899                                                                           CStringGetTextDatum("MODULE_PATHNAME"),
900                                                           CStringGetTextDatum(control->module_pathname));
901                 }
902
903                 /* And now back to C string */
904                 c_sql = text_to_cstring(DatumGetTextPP(t_sql));
905
906                 execute_sql_string(c_sql, filename);
907         }
908         PG_CATCH();
909         {
910                 creating_extension = false;
911                 CurrentExtensionObject = InvalidOid;
912                 PG_RE_THROW();
913         }
914         PG_END_TRY();
915
916         creating_extension = false;
917         CurrentExtensionObject = InvalidOid;
918
919         /*
920          * Restore the GUC variables we set above.
921          */
922         AtEOXact_GUC(true, save_nestlevel);
923 }
924
925 /*
926  * Find or create an ExtensionVersionInfo for the specified version name
927  *
928  * Currently, we just use a List of the ExtensionVersionInfo's.  Searching
929  * for them therefore uses about O(N^2) time when there are N versions of
930  * the extension.  We could change the data structure to a hash table if
931  * this ever becomes a bottleneck.
932  */
933 static ExtensionVersionInfo *
934 get_ext_ver_info(const char *versionname, List **evi_list)
935 {
936         ExtensionVersionInfo *evi;
937         ListCell   *lc;
938
939         foreach(lc, *evi_list)
940         {
941                 evi = (ExtensionVersionInfo *) lfirst(lc);
942                 if (strcmp(evi->name, versionname) == 0)
943                         return evi;
944         }
945
946         evi = (ExtensionVersionInfo *) palloc(sizeof(ExtensionVersionInfo));
947         evi->name = pstrdup(versionname);
948         evi->reachable = NIL;
949         evi->installable = false;
950         /* initialize for later application of Dijkstra's algorithm */
951         evi->distance_known = false;
952         evi->distance = INT_MAX;
953         evi->previous = NULL;
954
955         *evi_list = lappend(*evi_list, evi);
956
957         return evi;
958 }
959
960 /*
961  * Locate the nearest unprocessed ExtensionVersionInfo
962  *
963  * This part of the algorithm is also about O(N^2).  A priority queue would
964  * make it much faster, but for now there's no need.
965  */
966 static ExtensionVersionInfo *
967 get_nearest_unprocessed_vertex(List *evi_list)
968 {
969         ExtensionVersionInfo *evi = NULL;
970         ListCell   *lc;
971
972         foreach(lc, evi_list)
973         {
974                 ExtensionVersionInfo *evi2 = (ExtensionVersionInfo *) lfirst(lc);
975
976                 /* only vertices whose distance is still uncertain are candidates */
977                 if (evi2->distance_known)
978                         continue;
979                 /* remember the closest such vertex */
980                 if (evi == NULL ||
981                         evi->distance > evi2->distance)
982                         evi = evi2;
983         }
984
985         return evi;
986 }
987
988 /*
989  * Obtain information about the set of update scripts available for the
990  * specified extension.  The result is a List of ExtensionVersionInfo
991  * structs, each with a subsidiary list of the ExtensionVersionInfos for
992  * the versions that can be reached in one step from that version.
993  */
994 static List *
995 get_ext_ver_list(ExtensionControlFile *control)
996 {
997         List       *evi_list = NIL;
998         int                     extnamelen = strlen(control->name);
999         char       *location;
1000         DIR                *dir;
1001         struct dirent *de;
1002
1003         location = get_extension_script_directory(control);
1004         dir = AllocateDir(location);
1005         while ((de = ReadDir(dir, location)) != NULL)
1006         {
1007                 char       *vername;
1008                 char       *vername2;
1009                 ExtensionVersionInfo *evi;
1010                 ExtensionVersionInfo *evi2;
1011
1012                 /* must be a .sql file ... */
1013                 if (!is_extension_script_filename(de->d_name))
1014                         continue;
1015
1016                 /* ... matching extension name followed by separator */
1017                 if (strncmp(de->d_name, control->name, extnamelen) != 0 ||
1018                         de->d_name[extnamelen] != '-' ||
1019                         de->d_name[extnamelen + 1] != '-')
1020                         continue;
1021
1022                 /* extract version name(s) from 'extname--something.sql' filename */
1023                 vername = pstrdup(de->d_name + extnamelen + 2);
1024                 *strrchr(vername, '.') = '\0';
1025                 vername2 = strstr(vername, "--");
1026                 if (!vername2)
1027                 {
1028                         /* It's an install, not update, script; record its version name */
1029                         evi = get_ext_ver_info(vername, &evi_list);
1030                         evi->installable = true;
1031                         continue;
1032                 }
1033                 *vername2 = '\0';               /* terminate first version */
1034                 vername2 += 2;                  /* and point to second */
1035
1036                 /* if there's a third --, it's bogus, ignore it */
1037                 if (strstr(vername2, "--"))
1038                         continue;
1039
1040                 /* Create ExtensionVersionInfos and link them together */
1041                 evi = get_ext_ver_info(vername, &evi_list);
1042                 evi2 = get_ext_ver_info(vername2, &evi_list);
1043                 evi->reachable = lappend(evi->reachable, evi2);
1044         }
1045         FreeDir(dir);
1046
1047         return evi_list;
1048 }
1049
1050 /*
1051  * Given an initial and final version name, identify the sequence of update
1052  * scripts that have to be applied to perform that update.
1053  *
1054  * Result is a List of names of versions to transition through (the initial
1055  * version is *not* included).
1056  */
1057 static List *
1058 identify_update_path(ExtensionControlFile *control,
1059                                          const char *oldVersion, const char *newVersion)
1060 {
1061         List       *result;
1062         List       *evi_list;
1063         ExtensionVersionInfo *evi_start;
1064         ExtensionVersionInfo *evi_target;
1065
1066         /* Extract the version update graph from the script directory */
1067         evi_list = get_ext_ver_list(control);
1068
1069         /* Initialize start and end vertices */
1070         evi_start = get_ext_ver_info(oldVersion, &evi_list);
1071         evi_target = get_ext_ver_info(newVersion, &evi_list);
1072
1073         /* Find shortest path */
1074         result = find_update_path(evi_list, evi_start, evi_target, false);
1075
1076         if (result == NIL)
1077                 ereport(ERROR,
1078                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1079                                  errmsg("extension \"%s\" has no update path from version \"%s\" to version \"%s\"",
1080                                                 control->name, oldVersion, newVersion)));
1081
1082         return result;
1083 }
1084
1085 /*
1086  * Apply Dijkstra's algorithm to find the shortest path from evi_start to
1087  * evi_target.
1088  *
1089  * If reinitialize is false, assume the ExtensionVersionInfo list has not
1090  * been used for this before, and the initialization done by get_ext_ver_info
1091  * is still good.
1092  *
1093  * Result is a List of names of versions to transition through (the initial
1094  * version is *not* included).  Returns NIL if no such path.
1095  */
1096 static List *
1097 find_update_path(List *evi_list,
1098                                  ExtensionVersionInfo *evi_start,
1099                                  ExtensionVersionInfo *evi_target,
1100                                  bool reinitialize)
1101 {
1102         List       *result;
1103         ExtensionVersionInfo *evi;
1104         ListCell   *lc;
1105
1106         /* Caller error if start == target */
1107         Assert(evi_start != evi_target);
1108
1109         if (reinitialize)
1110         {
1111                 foreach(lc, evi_list)
1112                 {
1113                         evi = (ExtensionVersionInfo *) lfirst(lc);
1114                         evi->distance_known = false;
1115                         evi->distance = INT_MAX;
1116                         evi->previous = NULL;
1117                 }
1118         }
1119
1120         evi_start->distance = 0;
1121
1122         while ((evi = get_nearest_unprocessed_vertex(evi_list)) != NULL)
1123         {
1124                 if (evi->distance == INT_MAX)
1125                         break;                          /* all remaining vertices are unreachable */
1126                 evi->distance_known = true;
1127                 if (evi == evi_target)
1128                         break;                          /* found shortest path to target */
1129                 foreach(lc, evi->reachable)
1130                 {
1131                         ExtensionVersionInfo *evi2 = (ExtensionVersionInfo *) lfirst(lc);
1132                         int                     newdist;
1133
1134                         newdist = evi->distance + 1;
1135                         if (newdist < evi2->distance)
1136                         {
1137                                 evi2->distance = newdist;
1138                                 evi2->previous = evi;
1139                         }
1140                         else if (newdist == evi2->distance &&
1141                                          evi2->previous != NULL &&
1142                                          strcmp(evi->name, evi2->previous->name) < 0)
1143                         {
1144                                 /*
1145                                  * Break ties in favor of the version name that comes first
1146                                  * according to strcmp().  This behavior is undocumented and
1147                                  * users shouldn't rely on it.  We do it just to ensure that
1148                                  * if there is a tie, the update path that is chosen does not
1149                                  * depend on random factors like the order in which directory
1150                                  * entries get visited.
1151                                  */
1152                                 evi2->previous = evi;
1153                         }
1154                 }
1155         }
1156
1157         /* Return NIL if target is not reachable from start */
1158         if (!evi_target->distance_known)
1159                 return NIL;
1160
1161         /* Build and return list of version names representing the update path */
1162         result = NIL;
1163         for (evi = evi_target; evi != evi_start; evi = evi->previous)
1164                 result = lcons(evi->name, result);
1165
1166         return result;
1167 }
1168
1169 /*
1170  * CREATE EXTENSION worker
1171  *
1172  * When CASCADE is specified CreateExtensionInternal() recurses if required
1173  * extensions need to be installed. To sanely handle cyclic dependencies
1174  * cascade_parent contains the dependency chain leading to the current
1175  * invocation; thus allowing to error out if there's a cyclic dependency.
1176  */
1177 static ObjectAddress
1178 CreateExtensionInternal(CreateExtensionStmt *stmt, List *parents)
1179 {
1180         DefElem    *d_schema = NULL;
1181         DefElem    *d_new_version = NULL;
1182         DefElem    *d_old_version = NULL;
1183         DefElem    *d_cascade = NULL;
1184         char       *schemaName = NULL;
1185         Oid                     schemaOid = InvalidOid;
1186         char       *versionName;
1187         char       *oldVersionName;
1188         bool            cascade = false;
1189         Oid                     extowner = GetUserId();
1190         ExtensionControlFile *pcontrol;
1191         ExtensionControlFile *control;
1192         List       *updateVersions;
1193         List       *requiredExtensions;
1194         List       *requiredSchemas;
1195         Oid                     extensionOid;
1196         ListCell   *lc;
1197         ObjectAddress address;
1198
1199         /*
1200          * Read the primary control file.  Note we assume that it does not contain
1201          * any non-ASCII data, so there is no need to worry about encoding at this
1202          * point.
1203          */
1204         pcontrol = read_extension_control_file(stmt->extname);
1205
1206         /*
1207          * Read the statement option list
1208          */
1209         foreach(lc, stmt->options)
1210         {
1211                 DefElem    *defel = (DefElem *) lfirst(lc);
1212
1213                 if (strcmp(defel->defname, "schema") == 0)
1214                 {
1215                         if (d_schema)
1216                                 ereport(ERROR,
1217                                                 (errcode(ERRCODE_SYNTAX_ERROR),
1218                                                  errmsg("conflicting or redundant options")));
1219                         d_schema = defel;
1220                 }
1221                 else if (strcmp(defel->defname, "new_version") == 0)
1222                 {
1223                         if (d_new_version)
1224                                 ereport(ERROR,
1225                                                 (errcode(ERRCODE_SYNTAX_ERROR),
1226                                                  errmsg("conflicting or redundant options")));
1227                         d_new_version = defel;
1228                 }
1229                 else if (strcmp(defel->defname, "old_version") == 0)
1230                 {
1231                         if (d_old_version)
1232                                 ereport(ERROR,
1233                                                 (errcode(ERRCODE_SYNTAX_ERROR),
1234                                                  errmsg("conflicting or redundant options")));
1235                         d_old_version = defel;
1236                 }
1237                 else if (strcmp(defel->defname, "cascade") == 0)
1238                 {
1239                         if (d_cascade)
1240                                 ereport(ERROR,
1241                                                 (errcode(ERRCODE_SYNTAX_ERROR),
1242                                                  errmsg("conflicting or redundant options")));
1243                         d_cascade = defel;
1244                         cascade = defGetBoolean(d_cascade);
1245                 }
1246                 else
1247                         elog(ERROR, "unrecognized option: %s", defel->defname);
1248         }
1249
1250         /*
1251          * Determine the version to install
1252          */
1253         if (d_new_version && d_new_version->arg)
1254                 versionName = strVal(d_new_version->arg);
1255         else if (pcontrol->default_version)
1256                 versionName = pcontrol->default_version;
1257         else
1258         {
1259                 ereport(ERROR,
1260                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1261                                  errmsg("version to install must be specified")));
1262                 versionName = NULL;             /* keep compiler quiet */
1263         }
1264         check_valid_version_name(versionName);
1265
1266         /*
1267          * Determine the (unpackaged) version to update from, if any, and then
1268          * figure out what sequence of update scripts we need to apply.
1269          */
1270         if (d_old_version && d_old_version->arg)
1271         {
1272                 oldVersionName = strVal(d_old_version->arg);
1273                 check_valid_version_name(oldVersionName);
1274
1275                 if (strcmp(oldVersionName, versionName) == 0)
1276                         ereport(ERROR,
1277                                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1278                                          errmsg("FROM version must be different from installation target version \"%s\"",
1279                                                         versionName)));
1280
1281                 updateVersions = identify_update_path(pcontrol,
1282                                                                                           oldVersionName,
1283                                                                                           versionName);
1284
1285                 if (list_length(updateVersions) == 1)
1286                 {
1287                         /*
1288                          * Simple case where there's just one update script to run. We
1289                          * will not need any follow-on update steps.
1290                          */
1291                         Assert(strcmp((char *) linitial(updateVersions), versionName) == 0);
1292                         updateVersions = NIL;
1293                 }
1294                 else
1295                 {
1296                         /*
1297                          * Multi-step sequence.  We treat this as installing the version
1298                          * that is the target of the first script, followed by successive
1299                          * updates to the later versions.
1300                          */
1301                         versionName = (char *) linitial(updateVersions);
1302                         updateVersions = list_delete_first(updateVersions);
1303                 }
1304         }
1305         else
1306         {
1307                 oldVersionName = NULL;
1308                 updateVersions = NIL;
1309         }
1310
1311         /*
1312          * Fetch control parameters for installation target version
1313          */
1314         control = read_extension_aux_control_file(pcontrol, versionName);
1315
1316         /*
1317          * Determine the target schema to install the extension into
1318          */
1319         if (d_schema && d_schema->arg)
1320         {
1321                 /*
1322                  * User given schema, CREATE EXTENSION ... WITH SCHEMA ...
1323                  */
1324                 schemaName = strVal(d_schema->arg);
1325
1326                 /* If the user is giving us the schema name, it must exist already. */
1327                 schemaOid = get_namespace_oid(schemaName, false);
1328         }
1329
1330         if (control->schema != NULL)
1331         {
1332                 /*
1333                  * The extension is not relocatable and the author gave us a schema
1334                  * for it.
1335                  *
1336                  * Unless CASCADE parameter was given, it's an error to give a schema
1337                  * different from control->schema if control->schema is specified.
1338                  */
1339                 if (schemaName && strcmp(control->schema, schemaName) != 0 &&
1340                         !cascade)
1341                         ereport(ERROR,
1342                                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1343                                 errmsg("extension \"%s\" must be installed in schema \"%s\"",
1344                                            control->name,
1345                                            control->schema)));
1346
1347                 /* Always use the schema from control file for current extension. */
1348                 schemaName = control->schema;
1349
1350                 /* Find or create the schema in case it does not exist. */
1351                 schemaOid = get_namespace_oid(schemaName, true);
1352
1353                 if (!OidIsValid(schemaOid))
1354                 {
1355                         CreateSchemaStmt *csstmt = makeNode(CreateSchemaStmt);
1356
1357                         csstmt->schemaname = schemaName;
1358                         csstmt->authrole = NULL;        /* will be created by current user */
1359                         csstmt->schemaElts = NIL;
1360                         csstmt->if_not_exists = false;
1361                         CreateSchemaCommand(csstmt, NULL);
1362
1363                         /*
1364                          * CreateSchemaCommand includes CommandCounterIncrement, so new
1365                          * schema is now visible.
1366                          */
1367                         schemaOid = get_namespace_oid(schemaName, false);
1368                 }
1369         }
1370         else if (!OidIsValid(schemaOid))
1371         {
1372                 /*
1373                  * Neither user nor author of the extension specified schema, use the
1374                  * current default creation namespace, which is the first explicit
1375                  * entry in the search_path.
1376                  */
1377                 List       *search_path = fetch_search_path(false);
1378
1379                 if (search_path == NIL) /* nothing valid in search_path? */
1380                         ereport(ERROR,
1381                                         (errcode(ERRCODE_UNDEFINED_SCHEMA),
1382                                          errmsg("no schema has been selected to create in")));
1383                 schemaOid = linitial_oid(search_path);
1384                 schemaName = get_namespace_name(schemaOid);
1385                 if (schemaName == NULL) /* recently-deleted namespace? */
1386                         ereport(ERROR,
1387                                         (errcode(ERRCODE_UNDEFINED_SCHEMA),
1388                                          errmsg("no schema has been selected to create in")));
1389
1390                 list_free(search_path);
1391         }
1392
1393         /*
1394          * We don't check creation rights on the target namespace here.  If the
1395          * extension script actually creates any objects there, it will fail if
1396          * the user doesn't have such permissions.  But there are cases such as
1397          * procedural languages where it's convenient to set schema = pg_catalog
1398          * yet we don't want to restrict the command to users with ACL_CREATE for
1399          * pg_catalog.
1400          */
1401
1402         /*
1403          * Look up the prerequisite extensions, and build lists of their OIDs and
1404          * the OIDs of their target schemas.
1405          */
1406         requiredExtensions = NIL;
1407         requiredSchemas = NIL;
1408         foreach(lc, control->requires)
1409         {
1410                 char       *curreq = (char *) lfirst(lc);
1411                 Oid                     reqext;
1412                 Oid                     reqschema;
1413
1414                 reqext = get_extension_oid(curreq, true);
1415                 if (!OidIsValid(reqext))
1416                 {
1417                         if (cascade)
1418                         {
1419                                 CreateExtensionStmt *ces;
1420                                 ListCell   *lc;
1421                                 ObjectAddress addr;
1422                                 List *cascade_parents;
1423
1424                                 /* Check extension name validity before trying to cascade */
1425                                 check_valid_extension_name(curreq);
1426
1427                                 /* Check for cyclic dependency between extensions. */
1428                                 foreach(lc, parents)
1429                                 {
1430                                         char       *pname = (char *) lfirst(lc);
1431
1432                                         if (strcmp(pname, curreq) == 0)
1433                                                 ereport(ERROR,
1434                                                                 (errcode(ERRCODE_INVALID_RECURSION),
1435                                                                  errmsg("cyclic dependency detected between extensions \"%s\" and \"%s\"",
1436                                                                                 curreq, stmt->extname)));
1437                                 }
1438
1439                                 ereport(NOTICE,
1440                                                 (errmsg("installing required extension \"%s\"",
1441                                                                 curreq)));
1442
1443                                 /* Create and execute new CREATE EXTENSION statement. */
1444                                 ces = makeNode(CreateExtensionStmt);
1445                                 ces->extname = curreq;
1446
1447                                 /* Propagate the CASCADE option */
1448                                 ces->options = list_make1(d_cascade);
1449
1450                                 /* Propagate the SCHEMA option if given. */
1451                                 if (d_schema && d_schema->arg)
1452                                         ces->options = lappend(ces->options, d_schema);
1453
1454                                 /*
1455                                  * Pass the current list of parents + the current extension to
1456                                  * the "child" CreateExtensionInternal().
1457                                  */
1458                                 cascade_parents =
1459                                         lappend(list_copy(parents), stmt->extname);
1460
1461                                 /* Create the required extension. */
1462                                 addr = CreateExtensionInternal(ces, cascade_parents);
1463                                 reqext = addr.objectId;
1464                         }
1465                         else
1466                                 ereport(ERROR,
1467                                                 (errcode(ERRCODE_UNDEFINED_OBJECT),
1468                                                  errmsg("required extension \"%s\" is not installed",
1469                                                                 curreq),
1470                                                  errhint("Use CREATE EXTENSION CASCADE to install required extensions too.")));
1471                 }
1472
1473                 reqschema = get_extension_schema(reqext);
1474                 requiredExtensions = lappend_oid(requiredExtensions, reqext);
1475                 requiredSchemas = lappend_oid(requiredSchemas, reqschema);
1476         }
1477
1478         /*
1479          * Insert new tuple into pg_extension, and create dependency entries.
1480          */
1481         address = InsertExtensionTuple(control->name, extowner,
1482                                                                    schemaOid, control->relocatable,
1483                                                                    versionName,
1484                                                                    PointerGetDatum(NULL),
1485                                                                    PointerGetDatum(NULL),
1486                                                                    requiredExtensions);
1487         extensionOid = address.objectId;
1488
1489         /*
1490          * Apply any control-file comment on extension
1491          */
1492         if (control->comment != NULL)
1493                 CreateComments(extensionOid, ExtensionRelationId, 0, control->comment);
1494
1495         /*
1496          * Execute the installation script file
1497          */
1498         execute_extension_script(extensionOid, control,
1499                                                          oldVersionName, versionName,
1500                                                          requiredSchemas,
1501                                                          schemaName, schemaOid);
1502
1503         /*
1504          * If additional update scripts have to be executed, apply the updates as
1505          * though a series of ALTER EXTENSION UPDATE commands were given
1506          */
1507         ApplyExtensionUpdates(extensionOid, pcontrol,
1508                                                   versionName, updateVersions);
1509
1510         return address;
1511 }
1512
1513 /*
1514  * CREATE EXTENSION
1515  */
1516 ObjectAddress
1517 CreateExtension(CreateExtensionStmt *stmt)
1518 {
1519         /* Check extension name validity before any filesystem access */
1520         check_valid_extension_name(stmt->extname);
1521
1522         /*
1523          * Check for duplicate extension name.  The unique index on
1524          * pg_extension.extname would catch this anyway, and serves as a backstop
1525          * in case of race conditions; but this is a friendlier error message, and
1526          * besides we need a check to support IF NOT EXISTS.
1527          */
1528         if (get_extension_oid(stmt->extname, true) != InvalidOid)
1529         {
1530                 if (stmt->if_not_exists)
1531                 {
1532                         ereport(NOTICE,
1533                                         (errcode(ERRCODE_DUPLICATE_OBJECT),
1534                                          errmsg("extension \"%s\" already exists, skipping",
1535                                                         stmt->extname)));
1536                         return InvalidObjectAddress;
1537                 }
1538                 else
1539                         ereport(ERROR,
1540                                         (errcode(ERRCODE_DUPLICATE_OBJECT),
1541                                          errmsg("extension \"%s\" already exists",
1542                                                         stmt->extname)));
1543         }
1544
1545         /*
1546          * We use global variables to track the extension being created, so we can
1547          * create only one extension at the same time.
1548          */
1549         if (creating_extension)
1550                 ereport(ERROR,
1551                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1552                                  errmsg("nested CREATE EXTENSION is not supported")));
1553
1554
1555         /* Finally create the extension. */
1556         return CreateExtensionInternal(stmt, NIL);
1557 }
1558
1559 /*
1560  * InsertExtensionTuple
1561  *
1562  * Insert the new pg_extension row, and create extension's dependency entries.
1563  * Return the OID assigned to the new row.
1564  *
1565  * This is exported for the benefit of pg_upgrade, which has to create a
1566  * pg_extension entry (and the extension-level dependencies) without
1567  * actually running the extension's script.
1568  *
1569  * extConfig and extCondition should be arrays or PointerGetDatum(NULL).
1570  * We declare them as plain Datum to avoid needing array.h in extension.h.
1571  */
1572 ObjectAddress
1573 InsertExtensionTuple(const char *extName, Oid extOwner,
1574                                          Oid schemaOid, bool relocatable, const char *extVersion,
1575                                          Datum extConfig, Datum extCondition,
1576                                          List *requiredExtensions)
1577 {
1578         Oid                     extensionOid;
1579         Relation        rel;
1580         Datum           values[Natts_pg_extension];
1581         bool            nulls[Natts_pg_extension];
1582         HeapTuple       tuple;
1583         ObjectAddress myself;
1584         ObjectAddress nsp;
1585         ListCell   *lc;
1586
1587         /*
1588          * Build and insert the pg_extension tuple
1589          */
1590         rel = heap_open(ExtensionRelationId, RowExclusiveLock);
1591
1592         memset(values, 0, sizeof(values));
1593         memset(nulls, 0, sizeof(nulls));
1594
1595         values[Anum_pg_extension_extname - 1] =
1596                 DirectFunctionCall1(namein, CStringGetDatum(extName));
1597         values[Anum_pg_extension_extowner - 1] = ObjectIdGetDatum(extOwner);
1598         values[Anum_pg_extension_extnamespace - 1] = ObjectIdGetDatum(schemaOid);
1599         values[Anum_pg_extension_extrelocatable - 1] = BoolGetDatum(relocatable);
1600         values[Anum_pg_extension_extversion - 1] = CStringGetTextDatum(extVersion);
1601
1602         if (extConfig == PointerGetDatum(NULL))
1603                 nulls[Anum_pg_extension_extconfig - 1] = true;
1604         else
1605                 values[Anum_pg_extension_extconfig - 1] = extConfig;
1606
1607         if (extCondition == PointerGetDatum(NULL))
1608                 nulls[Anum_pg_extension_extcondition - 1] = true;
1609         else
1610                 values[Anum_pg_extension_extcondition - 1] = extCondition;
1611
1612         tuple = heap_form_tuple(rel->rd_att, values, nulls);
1613
1614         extensionOid = simple_heap_insert(rel, tuple);
1615         CatalogUpdateIndexes(rel, tuple);
1616
1617         heap_freetuple(tuple);
1618         heap_close(rel, RowExclusiveLock);
1619
1620         /*
1621          * Record dependencies on owner, schema, and prerequisite extensions
1622          */
1623         recordDependencyOnOwner(ExtensionRelationId, extensionOid, extOwner);
1624
1625         myself.classId = ExtensionRelationId;
1626         myself.objectId = extensionOid;
1627         myself.objectSubId = 0;
1628
1629         nsp.classId = NamespaceRelationId;
1630         nsp.objectId = schemaOid;
1631         nsp.objectSubId = 0;
1632
1633         recordDependencyOn(&myself, &nsp, DEPENDENCY_NORMAL);
1634
1635         foreach(lc, requiredExtensions)
1636         {
1637                 Oid                     reqext = lfirst_oid(lc);
1638                 ObjectAddress otherext;
1639
1640                 otherext.classId = ExtensionRelationId;
1641                 otherext.objectId = reqext;
1642                 otherext.objectSubId = 0;
1643
1644                 recordDependencyOn(&myself, &otherext, DEPENDENCY_NORMAL);
1645         }
1646         /* Post creation hook for new extension */
1647         InvokeObjectPostCreateHook(ExtensionRelationId, extensionOid, 0);
1648
1649         return myself;
1650 }
1651
1652 /*
1653  * Guts of extension deletion.
1654  *
1655  * All we need do here is remove the pg_extension tuple itself.  Everything
1656  * else is taken care of by the dependency infrastructure.
1657  */
1658 void
1659 RemoveExtensionById(Oid extId)
1660 {
1661         Relation        rel;
1662         SysScanDesc scandesc;
1663         HeapTuple       tuple;
1664         ScanKeyData entry[1];
1665
1666         /*
1667          * Disallow deletion of any extension that's currently open for insertion;
1668          * else subsequent executions of recordDependencyOnCurrentExtension()
1669          * could create dangling pg_depend records that refer to a no-longer-valid
1670          * pg_extension OID.  This is needed not so much because we think people
1671          * might write "DROP EXTENSION foo" in foo's own script files, as because
1672          * errors in dependency management in extension script files could give
1673          * rise to cases where an extension is dropped as a result of recursing
1674          * from some contained object.  Because of that, we must test for the case
1675          * here, not at some higher level of the DROP EXTENSION command.
1676          */
1677         if (extId == CurrentExtensionObject)
1678                 ereport(ERROR,
1679                                 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1680                   errmsg("cannot drop extension \"%s\" because it is being modified",
1681                                  get_extension_name(extId))));
1682
1683         rel = heap_open(ExtensionRelationId, RowExclusiveLock);
1684
1685         ScanKeyInit(&entry[0],
1686                                 ObjectIdAttributeNumber,
1687                                 BTEqualStrategyNumber, F_OIDEQ,
1688                                 ObjectIdGetDatum(extId));
1689         scandesc = systable_beginscan(rel, ExtensionOidIndexId, true,
1690                                                                   NULL, 1, entry);
1691
1692         tuple = systable_getnext(scandesc);
1693
1694         /* We assume that there can be at most one matching tuple */
1695         if (HeapTupleIsValid(tuple))
1696                 simple_heap_delete(rel, &tuple->t_self);
1697
1698         systable_endscan(scandesc);
1699
1700         heap_close(rel, RowExclusiveLock);
1701 }
1702
1703 /*
1704  * This function lists the available extensions (one row per primary control
1705  * file in the control directory).  We parse each control file and report the
1706  * interesting fields.
1707  *
1708  * The system view pg_available_extensions provides a user interface to this
1709  * SRF, adding information about whether the extensions are installed in the
1710  * current DB.
1711  */
1712 Datum
1713 pg_available_extensions(PG_FUNCTION_ARGS)
1714 {
1715         ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
1716         TupleDesc       tupdesc;
1717         Tuplestorestate *tupstore;
1718         MemoryContext per_query_ctx;
1719         MemoryContext oldcontext;
1720         char       *location;
1721         DIR                *dir;
1722         struct dirent *de;
1723
1724         /* check to see if caller supports us returning a tuplestore */
1725         if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo))
1726                 ereport(ERROR,
1727                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1728                                  errmsg("set-valued function called in context that cannot accept a set")));
1729         if (!(rsinfo->allowedModes & SFRM_Materialize))
1730                 ereport(ERROR,
1731                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1732                                  errmsg("materialize mode required, but it is not " \
1733                                                 "allowed in this context")));
1734
1735         /* Build a tuple descriptor for our result type */
1736         if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
1737                 elog(ERROR, "return type must be a row type");
1738
1739         /* Build tuplestore to hold the result rows */
1740         per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
1741         oldcontext = MemoryContextSwitchTo(per_query_ctx);
1742
1743         tupstore = tuplestore_begin_heap(true, false, work_mem);
1744         rsinfo->returnMode = SFRM_Materialize;
1745         rsinfo->setResult = tupstore;
1746         rsinfo->setDesc = tupdesc;
1747
1748         MemoryContextSwitchTo(oldcontext);
1749
1750         location = get_extension_control_directory();
1751         dir = AllocateDir(location);
1752
1753         /*
1754          * If the control directory doesn't exist, we want to silently return an
1755          * empty set.  Any other error will be reported by ReadDir.
1756          */
1757         if (dir == NULL && errno == ENOENT)
1758         {
1759                 /* do nothing */
1760         }
1761         else
1762         {
1763                 while ((de = ReadDir(dir, location)) != NULL)
1764                 {
1765                         ExtensionControlFile *control;
1766                         char       *extname;
1767                         Datum           values[3];
1768                         bool            nulls[3];
1769
1770                         if (!is_extension_control_filename(de->d_name))
1771                                 continue;
1772
1773                         /* extract extension name from 'name.control' filename */
1774                         extname = pstrdup(de->d_name);
1775                         *strrchr(extname, '.') = '\0';
1776
1777                         /* ignore it if it's an auxiliary control file */
1778                         if (strstr(extname, "--"))
1779                                 continue;
1780
1781                         control = read_extension_control_file(extname);
1782
1783                         memset(values, 0, sizeof(values));
1784                         memset(nulls, 0, sizeof(nulls));
1785
1786                         /* name */
1787                         values[0] = DirectFunctionCall1(namein,
1788                                                                                         CStringGetDatum(control->name));
1789                         /* default_version */
1790                         if (control->default_version == NULL)
1791                                 nulls[1] = true;
1792                         else
1793                                 values[1] = CStringGetTextDatum(control->default_version);
1794                         /* comment */
1795                         if (control->comment == NULL)
1796                                 nulls[2] = true;
1797                         else
1798                                 values[2] = CStringGetTextDatum(control->comment);
1799
1800                         tuplestore_putvalues(tupstore, tupdesc, values, nulls);
1801                 }
1802
1803                 FreeDir(dir);
1804         }
1805
1806         /* clean up and return the tuplestore */
1807         tuplestore_donestoring(tupstore);
1808
1809         return (Datum) 0;
1810 }
1811
1812 /*
1813  * This function lists the available extension versions (one row per
1814  * extension installation script).  For each version, we parse the related
1815  * control file(s) and report the interesting fields.
1816  *
1817  * The system view pg_available_extension_versions provides a user interface
1818  * to this SRF, adding information about which versions are installed in the
1819  * current DB.
1820  */
1821 Datum
1822 pg_available_extension_versions(PG_FUNCTION_ARGS)
1823 {
1824         ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
1825         TupleDesc       tupdesc;
1826         Tuplestorestate *tupstore;
1827         MemoryContext per_query_ctx;
1828         MemoryContext oldcontext;
1829         char       *location;
1830         DIR                *dir;
1831         struct dirent *de;
1832
1833         /* check to see if caller supports us returning a tuplestore */
1834         if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo))
1835                 ereport(ERROR,
1836                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1837                                  errmsg("set-valued function called in context that cannot accept a set")));
1838         if (!(rsinfo->allowedModes & SFRM_Materialize))
1839                 ereport(ERROR,
1840                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1841                                  errmsg("materialize mode required, but it is not " \
1842                                                 "allowed in this context")));
1843
1844         /* Build a tuple descriptor for our result type */
1845         if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
1846                 elog(ERROR, "return type must be a row type");
1847
1848         /* Build tuplestore to hold the result rows */
1849         per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
1850         oldcontext = MemoryContextSwitchTo(per_query_ctx);
1851
1852         tupstore = tuplestore_begin_heap(true, false, work_mem);
1853         rsinfo->returnMode = SFRM_Materialize;
1854         rsinfo->setResult = tupstore;
1855         rsinfo->setDesc = tupdesc;
1856
1857         MemoryContextSwitchTo(oldcontext);
1858
1859         location = get_extension_control_directory();
1860         dir = AllocateDir(location);
1861
1862         /*
1863          * If the control directory doesn't exist, we want to silently return an
1864          * empty set.  Any other error will be reported by ReadDir.
1865          */
1866         if (dir == NULL && errno == ENOENT)
1867         {
1868                 /* do nothing */
1869         }
1870         else
1871         {
1872                 while ((de = ReadDir(dir, location)) != NULL)
1873                 {
1874                         ExtensionControlFile *control;
1875                         char       *extname;
1876
1877                         if (!is_extension_control_filename(de->d_name))
1878                                 continue;
1879
1880                         /* extract extension name from 'name.control' filename */
1881                         extname = pstrdup(de->d_name);
1882                         *strrchr(extname, '.') = '\0';
1883
1884                         /* ignore it if it's an auxiliary control file */
1885                         if (strstr(extname, "--"))
1886                                 continue;
1887
1888                         /* read the control file */
1889                         control = read_extension_control_file(extname);
1890
1891                         /* scan extension's script directory for install scripts */
1892                         get_available_versions_for_extension(control, tupstore, tupdesc);
1893                 }
1894
1895                 FreeDir(dir);
1896         }
1897
1898         /* clean up and return the tuplestore */
1899         tuplestore_donestoring(tupstore);
1900
1901         return (Datum) 0;
1902 }
1903
1904 /*
1905  * Inner loop for pg_available_extension_versions:
1906  *              read versions of one extension, add rows to tupstore
1907  */
1908 static void
1909 get_available_versions_for_extension(ExtensionControlFile *pcontrol,
1910                                                                          Tuplestorestate *tupstore,
1911                                                                          TupleDesc tupdesc)
1912 {
1913         int                     extnamelen = strlen(pcontrol->name);
1914         char       *location;
1915         DIR                *dir;
1916         struct dirent *de;
1917
1918         location = get_extension_script_directory(pcontrol);
1919         dir = AllocateDir(location);
1920         /* Note this will fail if script directory doesn't exist */
1921         while ((de = ReadDir(dir, location)) != NULL)
1922         {
1923                 ExtensionControlFile *control;
1924                 char       *vername;
1925                 Datum           values[7];
1926                 bool            nulls[7];
1927
1928                 /* must be a .sql file ... */
1929                 if (!is_extension_script_filename(de->d_name))
1930                         continue;
1931
1932                 /* ... matching extension name followed by separator */
1933                 if (strncmp(de->d_name, pcontrol->name, extnamelen) != 0 ||
1934                         de->d_name[extnamelen] != '-' ||
1935                         de->d_name[extnamelen + 1] != '-')
1936                         continue;
1937
1938                 /* extract version name from 'extname--something.sql' filename */
1939                 vername = pstrdup(de->d_name + extnamelen + 2);
1940                 *strrchr(vername, '.') = '\0';
1941
1942                 /* ignore it if it's an update script */
1943                 if (strstr(vername, "--"))
1944                         continue;
1945
1946                 /*
1947                  * Fetch parameters for specific version (pcontrol is not changed)
1948                  */
1949                 control = read_extension_aux_control_file(pcontrol, vername);
1950
1951                 memset(values, 0, sizeof(values));
1952                 memset(nulls, 0, sizeof(nulls));
1953
1954                 /* name */
1955                 values[0] = DirectFunctionCall1(namein,
1956                                                                                 CStringGetDatum(control->name));
1957                 /* version */
1958                 values[1] = CStringGetTextDatum(vername);
1959                 /* superuser */
1960                 values[2] = BoolGetDatum(control->superuser);
1961                 /* relocatable */
1962                 values[3] = BoolGetDatum(control->relocatable);
1963                 /* schema */
1964                 if (control->schema == NULL)
1965                         nulls[4] = true;
1966                 else
1967                         values[4] = DirectFunctionCall1(namein,
1968                                                                                         CStringGetDatum(control->schema));
1969                 /* requires */
1970                 if (control->requires == NIL)
1971                         nulls[5] = true;
1972                 else
1973                 {
1974                         Datum      *datums;
1975                         int                     ndatums;
1976                         ArrayType  *a;
1977                         ListCell   *lc;
1978
1979                         ndatums = list_length(control->requires);
1980                         datums = (Datum *) palloc(ndatums * sizeof(Datum));
1981                         ndatums = 0;
1982                         foreach(lc, control->requires)
1983                         {
1984                                 char       *curreq = (char *) lfirst(lc);
1985
1986                                 datums[ndatums++] =
1987                                         DirectFunctionCall1(namein, CStringGetDatum(curreq));
1988                         }
1989                         a = construct_array(datums, ndatums,
1990                                                                 NAMEOID,
1991                                                                 NAMEDATALEN, false, 'c');
1992                         values[5] = PointerGetDatum(a);
1993                 }
1994                 /* comment */
1995                 if (control->comment == NULL)
1996                         nulls[6] = true;
1997                 else
1998                         values[6] = CStringGetTextDatum(control->comment);
1999
2000                 tuplestore_putvalues(tupstore, tupdesc, values, nulls);
2001         }
2002
2003         FreeDir(dir);
2004 }
2005
2006 /*
2007  * This function reports the version update paths that exist for the
2008  * specified extension.
2009  */
2010 Datum
2011 pg_extension_update_paths(PG_FUNCTION_ARGS)
2012 {
2013         Name            extname = PG_GETARG_NAME(0);
2014         ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
2015         TupleDesc       tupdesc;
2016         Tuplestorestate *tupstore;
2017         MemoryContext per_query_ctx;
2018         MemoryContext oldcontext;
2019         List       *evi_list;
2020         ExtensionControlFile *control;
2021         ListCell   *lc1;
2022
2023         /* Check extension name validity before any filesystem access */
2024         check_valid_extension_name(NameStr(*extname));
2025
2026         /* check to see if caller supports us returning a tuplestore */
2027         if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo))
2028                 ereport(ERROR,
2029                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2030                                  errmsg("set-valued function called in context that cannot accept a set")));
2031         if (!(rsinfo->allowedModes & SFRM_Materialize))
2032                 ereport(ERROR,
2033                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2034                                  errmsg("materialize mode required, but it is not " \
2035                                                 "allowed in this context")));
2036
2037         /* Build a tuple descriptor for our result type */
2038         if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
2039                 elog(ERROR, "return type must be a row type");
2040
2041         /* Build tuplestore to hold the result rows */
2042         per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
2043         oldcontext = MemoryContextSwitchTo(per_query_ctx);
2044
2045         tupstore = tuplestore_begin_heap(true, false, work_mem);
2046         rsinfo->returnMode = SFRM_Materialize;
2047         rsinfo->setResult = tupstore;
2048         rsinfo->setDesc = tupdesc;
2049
2050         MemoryContextSwitchTo(oldcontext);
2051
2052         /* Read the extension's control file */
2053         control = read_extension_control_file(NameStr(*extname));
2054
2055         /* Extract the version update graph from the script directory */
2056         evi_list = get_ext_ver_list(control);
2057
2058         /* Iterate over all pairs of versions */
2059         foreach(lc1, evi_list)
2060         {
2061                 ExtensionVersionInfo *evi1 = (ExtensionVersionInfo *) lfirst(lc1);
2062                 ListCell   *lc2;
2063
2064                 foreach(lc2, evi_list)
2065                 {
2066                         ExtensionVersionInfo *evi2 = (ExtensionVersionInfo *) lfirst(lc2);
2067                         List       *path;
2068                         Datum           values[3];
2069                         bool            nulls[3];
2070
2071                         if (evi1 == evi2)
2072                                 continue;
2073
2074                         /* Find shortest path from evi1 to evi2 */
2075                         path = find_update_path(evi_list, evi1, evi2, true);
2076
2077                         /* Emit result row */
2078                         memset(values, 0, sizeof(values));
2079                         memset(nulls, 0, sizeof(nulls));
2080
2081                         /* source */
2082                         values[0] = CStringGetTextDatum(evi1->name);
2083                         /* target */
2084                         values[1] = CStringGetTextDatum(evi2->name);
2085                         /* path */
2086                         if (path == NIL)
2087                                 nulls[2] = true;
2088                         else
2089                         {
2090                                 StringInfoData pathbuf;
2091                                 ListCell   *lcv;
2092
2093                                 initStringInfo(&pathbuf);
2094                                 /* The path doesn't include start vertex, but show it */
2095                                 appendStringInfoString(&pathbuf, evi1->name);
2096                                 foreach(lcv, path)
2097                                 {
2098                                         char       *versionName = (char *) lfirst(lcv);
2099
2100                                         appendStringInfoString(&pathbuf, "--");
2101                                         appendStringInfoString(&pathbuf, versionName);
2102                                 }
2103                                 values[2] = CStringGetTextDatum(pathbuf.data);
2104                                 pfree(pathbuf.data);
2105                         }
2106
2107                         tuplestore_putvalues(tupstore, tupdesc, values, nulls);
2108                 }
2109         }
2110
2111         /* clean up and return the tuplestore */
2112         tuplestore_donestoring(tupstore);
2113
2114         return (Datum) 0;
2115 }
2116
2117 /*
2118  * pg_extension_config_dump
2119  *
2120  * Record information about a configuration table that belongs to an
2121  * extension being created, but whose contents should be dumped in whole
2122  * or in part during pg_dump.
2123  */
2124 Datum
2125 pg_extension_config_dump(PG_FUNCTION_ARGS)
2126 {
2127         Oid                     tableoid = PG_GETARG_OID(0);
2128         text       *wherecond = PG_GETARG_TEXT_P(1);
2129         char       *tablename;
2130         Relation        extRel;
2131         ScanKeyData key[1];
2132         SysScanDesc extScan;
2133         HeapTuple       extTup;
2134         Datum           arrayDatum;
2135         Datum           elementDatum;
2136         int                     arrayLength;
2137         int                     arrayIndex;
2138         bool            isnull;
2139         Datum           repl_val[Natts_pg_extension];
2140         bool            repl_null[Natts_pg_extension];
2141         bool            repl_repl[Natts_pg_extension];
2142         ArrayType  *a;
2143
2144         /*
2145          * We only allow this to be called from an extension's SQL script. We
2146          * shouldn't need any permissions check beyond that.
2147          */
2148         if (!creating_extension)
2149                 ereport(ERROR,
2150                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2151                                  errmsg("pg_extension_config_dump() can only be called "
2152                                                 "from an SQL script executed by CREATE EXTENSION")));
2153
2154         /*
2155          * Check that the table exists and is a member of the extension being
2156          * created.  This ensures that we don't need to register an additional
2157          * dependency to protect the extconfig entry.
2158          */
2159         tablename = get_rel_name(tableoid);
2160         if (tablename == NULL)
2161                 ereport(ERROR,
2162                                 (errcode(ERRCODE_UNDEFINED_TABLE),
2163                                  errmsg("OID %u does not refer to a table", tableoid)));
2164         if (getExtensionOfObject(RelationRelationId, tableoid) !=
2165                 CurrentExtensionObject)
2166                 ereport(ERROR,
2167                                 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
2168                 errmsg("table \"%s\" is not a member of the extension being created",
2169                            tablename)));
2170
2171         /*
2172          * Add the table OID and WHERE condition to the extension's extconfig and
2173          * extcondition arrays.
2174          *
2175          * If the table is already in extconfig, treat this as an update of the
2176          * WHERE condition.
2177          */
2178
2179         /* Find the pg_extension tuple */
2180         extRel = heap_open(ExtensionRelationId, RowExclusiveLock);
2181
2182         ScanKeyInit(&key[0],
2183                                 ObjectIdAttributeNumber,
2184                                 BTEqualStrategyNumber, F_OIDEQ,
2185                                 ObjectIdGetDatum(CurrentExtensionObject));
2186
2187         extScan = systable_beginscan(extRel, ExtensionOidIndexId, true,
2188                                                                  NULL, 1, key);
2189
2190         extTup = systable_getnext(extScan);
2191
2192         if (!HeapTupleIsValid(extTup))          /* should not happen */
2193                 elog(ERROR, "extension with oid %u does not exist",
2194                          CurrentExtensionObject);
2195
2196         memset(repl_val, 0, sizeof(repl_val));
2197         memset(repl_null, false, sizeof(repl_null));
2198         memset(repl_repl, false, sizeof(repl_repl));
2199
2200         /* Build or modify the extconfig value */
2201         elementDatum = ObjectIdGetDatum(tableoid);
2202
2203         arrayDatum = heap_getattr(extTup, Anum_pg_extension_extconfig,
2204                                                           RelationGetDescr(extRel), &isnull);
2205         if (isnull)
2206         {
2207                 /* Previously empty extconfig, so build 1-element array */
2208                 arrayLength = 0;
2209                 arrayIndex = 1;
2210
2211                 a = construct_array(&elementDatum, 1,
2212                                                         OIDOID,
2213                                                         sizeof(Oid), true, 'i');
2214         }
2215         else
2216         {
2217                 /* Modify or extend existing extconfig array */
2218                 Oid                *arrayData;
2219                 int                     i;
2220
2221                 a = DatumGetArrayTypeP(arrayDatum);
2222
2223                 arrayLength = ARR_DIMS(a)[0];
2224                 if (ARR_NDIM(a) != 1 ||
2225                         ARR_LBOUND(a)[0] != 1 ||
2226                         arrayLength < 0 ||
2227                         ARR_HASNULL(a) ||
2228                         ARR_ELEMTYPE(a) != OIDOID)
2229                         elog(ERROR, "extconfig is not a 1-D Oid array");
2230                 arrayData = (Oid *) ARR_DATA_PTR(a);
2231
2232                 arrayIndex = arrayLength + 1;   /* set up to add after end */
2233
2234                 for (i = 0; i < arrayLength; i++)
2235                 {
2236                         if (arrayData[i] == tableoid)
2237                         {
2238                                 arrayIndex = i + 1;             /* replace this element instead */
2239                                 break;
2240                         }
2241                 }
2242
2243                 a = array_set(a, 1, &arrayIndex,
2244                                           elementDatum,
2245                                           false,
2246                                           -1 /* varlena array */ ,
2247                                           sizeof(Oid) /* OID's typlen */ ,
2248                                           true /* OID's typbyval */ ,
2249                                           'i' /* OID's typalign */ );
2250         }
2251         repl_val[Anum_pg_extension_extconfig - 1] = PointerGetDatum(a);
2252         repl_repl[Anum_pg_extension_extconfig - 1] = true;
2253
2254         /* Build or modify the extcondition value */
2255         elementDatum = PointerGetDatum(wherecond);
2256
2257         arrayDatum = heap_getattr(extTup, Anum_pg_extension_extcondition,
2258                                                           RelationGetDescr(extRel), &isnull);
2259         if (isnull)
2260         {
2261                 if (arrayLength != 0)
2262                         elog(ERROR, "extconfig and extcondition arrays do not match");
2263
2264                 a = construct_array(&elementDatum, 1,
2265                                                         TEXTOID,
2266                                                         -1, false, 'i');
2267         }
2268         else
2269         {
2270                 a = DatumGetArrayTypeP(arrayDatum);
2271
2272                 if (ARR_NDIM(a) != 1 ||
2273                         ARR_LBOUND(a)[0] != 1 ||
2274                         ARR_HASNULL(a) ||
2275                         ARR_ELEMTYPE(a) != TEXTOID)
2276                         elog(ERROR, "extcondition is not a 1-D text array");
2277                 if (ARR_DIMS(a)[0] != arrayLength)
2278                         elog(ERROR, "extconfig and extcondition arrays do not match");
2279
2280                 /* Add or replace at same index as in extconfig */
2281                 a = array_set(a, 1, &arrayIndex,
2282                                           elementDatum,
2283                                           false,
2284                                           -1 /* varlena array */ ,
2285                                           -1 /* TEXT's typlen */ ,
2286                                           false /* TEXT's typbyval */ ,
2287                                           'i' /* TEXT's typalign */ );
2288         }
2289         repl_val[Anum_pg_extension_extcondition - 1] = PointerGetDatum(a);
2290         repl_repl[Anum_pg_extension_extcondition - 1] = true;
2291
2292         extTup = heap_modify_tuple(extTup, RelationGetDescr(extRel),
2293                                                            repl_val, repl_null, repl_repl);
2294
2295         simple_heap_update(extRel, &extTup->t_self, extTup);
2296         CatalogUpdateIndexes(extRel, extTup);
2297
2298         systable_endscan(extScan);
2299
2300         heap_close(extRel, RowExclusiveLock);
2301
2302         PG_RETURN_VOID();
2303 }
2304
2305 /*
2306  * extension_config_remove
2307  *
2308  * Remove the specified table OID from extension's extconfig, if present.
2309  * This is not currently exposed as a function, but it could be;
2310  * for now, we just invoke it from ALTER EXTENSION DROP.
2311  */
2312 static void
2313 extension_config_remove(Oid extensionoid, Oid tableoid)
2314 {
2315         Relation        extRel;
2316         ScanKeyData key[1];
2317         SysScanDesc extScan;
2318         HeapTuple       extTup;
2319         Datum           arrayDatum;
2320         int                     arrayLength;
2321         int                     arrayIndex;
2322         bool            isnull;
2323         Datum           repl_val[Natts_pg_extension];
2324         bool            repl_null[Natts_pg_extension];
2325         bool            repl_repl[Natts_pg_extension];
2326         ArrayType  *a;
2327
2328         /* Find the pg_extension tuple */
2329         extRel = heap_open(ExtensionRelationId, RowExclusiveLock);
2330
2331         ScanKeyInit(&key[0],
2332                                 ObjectIdAttributeNumber,
2333                                 BTEqualStrategyNumber, F_OIDEQ,
2334                                 ObjectIdGetDatum(extensionoid));
2335
2336         extScan = systable_beginscan(extRel, ExtensionOidIndexId, true,
2337                                                                  NULL, 1, key);
2338
2339         extTup = systable_getnext(extScan);
2340
2341         if (!HeapTupleIsValid(extTup))          /* should not happen */
2342                 elog(ERROR, "extension with oid %u does not exist",
2343                          extensionoid);
2344
2345         /* Search extconfig for the tableoid */
2346         arrayDatum = heap_getattr(extTup, Anum_pg_extension_extconfig,
2347                                                           RelationGetDescr(extRel), &isnull);
2348         if (isnull)
2349         {
2350                 /* nothing to do */
2351                 a = NULL;
2352                 arrayLength = 0;
2353                 arrayIndex = -1;
2354         }
2355         else
2356         {
2357                 Oid                *arrayData;
2358                 int                     i;
2359
2360                 a = DatumGetArrayTypeP(arrayDatum);
2361
2362                 arrayLength = ARR_DIMS(a)[0];
2363                 if (ARR_NDIM(a) != 1 ||
2364                         ARR_LBOUND(a)[0] != 1 ||
2365                         arrayLength < 0 ||
2366                         ARR_HASNULL(a) ||
2367                         ARR_ELEMTYPE(a) != OIDOID)
2368                         elog(ERROR, "extconfig is not a 1-D Oid array");
2369                 arrayData = (Oid *) ARR_DATA_PTR(a);
2370
2371                 arrayIndex = -1;                /* flag for no deletion needed */
2372
2373                 for (i = 0; i < arrayLength; i++)
2374                 {
2375                         if (arrayData[i] == tableoid)
2376                         {
2377                                 arrayIndex = i; /* index to remove */
2378                                 break;
2379                         }
2380                 }
2381         }
2382
2383         /* If tableoid is not in extconfig, nothing to do */
2384         if (arrayIndex < 0)
2385         {
2386                 systable_endscan(extScan);
2387                 heap_close(extRel, RowExclusiveLock);
2388                 return;
2389         }
2390
2391         /* Modify or delete the extconfig value */
2392         memset(repl_val, 0, sizeof(repl_val));
2393         memset(repl_null, false, sizeof(repl_null));
2394         memset(repl_repl, false, sizeof(repl_repl));
2395
2396         if (arrayLength <= 1)
2397         {
2398                 /* removing only element, just set array to null */
2399                 repl_null[Anum_pg_extension_extconfig - 1] = true;
2400         }
2401         else
2402         {
2403                 /* squeeze out the target element */
2404                 Datum      *dvalues;
2405                 bool       *dnulls;
2406                 int                     nelems;
2407                 int                     i;
2408
2409                 deconstruct_array(a, OIDOID, sizeof(Oid), true, 'i',
2410                                                   &dvalues, &dnulls, &nelems);
2411
2412                 /* We already checked there are no nulls, so ignore dnulls */
2413                 for (i = arrayIndex; i < arrayLength - 1; i++)
2414                         dvalues[i] = dvalues[i + 1];
2415
2416                 a = construct_array(dvalues, arrayLength - 1,
2417                                                         OIDOID, sizeof(Oid), true, 'i');
2418
2419                 repl_val[Anum_pg_extension_extconfig - 1] = PointerGetDatum(a);
2420         }
2421         repl_repl[Anum_pg_extension_extconfig - 1] = true;
2422
2423         /* Modify or delete the extcondition value */
2424         arrayDatum = heap_getattr(extTup, Anum_pg_extension_extcondition,
2425                                                           RelationGetDescr(extRel), &isnull);
2426         if (isnull)
2427         {
2428                 elog(ERROR, "extconfig and extcondition arrays do not match");
2429         }
2430         else
2431         {
2432                 a = DatumGetArrayTypeP(arrayDatum);
2433
2434                 if (ARR_NDIM(a) != 1 ||
2435                         ARR_LBOUND(a)[0] != 1 ||
2436                         ARR_HASNULL(a) ||
2437                         ARR_ELEMTYPE(a) != TEXTOID)
2438                         elog(ERROR, "extcondition is not a 1-D text array");
2439                 if (ARR_DIMS(a)[0] != arrayLength)
2440                         elog(ERROR, "extconfig and extcondition arrays do not match");
2441         }
2442
2443         if (arrayLength <= 1)
2444         {
2445                 /* removing only element, just set array to null */
2446                 repl_null[Anum_pg_extension_extcondition - 1] = true;
2447         }
2448         else
2449         {
2450                 /* squeeze out the target element */
2451                 Datum      *dvalues;
2452                 bool       *dnulls;
2453                 int                     nelems;
2454                 int                     i;
2455
2456                 deconstruct_array(a, TEXTOID, -1, false, 'i',
2457                                                   &dvalues, &dnulls, &nelems);
2458
2459                 /* We already checked there are no nulls, so ignore dnulls */
2460                 for (i = arrayIndex; i < arrayLength - 1; i++)
2461                         dvalues[i] = dvalues[i + 1];
2462
2463                 a = construct_array(dvalues, arrayLength - 1,
2464                                                         TEXTOID, -1, false, 'i');
2465
2466                 repl_val[Anum_pg_extension_extcondition - 1] = PointerGetDatum(a);
2467         }
2468         repl_repl[Anum_pg_extension_extcondition - 1] = true;
2469
2470         extTup = heap_modify_tuple(extTup, RelationGetDescr(extRel),
2471                                                            repl_val, repl_null, repl_repl);
2472
2473         simple_heap_update(extRel, &extTup->t_self, extTup);
2474         CatalogUpdateIndexes(extRel, extTup);
2475
2476         systable_endscan(extScan);
2477
2478         heap_close(extRel, RowExclusiveLock);
2479 }
2480
2481 /*
2482  * Execute ALTER EXTENSION SET SCHEMA
2483  */
2484 ObjectAddress
2485 AlterExtensionNamespace(List *names, const char *newschema, Oid *oldschema)
2486 {
2487         char       *extensionName;
2488         Oid                     extensionOid;
2489         Oid                     nspOid;
2490         Oid                     oldNspOid = InvalidOid;
2491         AclResult       aclresult;
2492         Relation        extRel;
2493         ScanKeyData key[2];
2494         SysScanDesc extScan;
2495         HeapTuple       extTup;
2496         Form_pg_extension extForm;
2497         Relation        depRel;
2498         SysScanDesc depScan;
2499         HeapTuple       depTup;
2500         ObjectAddresses *objsMoved;
2501         ObjectAddress extAddr;
2502
2503         if (list_length(names) != 1)
2504                 ereport(ERROR,
2505                                 (errcode(ERRCODE_SYNTAX_ERROR),
2506                                  errmsg("extension name cannot be qualified")));
2507         extensionName = strVal(linitial(names));
2508
2509         extensionOid = get_extension_oid(extensionName, false);
2510
2511         nspOid = LookupCreationNamespace(newschema);
2512
2513         /*
2514          * Permission check: must own extension.  Note that we don't bother to
2515          * check ownership of the individual member objects ...
2516          */
2517         if (!pg_extension_ownercheck(extensionOid, GetUserId()))
2518                 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_EXTENSION,
2519                                            extensionName);
2520
2521         /* Permission check: must have creation rights in target namespace */
2522         aclresult = pg_namespace_aclcheck(nspOid, GetUserId(), ACL_CREATE);
2523         if (aclresult != ACLCHECK_OK)
2524                 aclcheck_error(aclresult, ACL_KIND_NAMESPACE, newschema);
2525
2526         /*
2527          * If the schema is currently a member of the extension, disallow moving
2528          * the extension into the schema.  That would create a dependency loop.
2529          */
2530         if (getExtensionOfObject(NamespaceRelationId, nspOid) == extensionOid)
2531                 ereport(ERROR,
2532                                 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
2533                                  errmsg("cannot move extension \"%s\" into schema \"%s\" "
2534                                                 "because the extension contains the schema",
2535                                                 extensionName, newschema)));
2536
2537         /* Locate the pg_extension tuple */
2538         extRel = heap_open(ExtensionRelationId, RowExclusiveLock);
2539
2540         ScanKeyInit(&key[0],
2541                                 ObjectIdAttributeNumber,
2542                                 BTEqualStrategyNumber, F_OIDEQ,
2543                                 ObjectIdGetDatum(extensionOid));
2544
2545         extScan = systable_beginscan(extRel, ExtensionOidIndexId, true,
2546                                                                  NULL, 1, key);
2547
2548         extTup = systable_getnext(extScan);
2549
2550         if (!HeapTupleIsValid(extTup))          /* should not happen */
2551                 elog(ERROR, "extension with oid %u does not exist", extensionOid);
2552
2553         /* Copy tuple so we can modify it below */
2554         extTup = heap_copytuple(extTup);
2555         extForm = (Form_pg_extension) GETSTRUCT(extTup);
2556
2557         systable_endscan(extScan);
2558
2559         /*
2560          * If the extension is already in the target schema, just silently do
2561          * nothing.
2562          */
2563         if (extForm->extnamespace == nspOid)
2564         {
2565                 heap_close(extRel, RowExclusiveLock);
2566                 return InvalidObjectAddress;
2567         }
2568
2569         /* Check extension is supposed to be relocatable */
2570         if (!extForm->extrelocatable)
2571                 ereport(ERROR,
2572                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2573                                  errmsg("extension \"%s\" does not support SET SCHEMA",
2574                                                 NameStr(extForm->extname))));
2575
2576         objsMoved = new_object_addresses();
2577
2578         /*
2579          * Scan pg_depend to find objects that depend directly on the extension,
2580          * and alter each one's schema.
2581          */
2582         depRel = heap_open(DependRelationId, AccessShareLock);
2583
2584         ScanKeyInit(&key[0],
2585                                 Anum_pg_depend_refclassid,
2586                                 BTEqualStrategyNumber, F_OIDEQ,
2587                                 ObjectIdGetDatum(ExtensionRelationId));
2588         ScanKeyInit(&key[1],
2589                                 Anum_pg_depend_refobjid,
2590                                 BTEqualStrategyNumber, F_OIDEQ,
2591                                 ObjectIdGetDatum(extensionOid));
2592
2593         depScan = systable_beginscan(depRel, DependReferenceIndexId, true,
2594                                                                  NULL, 2, key);
2595
2596         while (HeapTupleIsValid(depTup = systable_getnext(depScan)))
2597         {
2598                 Form_pg_depend pg_depend = (Form_pg_depend) GETSTRUCT(depTup);
2599                 ObjectAddress dep;
2600                 Oid                     dep_oldNspOid;
2601
2602                 /*
2603                  * Ignore non-membership dependencies.  (Currently, the only other
2604                  * case we could see here is a normal dependency from another
2605                  * extension.)
2606                  */
2607                 if (pg_depend->deptype != DEPENDENCY_EXTENSION)
2608                         continue;
2609
2610                 dep.classId = pg_depend->classid;
2611                 dep.objectId = pg_depend->objid;
2612                 dep.objectSubId = pg_depend->objsubid;
2613
2614                 if (dep.objectSubId != 0)               /* should not happen */
2615                         elog(ERROR, "extension should not have a sub-object dependency");
2616
2617                 /* Relocate the object */
2618                 dep_oldNspOid = AlterObjectNamespace_oid(dep.classId,
2619                                                                                                  dep.objectId,
2620                                                                                                  nspOid,
2621                                                                                                  objsMoved);
2622
2623                 /*
2624                  * Remember previous namespace of first object that has one
2625                  */
2626                 if (oldNspOid == InvalidOid && dep_oldNspOid != InvalidOid)
2627                         oldNspOid = dep_oldNspOid;
2628
2629                 /*
2630                  * If not all the objects had the same old namespace (ignoring any
2631                  * that are not in namespaces), complain.
2632                  */
2633                 if (dep_oldNspOid != InvalidOid && dep_oldNspOid != oldNspOid)
2634                         ereport(ERROR,
2635                                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2636                                          errmsg("extension \"%s\" does not support SET SCHEMA",
2637                                                         NameStr(extForm->extname)),
2638                                          errdetail("%s is not in the extension's schema \"%s\"",
2639                                                            getObjectDescription(&dep),
2640                                                            get_namespace_name(oldNspOid))));
2641         }
2642
2643         /* report old schema, if caller wants it */
2644         if (oldschema)
2645                 *oldschema = oldNspOid;
2646
2647         systable_endscan(depScan);
2648
2649         relation_close(depRel, AccessShareLock);
2650
2651         /* Now adjust pg_extension.extnamespace */
2652         extForm->extnamespace = nspOid;
2653
2654         simple_heap_update(extRel, &extTup->t_self, extTup);
2655         CatalogUpdateIndexes(extRel, extTup);
2656
2657         heap_close(extRel, RowExclusiveLock);
2658
2659         /* update dependencies to point to the new schema */
2660         changeDependencyFor(ExtensionRelationId, extensionOid,
2661                                                 NamespaceRelationId, oldNspOid, nspOid);
2662
2663         InvokeObjectPostAlterHook(ExtensionRelationId, extensionOid, 0);
2664
2665         ObjectAddressSet(extAddr, ExtensionRelationId, extensionOid);
2666
2667         return extAddr;
2668 }
2669
2670 /*
2671  * Execute ALTER EXTENSION UPDATE
2672  */
2673 ObjectAddress
2674 ExecAlterExtensionStmt(AlterExtensionStmt *stmt)
2675 {
2676         DefElem    *d_new_version = NULL;
2677         char       *versionName;
2678         char       *oldVersionName;
2679         ExtensionControlFile *control;
2680         Oid                     extensionOid;
2681         Relation        extRel;
2682         ScanKeyData key[1];
2683         SysScanDesc extScan;
2684         HeapTuple       extTup;
2685         List       *updateVersions;
2686         Datum           datum;
2687         bool            isnull;
2688         ListCell   *lc;
2689         ObjectAddress address;
2690
2691         /*
2692          * We use global variables to track the extension being created, so we can
2693          * create/update only one extension at the same time.
2694          */
2695         if (creating_extension)
2696                 ereport(ERROR,
2697                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2698                                  errmsg("nested ALTER EXTENSION is not supported")));
2699
2700         /*
2701          * Look up the extension --- it must already exist in pg_extension
2702          */
2703         extRel = heap_open(ExtensionRelationId, AccessShareLock);
2704
2705         ScanKeyInit(&key[0],
2706                                 Anum_pg_extension_extname,
2707                                 BTEqualStrategyNumber, F_NAMEEQ,
2708                                 CStringGetDatum(stmt->extname));
2709
2710         extScan = systable_beginscan(extRel, ExtensionNameIndexId, true,
2711                                                                  NULL, 1, key);
2712
2713         extTup = systable_getnext(extScan);
2714
2715         if (!HeapTupleIsValid(extTup))
2716                 ereport(ERROR,
2717                                 (errcode(ERRCODE_UNDEFINED_OBJECT),
2718                                  errmsg("extension \"%s\" does not exist",
2719                                                 stmt->extname)));
2720
2721         extensionOid = HeapTupleGetOid(extTup);
2722
2723         /*
2724          * Determine the existing version we are updating from
2725          */
2726         datum = heap_getattr(extTup, Anum_pg_extension_extversion,
2727                                                  RelationGetDescr(extRel), &isnull);
2728         if (isnull)
2729                 elog(ERROR, "extversion is null");
2730         oldVersionName = text_to_cstring(DatumGetTextPP(datum));
2731
2732         systable_endscan(extScan);
2733
2734         heap_close(extRel, AccessShareLock);
2735
2736         /* Permission check: must own extension */
2737         if (!pg_extension_ownercheck(extensionOid, GetUserId()))
2738                 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_EXTENSION,
2739                                            stmt->extname);
2740
2741         /*
2742          * Read the primary control file.  Note we assume that it does not contain
2743          * any non-ASCII data, so there is no need to worry about encoding at this
2744          * point.
2745          */
2746         control = read_extension_control_file(stmt->extname);
2747
2748         /*
2749          * Read the statement option list
2750          */
2751         foreach(lc, stmt->options)
2752         {
2753                 DefElem    *defel = (DefElem *) lfirst(lc);
2754
2755                 if (strcmp(defel->defname, "new_version") == 0)
2756                 {
2757                         if (d_new_version)
2758                                 ereport(ERROR,
2759                                                 (errcode(ERRCODE_SYNTAX_ERROR),
2760                                                  errmsg("conflicting or redundant options")));
2761                         d_new_version = defel;
2762                 }
2763                 else
2764                         elog(ERROR, "unrecognized option: %s", defel->defname);
2765         }
2766
2767         /*
2768          * Determine the version to update to
2769          */
2770         if (d_new_version && d_new_version->arg)
2771                 versionName = strVal(d_new_version->arg);
2772         else if (control->default_version)
2773                 versionName = control->default_version;
2774         else
2775         {
2776                 ereport(ERROR,
2777                                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2778                                  errmsg("version to install must be specified")));
2779                 versionName = NULL;             /* keep compiler quiet */
2780         }
2781         check_valid_version_name(versionName);
2782
2783         /*
2784          * If we're already at that version, just say so
2785          */
2786         if (strcmp(oldVersionName, versionName) == 0)
2787         {
2788                 ereport(NOTICE,
2789                    (errmsg("version \"%s\" of extension \"%s\" is already installed",
2790                                    versionName, stmt->extname)));
2791                 return InvalidObjectAddress;
2792         }
2793
2794         /*
2795          * Identify the series of update script files we need to execute
2796          */
2797         updateVersions = identify_update_path(control,
2798                                                                                   oldVersionName,
2799                                                                                   versionName);
2800
2801         /*
2802          * Update the pg_extension row and execute the update scripts, one at a
2803          * time
2804          */
2805         ApplyExtensionUpdates(extensionOid, control,
2806                                                   oldVersionName, updateVersions);
2807
2808         ObjectAddressSet(address, ExtensionRelationId, extensionOid);
2809
2810         return address;
2811 }
2812
2813 /*
2814  * Apply a series of update scripts as though individual ALTER EXTENSION
2815  * UPDATE commands had been given, including altering the pg_extension row
2816  * and dependencies each time.
2817  *
2818  * This might be more work than necessary, but it ensures that old update
2819  * scripts don't break if newer versions have different control parameters.
2820  */
2821 static void
2822 ApplyExtensionUpdates(Oid extensionOid,
2823                                           ExtensionControlFile *pcontrol,
2824                                           const char *initialVersion,
2825                                           List *updateVersions)
2826 {
2827         const char *oldVersionName = initialVersion;
2828         ListCell   *lcv;
2829
2830         foreach(lcv, updateVersions)
2831         {
2832                 char       *versionName = (char *) lfirst(lcv);
2833                 ExtensionControlFile *control;
2834                 char       *schemaName;
2835                 Oid                     schemaOid;
2836                 List       *requiredExtensions;
2837                 List       *requiredSchemas;
2838                 Relation        extRel;
2839                 ScanKeyData key[1];
2840                 SysScanDesc extScan;
2841                 HeapTuple       extTup;
2842                 Form_pg_extension extForm;
2843                 Datum           values[Natts_pg_extension];
2844                 bool            nulls[Natts_pg_extension];
2845                 bool            repl[Natts_pg_extension];
2846                 ObjectAddress myself;
2847                 ListCell   *lc;
2848
2849                 /*
2850                  * Fetch parameters for specific version (pcontrol is not changed)
2851                  */
2852                 control = read_extension_aux_control_file(pcontrol, versionName);
2853
2854                 /* Find the pg_extension tuple */
2855                 extRel = heap_open(ExtensionRelationId, RowExclusiveLock);
2856
2857                 ScanKeyInit(&key[0],
2858                                         ObjectIdAttributeNumber,
2859                                         BTEqualStrategyNumber, F_OIDEQ,
2860                                         ObjectIdGetDatum(extensionOid));
2861
2862                 extScan = systable_beginscan(extRel, ExtensionOidIndexId, true,
2863                                                                          NULL, 1, key);
2864
2865                 extTup = systable_getnext(extScan);
2866
2867                 if (!HeapTupleIsValid(extTup))  /* should not happen */
2868                         elog(ERROR, "extension with oid %u does not exist",
2869                                  extensionOid);
2870
2871                 extForm = (Form_pg_extension) GETSTRUCT(extTup);
2872
2873                 /*
2874                  * Determine the target schema (set by original install)
2875                  */
2876                 schemaOid = extForm->extnamespace;
2877                 schemaName = get_namespace_name(schemaOid);
2878
2879                 /*
2880                  * Modify extrelocatable and extversion in the pg_extension tuple
2881                  */
2882                 memset(values, 0, sizeof(values));
2883                 memset(nulls, 0, sizeof(nulls));
2884                 memset(repl, 0, sizeof(repl));
2885
2886                 values[Anum_pg_extension_extrelocatable - 1] =
2887                         BoolGetDatum(control->relocatable);
2888                 repl[Anum_pg_extension_extrelocatable - 1] = true;
2889                 values[Anum_pg_extension_extversion - 1] =
2890                         CStringGetTextDatum(versionName);
2891                 repl[Anum_pg_extension_extversion - 1] = true;
2892
2893                 extTup = heap_modify_tuple(extTup, RelationGetDescr(extRel),
2894                                                                    values, nulls, repl);
2895
2896                 simple_heap_update(extRel, &extTup->t_self, extTup);
2897                 CatalogUpdateIndexes(extRel, extTup);
2898
2899                 systable_endscan(extScan);
2900
2901                 heap_close(extRel, RowExclusiveLock);
2902
2903                 /*
2904                  * Look up the prerequisite extensions for this version, and build
2905                  * lists of their OIDs and the OIDs of their target schemas.
2906                  */
2907                 requiredExtensions = NIL;
2908                 requiredSchemas = NIL;
2909                 foreach(lc, control->requires)
2910                 {
2911                         char       *curreq = (char *) lfirst(lc);
2912                         Oid                     reqext;
2913                         Oid                     reqschema;
2914
2915                         /*
2916                          * We intentionally don't use get_extension_oid's default error
2917                          * message here, because it would be confusing in this context.
2918                          */
2919                         reqext = get_extension_oid(curreq, true);
2920                         if (!OidIsValid(reqext))
2921                                 ereport(ERROR,
2922                                                 (errcode(ERRCODE_UNDEFINED_OBJECT),
2923                                                  errmsg("required extension \"%s\" is not installed",
2924                                                                 curreq)));
2925                         reqschema = get_extension_schema(reqext);
2926                         requiredExtensions = lappend_oid(requiredExtensions, reqext);
2927                         requiredSchemas = lappend_oid(requiredSchemas, reqschema);
2928                 }
2929
2930                 /*
2931                  * Remove and recreate dependencies on prerequisite extensions
2932                  */
2933                 deleteDependencyRecordsForClass(ExtensionRelationId, extensionOid,
2934                                                                                 ExtensionRelationId,
2935                                                                                 DEPENDENCY_NORMAL);
2936
2937                 myself.classId = ExtensionRelationId;
2938                 myself.objectId = extensionOid;
2939                 myself.objectSubId = 0;
2940
2941                 foreach(lc, requiredExtensions)
2942                 {
2943                         Oid                     reqext = lfirst_oid(lc);
2944                         ObjectAddress otherext;
2945
2946                         otherext.classId = ExtensionRelationId;
2947                         otherext.objectId = reqext;
2948                         otherext.objectSubId = 0;
2949
2950                         recordDependencyOn(&myself, &otherext, DEPENDENCY_NORMAL);
2951                 }
2952
2953                 InvokeObjectPostAlterHook(ExtensionRelationId, extensionOid, 0);
2954
2955                 /*
2956                  * Finally, execute the update script file
2957                  */
2958                 execute_extension_script(extensionOid, control,
2959                                                                  oldVersionName, versionName,
2960                                                                  requiredSchemas,
2961                                                                  schemaName, schemaOid);
2962
2963                 /*
2964                  * Update prior-version name and loop around.  Since
2965                  * execute_sql_string did a final CommandCounterIncrement, we can
2966                  * update the pg_extension row again.
2967                  */
2968                 oldVersionName = versionName;
2969         }
2970 }
2971
2972 /*
2973  * Execute ALTER EXTENSION ADD/DROP
2974  *
2975  * Return value is the address of the altered extension.
2976  *
2977  * objAddr is an output argument which, if not NULL, is set to the address of
2978  * the added/dropped object.
2979  */
2980 ObjectAddress
2981 ExecAlterExtensionContentsStmt(AlterExtensionContentsStmt *stmt,
2982                                                            ObjectAddress *objAddr)
2983 {
2984         ObjectAddress extension;
2985         ObjectAddress object;
2986         Relation        relation;
2987         Oid                     oldExtension;
2988
2989         extension.classId = ExtensionRelationId;
2990         extension.objectId = get_extension_oid(stmt->extname, false);
2991         extension.objectSubId = 0;
2992
2993         /* Permission check: must own extension */
2994         if (!pg_extension_ownercheck(extension.objectId, GetUserId()))
2995                 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_EXTENSION,
2996                                            stmt->extname);
2997
2998         /*
2999          * Translate the parser representation that identifies the object into an
3000          * ObjectAddress.  get_object_address() will throw an error if the object
3001          * does not exist, and will also acquire a lock on the object to guard
3002          * against concurrent DROP and ALTER EXTENSION ADD/DROP operations.
3003          */
3004         object = get_object_address(stmt->objtype, stmt->objname, stmt->objargs,
3005                                                                 &relation, ShareUpdateExclusiveLock, false);
3006
3007         Assert(object.objectSubId == 0);
3008         if (objAddr)
3009                 *objAddr = object;
3010
3011         /* Permission check: must own target object, too */
3012         check_object_ownership(GetUserId(), stmt->objtype, object,
3013                                                    stmt->objname, stmt->objargs, relation);
3014
3015         /*
3016          * Check existing extension membership.
3017          */
3018         oldExtension = getExtensionOfObject(object.classId, object.objectId);
3019
3020         if (stmt->action > 0)
3021         {
3022                 /*
3023                  * ADD, so complain if object is already attached to some extension.
3024                  */
3025                 if (OidIsValid(oldExtension))
3026                         ereport(ERROR,
3027                                         (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
3028                                          errmsg("%s is already a member of extension \"%s\"",
3029                                                         getObjectDescription(&object),
3030                                                         get_extension_name(oldExtension))));
3031
3032                 /*
3033                  * Prevent a schema from being added to an extension if the schema
3034                  * contains the extension.  That would create a dependency loop.
3035                  */
3036                 if (object.classId == NamespaceRelationId &&
3037                         object.objectId == get_extension_schema(extension.objectId))
3038                         ereport(ERROR,
3039                                         (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
3040                                          errmsg("cannot add schema \"%s\" to extension \"%s\" "
3041                                                         "because the schema contains the extension",
3042                                                         get_namespace_name(object.objectId),
3043                                                         stmt->extname)));
3044
3045                 /*
3046                  * OK, add the dependency.
3047                  */
3048                 recordDependencyOn(&object, &extension, DEPENDENCY_EXTENSION);
3049         }
3050         else
3051         {
3052                 /*
3053                  * DROP, so complain if it's not a member.
3054                  */
3055                 if (oldExtension != extension.objectId)
3056                         ereport(ERROR,
3057                                         (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
3058                                          errmsg("%s is not a member of extension \"%s\"",
3059                                                         getObjectDescription(&object),
3060                                                         stmt->extname)));
3061
3062                 /*
3063                  * OK, drop the dependency.
3064                  */
3065                 if (deleteDependencyRecordsForClass(object.classId, object.objectId,
3066                                                                                         ExtensionRelationId,
3067                                                                                         DEPENDENCY_EXTENSION) != 1)
3068                         elog(ERROR, "unexpected number of extension dependency records");
3069
3070                 /*
3071                  * If it's a relation, it might have an entry in the extension's
3072                  * extconfig array, which we must remove.
3073                  */
3074                 if (object.classId == RelationRelationId)
3075                         extension_config_remove(extension.objectId, object.objectId);
3076         }
3077
3078         InvokeObjectPostAlterHook(ExtensionRelationId, extension.objectId, 0);
3079
3080         /*
3081          * If get_object_address() opened the relation for us, we close it to keep
3082          * the reference count correct - but we retain any locks acquired by
3083          * get_object_address() until commit time, to guard against concurrent
3084          * activity.
3085          */
3086         if (relation != NULL)
3087                 relation_close(relation, NoLock);
3088
3089         return extension;
3090 }
3091
3092 /*
3093  * Read the whole of file into memory.
3094  *
3095  * The file contents are returned as a single palloc'd chunk. For convenience
3096  * of the callers, an extra \0 byte is added to the end.
3097  */
3098 static char *
3099 read_whole_file(const char *filename, int *length)
3100 {
3101         char       *buf;
3102         FILE       *file;
3103         size_t          bytes_to_read;
3104         struct stat fst;
3105
3106         if (stat(filename, &fst) < 0)
3107                 ereport(ERROR,
3108                                 (errcode_for_file_access(),
3109                                  errmsg("could not stat file \"%s\": %m", filename)));
3110
3111         if (fst.st_size > (MaxAllocSize - 1))
3112                 ereport(ERROR,
3113                                 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
3114                                  errmsg("file \"%s\" is too large", filename)));
3115         bytes_to_read = (size_t) fst.st_size;
3116
3117         if ((file = AllocateFile(filename, PG_BINARY_R)) == NULL)
3118                 ereport(ERROR,
3119                                 (errcode_for_file_access(),
3120                                  errmsg("could not open file \"%s\" for reading: %m",
3121                                                 filename)));
3122
3123         buf = (char *) palloc(bytes_to_read + 1);
3124
3125         *length = fread(buf, 1, bytes_to_read, file);
3126
3127         if (ferror(file))
3128                 ereport(ERROR,
3129                                 (errcode_for_file_access(),
3130                                  errmsg("could not read file \"%s\": %m", filename)));
3131
3132         FreeFile(file);
3133
3134         buf[*length] = '\0';
3135         return buf;
3136 }