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