PostgreSQL Source Code git master
Loading...
Searching...
No Matches
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-2026, 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/table.h"
36#include "access/xact.h"
37#include "catalog/catalog.h"
38#include "catalog/dependency.h"
39#include "catalog/indexing.h"
40#include "catalog/namespace.h"
42#include "catalog/pg_authid.h"
44#include "catalog/pg_database.h"
45#include "catalog/pg_depend.h"
48#include "catalog/pg_proc.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/pg_list.h"
59#include "nodes/queryjumble.h"
60#include "storage/fd.h"
61#include "tcop/utility.h"
62#include "utils/acl.h"
63#include "utils/builtins.h"
64#include "utils/conffiles.h"
65#include "utils/fmgroids.h"
66#include "utils/inval.h"
67#include "utils/lsyscache.h"
68#include "utils/memutils.h"
69#include "utils/rel.h"
70#include "utils/snapmgr.h"
71#include "utils/syscache.h"
72#include "utils/tuplestore.h"
73#include "utils/varlena.h"
74
75
76/* GUC */
78
79/* Globally visible state variables */
80bool creating_extension = false;
82
83/*
84 * Internal data structure to hold the results of parsing a control file
85 */
87{
88 char *name; /* name of the extension */
89 char *basedir; /* base directory where control and script
90 * files are located */
91 char *control_dir; /* directory where control file was found */
92 char *directory; /* directory for script files */
93 char *default_version; /* default install target version, if any */
94 char *module_pathname; /* string to substitute for
95 * MODULE_PATHNAME */
96 char *comment; /* comment, if any */
97 char *schema; /* target schema (allowed if !relocatable) */
98 bool relocatable; /* is ALTER EXTENSION SET SCHEMA supported? */
99 bool superuser; /* must be superuser to install? */
100 bool trusted; /* allow becoming superuser on the fly? */
101 int encoding; /* encoding of the script file, or -1 */
102 List *requires; /* names of prerequisite extensions */
103 List *no_relocate; /* names of prerequisite extensions that
104 * should not be relocated */
106
107/*
108 * Internal data structure for update path information
109 */
111{
112 char *name; /* name of the starting version */
113 List *reachable; /* List of ExtensionVersionInfo's */
114 bool installable; /* does this version have an install script? */
115 /* working state for Dijkstra's algorithm: */
116 bool distance_known; /* is distance from start known yet? */
117 int distance; /* current worst-case distance estimate */
118 struct ExtensionVersionInfo *previous; /* current best predecessor */
120
121/*
122 * Information for script_error_callback()
123 */
124typedef struct
125{
126 const char *sql; /* entire script file contents */
127 const char *filename; /* script file pathname */
128 ParseLoc stmt_location; /* current stmt start loc, or -1 if unknown */
129 ParseLoc stmt_len; /* length in bytes; 0 means "rest of string" */
131
132/*
133 * A location based on the extension_control_path GUC.
134 *
135 * The macro field stores the name of a macro (for example “$system”) that
136 * the extension_control_path processing supports, and which can be replaced
137 * by a system value stored in loc.
138 *
139 * For non-system paths the macro field is NULL.
140 */
141typedef struct
142{
143 char *macro;
144 char *loc;
146
147/*
148 * Cache structure for get_function_sibling_type (and maybe later,
149 * allied lookup functions).
150 */
152{
153 struct ExtensionSiblingCache *next; /* list link */
154 /* lookup key: requesting function's OID and type name */
156 const char *typname;
157 bool valid; /* is entry currently valid? */
158 uint32 exthash; /* cache hash of owning extension's OID */
159 Oid typeoid; /* OID associated with typname */
161
162/* Head of linked list of ExtensionSiblingCache structs */
164
165/* Local functions */
167 uint32 hashvalue);
171 bool reject_indirect,
172 bool reinitialize);
174 char *extensionName,
175 char *origSchemaName,
176 bool cascade,
177 List *parents,
178 bool is_create);
180 Tuplestorestate *tupstore,
181 TupleDesc tupdesc,
182 ExtensionLocation *location);
183static Datum convert_requires_to_datum(List *requires);
186 const char *initialVersion,
188 char *origSchemaName,
189 bool cascade,
190 bool is_create);
193 ObjectAddress object);
194static char *read_whole_file(const char *filename, int *length);
195static ExtensionControlFile *new_ExtensionControlFile(const char *extname);
196
197char *find_in_paths(const char *basename, List *paths);
198
199/*
200 * Return the extension location. If the current user doesn't have sufficient
201 * privilege, don't show the location.
202 */
203static char *
205{
206 /* We only want to show extension paths for superusers. */
207 if (superuser())
208 {
209 /* Return the macro value if present to avoid showing system paths. */
210 if (loc->macro != NULL)
211 return loc->macro;
212 else
213 return loc->loc;
214 }
215 else
216 {
217 /* Similar to pg_stat_activity for unprivileged users */
218 return "<insufficient privilege>";
219 }
220}
221
222/*
223 * get_extension_oid - given an extension name, look up the OID
224 *
225 * If missing_ok is false, throw an error if extension name not found. If
226 * true, just return InvalidOid.
227 */
228Oid
229get_extension_oid(const char *extname, bool missing_ok)
230{
231 Oid result;
232
234 CStringGetDatum(extname));
235
236 if (!OidIsValid(result) && !missing_ok)
239 errmsg("extension \"%s\" does not exist",
240 extname)));
241
242 return result;
243}
244
245/*
246 * get_extension_name - given an extension OID, look up the name
247 *
248 * Returns a palloc'd string, or NULL if no such extension.
249 */
250char *
252{
253 char *result;
254 HeapTuple tuple;
255
257
258 if (!HeapTupleIsValid(tuple))
259 return NULL;
260
261 result = pstrdup(NameStr(((Form_pg_extension) GETSTRUCT(tuple))->extname));
262 ReleaseSysCache(tuple);
263
264 return result;
265}
266
267/*
268 * get_extension_schema - given an extension OID, fetch its extnamespace
269 *
270 * Returns InvalidOid if no such extension.
271 */
272Oid
274{
275 Oid result;
276 HeapTuple tuple;
277
279
280 if (!HeapTupleIsValid(tuple))
281 return InvalidOid;
282
283 result = ((Form_pg_extension) GETSTRUCT(tuple))->extnamespace;
284 ReleaseSysCache(tuple);
285
286 return result;
287}
288
289/*
290 * get_function_sibling_type - find a type belonging to same extension as func
291 *
292 * Returns the type's OID, or InvalidOid if not found.
293 *
294 * This is useful in extensions, which won't have fixed object OIDs.
295 * We work from the calling function's own OID, which it can get from its
296 * FunctionCallInfo parameter, and look up the owning extension and thence
297 * a type belonging to the same extension.
298 *
299 * Notice that the type is specified by name only, without a schema.
300 * That's because this will typically be used by relocatable extensions
301 * which can't make a-priori assumptions about which schema their objects
302 * are in. As long as the extension only defines one type of this name,
303 * the answer is unique anyway.
304 *
305 * We might later add the ability to look up functions, operators, etc.
306 *
307 * This code is simply a frontend for some pg_depend lookups. Those lookups
308 * are fairly expensive, so we provide a simple cache facility. We assume
309 * that the passed typname is actually a C constant, or at least permanently
310 * allocated, so that we need not copy that string.
311 */
312Oid
314{
316 Oid extoid;
317 Oid typeoid;
318
319 /*
320 * See if we have the answer cached. Someday there may be enough callers
321 * to justify a hash table, but for now, a simple linked list is fine.
322 */
325 {
326 if (funcoid == cache_entry->reqfuncoid &&
327 strcmp(typname, cache_entry->typname) == 0)
328 break;
329 }
330 if (cache_entry && cache_entry->valid)
331 return cache_entry->typeoid;
332
333 /*
334 * Nope, so do the expensive lookups. We do not expect failures, so we do
335 * not cache negative results.
336 */
338 if (!OidIsValid(extoid))
339 return InvalidOid;
341 if (!OidIsValid(typeoid))
342 return InvalidOid;
343
344 /*
345 * Build, or revalidate, cache entry.
346 */
347 if (cache_entry == NULL)
348 {
349 /* Register invalidation hook if this is first entry */
350 if (ext_sibling_list == NULL)
353 (Datum) 0);
354
355 /* Momentarily zero the space to ensure valid flag is false */
358 sizeof(ExtensionSiblingCache));
361 }
362
364 cache_entry->typname = typname;
367 cache_entry->typeoid = typeoid;
368 /* Mark it valid only once it's fully populated */
369 cache_entry->valid = true;
370
371 return typeoid;
372}
373
374/*
375 * ext_sibling_callback
376 * Syscache inval callback function for EXTENSIONOID cache
377 *
378 * It seems sufficient to invalidate ExtensionSiblingCache entries when
379 * the owning extension's pg_extension entry is modified or deleted.
380 * Neither a requesting function's OID, nor the OID of the object it's
381 * looking for, could change without an extension update or drop/recreate.
382 */
383static void
385{
387
390 {
391 if (hashvalue == 0 ||
392 cache_entry->exthash == hashvalue)
393 cache_entry->valid = false;
394 }
395}
396
397/*
398 * Utility functions to check validity of extension and version names
399 */
400static void
402{
403 int namelen = strlen(extensionname);
404
405 /*
406 * Disallow empty names (the parser rejects empty identifiers anyway, but
407 * let's check).
408 */
409 if (namelen == 0)
412 errmsg("invalid extension name: \"%s\"", extensionname),
413 errdetail("Extension names must not be empty.")));
414
415 /*
416 * No double dashes, since that would make script filenames ambiguous.
417 */
418 if (strstr(extensionname, "--"))
421 errmsg("invalid extension name: \"%s\"", extensionname),
422 errdetail("Extension names must not contain \"--\".")));
423
424 /*
425 * No leading or trailing dash either. (We could probably allow this, but
426 * it would require much care in filename parsing and would make filenames
427 * visually if not formally ambiguous. Since there's no real-world use
428 * case, let's just forbid it.)
429 */
430 if (extensionname[0] == '-' || extensionname[namelen - 1] == '-')
433 errmsg("invalid extension name: \"%s\"", extensionname),
434 errdetail("Extension names must not begin or end with \"-\".")));
435
436 /*
437 * No directory separators either (this is sufficient to prevent ".."
438 * style attacks).
439 */
443 errmsg("invalid extension name: \"%s\"", extensionname),
444 errdetail("Extension names must not contain directory separator characters.")));
445}
446
447static void
449{
450 int namelen = strlen(versionname);
451
452 /*
453 * Disallow empty names (we could possibly allow this, but there seems
454 * little point).
455 */
456 if (namelen == 0)
459 errmsg("invalid extension version name: \"%s\"", versionname),
460 errdetail("Version names must not be empty.")));
461
462 /*
463 * No double dashes, since that would make script filenames ambiguous.
464 */
465 if (strstr(versionname, "--"))
468 errmsg("invalid extension version name: \"%s\"", versionname),
469 errdetail("Version names must not contain \"--\".")));
470
471 /*
472 * No leading or trailing dash either.
473 */
474 if (versionname[0] == '-' || versionname[namelen - 1] == '-')
477 errmsg("invalid extension version name: \"%s\"", versionname),
478 errdetail("Version names must not begin or end with \"-\".")));
479
480 /*
481 * No directory separators either (this is sufficient to prevent ".."
482 * style attacks).
483 */
487 errmsg("invalid extension version name: \"%s\"", versionname),
488 errdetail("Version names must not contain directory separator characters.")));
489}
490
491/*
492 * Utility functions to handle extension-related path names
493 */
494static bool
496{
497 const char *extension = strrchr(filename, '.');
498
499 return (extension != NULL) && (strcmp(extension, ".control") == 0);
500}
501
502static bool
504{
505 const char *extension = strrchr(filename, '.');
506
507 return (extension != NULL) && (strcmp(extension, ".sql") == 0);
508}
509
510/*
511 * Return a list of directories declared in the extension_control_path GUC.
512 */
513static List *
515{
516 char sharepath[MAXPGPATH];
517 char *system_dir;
518 char *ecp;
519 List *paths = NIL;
520
522
523 system_dir = psprintf("%s/extension", sharepath);
524
526 {
528
529 location->macro = NULL;
530 location->loc = system_dir;
531 paths = lappend(paths, location);
532 }
533 else
534 {
535 /* Duplicate the string so we can modify it */
537
538 for (;;)
539 {
540 int len;
541 char *mangled;
544
545 /* Get the length of the next path on ecp */
546 if (piece == NULL)
547 len = strlen(ecp);
548 else
549 len = piece - ecp;
550
551 /* Copy the next path found on ecp */
552 piece = palloc(len + 1);
553 strlcpy(piece, ecp, len + 1);
554
555 /*
556 * Substitute the path macro if needed or append "extension"
557 * suffix if it is a custom extension control path.
558 */
559 if (strcmp(piece, "$system") == 0)
560 {
561 location->macro = pstrdup(piece);
563 }
564 else
565 {
566 location->macro = NULL;
567 mangled = psprintf("%s/extension", piece);
568 }
569 pfree(piece);
570
571 /* Canonicalize the path based on the OS and add to the list */
573 location->loc = mangled;
574 paths = lappend(paths, location);
575
576 /* Break if ecp is empty or move to the next path on ecp */
577 if (ecp[len] == '\0')
578 break;
579 else
580 ecp += len + 1;
581 }
582 }
583
584 return paths;
585}
586
587/*
588 * Find control file for extension with name in control->name, looking in
589 * available paths. Return the full file name, or NULL if not found.
590 * If found, the directory is recorded in control->control_dir.
591 */
592static char *
594{
595 char *basename;
596 char *result;
597 List *paths;
598
599 Assert(control->name);
600
601 basename = psprintf("%s.control", control->name);
602
604 result = find_in_paths(basename, paths);
605
606 if (result)
607 {
608 const char *p;
609
610 p = strrchr(result, '/');
611 Assert(p);
612 control->control_dir = pnstrdup(result, p - result);
613 }
614
615 return result;
616}
617
618static char *
620{
621 /*
622 * The directory parameter can be omitted, absolute, or relative to the
623 * installation's base directory, which can be the sharedir or a custom
624 * path that was set via extension_control_path. It depends on where the
625 * .control file was found.
626 */
627 if (!control->directory)
628 return pstrdup(control->control_dir);
629
630 if (is_absolute_path(control->directory))
631 return pstrdup(control->directory);
632
633 Assert(control->basedir != NULL);
634 return psprintf("%s/%s", control->basedir, control->directory);
635}
636
637static char *
639 const char *version)
640{
641 char *result;
642 char *scriptdir;
643
645
646 result = (char *) palloc(MAXPGPATH);
647 snprintf(result, MAXPGPATH, "%s/%s--%s.control",
648 scriptdir, control->name, version);
649
651
652 return result;
653}
654
655static char *
657 const char *from_version, const char *version)
658{
659 char *result;
660 char *scriptdir;
661
663
664 result = (char *) palloc(MAXPGPATH);
665 if (from_version)
666 snprintf(result, MAXPGPATH, "%s/%s--%s--%s.sql",
667 scriptdir, control->name, from_version, version);
668 else
669 snprintf(result, MAXPGPATH, "%s/%s--%s.sql",
670 scriptdir, control->name, version);
671
673
674 return result;
675}
676
677
678/*
679 * Parse contents of primary or auxiliary control file, and fill in
680 * fields of *control. We parse primary file if version == NULL,
681 * else the optional auxiliary file for that version.
682 *
683 * If control->control_dir is not NULL, use that to read and parse the
684 * control file, otherwise search for the file in extension_control_path.
685 *
686 * Control files are supposed to be very short, half a dozen lines,
687 * so we don't worry about memory allocation risks here. Also we don't
688 * worry about what encoding it's in; all values are expected to be ASCII.
689 */
690static void
692 const char *version)
693{
694 char *filename;
695 FILE *file;
696 ConfigVariable *item,
697 *head = NULL,
698 *tail = NULL;
699
700 /*
701 * Locate the file to read. Auxiliary files are optional.
702 */
703 if (version)
705 else
706 {
707 /*
708 * If control_dir is already set, use it, else do a path search.
709 */
710 if (control->control_dir)
711 {
712 filename = psprintf("%s/%s.control", control->control_dir, control->name);
713 }
714 else
716 }
717
718 if (!filename)
719 {
722 errmsg("extension \"%s\" is not available", control->name),
723 errhint("The extension must first be installed on the system where PostgreSQL is running.")));
724 }
725
726 /* Assert that the control_dir ends with /extension */
727 Assert(control->control_dir != NULL);
728 Assert(strcmp(control->control_dir + strlen(control->control_dir) - strlen("/extension"), "/extension") == 0);
729
730 control->basedir = pnstrdup(
731 control->control_dir,
732 strlen(control->control_dir) - strlen("/extension"));
733
734 if ((file = AllocateFile(filename, "r")) == NULL)
735 {
736 /* no complaint for missing auxiliary file */
737 if (errno == ENOENT && version)
738 {
740 return;
741 }
742
745 errmsg("could not open extension control file \"%s\": %m",
746 filename)));
747 }
748
749 /*
750 * Parse the file content, using GUC's file parsing code. We need not
751 * check the return value since any errors will be thrown at ERROR level.
752 */
754 &head, &tail);
755
756 FreeFile(file);
757
758 /*
759 * Convert the ConfigVariable list into ExtensionControlFile entries.
760 */
761 for (item = head; item != NULL; item = item->next)
762 {
763 if (strcmp(item->name, "directory") == 0)
764 {
765 if (version)
768 errmsg("parameter \"%s\" cannot be set in a secondary extension control file",
769 item->name)));
770
771 control->directory = pstrdup(item->value);
772 }
773 else if (strcmp(item->name, "default_version") == 0)
774 {
775 if (version)
778 errmsg("parameter \"%s\" cannot be set in a secondary extension control file",
779 item->name)));
780
781 control->default_version = pstrdup(item->value);
782 }
783 else if (strcmp(item->name, "module_pathname") == 0)
784 {
785 control->module_pathname = pstrdup(item->value);
786 }
787 else if (strcmp(item->name, "comment") == 0)
788 {
789 control->comment = pstrdup(item->value);
790 }
791 else if (strcmp(item->name, "schema") == 0)
792 {
793 control->schema = pstrdup(item->value);
794 }
795 else if (strcmp(item->name, "relocatable") == 0)
796 {
797 if (!parse_bool(item->value, &control->relocatable))
800 errmsg("parameter \"%s\" requires a Boolean value",
801 item->name)));
802 }
803 else if (strcmp(item->name, "superuser") == 0)
804 {
805 if (!parse_bool(item->value, &control->superuser))
808 errmsg("parameter \"%s\" requires a Boolean value",
809 item->name)));
810 }
811 else if (strcmp(item->name, "trusted") == 0)
812 {
813 if (!parse_bool(item->value, &control->trusted))
816 errmsg("parameter \"%s\" requires a Boolean value",
817 item->name)));
818 }
819 else if (strcmp(item->name, "encoding") == 0)
820 {
821 control->encoding = pg_valid_server_encoding(item->value);
822 if (control->encoding < 0)
825 errmsg("\"%s\" is not a valid encoding name",
826 item->value)));
827 }
828 else if (strcmp(item->name, "requires") == 0)
829 {
830 /* Need a modifiable copy of string */
831 char *rawnames = pstrdup(item->value);
832
833 /* Parse string into list of identifiers */
834 if (!SplitIdentifierString(rawnames, ',', &control->requires))
835 {
836 /* syntax error in name list */
839 errmsg("parameter \"%s\" must be a list of extension names",
840 item->name)));
841 }
842 }
843 else if (strcmp(item->name, "no_relocate") == 0)
844 {
845 /* Need a modifiable copy of string */
846 char *rawnames = pstrdup(item->value);
847
848 /* Parse string into list of identifiers */
849 if (!SplitIdentifierString(rawnames, ',', &control->no_relocate))
850 {
851 /* syntax error in name list */
854 errmsg("parameter \"%s\" must be a list of extension names",
855 item->name)));
856 }
857 }
858 else
861 errmsg("unrecognized parameter \"%s\" in file \"%s\"",
862 item->name, filename)));
863 }
864
866
867 if (control->relocatable && control->schema != NULL)
870 errmsg("parameter \"schema\" cannot be specified when \"relocatable\" is true")));
871
873}
874
875/*
876 * Read the primary control file for the specified extension.
877 */
879read_extension_control_file(const char *extname)
880{
882
883 /*
884 * Parse the primary control file.
885 */
887
888 return control;
889}
890
891/*
892 * Read the auxiliary control file for the specified extension and version.
893 *
894 * Returns a new modified ExtensionControlFile struct; the original struct
895 * (reflecting just the primary control file) is not modified.
896 */
899 const char *version)
900{
902
903 /*
904 * Flat-copy the struct. Pointer fields share values with original.
905 */
908
909 /*
910 * Parse the auxiliary control file, overwriting struct fields
911 */
913
914 return acontrol;
915}
916
917/*
918 * Read an SQL script file into a string, and convert to database encoding
919 */
920static char *
922 const char *filename)
923{
924 int src_encoding;
925 char *src_str;
926 char *dest_str;
927 int len;
928
930
931 /* use database encoding if not given */
932 if (control->encoding < 0)
934 else
935 src_encoding = control->encoding;
936
937 /* make sure that source string is valid in the expected encoding */
939
940 /*
941 * Convert the encoding to the database encoding. read_whole_file
942 * null-terminated the string, so if no conversion happens the string is
943 * valid as is.
944 */
946
947 return dest_str;
948}
949
950/*
951 * error context callback for failures in script-file execution
952 */
953static void
955{
957 const char *query = callback_arg->sql;
958 int location = callback_arg->stmt_location;
959 int len = callback_arg->stmt_len;
961 const char *lastslash;
962
963 /*
964 * If there is a syntax error position, convert to internal syntax error;
965 * otherwise report the current query as an item of context stack.
966 *
967 * Note: we'll provide no context except the filename if there's neither
968 * an error position nor any known current query. That shouldn't happen
969 * though: all errors reported during raw parsing should come with an
970 * error position.
971 */
973 if (syntaxerrposition > 0)
974 {
975 /*
976 * If we do not know the bounds of the current statement (as would
977 * happen for an error occurring during initial raw parsing), we have
978 * to use a heuristic to decide how much of the script to show. We'll
979 * also use the heuristic in the unlikely case that syntaxerrposition
980 * is outside what we think the statement bounds are.
981 */
982 if (location < 0 || syntaxerrposition < location ||
983 (len > 0 && syntaxerrposition > location + len))
984 {
985 /*
986 * Our heuristic is pretty simple: look for semicolon-newline
987 * sequences, and break at the last one strictly before
988 * syntaxerrposition and the first one strictly after. It's
989 * certainly possible to fool this with semicolon-newline embedded
990 * in a string literal, but it seems better to do this than to
991 * show the entire extension script.
992 *
993 * Notice we cope with Windows-style newlines (\r\n) regardless of
994 * platform. This is because there might be such newlines in
995 * script files on other platforms.
996 */
997 int slen = strlen(query);
998
999 location = len = 0;
1000 for (int loc = 0; loc < slen; loc++)
1001 {
1002 if (query[loc] != ';')
1003 continue;
1004 if (query[loc + 1] == '\r')
1005 loc++;
1006 if (query[loc + 1] == '\n')
1007 {
1008 int bkpt = loc + 2;
1009
1010 if (bkpt < syntaxerrposition)
1011 location = bkpt;
1012 else if (bkpt > syntaxerrposition)
1013 {
1014 len = bkpt - location;
1015 break; /* no need to keep searching */
1016 }
1017 }
1018 }
1019 }
1020
1021 /* Trim leading/trailing whitespace, for consistency */
1022 query = CleanQuerytext(query, &location, &len);
1023
1024 /*
1025 * Adjust syntaxerrposition. It shouldn't be pointing into the
1026 * whitespace we just trimmed, but cope if it is.
1027 */
1028 syntaxerrposition -= location;
1029 if (syntaxerrposition < 0)
1031 else if (syntaxerrposition > len)
1033
1034 /* And report. */
1035 errposition(0);
1037 internalerrquery(pnstrdup(query, len));
1038 }
1039 else if (location >= 0)
1040 {
1041 /*
1042 * Since no syntax cursor will be shown, it's okay and helpful to trim
1043 * the reported query string to just the current statement.
1044 */
1045 query = CleanQuerytext(query, &location, &len);
1046 errcontext("SQL statement \"%.*s\"", len, query);
1047 }
1048
1049 /*
1050 * Trim the reported file name to remove the path. We know that
1051 * get_extension_script_filename() inserted a '/', regardless of whether
1052 * we're on Windows.
1053 */
1054 lastslash = strrchr(callback_arg->filename, '/');
1055 if (lastslash)
1056 lastslash++;
1057 else
1058 lastslash = callback_arg->filename; /* shouldn't happen, but cope */
1059
1060 /*
1061 * If we have a location (which, as said above, we really always should)
1062 * then report a line number to aid in localizing problems in big scripts.
1063 */
1064 if (location >= 0)
1065 {
1066 int linenumber = 1;
1067
1068 for (query = callback_arg->sql; *query; query++)
1069 {
1070 if (--location < 0)
1071 break;
1072 if (*query == '\n')
1073 linenumber++;
1074 }
1075 errcontext("extension script file \"%s\", near line %d",
1076 lastslash, linenumber);
1077 }
1078 else
1079 errcontext("extension script file \"%s\"", lastslash);
1080}
1081
1082/*
1083 * Execute given SQL string.
1084 *
1085 * The filename the string came from is also provided, for error reporting.
1086 *
1087 * Note: it's tempting to just use SPI to execute the string, but that does
1088 * not work very well. The really serious problem is that SPI will parse,
1089 * analyze, and plan the whole string before executing any of it; of course
1090 * this fails if there are any plannable statements referring to objects
1091 * created earlier in the script. A lesser annoyance is that SPI insists
1092 * on printing the whole string as errcontext in case of any error, and that
1093 * could be very long.
1094 */
1095static void
1096execute_sql_string(const char *sql, const char *filename)
1097{
1098 script_error_callback_arg callback_arg;
1101 DestReceiver *dest;
1102 ListCell *lc1;
1103
1104 /*
1105 * Setup error traceback support for ereport().
1106 */
1107 callback_arg.sql = sql;
1108 callback_arg.filename = filename;
1109 callback_arg.stmt_location = -1;
1110 callback_arg.stmt_len = -1;
1111
1113 scripterrcontext.arg = &callback_arg;
1116
1117 /*
1118 * Parse the SQL string into a list of raw parse trees.
1119 */
1121
1122 /* All output from SELECTs goes to the bit bucket */
1124
1125 /*
1126 * Do parse analysis, rule rewrite, planning, and execution for each raw
1127 * parsetree. We must fully execute each query before beginning parse
1128 * analysis on the next one, since there may be interdependencies.
1129 */
1130 foreach(lc1, raw_parsetree_list)
1131 {
1132 RawStmt *parsetree = lfirst_node(RawStmt, lc1);
1134 oldcontext;
1135 List *stmt_list;
1136 ListCell *lc2;
1137
1138 /* Report location of this query for error context callback */
1139 callback_arg.stmt_location = parsetree->stmt_location;
1140 callback_arg.stmt_len = parsetree->stmt_len;
1141
1142 /*
1143 * We do the work for each parsetree in a short-lived context, to
1144 * limit the memory used when there are many commands in the string.
1145 */
1148 "execute_sql_string per-statement context",
1151
1152 /* Be sure parser can see any DDL done so far */
1154
1155 stmt_list = pg_analyze_and_rewrite_fixedparams(parsetree,
1156 sql,
1157 NULL,
1158 0,
1159 NULL);
1160 stmt_list = pg_plan_queries(stmt_list, sql, CURSOR_OPT_PARALLEL_OK, NULL);
1161
1162 foreach(lc2, stmt_list)
1163 {
1165
1167
1169
1170 if (stmt->utilityStmt == NULL)
1171 {
1173
1175 sql,
1177 dest, NULL, NULL, 0);
1178
1179 ExecutorStart(qdesc, 0);
1183
1185 }
1186 else
1187 {
1188 if (IsA(stmt->utilityStmt, TransactionStmt))
1189 ereport(ERROR,
1191 errmsg("transaction control statements are not allowed within an extension script")));
1192
1194 sql,
1195 false,
1197 NULL,
1198 NULL,
1199 dest,
1200 NULL);
1201 }
1202
1204 }
1205
1206 /* Clean up per-parsetree context. */
1207 MemoryContextSwitchTo(oldcontext);
1209 }
1210
1212
1213 /* Be sure to advance the command counter after the last script command */
1215}
1216
1217/*
1218 * Policy function: is the given extension trusted for installation by a
1219 * non-superuser?
1220 *
1221 * (Update the errhint logic below if you change this.)
1222 */
1223static bool
1225{
1227
1228 /* Never trust unless extension's control file says it's okay */
1229 if (!control->trusted)
1230 return false;
1231 /* Allow if user has CREATE privilege on current database */
1233 if (aclresult == ACLCHECK_OK)
1234 return true;
1235 return false;
1236}
1237
1238/*
1239 * Execute the appropriate script file for installing or updating the extension
1240 *
1241 * If from_version isn't NULL, it's an update
1242 *
1243 * Note: requiredSchemas must be one-for-one with the control->requires list
1244 */
1245static void
1247 const char *from_version,
1248 const char *version,
1250 const char *schemaName)
1251{
1252 bool switch_to_superuser = false;
1253 char *filename;
1254 Oid save_userid = 0;
1255 int save_sec_context = 0;
1256 int save_nestlevel;
1258 ListCell *lc;
1259 ListCell *lc2;
1260
1261 /*
1262 * Enforce superuser-ness if appropriate. We postpone these checks until
1263 * here so that the control flags are correctly associated with the right
1264 * script(s) if they happen to be set in secondary control files.
1265 */
1266 if (control->superuser && !superuser())
1267 {
1268 if (extension_is_trusted(control))
1269 switch_to_superuser = true;
1270 else if (from_version == NULL)
1271 ereport(ERROR,
1273 errmsg("permission denied to create extension \"%s\"",
1274 control->name),
1275 control->trusted
1276 ? errhint("Must have CREATE privilege on current database to create this extension.")
1277 : errhint("Must be superuser to create this extension.")));
1278 else
1279 ereport(ERROR,
1281 errmsg("permission denied to update extension \"%s\"",
1282 control->name),
1283 control->trusted
1284 ? errhint("Must have CREATE privilege on current database to update this extension.")
1285 : errhint("Must be superuser to update this extension.")));
1286 }
1287
1289
1290 if (from_version == NULL)
1291 elog(DEBUG1, "executing extension script for \"%s\" version '%s'", control->name, version);
1292 else
1293 elog(DEBUG1, "executing extension script for \"%s\" update from version '%s' to '%s'", control->name, from_version, version);
1294
1295 /*
1296 * If installing a trusted extension on behalf of a non-superuser, become
1297 * the bootstrap superuser. (This switch will be cleaned up automatically
1298 * if the transaction aborts, as will the GUC changes below.)
1299 */
1301 {
1302 GetUserIdAndSecContext(&save_userid, &save_sec_context);
1304 save_sec_context | SECURITY_LOCAL_USERID_CHANGE);
1305 }
1306
1307 /*
1308 * Force client_min_messages and log_min_messages to be at least WARNING,
1309 * so that we won't spam the user with useless NOTICE messages from common
1310 * script actions like creating shell types.
1311 *
1312 * We use the equivalent of a function SET option to allow the setting to
1313 * persist for exactly the duration of the script execution. guc.c also
1314 * takes care of undoing the setting on error.
1315 *
1316 * log_min_messages can't be set by ordinary users, so for that one we
1317 * pretend to be superuser.
1318 */
1319 save_nestlevel = NewGUCNestLevel();
1320
1322 (void) set_config_option("client_min_messages", "warning",
1324 GUC_ACTION_SAVE, true, 0, false);
1326 (void) set_config_option_ext("log_min_messages", "warning",
1329 GUC_ACTION_SAVE, true, 0, false);
1330
1331 /*
1332 * Similarly disable check_function_bodies, to ensure that SQL functions
1333 * won't be parsed during creation.
1334 */
1336 (void) set_config_option("check_function_bodies", "off",
1338 GUC_ACTION_SAVE, true, 0, false);
1339
1340 /*
1341 * Set up the search path to have the target schema first, making it be
1342 * the default creation target namespace. Then add the schemas of any
1343 * prerequisite extensions, unless they are in pg_catalog which would be
1344 * searched anyway. (Listing pg_catalog explicitly in a non-first
1345 * position would be bad for security.) Finally add pg_temp to ensure
1346 * that temp objects can't take precedence over others.
1347 */
1350 foreach(lc, requiredSchemas)
1351 {
1354
1355 if (reqname && strcmp(reqname, "pg_catalog") != 0)
1357 }
1358 appendStringInfoString(&pathbuf, ", pg_temp");
1359
1360 (void) set_config_option("search_path", pathbuf.data,
1362 GUC_ACTION_SAVE, true, 0, false);
1363
1364 /*
1365 * Set creating_extension and related variables so that
1366 * recordDependencyOnCurrentExtension and other functions do the right
1367 * things. On failure, ensure we reset these variables.
1368 */
1369 creating_extension = true;
1371 PG_TRY();
1372 {
1373 char *c_sql = read_extension_script_file(control, filename);
1374 Datum t_sql;
1375
1376 /*
1377 * We filter each substitution through quote_identifier(). When the
1378 * arg contains one of the following characters, no one collection of
1379 * quoting can work inside $$dollar-quoted string literals$$,
1380 * 'single-quoted string literals', and outside of any literal. To
1381 * avoid a security snare for extension authors, error on substitution
1382 * for arguments containing these.
1383 */
1384 const char *quoting_relevant_chars = "\"$'\\";
1385
1386 /* We use various functions that want to operate on text datums */
1388
1389 /*
1390 * Reduce any lines beginning with "\echo" to empty. This allows
1391 * scripts to contain messages telling people not to run them via
1392 * psql, which has been found to be necessary due to old habits.
1393 */
1396 t_sql,
1397 CStringGetTextDatum("^\\\\echo.*$"),
1399 CStringGetTextDatum("ng"));
1400
1401 /*
1402 * If the script uses @extowner@, substitute the calling username.
1403 */
1404 if (strstr(c_sql, "@extowner@"))
1405 {
1406 Oid uid = switch_to_superuser ? save_userid : GetUserId();
1407 const char *userName = GetUserNameFromId(uid, false);
1408 const char *qUserName = quote_identifier(userName);
1409
1412 t_sql,
1413 CStringGetTextDatum("@extowner@"),
1416 ereport(ERROR,
1418 errmsg("invalid character in extension owner: must not contain any of \"%s\"",
1420 }
1421
1422 /*
1423 * If it's not relocatable, substitute the target schema name for
1424 * occurrences of @extschema@.
1425 *
1426 * For a relocatable extension, we needn't do this. There cannot be
1427 * any need for @extschema@, else it wouldn't be relocatable.
1428 */
1429 if (!control->relocatable)
1430 {
1431 Datum old = t_sql;
1433
1436 t_sql,
1437 CStringGetTextDatum("@extschema@"),
1440 ereport(ERROR,
1442 errmsg("invalid character in extension \"%s\" schema: must not contain any of \"%s\"",
1443 control->name, quoting_relevant_chars)));
1444 }
1445
1446 /*
1447 * Likewise, substitute required extensions' schema names for
1448 * occurrences of @extschema:extension_name@.
1449 */
1450 Assert(list_length(control->requires) == list_length(requiredSchemas));
1451 forboth(lc, control->requires, lc2, requiredSchemas)
1452 {
1453 Datum old = t_sql;
1454 char *reqextname = (char *) lfirst(lc);
1458 char *repltoken;
1459
1460 repltoken = psprintf("@extschema:%s@", reqextname);
1463 t_sql,
1467 ereport(ERROR,
1469 errmsg("invalid character in extension \"%s\" schema: must not contain any of \"%s\"",
1471 }
1472
1473 /*
1474 * If module_pathname was set in the control file, substitute its
1475 * value for occurrences of MODULE_PATHNAME.
1476 */
1477 if (control->module_pathname)
1478 {
1481 t_sql,
1482 CStringGetTextDatum("MODULE_PATHNAME"),
1484 }
1485
1486 /* And now back to C string */
1488
1490 }
1491 PG_FINALLY();
1492 {
1493 creating_extension = false;
1495 }
1496 PG_END_TRY();
1497
1498 /*
1499 * Restore the GUC variables we set above.
1500 */
1501 AtEOXact_GUC(true, save_nestlevel);
1502
1503 /*
1504 * Restore authentication state if needed.
1505 */
1507 SetUserIdAndSecContext(save_userid, save_sec_context);
1508}
1509
1510/*
1511 * Find or create an ExtensionVersionInfo for the specified version name
1512 *
1513 * Currently, we just use a List of the ExtensionVersionInfo's. Searching
1514 * for them therefore uses about O(N^2) time when there are N versions of
1515 * the extension. We could change the data structure to a hash table if
1516 * this ever becomes a bottleneck.
1517 */
1518static ExtensionVersionInfo *
1520{
1522 ListCell *lc;
1523
1524 foreach(lc, *evi_list)
1525 {
1527 if (strcmp(evi->name, versionname) == 0)
1528 return evi;
1529 }
1530
1532 evi->name = pstrdup(versionname);
1533 evi->reachable = NIL;
1534 evi->installable = false;
1535 /* initialize for later application of Dijkstra's algorithm */
1536 evi->distance_known = false;
1537 evi->distance = INT_MAX;
1538 evi->previous = NULL;
1539
1541
1542 return evi;
1543}
1544
1545/*
1546 * Locate the nearest unprocessed ExtensionVersionInfo
1547 *
1548 * This part of the algorithm is also about O(N^2). A priority queue would
1549 * make it much faster, but for now there's no need.
1550 */
1551static ExtensionVersionInfo *
1553{
1555 ListCell *lc;
1556
1557 foreach(lc, evi_list)
1558 {
1560
1561 /* only vertices whose distance is still uncertain are candidates */
1562 if (evi2->distance_known)
1563 continue;
1564 /* remember the closest such vertex */
1565 if (evi == NULL ||
1566 evi->distance > evi2->distance)
1567 evi = evi2;
1568 }
1569
1570 return evi;
1571}
1572
1573/*
1574 * Obtain information about the set of update scripts available for the
1575 * specified extension. The result is a List of ExtensionVersionInfo
1576 * structs, each with a subsidiary list of the ExtensionVersionInfos for
1577 * the versions that can be reached in one step from that version.
1578 */
1579static List *
1581{
1582 List *evi_list = NIL;
1583 int extnamelen = strlen(control->name);
1584 char *location;
1585 DIR *dir;
1586 struct dirent *de;
1587
1588 location = get_extension_script_directory(control);
1589 dir = AllocateDir(location);
1590 while ((de = ReadDir(dir, location)) != NULL)
1591 {
1592 char *vername;
1593 char *vername2;
1596
1597 /* must be a .sql file ... */
1598 if (!is_extension_script_filename(de->d_name))
1599 continue;
1600
1601 /* ... matching extension name followed by separator */
1602 if (strncmp(de->d_name, control->name, extnamelen) != 0 ||
1603 de->d_name[extnamelen] != '-' ||
1604 de->d_name[extnamelen + 1] != '-')
1605 continue;
1606
1607 /* extract version name(s) from 'extname--something.sql' filename */
1608 vername = pstrdup(de->d_name + extnamelen + 2);
1609 *strrchr(vername, '.') = '\0';
1610 vername2 = strstr(vername, "--");
1611 if (!vername2)
1612 {
1613 /* It's an install, not update, script; record its version name */
1615 evi->installable = true;
1616 continue;
1617 }
1618 *vername2 = '\0'; /* terminate first version */
1619 vername2 += 2; /* and point to second */
1620
1621 /* if there's a third --, it's bogus, ignore it */
1622 if (strstr(vername2, "--"))
1623 continue;
1624
1625 /* Create ExtensionVersionInfos and link them together */
1628 evi->reachable = lappend(evi->reachable, evi2);
1629 }
1630 FreeDir(dir);
1631
1632 return evi_list;
1633}
1634
1635/*
1636 * Given an initial and final version name, identify the sequence of update
1637 * scripts that have to be applied to perform that update.
1638 *
1639 * Result is a List of names of versions to transition through (the initial
1640 * version is *not* included).
1641 */
1642static List *
1644 const char *oldVersion, const char *newVersion)
1645{
1646 List *result;
1647 List *evi_list;
1650
1651 /* Extract the version update graph from the script directory */
1652 evi_list = get_ext_ver_list(control);
1653
1654 /* Initialize start and end vertices */
1657
1658 /* Find shortest path */
1659 result = find_update_path(evi_list, evi_start, evi_target, false, false);
1660
1661 if (result == NIL)
1662 ereport(ERROR,
1664 errmsg("extension \"%s\" has no update path from version \"%s\" to version \"%s\"",
1665 control->name, oldVersion, newVersion)));
1666
1667 return result;
1668}
1669
1670/*
1671 * Apply Dijkstra's algorithm to find the shortest path from evi_start to
1672 * evi_target.
1673 *
1674 * If reject_indirect is true, ignore paths that go through installable
1675 * versions. This saves work when the caller will consider starting from
1676 * all installable versions anyway.
1677 *
1678 * If reinitialize is false, assume the ExtensionVersionInfo list has not
1679 * been used for this before, and the initialization done by get_ext_ver_info
1680 * is still good. Otherwise, reinitialize all transient fields used here.
1681 *
1682 * Result is a List of names of versions to transition through (the initial
1683 * version is *not* included). Returns NIL if no such path.
1684 */
1685static List *
1689 bool reject_indirect,
1690 bool reinitialize)
1691{
1692 List *result;
1694 ListCell *lc;
1695
1696 /* Caller error if start == target */
1698 /* Caller error if reject_indirect and target is installable */
1699 Assert(!(reject_indirect && evi_target->installable));
1700
1701 if (reinitialize)
1702 {
1703 foreach(lc, evi_list)
1704 {
1706 evi->distance_known = false;
1707 evi->distance = INT_MAX;
1708 evi->previous = NULL;
1709 }
1710 }
1711
1712 evi_start->distance = 0;
1713
1715 {
1716 if (evi->distance == INT_MAX)
1717 break; /* all remaining vertices are unreachable */
1718 evi->distance_known = true;
1719 if (evi == evi_target)
1720 break; /* found shortest path to target */
1721 foreach(lc, evi->reachable)
1722 {
1724 int newdist;
1725
1726 /* if reject_indirect, treat installable versions as unreachable */
1727 if (reject_indirect && evi2->installable)
1728 continue;
1729 newdist = evi->distance + 1;
1730 if (newdist < evi2->distance)
1731 {
1732 evi2->distance = newdist;
1733 evi2->previous = evi;
1734 }
1735 else if (newdist == evi2->distance &&
1736 evi2->previous != NULL &&
1737 strcmp(evi->name, evi2->previous->name) < 0)
1738 {
1739 /*
1740 * Break ties in favor of the version name that comes first
1741 * according to strcmp(). This behavior is undocumented and
1742 * users shouldn't rely on it. We do it just to ensure that
1743 * if there is a tie, the update path that is chosen does not
1744 * depend on random factors like the order in which directory
1745 * entries get visited.
1746 */
1747 evi2->previous = evi;
1748 }
1749 }
1750 }
1751
1752 /* Return NIL if target is not reachable from start */
1753 if (!evi_target->distance_known)
1754 return NIL;
1755
1756 /* Build and return list of version names representing the update path */
1757 result = NIL;
1758 for (evi = evi_target; evi != evi_start; evi = evi->previous)
1759 result = lcons(evi->name, result);
1760
1761 return result;
1762}
1763
1764/*
1765 * Given a target version that is not directly installable, find the
1766 * best installation sequence starting from a directly-installable version.
1767 *
1768 * evi_list: previously-collected version update graph
1769 * evi_target: member of that list that we want to reach
1770 *
1771 * Returns the best starting-point version, or NULL if there is none.
1772 * On success, *best_path is set to the path from the start point.
1773 *
1774 * If there's more than one possible start point, prefer shorter update paths,
1775 * and break any ties arbitrarily on the basis of strcmp'ing the starting
1776 * versions' names.
1777 */
1778static ExtensionVersionInfo *
1780 List **best_path)
1781{
1783 ListCell *lc;
1784
1785 *best_path = NIL;
1786
1787 /*
1788 * We don't expect to be called for an installable target, but if we are,
1789 * the answer is easy: just start from there, with an empty update path.
1790 */
1791 if (evi_target->installable)
1792 return evi_target;
1793
1794 /* Consider all installable versions as start points */
1795 foreach(lc, evi_list)
1796 {
1798 List *path;
1799
1800 if (!evi1->installable)
1801 continue;
1802
1803 /*
1804 * Find shortest path from evi1 to evi_target; but no need to consider
1805 * paths going through other installable versions.
1806 */
1807 path = find_update_path(evi_list, evi1, evi_target, true, true);
1808 if (path == NIL)
1809 continue;
1810
1811 /* Remember best path */
1812 if (evi_start == NULL ||
1813 list_length(path) < list_length(*best_path) ||
1814 (list_length(path) == list_length(*best_path) &&
1815 strcmp(evi_start->name, evi1->name) < 0))
1816 {
1817 evi_start = evi1;
1818 *best_path = path;
1819 }
1820 }
1821
1822 return evi_start;
1823}
1824
1825/*
1826 * CREATE EXTENSION worker
1827 *
1828 * When CASCADE is specified, CreateExtensionInternal() recurses if required
1829 * extensions need to be installed. To sanely handle cyclic dependencies,
1830 * the "parents" list contains a list of names of extensions already being
1831 * installed, allowing us to error out if we recurse to one of those.
1832 */
1833static ObjectAddress
1835 char *schemaName,
1836 const char *versionName,
1837 bool cascade,
1838 List *parents,
1839 bool is_create)
1840{
1841 char *origSchemaName = schemaName;
1845 ExtensionControlFile *control;
1846 char *filename;
1847 struct stat fst;
1852 ObjectAddress address;
1853 ListCell *lc;
1854
1855 /*
1856 * Read the primary control file. Note we assume that it does not contain
1857 * any non-ASCII data, so there is no need to worry about encoding at this
1858 * point.
1859 */
1861
1862 /*
1863 * Determine the version to install
1864 */
1865 if (versionName == NULL)
1866 {
1867 if (pcontrol->default_version)
1868 versionName = pcontrol->default_version;
1869 else
1870 ereport(ERROR,
1872 errmsg("version to install must be specified")));
1873 }
1875
1876 /*
1877 * Figure out which script(s) we need to run to install the desired
1878 * version of the extension. If we do not have a script that directly
1879 * does what is needed, we try to find a sequence of update scripts that
1880 * will get us there.
1881 */
1883 if (stat(filename, &fst) == 0)
1884 {
1885 /* Easy, no extra scripts */
1887 }
1888 else
1889 {
1890 /* Look for best way to install this version */
1891 List *evi_list;
1894
1895 /* Extract the version update graph from the script directory */
1897
1898 /* Identify the target version */
1900
1901 /* Identify best path to reach target */
1904
1905 /* Fail if no path ... */
1906 if (evi_start == NULL)
1907 ereport(ERROR,
1909 errmsg("extension \"%s\" has no installation script nor update path for version \"%s\"",
1910 pcontrol->name, versionName)));
1911
1912 /* Otherwise, install best starting point and then upgrade */
1913 versionName = evi_start->name;
1914 }
1915
1916 /*
1917 * Fetch control parameters for installation target version
1918 */
1920
1921 /*
1922 * Determine the target schema to install the extension into
1923 */
1924 if (schemaName)
1925 {
1926 /* If the user is giving us the schema name, it must exist already. */
1928 }
1929
1930 if (control->schema != NULL)
1931 {
1932 /*
1933 * The extension is not relocatable and the author gave us a schema
1934 * for it.
1935 *
1936 * Unless CASCADE parameter was given, it's an error to give a schema
1937 * different from control->schema if control->schema is specified.
1938 */
1939 if (schemaName && strcmp(control->schema, schemaName) != 0 &&
1940 !cascade)
1941 ereport(ERROR,
1943 errmsg("extension \"%s\" must be installed in schema \"%s\"",
1944 control->name,
1945 control->schema)));
1946
1947 /* Always use the schema from control file for current extension. */
1948 schemaName = control->schema;
1949
1950 /* Find or create the schema in case it does not exist. */
1952
1953 if (!OidIsValid(schemaOid))
1954 {
1956
1957 csstmt->schemaname = schemaName;
1958 csstmt->authrole = NULL; /* will be created by current user */
1959 csstmt->schemaElts = NIL;
1960 csstmt->if_not_exists = false;
1961 CreateSchemaCommand(csstmt, "(generated CREATE SCHEMA command)",
1962 -1, -1);
1963
1964 /*
1965 * CreateSchemaCommand includes CommandCounterIncrement, so new
1966 * schema is now visible.
1967 */
1969 }
1970 }
1971 else if (!OidIsValid(schemaOid))
1972 {
1973 /*
1974 * Neither user nor author of the extension specified schema; use the
1975 * current default creation namespace, which is the first explicit
1976 * entry in the search_path.
1977 */
1978 List *search_path = fetch_search_path(false);
1979
1980 if (search_path == NIL) /* nothing valid in search_path? */
1981 ereport(ERROR,
1983 errmsg("no schema has been selected to create in")));
1984 schemaOid = linitial_oid(search_path);
1986 if (schemaName == NULL) /* recently-deleted namespace? */
1987 ereport(ERROR,
1989 errmsg("no schema has been selected to create in")));
1990
1991 list_free(search_path);
1992 }
1993
1994 /*
1995 * Make note if a temporary namespace has been accessed in this
1996 * transaction.
1997 */
2000
2001 /*
2002 * We don't check creation rights on the target namespace here. If the
2003 * extension script actually creates any objects there, it will fail if
2004 * the user doesn't have such permissions. But there are cases such as
2005 * procedural languages where it's convenient to set schema = pg_catalog
2006 * yet we don't want to restrict the command to users with ACL_CREATE for
2007 * pg_catalog.
2008 */
2009
2010 /*
2011 * Look up the prerequisite extensions, install them if necessary, and
2012 * build lists of their OIDs and the OIDs of their target schemas.
2013 */
2016 foreach(lc, control->requires)
2017 {
2018 char *curreq = (char *) lfirst(lc);
2019 Oid reqext;
2020 Oid reqschema;
2021
2025 cascade,
2026 parents,
2027 is_create);
2031 }
2032
2033 /*
2034 * Insert new tuple into pg_extension, and create dependency entries.
2035 */
2036 address = InsertExtensionTuple(control->name, extowner,
2037 schemaOid, control->relocatable,
2042 extensionOid = address.objectId;
2043
2044 /*
2045 * Apply any control-file comment on extension
2046 */
2047 if (control->comment != NULL)
2049
2050 /*
2051 * Execute the installation script file
2052 */
2056 schemaName);
2057
2058 /*
2059 * If additional update scripts have to be executed, apply the updates as
2060 * though a series of ALTER EXTENSION UPDATE commands were given
2061 */
2064 origSchemaName, cascade, is_create);
2065
2066 return address;
2067}
2068
2069/*
2070 * Get the OID of an extension listed in "requires", possibly creating it.
2071 */
2072static Oid
2074 char *extensionName,
2075 char *origSchemaName,
2076 bool cascade,
2077 List *parents,
2078 bool is_create)
2079{
2081
2084 {
2085 if (cascade)
2086 {
2087 /* Must install it. */
2088 ObjectAddress addr;
2090 ListCell *lc;
2091
2092 /* Check extension name validity before trying to cascade. */
2094
2095 /* Check for cyclic dependency between extensions. */
2096 foreach(lc, parents)
2097 {
2098 char *pname = (char *) lfirst(lc);
2099
2100 if (strcmp(pname, reqExtensionName) == 0)
2101 ereport(ERROR,
2103 errmsg("cyclic dependency detected between extensions \"%s\" and \"%s\"",
2105 }
2106
2108 (errmsg("installing required extension \"%s\"",
2110
2111 /* Add current extension to list of parents to pass down. */
2113
2114 /*
2115 * Create the required extension. We propagate the SCHEMA option
2116 * if any, and CASCADE, but no other options.
2117 */
2120 NULL,
2121 cascade,
2123 is_create);
2124
2125 /* Get its newly-assigned OID. */
2127 }
2128 else
2129 ereport(ERROR,
2131 errmsg("required extension \"%s\" is not installed",
2133 is_create ?
2134 errhint("Use CREATE EXTENSION ... CASCADE to install required extensions too.") : 0));
2135 }
2136
2137 return reqExtensionOid;
2138}
2139
2140/*
2141 * CREATE EXTENSION
2142 */
2145{
2149 char *schemaName = NULL;
2150 char *versionName = NULL;
2151 bool cascade = false;
2152 ListCell *lc;
2153
2154 /* Check extension name validity before any filesystem access */
2156
2157 /*
2158 * Check for duplicate extension name. The unique index on
2159 * pg_extension.extname would catch this anyway, and serves as a backstop
2160 * in case of race conditions; but this is a friendlier error message, and
2161 * besides we need a check to support IF NOT EXISTS.
2162 */
2163 if (get_extension_oid(stmt->extname, true) != InvalidOid)
2164 {
2165 if (stmt->if_not_exists)
2166 {
2169 errmsg("extension \"%s\" already exists, skipping",
2170 stmt->extname)));
2171 return InvalidObjectAddress;
2172 }
2173 else
2174 ereport(ERROR,
2176 errmsg("extension \"%s\" already exists",
2177 stmt->extname)));
2178 }
2179
2180 /*
2181 * We use global variables to track the extension being created, so we can
2182 * create only one extension at the same time.
2183 */
2185 ereport(ERROR,
2187 errmsg("nested CREATE EXTENSION is not supported")));
2188
2189 /* Deconstruct the statement option list */
2190 foreach(lc, stmt->options)
2191 {
2192 DefElem *defel = (DefElem *) lfirst(lc);
2193
2194 if (strcmp(defel->defname, "schema") == 0)
2195 {
2196 if (d_schema)
2198 d_schema = defel;
2200 }
2201 else if (strcmp(defel->defname, "new_version") == 0)
2202 {
2203 if (d_new_version)
2207 }
2208 else if (strcmp(defel->defname, "cascade") == 0)
2209 {
2210 if (d_cascade)
2212 d_cascade = defel;
2213 cascade = defGetBoolean(d_cascade);
2214 }
2215 else
2216 elog(ERROR, "unrecognized option: %s", defel->defname);
2217 }
2218
2219 /* Call CreateExtensionInternal to do the real work. */
2220 return CreateExtensionInternal(stmt->extname,
2221 schemaName,
2223 cascade,
2224 NIL,
2225 true);
2226}
2227
2228/*
2229 * InsertExtensionTuple
2230 *
2231 * Insert the new pg_extension row, and create extension's dependency entries.
2232 * Return the OID assigned to the new row.
2233 *
2234 * This is exported for the benefit of pg_upgrade, which has to create a
2235 * pg_extension entry (and the extension-level dependencies) without
2236 * actually running the extension's script.
2237 *
2238 * extConfig and extCondition should be arrays or PointerGetDatum(NULL).
2239 * We declare them as plain Datum to avoid needing array.h in extension.h.
2240 */
2243 Oid schemaOid, bool relocatable, const char *extVersion,
2246{
2248 Relation rel;
2250 bool nulls[Natts_pg_extension];
2251 HeapTuple tuple;
2255 ListCell *lc;
2256
2257 /*
2258 * Build and insert the pg_extension tuple
2259 */
2261
2262 memset(values, 0, sizeof(values));
2263 memset(nulls, 0, sizeof(nulls));
2264
2274
2276 nulls[Anum_pg_extension_extconfig - 1] = true;
2277 else
2279
2281 nulls[Anum_pg_extension_extcondition - 1] = true;
2282 else
2284
2285 tuple = heap_form_tuple(rel->rd_att, values, nulls);
2286
2287 CatalogTupleInsert(rel, tuple);
2288
2289 heap_freetuple(tuple);
2291
2292 /*
2293 * Record dependencies on owner, schema, and prerequisite extensions
2294 */
2296
2298
2300
2303
2304 foreach(lc, requiredExtensions)
2305 {
2308
2311 }
2312
2313 /* Record all of them (this includes duplicate elimination) */
2316
2317 /* Post creation hook for new extension */
2319
2320 return myself;
2321}
2322
2323/*
2324 * Guts of extension deletion.
2325 *
2326 * All we need do here is remove the pg_extension tuple itself. Everything
2327 * else is taken care of by the dependency infrastructure.
2328 */
2329void
2331{
2332 Relation rel;
2333 SysScanDesc scandesc;
2334 HeapTuple tuple;
2335 ScanKeyData entry[1];
2336
2337 /*
2338 * Disallow deletion of any extension that's currently open for insertion;
2339 * else subsequent executions of recordDependencyOnCurrentExtension()
2340 * could create dangling pg_depend records that refer to a no-longer-valid
2341 * pg_extension OID. This is needed not so much because we think people
2342 * might write "DROP EXTENSION foo" in foo's own script files, as because
2343 * errors in dependency management in extension script files could give
2344 * rise to cases where an extension is dropped as a result of recursing
2345 * from some contained object. Because of that, we must test for the case
2346 * here, not at some higher level of the DROP EXTENSION command.
2347 */
2349 ereport(ERROR,
2351 errmsg("cannot drop extension \"%s\" because it is being modified",
2353
2355
2356 ScanKeyInit(&entry[0],
2360 scandesc = systable_beginscan(rel, ExtensionOidIndexId, true,
2361 NULL, 1, entry);
2362
2363 tuple = systable_getnext(scandesc);
2364
2365 /* We assume that there can be at most one matching tuple */
2366 if (HeapTupleIsValid(tuple))
2367 CatalogTupleDelete(rel, &tuple->t_self);
2368
2369 systable_endscan(scandesc);
2370
2372}
2373
2374/*
2375 * This function lists the available extensions (one row per primary control
2376 * file in the control directory). We parse each control file and report the
2377 * interesting fields.
2378 *
2379 * The system view pg_available_extensions provides a user interface to this
2380 * SRF, adding information about whether the extensions are installed in the
2381 * current DB.
2382 */
2383Datum
2385{
2386 ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
2387 List *locations;
2388 DIR *dir;
2389 struct dirent *de;
2390 List *found_ext = NIL;
2391
2392 /* Build tuplestore to hold the result rows */
2393 InitMaterializedSRF(fcinfo, 0);
2394
2396
2398 {
2399 dir = AllocateDir(location->loc);
2400
2401 /*
2402 * If the control directory doesn't exist, we want to silently return
2403 * an empty set. Any other error will be reported by ReadDir.
2404 */
2405 if (dir == NULL && errno == ENOENT)
2406 {
2407 /* do nothing */
2408 }
2409 else
2410 {
2411 while ((de = ReadDir(dir, location->loc)) != NULL)
2412 {
2413 ExtensionControlFile *control;
2414 char *extname;
2416 Datum values[4];
2417 bool nulls[4];
2418
2419 if (!is_extension_control_filename(de->d_name))
2420 continue;
2421
2422 /* extract extension name from 'name.control' filename */
2423 extname = pstrdup(de->d_name);
2424 *strrchr(extname, '.') = '\0';
2425
2426 /* ignore it if it's an auxiliary control file */
2427 if (strstr(extname, "--"))
2428 continue;
2429
2430 /*
2431 * Ignore already-found names. They are not reachable by the
2432 * path search, so don't show them.
2433 */
2434 extname_str = makeString(extname);
2436 continue;
2437 else
2439
2440 control = new_ExtensionControlFile(extname);
2441 control->control_dir = pstrdup(location->loc);
2443
2444 memset(values, 0, sizeof(values));
2445 memset(nulls, 0, sizeof(nulls));
2446
2447 /* name */
2449 CStringGetDatum(control->name));
2450 /* default_version */
2451 if (control->default_version == NULL)
2452 nulls[1] = true;
2453 else
2455
2456 /* location */
2458
2459 /* comment */
2460 if (control->comment == NULL)
2461 nulls[3] = true;
2462 else
2463 values[3] = CStringGetTextDatum(control->comment);
2464
2465 tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
2466 values, nulls);
2467 }
2468
2469 FreeDir(dir);
2470 }
2471 }
2472
2473 return (Datum) 0;
2474}
2475
2476/*
2477 * This function lists the available extension versions (one row per
2478 * extension installation script). For each version, we parse the related
2479 * control file(s) and report the interesting fields.
2480 *
2481 * The system view pg_available_extension_versions provides a user interface
2482 * to this SRF, adding information about which versions are installed in the
2483 * current DB.
2484 */
2485Datum
2487{
2488 ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
2489 List *locations;
2490 DIR *dir;
2491 struct dirent *de;
2492 List *found_ext = NIL;
2493
2494 /* Build tuplestore to hold the result rows */
2495 InitMaterializedSRF(fcinfo, 0);
2496
2498
2500 {
2501 dir = AllocateDir(location->loc);
2502
2503 /*
2504 * If the control directory doesn't exist, we want to silently return
2505 * an empty set. Any other error will be reported by ReadDir.
2506 */
2507 if (dir == NULL && errno == ENOENT)
2508 {
2509 /* do nothing */
2510 }
2511 else
2512 {
2513 while ((de = ReadDir(dir, location->loc)) != NULL)
2514 {
2515 ExtensionControlFile *control;
2516 char *extname;
2518
2519 if (!is_extension_control_filename(de->d_name))
2520 continue;
2521
2522 /* extract extension name from 'name.control' filename */
2523 extname = pstrdup(de->d_name);
2524 *strrchr(extname, '.') = '\0';
2525
2526 /* ignore it if it's an auxiliary control file */
2527 if (strstr(extname, "--"))
2528 continue;
2529
2530 /*
2531 * Ignore already-found names. They are not reachable by the
2532 * path search, so don't show them.
2533 */
2534 extname_str = makeString(extname);
2536 continue;
2537 else
2539
2540 /* read the control file */
2541 control = new_ExtensionControlFile(extname);
2542 control->control_dir = pstrdup(location->loc);
2544
2545 /* scan extension's script directory for install scripts */
2546 get_available_versions_for_extension(control, rsinfo->setResult,
2547 rsinfo->setDesc,
2548 location);
2549 }
2550
2551 FreeDir(dir);
2552 }
2553 }
2554
2555 return (Datum) 0;
2556}
2557
2558/*
2559 * Inner loop for pg_available_extension_versions:
2560 * read versions of one extension, add rows to tupstore
2561 */
2562static void
2564 Tuplestorestate *tupstore,
2565 TupleDesc tupdesc,
2566 ExtensionLocation *location)
2567{
2568 List *evi_list;
2569 ListCell *lc;
2570
2571 /* Extract the version update graph from the script directory */
2573
2574 /* For each installable version ... */
2575 foreach(lc, evi_list)
2576 {
2578 ExtensionControlFile *control;
2579 Datum values[9];
2580 bool nulls[9];
2581 ListCell *lc2;
2582
2583 if (!evi->installable)
2584 continue;
2585
2586 /*
2587 * Fetch parameters for specific version (pcontrol is not changed)
2588 */
2590
2591 memset(values, 0, sizeof(values));
2592 memset(nulls, 0, sizeof(nulls));
2593
2594 /* name */
2596 CStringGetDatum(control->name));
2597 /* version */
2598 values[1] = CStringGetTextDatum(evi->name);
2599 /* superuser */
2600 values[2] = BoolGetDatum(control->superuser);
2601 /* trusted */
2602 values[3] = BoolGetDatum(control->trusted);
2603 /* relocatable */
2604 values[4] = BoolGetDatum(control->relocatable);
2605 /* schema */
2606 if (control->schema == NULL)
2607 nulls[5] = true;
2608 else
2610 CStringGetDatum(control->schema));
2611 /* requires */
2612 if (control->requires == NIL)
2613 nulls[6] = true;
2614 else
2615 values[6] = convert_requires_to_datum(control->requires);
2616
2617 /* location */
2619
2620 /* comment */
2621 if (control->comment == NULL)
2622 nulls[8] = true;
2623 else
2624 values[8] = CStringGetTextDatum(control->comment);
2625
2626 tuplestore_putvalues(tupstore, tupdesc, values, nulls);
2627
2628 /*
2629 * Find all non-directly-installable versions that would be installed
2630 * starting from this version, and report them, inheriting the
2631 * parameters that aren't changed in updates from this version.
2632 */
2633 foreach(lc2, evi_list)
2634 {
2636 List *best_path;
2637
2638 if (evi2->installable)
2639 continue;
2641 {
2642 /*
2643 * Fetch parameters for this version (pcontrol is not changed)
2644 */
2646
2647 /* name stays the same */
2648 /* version */
2649 values[1] = CStringGetTextDatum(evi2->name);
2650 /* superuser */
2651 values[2] = BoolGetDatum(control->superuser);
2652 /* trusted */
2653 values[3] = BoolGetDatum(control->trusted);
2654 /* relocatable */
2655 values[4] = BoolGetDatum(control->relocatable);
2656 /* schema stays the same */
2657 /* requires */
2658 if (control->requires == NIL)
2659 nulls[6] = true;
2660 else
2661 {
2662 values[6] = convert_requires_to_datum(control->requires);
2663 nulls[6] = false;
2664 }
2665 /* comment and location stay the same */
2666
2667 tuplestore_putvalues(tupstore, tupdesc, values, nulls);
2668 }
2669 }
2670 }
2671}
2672
2673/*
2674 * Test whether the given extension exists (not whether it's installed)
2675 *
2676 * This checks for the existence of a matching control file in the extension
2677 * directory. That's not a bulletproof check, since the file might be
2678 * invalid, but this is only used for hints so it doesn't have to be 100%
2679 * right.
2680 */
2681bool
2683{
2684 bool result = false;
2685 List *locations;
2686 DIR *dir;
2687 struct dirent *de;
2688
2690
2692 {
2693 dir = AllocateDir(location->loc);
2694
2695 /*
2696 * If the control directory doesn't exist, we want to silently return
2697 * false. Any other error will be reported by ReadDir.
2698 */
2699 if (dir == NULL && errno == ENOENT)
2700 {
2701 /* do nothing */
2702 }
2703 else
2704 {
2705 while ((de = ReadDir(dir, location->loc)) != NULL)
2706 {
2707 char *extname;
2708
2709 if (!is_extension_control_filename(de->d_name))
2710 continue;
2711
2712 /* extract extension name from 'name.control' filename */
2713 extname = pstrdup(de->d_name);
2714 *strrchr(extname, '.') = '\0';
2715
2716 /* ignore it if it's an auxiliary control file */
2717 if (strstr(extname, "--"))
2718 continue;
2719
2720 /* done if it matches request */
2721 if (strcmp(extname, extensionName) == 0)
2722 {
2723 result = true;
2724 break;
2725 }
2726 }
2727
2728 FreeDir(dir);
2729 }
2730 if (result)
2731 break;
2732 }
2733
2734 return result;
2735}
2736
2737/*
2738 * Convert a list of extension names to a name[] Datum
2739 */
2740static Datum
2742{
2743 Datum *datums;
2744 int ndatums;
2745 ArrayType *a;
2746 ListCell *lc;
2747
2748 ndatums = list_length(requires);
2749 datums = (Datum *) palloc(ndatums * sizeof(Datum));
2750 ndatums = 0;
2751 foreach(lc, requires)
2752 {
2753 char *curreq = (char *) lfirst(lc);
2754
2755 datums[ndatums++] =
2757 }
2758 a = construct_array_builtin(datums, ndatums, NAMEOID);
2759 return PointerGetDatum(a);
2760}
2761
2762/*
2763 * This function reports the version update paths that exist for the
2764 * specified extension.
2765 */
2766Datum
2768{
2769 Name extname = PG_GETARG_NAME(0);
2770 ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
2771 List *evi_list;
2772 ExtensionControlFile *control;
2773 ListCell *lc1;
2774
2775 /* Check extension name validity before any filesystem access */
2777
2778 /* Build tuplestore to hold the result rows */
2779 InitMaterializedSRF(fcinfo, 0);
2780
2781 /* Read the extension's control file */
2782 control = read_extension_control_file(NameStr(*extname));
2783
2784 /* Extract the version update graph from the script directory */
2785 evi_list = get_ext_ver_list(control);
2786
2787 /* Iterate over all pairs of versions */
2788 foreach(lc1, evi_list)
2789 {
2791 ListCell *lc2;
2792
2793 foreach(lc2, evi_list)
2794 {
2796 List *path;
2797 Datum values[3];
2798 bool nulls[3];
2799
2800 if (evi1 == evi2)
2801 continue;
2802
2803 /* Find shortest path from evi1 to evi2 */
2804 path = find_update_path(evi_list, evi1, evi2, false, true);
2805
2806 /* Emit result row */
2807 memset(values, 0, sizeof(values));
2808 memset(nulls, 0, sizeof(nulls));
2809
2810 /* source */
2811 values[0] = CStringGetTextDatum(evi1->name);
2812 /* target */
2813 values[1] = CStringGetTextDatum(evi2->name);
2814 /* path */
2815 if (path == NIL)
2816 nulls[2] = true;
2817 else
2818 {
2820 ListCell *lcv;
2821
2823 /* The path doesn't include start vertex, but show it */
2825 foreach(lcv, path)
2826 {
2827 char *versionName = (char *) lfirst(lcv);
2828
2831 }
2833 pfree(pathbuf.data);
2834 }
2835
2836 tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
2837 values, nulls);
2838 }
2839 }
2840
2841 return (Datum) 0;
2842}
2843
2844/*
2845 * pg_extension_config_dump
2846 *
2847 * Record information about a configuration table that belongs to an
2848 * extension being created, but whose contents should be dumped in whole
2849 * or in part during pg_dump.
2850 */
2851Datum
2853{
2854 Oid tableoid = PG_GETARG_OID(0);
2856 char *tablename;
2858 ScanKeyData key[1];
2863 int arrayLength;
2864 int arrayIndex;
2865 bool isnull;
2869 ArrayType *a;
2870
2871 /*
2872 * We only allow this to be called from an extension's SQL script. We
2873 * shouldn't need any permissions check beyond that.
2874 */
2875 if (!creating_extension)
2876 ereport(ERROR,
2878 errmsg("%s can only be called from an SQL script executed by CREATE EXTENSION",
2879 "pg_extension_config_dump()")));
2880
2881 /*
2882 * Check that the table exists and is a member of the extension being
2883 * created. This ensures that we don't need to register an additional
2884 * dependency to protect the extconfig entry.
2885 */
2886 tablename = get_rel_name(tableoid);
2887 if (tablename == NULL)
2888 ereport(ERROR,
2890 errmsg("OID %u does not refer to a table", tableoid)));
2893 ereport(ERROR,
2895 errmsg("table \"%s\" is not a member of the extension being created",
2896 tablename)));
2897
2898 /*
2899 * Add the table OID and WHERE condition to the extension's extconfig and
2900 * extcondition arrays.
2901 *
2902 * If the table is already in extconfig, treat this as an update of the
2903 * WHERE condition.
2904 */
2905
2906 /* Find the pg_extension tuple */
2908
2909 ScanKeyInit(&key[0],
2913
2915 NULL, 1, key);
2916
2918
2919 if (!HeapTupleIsValid(extTup)) /* should not happen */
2920 elog(ERROR, "could not find tuple for extension %u",
2922
2923 memset(repl_val, 0, sizeof(repl_val));
2924 memset(repl_null, false, sizeof(repl_null));
2925 memset(repl_repl, false, sizeof(repl_repl));
2926
2927 /* Build or modify the extconfig value */
2928 elementDatum = ObjectIdGetDatum(tableoid);
2929
2931 RelationGetDescr(extRel), &isnull);
2932 if (isnull)
2933 {
2934 /* Previously empty extconfig, so build 1-element array */
2935 arrayLength = 0;
2936 arrayIndex = 1;
2937
2939 }
2940 else
2941 {
2942 /* Modify or extend existing extconfig array */
2943 Oid *arrayData;
2944 int i;
2945
2947
2948 arrayLength = ARR_DIMS(a)[0];
2949 if (ARR_NDIM(a) != 1 ||
2950 ARR_LBOUND(a)[0] != 1 ||
2951 arrayLength < 0 ||
2952 ARR_HASNULL(a) ||
2953 ARR_ELEMTYPE(a) != OIDOID)
2954 elog(ERROR, "extconfig is not a 1-D Oid array");
2955 arrayData = (Oid *) ARR_DATA_PTR(a);
2956
2957 arrayIndex = arrayLength + 1; /* set up to add after end */
2958
2959 for (i = 0; i < arrayLength; i++)
2960 {
2961 if (arrayData[i] == tableoid)
2962 {
2963 arrayIndex = i + 1; /* replace this element instead */
2964 break;
2965 }
2966 }
2967
2968 a = array_set(a, 1, &arrayIndex,
2970 false,
2971 -1 /* varlena array */ ,
2972 sizeof(Oid) /* OID's typlen */ ,
2973 true /* OID's typbyval */ ,
2974 TYPALIGN_INT /* OID's typalign */ );
2975 }
2978
2979 /* Build or modify the extcondition value */
2981
2983 RelationGetDescr(extRel), &isnull);
2984 if (isnull)
2985 {
2986 if (arrayLength != 0)
2987 elog(ERROR, "extconfig and extcondition arrays do not match");
2988
2990 }
2991 else
2992 {
2994
2995 if (ARR_NDIM(a) != 1 ||
2996 ARR_LBOUND(a)[0] != 1 ||
2997 ARR_HASNULL(a) ||
2999 elog(ERROR, "extcondition is not a 1-D text array");
3000 if (ARR_DIMS(a)[0] != arrayLength)
3001 elog(ERROR, "extconfig and extcondition arrays do not match");
3002
3003 /* Add or replace at same index as in extconfig */
3004 a = array_set(a, 1, &arrayIndex,
3006 false,
3007 -1 /* varlena array */ ,
3008 -1 /* TEXT's typlen */ ,
3009 false /* TEXT's typbyval */ ,
3010 TYPALIGN_INT /* TEXT's typalign */ );
3011 }
3014
3017
3019
3021
3023
3025}
3026
3027/*
3028 * pg_get_loaded_modules
3029 *
3030 * SQL-callable function to get per-loaded-module information. Modules
3031 * (shared libraries) aren't necessarily one-to-one with extensions, but
3032 * they're sufficiently closely related to make this file a good home.
3033 */
3034Datum
3036{
3037 ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
3039
3040 /* Build tuplestore to hold the result rows */
3041 InitMaterializedSRF(fcinfo, 0);
3042
3045 {
3046 const char *library_path,
3047 *module_name,
3049 const char *sep;
3050 Datum values[3] = {0};
3051 bool nulls[3] = {0};
3052
3054 &library_path,
3055 &module_name,
3057
3058 if (module_name == NULL)
3059 nulls[0] = true;
3060 else
3062 if (module_version == NULL)
3063 nulls[1] = true;
3064 else
3066
3067 /* For security reasons, we don't show the directory path */
3069 if (sep)
3070 library_path = sep + 1;
3072
3073 tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
3074 values, nulls);
3075 }
3076
3077 return (Datum) 0;
3078}
3079
3080/*
3081 * extension_config_remove
3082 *
3083 * Remove the specified table OID from extension's extconfig, if present.
3084 * This is not currently exposed as a function, but it could be;
3085 * for now, we just invoke it from ALTER EXTENSION DROP.
3086 */
3087static void
3089{
3091 ScanKeyData key[1];
3095 int arrayLength;
3096 int arrayIndex;
3097 bool isnull;
3101 ArrayType *a;
3102
3103 /* Find the pg_extension tuple */
3105
3106 ScanKeyInit(&key[0],
3110
3112 NULL, 1, key);
3113
3115
3116 if (!HeapTupleIsValid(extTup)) /* should not happen */
3117 elog(ERROR, "could not find tuple for extension %u",
3118 extensionoid);
3119
3120 /* Search extconfig for the tableoid */
3122 RelationGetDescr(extRel), &isnull);
3123 if (isnull)
3124 {
3125 /* nothing to do */
3126 a = NULL;
3127 arrayLength = 0;
3128 arrayIndex = -1;
3129 }
3130 else
3131 {
3132 Oid *arrayData;
3133 int i;
3134
3136
3137 arrayLength = ARR_DIMS(a)[0];
3138 if (ARR_NDIM(a) != 1 ||
3139 ARR_LBOUND(a)[0] != 1 ||
3140 arrayLength < 0 ||
3141 ARR_HASNULL(a) ||
3142 ARR_ELEMTYPE(a) != OIDOID)
3143 elog(ERROR, "extconfig is not a 1-D Oid array");
3144 arrayData = (Oid *) ARR_DATA_PTR(a);
3145
3146 arrayIndex = -1; /* flag for no deletion needed */
3147
3148 for (i = 0; i < arrayLength; i++)
3149 {
3150 if (arrayData[i] == tableoid)
3151 {
3152 arrayIndex = i; /* index to remove */
3153 break;
3154 }
3155 }
3156 }
3157
3158 /* If tableoid is not in extconfig, nothing to do */
3159 if (arrayIndex < 0)
3160 {
3163 return;
3164 }
3165
3166 /* Modify or delete the extconfig value */
3167 memset(repl_val, 0, sizeof(repl_val));
3168 memset(repl_null, false, sizeof(repl_null));
3169 memset(repl_repl, false, sizeof(repl_repl));
3170
3171 if (arrayLength <= 1)
3172 {
3173 /* removing only element, just set array to null */
3175 }
3176 else
3177 {
3178 /* squeeze out the target element */
3179 Datum *dvalues;
3180 int nelems;
3181 int i;
3182
3183 /* We already checked there are no nulls */
3184 deconstruct_array_builtin(a, OIDOID, &dvalues, NULL, &nelems);
3185
3186 for (i = arrayIndex; i < arrayLength - 1; i++)
3187 dvalues[i] = dvalues[i + 1];
3188
3190
3192 }
3194
3195 /* Modify or delete the extcondition value */
3197 RelationGetDescr(extRel), &isnull);
3198 if (isnull)
3199 {
3200 elog(ERROR, "extconfig and extcondition arrays do not match");
3201 }
3202 else
3203 {
3205
3206 if (ARR_NDIM(a) != 1 ||
3207 ARR_LBOUND(a)[0] != 1 ||
3208 ARR_HASNULL(a) ||
3210 elog(ERROR, "extcondition is not a 1-D text array");
3211 if (ARR_DIMS(a)[0] != arrayLength)
3212 elog(ERROR, "extconfig and extcondition arrays do not match");
3213 }
3214
3215 if (arrayLength <= 1)
3216 {
3217 /* removing only element, just set array to null */
3219 }
3220 else
3221 {
3222 /* squeeze out the target element */
3223 Datum *dvalues;
3224 int nelems;
3225 int i;
3226
3227 /* We already checked there are no nulls */
3228 deconstruct_array_builtin(a, TEXTOID, &dvalues, NULL, &nelems);
3229
3230 for (i = arrayIndex; i < arrayLength - 1; i++)
3231 dvalues[i] = dvalues[i + 1];
3232
3234
3236 }
3238
3241
3243
3245
3247}
3248
3249/*
3250 * Execute ALTER EXTENSION SET SCHEMA
3251 */
3253AlterExtensionNamespace(const char *extensionName, const char *newschema, Oid *oldschema)
3254{
3256 Oid nspOid;
3257 Oid oldNspOid;
3260 ScanKeyData key[2];
3269
3271
3272 nspOid = LookupCreationNamespace(newschema);
3273
3274 /*
3275 * Permission check: must own extension. Note that we don't bother to
3276 * check ownership of the individual member objects ...
3277 */
3281
3282 /* Permission check: must have creation rights in target namespace */
3284 if (aclresult != ACLCHECK_OK)
3286
3287 /*
3288 * If the schema is currently a member of the extension, disallow moving
3289 * the extension into the schema. That would create a dependency loop.
3290 */
3292 ereport(ERROR,
3294 errmsg("cannot move extension \"%s\" into schema \"%s\" "
3295 "because the extension contains the schema",
3296 extensionName, newschema)));
3297
3298 /* Locate the pg_extension tuple */
3300
3301 ScanKeyInit(&key[0],
3305
3307 NULL, 1, key);
3308
3310
3311 if (!HeapTupleIsValid(extTup)) /* should not happen */
3312 elog(ERROR, "could not find tuple for extension %u",
3313 extensionOid);
3314
3315 /* Copy tuple so we can modify it below */
3318
3320
3321 /*
3322 * If the extension is already in the target schema, just silently do
3323 * nothing.
3324 */
3325 if (extForm->extnamespace == nspOid)
3326 {
3328 return InvalidObjectAddress;
3329 }
3330
3331 /* Check extension is supposed to be relocatable */
3332 if (!extForm->extrelocatable)
3333 ereport(ERROR,
3335 errmsg("extension \"%s\" does not support SET SCHEMA",
3336 NameStr(extForm->extname))));
3337
3339
3340 /* store the OID of the namespace to-be-changed */
3341 oldNspOid = extForm->extnamespace;
3342
3343 /*
3344 * Scan pg_depend to find objects that depend directly on the extension,
3345 * and alter each one's schema.
3346 */
3348
3349 ScanKeyInit(&key[0],
3353 ScanKeyInit(&key[1],
3357
3359 NULL, 2, key);
3360
3362 {
3366
3367 /*
3368 * If a dependent extension has a no_relocate request for this
3369 * extension, disallow SET SCHEMA. (XXX it's a bit ugly to do this in
3370 * the same loop that's actually executing the renames: we may detect
3371 * the error condition only after having expended a fair amount of
3372 * work. However, the alternative is to do two scans of pg_depend,
3373 * which seems like optimizing for failure cases. The rename work
3374 * will all roll back cleanly enough if we do fail here.)
3375 */
3376 if (pg_depend->deptype == DEPENDENCY_NORMAL &&
3377 pg_depend->classid == ExtensionRelationId)
3378 {
3379 char *depextname = get_extension_name(pg_depend->objid);
3381 ListCell *lc;
3382
3384 foreach(lc, dcontrol->no_relocate)
3385 {
3386 char *nrextname = (char *) lfirst(lc);
3387
3388 if (strcmp(nrextname, NameStr(extForm->extname)) == 0)
3389 {
3390 ereport(ERROR,
3392 errmsg("cannot SET SCHEMA of extension \"%s\" because other extensions prevent it",
3393 NameStr(extForm->extname)),
3394 errdetail("Extension \"%s\" requests no relocation of extension \"%s\".",
3395 depextname,
3396 NameStr(extForm->extname))));
3397 }
3398 }
3399 }
3400
3401 /*
3402 * Otherwise, ignore non-membership dependencies. (Currently, the
3403 * only other case we could see here is a normal dependency from
3404 * another extension.)
3405 */
3406 if (pg_depend->deptype != DEPENDENCY_EXTENSION)
3407 continue;
3408
3409 dep.classId = pg_depend->classid;
3410 dep.objectId = pg_depend->objid;
3411 dep.objectSubId = pg_depend->objsubid;
3412
3413 if (dep.objectSubId != 0) /* should not happen */
3414 elog(ERROR, "extension should not have a sub-object dependency");
3415
3416 /* Relocate the object */
3418 dep.objectId,
3419 nspOid,
3420 objsMoved);
3421
3422 /*
3423 * If not all the objects had the same old namespace (ignoring any
3424 * that are not in namespaces or are dependent types), complain.
3425 */
3427 ereport(ERROR,
3429 errmsg("extension \"%s\" does not support SET SCHEMA",
3430 NameStr(extForm->extname)),
3431 errdetail("%s is not in the extension's schema \"%s\"",
3432 getObjectDescription(&dep, false),
3434 }
3435
3436 /* report old schema, if caller wants it */
3437 if (oldschema)
3439
3441
3443
3444 /* Now adjust pg_extension.extnamespace */
3445 extForm->extnamespace = nspOid;
3446
3448
3450
3451 /* update dependency to point to the new schema */
3454 elog(ERROR, "could not change schema dependency for extension %s",
3455 NameStr(extForm->extname));
3456
3458
3460
3461 return extAddr;
3462}
3463
3464/*
3465 * Execute ALTER EXTENSION UPDATE
3466 */
3469{
3471 char *versionName;
3472 char *oldVersionName;
3473 ExtensionControlFile *control;
3476 ScanKeyData key[1];
3480 Datum datum;
3481 bool isnull;
3482 ListCell *lc;
3483 ObjectAddress address;
3484
3485 /*
3486 * We use global variables to track the extension being created, so we can
3487 * create/update only one extension at the same time.
3488 */
3490 ereport(ERROR,
3492 errmsg("nested ALTER EXTENSION is not supported")));
3493
3494 /*
3495 * Look up the extension --- it must already exist in pg_extension
3496 */
3498
3499 ScanKeyInit(&key[0],
3502 CStringGetDatum(stmt->extname));
3503
3505 NULL, 1, key);
3506
3508
3510 ereport(ERROR,
3512 errmsg("extension \"%s\" does not exist",
3513 stmt->extname)));
3514
3516
3517 /*
3518 * Determine the existing version we are updating from
3519 */
3521 RelationGetDescr(extRel), &isnull);
3522 if (isnull)
3523 elog(ERROR, "extversion is null");
3525
3527
3529
3530 /* Permission check: must own extension */
3533 stmt->extname);
3534
3535 /*
3536 * Read the primary control file. Note we assume that it does not contain
3537 * any non-ASCII data, so there is no need to worry about encoding at this
3538 * point.
3539 */
3540 control = read_extension_control_file(stmt->extname);
3541
3542 /*
3543 * Read the statement option list
3544 */
3545 foreach(lc, stmt->options)
3546 {
3547 DefElem *defel = (DefElem *) lfirst(lc);
3548
3549 if (strcmp(defel->defname, "new_version") == 0)
3550 {
3551 if (d_new_version)
3554 }
3555 else
3556 elog(ERROR, "unrecognized option: %s", defel->defname);
3557 }
3558
3559 /*
3560 * Determine the version to update to
3561 */
3562 if (d_new_version && d_new_version->arg)
3564 else if (control->default_version)
3565 versionName = control->default_version;
3566 else
3567 {
3568 ereport(ERROR,
3570 errmsg("version to install must be specified")));
3571 versionName = NULL; /* keep compiler quiet */
3572 }
3574
3575 /*
3576 * If we're already at that version, just say so
3577 */
3579 {
3581 (errmsg("version \"%s\" of extension \"%s\" is already installed",
3582 versionName, stmt->extname)));
3583 return InvalidObjectAddress;
3584 }
3585
3586 /*
3587 * Identify the series of update script files we need to execute
3588 */
3591 versionName);
3592
3593 /*
3594 * Update the pg_extension row and execute the update scripts, one at a
3595 * time
3596 */
3599 NULL, false, false);
3600
3602
3603 return address;
3604}
3605
3606/*
3607 * Apply a series of update scripts as though individual ALTER EXTENSION
3608 * UPDATE commands had been given, including altering the pg_extension row
3609 * and dependencies each time.
3610 *
3611 * This might be more work than necessary, but it ensures that old update
3612 * scripts don't break if newer versions have different control parameters.
3613 */
3614static void
3617 const char *initialVersion,
3619 char *origSchemaName,
3620 bool cascade,
3621 bool is_create)
3622{
3623 const char *oldVersionName = initialVersion;
3624 ListCell *lcv;
3625
3626 foreach(lcv, updateVersions)
3627 {
3628 char *versionName = (char *) lfirst(lcv);
3629 ExtensionControlFile *control;
3630 char *schemaName;
3631 Oid schemaOid;
3635 ScanKeyData key[1];
3640 bool nulls[Natts_pg_extension];
3641 bool repl[Natts_pg_extension];
3643 ListCell *lc;
3644
3645 /*
3646 * Fetch parameters for specific version (pcontrol is not changed)
3647 */
3649
3650 /* Find the pg_extension tuple */
3652
3653 ScanKeyInit(&key[0],
3657
3659 NULL, 1, key);
3660
3662
3663 if (!HeapTupleIsValid(extTup)) /* should not happen */
3664 elog(ERROR, "could not find tuple for extension %u",
3665 extensionOid);
3666
3668
3669 /*
3670 * Determine the target schema (set by original install)
3671 */
3672 schemaOid = extForm->extnamespace;
3674
3675 /*
3676 * Modify extrelocatable and extversion in the pg_extension tuple
3677 */
3678 memset(values, 0, sizeof(values));
3679 memset(nulls, 0, sizeof(nulls));
3680 memset(repl, 0, sizeof(repl));
3681
3683 BoolGetDatum(control->relocatable);
3684 repl[Anum_pg_extension_extrelocatable - 1] = true;
3687 repl[Anum_pg_extension_extversion - 1] = true;
3688
3690 values, nulls, repl);
3691
3693
3695
3697
3698 /*
3699 * Look up the prerequisite extensions for this version, install them
3700 * if necessary, and build lists of their OIDs and the OIDs of their
3701 * target schemas.
3702 */
3705 foreach(lc, control->requires)
3706 {
3707 char *curreq = (char *) lfirst(lc);
3708 Oid reqext;
3709 Oid reqschema;
3710
3712 control->name,
3714 cascade,
3715 NIL,
3716 is_create);
3720 }
3721
3722 /*
3723 * Remove and recreate dependencies on prerequisite extensions
3724 */
3728
3729 myself.classId = ExtensionRelationId;
3730 myself.objectId = extensionOid;
3731 myself.objectSubId = 0;
3732
3733 foreach(lc, requiredExtensions)
3734 {
3737
3739 otherext.objectId = reqext;
3740 otherext.objectSubId = 0;
3741
3743 }
3744
3746
3747 /*
3748 * Finally, execute the update script file
3749 */
3753 schemaName);
3754
3755 /*
3756 * Update prior-version name and loop around. Since
3757 * execute_sql_string did a final CommandCounterIncrement, we can
3758 * update the pg_extension row again.
3759 */
3761 }
3762}
3763
3764/*
3765 * Execute ALTER EXTENSION ADD/DROP
3766 *
3767 * Return value is the address of the altered extension.
3768 *
3769 * objAddr is an output argument which, if not NULL, is set to the address of
3770 * the added/dropped object.
3771 */
3775{
3777 ObjectAddress object;
3778 Relation relation;
3779
3780 switch (stmt->objtype)
3781 {
3782 case OBJECT_DATABASE:
3783 case OBJECT_EXTENSION:
3784 case OBJECT_INDEX:
3785 case OBJECT_PUBLICATION:
3786 case OBJECT_ROLE:
3789 case OBJECT_TABLESPACE:
3790 ereport(ERROR,
3792 errmsg("cannot add an object of this type to an extension")));
3793 break;
3794 default:
3795 /* OK */
3796 break;
3797 }
3798
3799 /*
3800 * Find the extension and acquire a lock on it, to ensure it doesn't get
3801 * dropped concurrently. A sharable lock seems sufficient: there's no
3802 * reason not to allow other sorts of manipulations, such as add/drop of
3803 * other objects, to occur concurrently. Concurrently adding/dropping the
3804 * *same* object would be bad, but we prevent that by using a non-sharable
3805 * lock on the individual object, below.
3806 */
3808 (Node *) makeString(stmt->extname),
3809 &relation, AccessShareLock, false);
3810
3811 /* Permission check: must own extension */
3814 stmt->extname);
3815
3816 /*
3817 * Translate the parser representation that identifies the object into an
3818 * ObjectAddress. get_object_address() will throw an error if the object
3819 * does not exist, and will also acquire a lock on the object to guard
3820 * against concurrent DROP and ALTER EXTENSION ADD/DROP operations.
3821 */
3822 object = get_object_address(stmt->objtype, stmt->object,
3823 &relation, ShareUpdateExclusiveLock, false);
3824
3825 Assert(object.objectSubId == 0);
3826 if (objAddr)
3827 *objAddr = object;
3828
3829 /* Permission check: must own target object, too */
3830 check_object_ownership(GetUserId(), stmt->objtype, object,
3831 stmt->object, relation);
3832
3833 /* Do the update, recursing to any dependent objects */
3835
3836 /* Finish up */
3838
3839 /*
3840 * If get_object_address() opened the relation for us, we close it to keep
3841 * the reference count correct - but we retain any locks acquired by
3842 * get_object_address() until commit time, to guard against concurrent
3843 * activity.
3844 */
3845 if (relation != NULL)
3846 relation_close(relation, NoLock);
3847
3848 return extension;
3849}
3850
3851/*
3852 * ExecAlterExtensionContentsRecurse
3853 * Subroutine for ExecAlterExtensionContentsStmt
3854 *
3855 * Do the bare alteration of object's membership in extension,
3856 * without permission checks. Recurse to dependent objects, if any.
3857 */
3858static void
3861 ObjectAddress object)
3862{
3864
3865 /*
3866 * Check existing extension membership.
3867 */
3868 oldExtension = getExtensionOfObject(object.classId, object.objectId);
3869
3870 if (stmt->action > 0)
3871 {
3872 /*
3873 * ADD, so complain if object is already attached to some extension.
3874 */
3876 ereport(ERROR,
3878 errmsg("%s is already a member of extension \"%s\"",
3879 getObjectDescription(&object, false),
3881
3882 /*
3883 * Prevent a schema from being added to an extension if the schema
3884 * contains the extension. That would create a dependency loop.
3885 */
3886 if (object.classId == NamespaceRelationId &&
3887 object.objectId == get_extension_schema(extension.objectId))
3888 ereport(ERROR,
3890 errmsg("cannot add schema \"%s\" to extension \"%s\" "
3891 "because the schema contains the extension",
3892 get_namespace_name(object.objectId),
3893 stmt->extname)));
3894
3895 /*
3896 * OK, add the dependency.
3897 */
3899
3900 /*
3901 * Also record the initial ACL on the object, if any.
3902 *
3903 * Note that this will handle the object's ACLs, as well as any ACLs
3904 * on object subIds. (In other words, when the object is a table,
3905 * this will record the table's ACL and the ACLs for the columns on
3906 * the table, if any).
3907 */
3908 recordExtObjInitPriv(object.objectId, object.classId);
3909 }
3910 else
3911 {
3912 /*
3913 * DROP, so complain if it's not a member.
3914 */
3915 if (oldExtension != extension.objectId)
3916 ereport(ERROR,
3918 errmsg("%s is not a member of extension \"%s\"",
3919 getObjectDescription(&object, false),
3920 stmt->extname)));
3921
3922 /*
3923 * OK, drop the dependency.
3924 */
3925 if (deleteDependencyRecordsForClass(object.classId, object.objectId,
3928 elog(ERROR, "unexpected number of extension dependency records");
3929
3930 /*
3931 * If it's a relation, it might have an entry in the extension's
3932 * extconfig array, which we must remove.
3933 */
3934 if (object.classId == RelationRelationId)
3935 extension_config_remove(extension.objectId, object.objectId);
3936
3937 /*
3938 * Remove all the initial ACLs, if any.
3939 *
3940 * Note that this will remove the object's ACLs, as well as any ACLs
3941 * on object subIds. (In other words, when the object is a table,
3942 * this will remove the table's ACL and the ACLs for the columns on
3943 * the table, if any).
3944 */
3945 removeExtObjInitPriv(object.objectId, object.classId);
3946 }
3947
3948 /*
3949 * Recurse to any dependent objects; currently, this includes the array
3950 * type of a base type, the multirange type associated with a range type,
3951 * and the rowtype of a table.
3952 */
3953 if (object.classId == TypeRelationId)
3954 {
3956
3958 depobject.objectSubId = 0;
3959
3960 /* If it has an array type, update that too */
3961 depobject.objectId = get_array_type(object.objectId);
3962 if (OidIsValid(depobject.objectId))
3964
3965 /* If it is a range type, update the associated multirange too */
3966 if (type_is_range(object.objectId))
3967 {
3968 depobject.objectId = get_range_multirange(object.objectId);
3969 if (!OidIsValid(depobject.objectId))
3970 ereport(ERROR,
3972 errmsg("could not find multirange type for data type %s",
3973 format_type_be(object.objectId))));
3975 }
3976 }
3977 if (object.classId == RelationRelationId)
3978 {
3980
3982 depobject.objectSubId = 0;
3983
3984 /* It might not have a rowtype, but if it does, update that */
3985 depobject.objectId = get_rel_type_id(object.objectId);
3986 if (OidIsValid(depobject.objectId))
3988 }
3989}
3990
3991/*
3992 * Read the whole of file into memory.
3993 *
3994 * The file contents are returned as a single palloc'd chunk. For convenience
3995 * of the callers, an extra \0 byte is added to the end. That is not counted
3996 * in the length returned into *length.
3997 */
3998static char *
3999read_whole_file(const char *filename, int *length)
4000{
4001 char *buf;
4002 FILE *file;
4003 size_t bytes_to_read;
4004 struct stat fst;
4005
4006 if (stat(filename, &fst) < 0)
4007 ereport(ERROR,
4009 errmsg("could not stat file \"%s\": %m", filename)));
4010
4011 if (fst.st_size > (MaxAllocSize - 1))
4012 ereport(ERROR,
4014 errmsg("file \"%s\" is too large", filename)));
4015 bytes_to_read = (size_t) fst.st_size;
4016
4017 if ((file = AllocateFile(filename, PG_BINARY_R)) == NULL)
4018 ereport(ERROR,
4020 errmsg("could not open file \"%s\" for reading: %m",
4021 filename)));
4022
4023 buf = (char *) palloc(bytes_to_read + 1);
4024
4025 bytes_to_read = fread(buf, 1, bytes_to_read, file);
4026
4027 if (ferror(file))
4028 ereport(ERROR,
4030 errmsg("could not read file \"%s\": %m", filename)));
4031
4032 FreeFile(file);
4033
4034 buf[bytes_to_read] = '\0';
4035
4036 /*
4037 * On Windows, manually convert Windows-style newlines (\r\n) to the Unix
4038 * convention of \n only. This avoids gotchas due to script files
4039 * possibly getting converted when being transferred between platforms.
4040 * Ideally we'd do this by using text mode to read the file, but that also
4041 * causes control-Z to be treated as end-of-file. Historically we've
4042 * allowed control-Z in script files, so breaking that seems unwise.
4043 */
4044#ifdef WIN32
4045 {
4046 char *s,
4047 *d;
4048
4049 for (s = d = buf; *s; s++)
4050 {
4051 if (!(*s == '\r' && s[1] == '\n'))
4052 *d++ = *s;
4053 }
4054 *d = '\0';
4055 bytes_to_read = d - buf;
4056 }
4057#endif
4058
4059 *length = bytes_to_read;
4060 return buf;
4061}
4062
4063static ExtensionControlFile *
4064new_ExtensionControlFile(const char *extname)
4065{
4066 /*
4067 * Set up default values. Pointer fields are initially null.
4068 */
4070
4071 control->name = pstrdup(extname);
4072 control->relocatable = false;
4073 control->superuser = true;
4074 control->trusted = false;
4075 control->encoding = -1;
4076
4077 return control;
4078}
4079
4080/*
4081 * Search for the basename in the list of paths.
4082 *
4083 * Similar to find_in_path but for simplicity does not support custom error
4084 * messages and expects that paths already have all macros replaced.
4085 */
4086char *
4087find_in_paths(const char *basename, List *paths)
4088{
4089 ListCell *cell;
4090
4091 foreach(cell, paths)
4092 {
4093 ExtensionLocation *location = lfirst(cell);
4094 char *path = location->loc;
4095 char *full;
4096
4097 Assert(path != NULL);
4098
4099 path = pstrdup(path);
4100 canonicalize_path(path);
4101
4102 /* only absolute paths */
4103 if (!is_absolute_path(path))
4104 ereport(ERROR,
4106 errmsg("component in parameter \"%s\" is not an absolute path", "extension_control_path"));
4107
4108 full = psprintf("%s/%s", path, basename);
4109
4110 if (pg_file_exists(full))
4111 return full;
4112
4113 pfree(path);
4114 pfree(full);
4115 }
4116
4117 return NULL;
4118}
AclResult
Definition acl.h:183
@ ACLCHECK_OK
Definition acl.h:184
@ ACLCHECK_NOT_OWNER
Definition acl.h:186
void recordExtObjInitPriv(Oid objoid, Oid classoid)
Definition aclchk.c:4397
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition aclchk.c:2672
AclResult object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode)
Definition aclchk.c:3879
bool object_ownercheck(Oid classid, Oid objectid, Oid roleid)
Definition aclchk.c:4133
void removeExtObjInitPriv(Oid objoid, Oid classoid)
Definition aclchk.c:4561
Oid AlterObjectNamespace_oid(Oid classId, Oid objid, Oid nspOid, ObjectAddresses *objsMoved)
Definition alter.c:621
#define ARR_NDIM(a)
Definition array.h:290
#define ARR_DATA_PTR(a)
Definition array.h:322
#define DatumGetArrayTypeP(X)
Definition array.h:261
#define ARR_ELEMTYPE(a)
Definition array.h:292
#define ARR_DIMS(a)
Definition array.h:294
#define ARR_HASNULL(a)
Definition array.h:291
#define ARR_LBOUND(a)
Definition array.h:296
ArrayType * array_set(ArrayType *array, int nSubscripts, int *indx, Datum dataValue, bool isNull, int arraytyplen, int elmlen, bool elmbyval, char elmalign)
ArrayType * construct_array_builtin(Datum *elems, int nelems, Oid elmtype)
void deconstruct_array_builtin(const ArrayType *array, Oid elmtype, Datum **elemsp, bool **nullsp, int *nelemsp)
bool parse_bool(const char *value, bool *result)
Definition bool.c:31
static Datum values[MAXATTR]
Definition bootstrap.c:188
#define CStringGetTextDatum(s)
Definition builtins.h:98
#define NameStr(name)
Definition c.h:837
#define PG_BINARY_R
Definition c.h:1378
#define Assert(condition)
Definition c.h:945
uint32_t uint32
Definition c.h:618
#define OidIsValid(objectId)
Definition c.h:860
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition catalog.c:448
void CreateComments(Oid oid, Oid classoid, int32 subid, const char *comment)
Definition comment.c:153
#define CONF_FILE_START_DEPTH
Definition conffiles.h:17
char * defGetString(DefElem *def)
Definition define.c:34
bool defGetBoolean(DefElem *def)
Definition define.c:93
void errorConflictingDefElem(DefElem *defel, ParseState *pstate)
Definition define.c:370
void record_object_address_dependencies(const ObjectAddress *depender, ObjectAddresses *referenced, DependencyType behavior)
void add_exact_object_address(const ObjectAddress *object, ObjectAddresses *addrs)
ObjectAddresses * new_object_addresses(void)
void free_object_addresses(ObjectAddresses *addrs)
@ 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
DynamicFileList * get_next_loaded_module(DynamicFileList *dfptr)
Definition dfmgr.c:431
DynamicFileList * get_first_loaded_module(void)
Definition dfmgr.c:425
void get_loaded_module_details(DynamicFileList *dfptr, const char **library_path, const char **module_name, const char **module_version)
Definition dfmgr.c:445
char * substitute_path_macro(const char *str, const char *macro, const char *value)
Definition dfmgr.c:536
Datum arg
Definition elog.c:1322
int errcode_for_file_access(void)
Definition elog.c:897
ErrorContextCallback * error_context_stack
Definition elog.c:99
int errcode(int sqlerrcode)
Definition elog.c:874
#define errcontext
Definition elog.h:198
int errhint(const char *fmt,...) pg_attribute_printf(1
int internalerrquery(const char *query)
int internalerrposition(int cursorpos)
int errdetail(const char *fmt,...) pg_attribute_printf(1
#define PG_TRY(...)
Definition elog.h:372
#define WARNING
Definition elog.h:36
#define PG_END_TRY(...)
Definition elog.h:397
#define DEBUG1
Definition elog.h:30
#define ERROR
Definition elog.h:39
int geterrposition(void)
#define elog(elevel,...)
Definition elog.h:226
#define NOTICE
Definition elog.h:35
#define PG_FINALLY(...)
Definition elog.h:389
int errposition(int cursorpos)
#define ereport(elevel,...)
Definition elog.h:150
void ExecutorEnd(QueryDesc *queryDesc)
Definition execMain.c:468
void ExecutorFinish(QueryDesc *queryDesc)
Definition execMain.c:408
void ExecutorStart(QueryDesc *queryDesc, int eflags)
Definition execMain.c:124
void ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count)
Definition execMain.c:299
static char * get_extension_aux_control_filename(ExtensionControlFile *control, const char *version)
Definition extension.c:638
Oid get_extension_schema(Oid ext_oid)
Definition extension.c:273
static bool is_extension_script_filename(const char *filename)
Definition extension.c:503
static char * read_whole_file(const char *filename, int *length)
Definition extension.c:3999
ObjectAddress InsertExtensionTuple(const char *extName, Oid extOwner, Oid schemaOid, bool relocatable, const char *extVersion, Datum extConfig, Datum extCondition, List *requiredExtensions)
Definition extension.c:2242
static void check_valid_extension_name(const char *extensionname)
Definition extension.c:401
Oid get_function_sibling_type(Oid funcoid, const char *typname)
Definition extension.c:313
static ExtensionVersionInfo * get_nearest_unprocessed_vertex(List *evi_list)
Definition extension.c:1552
ObjectAddress CreateExtension(ParseState *pstate, CreateExtensionStmt *stmt)
Definition extension.c:2144
static void check_valid_version_name(const char *versionname)
Definition extension.c:448
static void get_available_versions_for_extension(ExtensionControlFile *pcontrol, Tuplestorestate *tupstore, TupleDesc tupdesc, ExtensionLocation *location)
Definition extension.c:2563
static bool is_extension_control_filename(const char *filename)
Definition extension.c:495
Datum pg_get_loaded_modules(PG_FUNCTION_ARGS)
Definition extension.c:3035
static ExtensionSiblingCache * ext_sibling_list
Definition extension.c:163
static Oid get_required_extension(char *reqExtensionName, char *extensionName, char *origSchemaName, bool cascade, List *parents, bool is_create)
Definition extension.c:2073
static void script_error_callback(void *arg)
Definition extension.c:954
static ExtensionControlFile * read_extension_aux_control_file(const ExtensionControlFile *pcontrol, const char *version)
Definition extension.c:898
static char * get_extension_location(ExtensionLocation *loc)
Definition extension.c:204
char * Extension_control_path
Definition extension.c:77
static void parse_extension_control_file(ExtensionControlFile *control, const char *version)
Definition extension.c:691
bool creating_extension
Definition extension.c:80
static List * get_extension_control_directories(void)
Definition extension.c:514
Datum pg_available_extension_versions(PG_FUNCTION_ARGS)
Definition extension.c:2486
static void extension_config_remove(Oid extensionoid, Oid tableoid)
Definition extension.c:3088
static void execute_sql_string(const char *sql, const char *filename)
Definition extension.c:1096
static char * get_extension_script_directory(ExtensionControlFile *control)
Definition extension.c:619
static void ext_sibling_callback(Datum arg, SysCacheIdentifier cacheid, uint32 hashvalue)
Definition extension.c:384
static char * find_extension_control_filename(ExtensionControlFile *control)
Definition extension.c:593
ObjectAddress AlterExtensionNamespace(const char *extensionName, const char *newschema, Oid *oldschema)
Definition extension.c:3253
static ExtensionVersionInfo * find_install_path(List *evi_list, ExtensionVersionInfo *evi_target, List **best_path)
Definition extension.c:1779
static ExtensionControlFile * read_extension_control_file(const char *extname)
Definition extension.c:879
ObjectAddress ExecAlterExtensionStmt(ParseState *pstate, AlterExtensionStmt *stmt)
Definition extension.c:3468
Oid CurrentExtensionObject
Definition extension.c:81
ObjectAddress ExecAlterExtensionContentsStmt(AlterExtensionContentsStmt *stmt, ObjectAddress *objAddr)
Definition extension.c:3773
Datum pg_extension_update_paths(PG_FUNCTION_ARGS)
Definition extension.c:2767
static char * read_extension_script_file(const ExtensionControlFile *control, const char *filename)
Definition extension.c:921
static void ExecAlterExtensionContentsRecurse(AlterExtensionContentsStmt *stmt, ObjectAddress extension, ObjectAddress object)
Definition extension.c:3859
Oid get_extension_oid(const char *extname, bool missing_ok)
Definition extension.c:229
Datum pg_available_extensions(PG_FUNCTION_ARGS)
Definition extension.c:2384
static ExtensionControlFile * new_ExtensionControlFile(const char *extname)
Definition extension.c:4064
Datum pg_extension_config_dump(PG_FUNCTION_ARGS)
Definition extension.c:2852
char * find_in_paths(const char *basename, List *paths)
Definition extension.c:4087
static Datum convert_requires_to_datum(List *requires)
Definition extension.c:2741
static List * identify_update_path(ExtensionControlFile *control, const char *oldVersion, const char *newVersion)
Definition extension.c:1643
static ExtensionVersionInfo * get_ext_ver_info(const char *versionname, List **evi_list)
Definition extension.c:1519
char * get_extension_name(Oid ext_oid)
Definition extension.c:251
void RemoveExtensionById(Oid extId)
Definition extension.c:2330
static List * get_ext_ver_list(ExtensionControlFile *control)
Definition extension.c:1580
static List * find_update_path(List *evi_list, ExtensionVersionInfo *evi_start, ExtensionVersionInfo *evi_target, bool reject_indirect, bool reinitialize)
Definition extension.c:1686
static char * get_extension_script_filename(ExtensionControlFile *control, const char *from_version, const char *version)
Definition extension.c:656
static void execute_extension_script(Oid extensionOid, ExtensionControlFile *control, const char *from_version, const char *version, List *requiredSchemas, const char *schemaName)
Definition extension.c:1246
bool extension_file_exists(const char *extensionName)
Definition extension.c:2682
static bool extension_is_trusted(ExtensionControlFile *control)
Definition extension.c:1224
static void ApplyExtensionUpdates(Oid extensionOid, ExtensionControlFile *pcontrol, const char *initialVersion, List *updateVersions, char *origSchemaName, bool cascade, bool is_create)
Definition extension.c:3615
static ObjectAddress CreateExtensionInternal(char *extensionName, char *schemaName, const char *versionName, bool cascade, List *parents, bool is_create)
Definition extension.c:1834
int FreeDir(DIR *dir)
Definition fd.c:3009
int FreeFile(FILE *file)
Definition fd.c:2827
bool pg_file_exists(const char *name)
Definition fd.c:504
DIR * AllocateDir(const char *dirname)
Definition fd.c:2891
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition fd.c:2957
FILE * AllocateFile(const char *name, const char *mode)
Definition fd.c:2628
#define palloc_object(type)
Definition fe_memutils.h:74
#define MaxAllocSize
Definition fe_memutils.h:22
#define palloc0_object(type)
Definition fe_memutils.h:75
Datum DirectFunctionCall4Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4)
Definition fmgr.c:861
Datum DirectFunctionCall3Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2, Datum arg3)
Definition fmgr.c:836
#define PG_RETURN_VOID()
Definition fmgr.h:350
#define PG_GETARG_OID(n)
Definition fmgr.h:275
#define PG_GETARG_TEXT_PP(n)
Definition fmgr.h:310
#define DatumGetTextPP(X)
Definition fmgr.h:293
#define DirectFunctionCall1(func, arg1)
Definition fmgr.h:684
#define PG_GETARG_NAME(n)
Definition fmgr.h:279
#define PG_FUNCTION_ARGS
Definition fmgr.h:193
char * format_type_be(Oid type_oid)
void InitMaterializedSRF(FunctionCallInfo fcinfo, bits32 flags)
Definition funcapi.c:76
void systable_endscan(SysScanDesc sysscan)
Definition genam.c:603
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition genam.c:514
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition genam.c:388
char my_exec_path[MAXPGPATH]
Definition globals.c:81
Oid MyDatabaseId
Definition globals.c:94
void FreeConfigVariables(ConfigVariable *list)
Definition guc-file.l:617
bool ParseConfigFp(FILE *fp, const char *config_file, int depth, int elevel, ConfigVariable **head_p, ConfigVariable **tail_p)
Definition guc-file.l:350
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:3288
int NewGUCNestLevel(void)
Definition guc.c:2142
void AtEOXact_GUC(bool isCommit, int nestLevel)
Definition guc.c:2169
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:3248
@ GUC_ACTION_SAVE
Definition guc.h:205
@ PGC_S_SESSION
Definition guc.h:126
@ PGC_SUSET
Definition guc.h:78
@ PGC_USERSET
Definition guc.h:79
bool check_function_bodies
Definition guc_tables.c:539
int client_min_messages
Definition guc_tables.c:550
int log_min_messages[]
Definition guc_tables.c:664
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, const Datum *replValues, const bool *replIsnull, const bool *doReplace)
Definition heaptuple.c:1130
HeapTuple heap_copytuple(HeapTuple tuple)
Definition heaptuple.c:698
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
Definition heaptuple.c:1037
void heap_freetuple(HeapTuple htup)
Definition heaptuple.c:1384
#define HeapTupleIsValid(tuple)
Definition htup.h:78
static Datum heap_getattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
static void * GETSTRUCT(const HeapTupleData *tuple)
#define stmt
void CatalogTupleUpdate(Relation heapRel, const ItemPointerData *otid, HeapTuple tup)
Definition indexing.c:313
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition indexing.c:233
void CatalogTupleDelete(Relation heapRel, const ItemPointerData *tid)
Definition indexing.c:365
void CacheRegisterSyscacheCallback(SysCacheIdentifier cacheid, SyscacheCallbackFunction func, Datum arg)
Definition inval.c:1816
int a
Definition isn.c:73
int i
Definition isn.c:77
List * lappend(List *list, void *datum)
Definition list.c:339
List * list_copy(const List *oldlist)
Definition list.c:1573
List * lappend_oid(List *list, Oid datum)
Definition list.c:375
List * lcons(void *datum, List *list)
Definition list.c:495
void list_free(List *list)
Definition list.c:1546
bool list_member(const List *list, const void *datum)
Definition list.c:661
#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_rel_name(Oid relid)
Definition lsyscache.c:2148
bool type_is_range(Oid typid)
Definition lsyscache.c:2910
Oid get_rel_type_id(Oid relid)
Definition lsyscache.c:2199
Oid get_range_multirange(Oid rangeOid)
Definition lsyscache.c:3680
char * get_namespace_name(Oid nspid)
Definition lsyscache.c:3588
Oid get_array_type(Oid typid)
Definition lsyscache.c:3009
int GetDatabaseEncoding(void)
Definition mbutils.c:1389
char * pg_any_to_server(const char *s, int len, int encoding)
Definition mbutils.c:687
bool pg_verify_mbstr(int encoding, const char *mbstr, int len, bool noError)
Definition mbutils.c:1694
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition mcxt.c:1266
char * pstrdup(const char *in)
Definition mcxt.c:1781
void pfree(void *pointer)
Definition mcxt.c:1616
void * palloc(Size size)
Definition mcxt.c:1387
MemoryContext CurrentMemoryContext
Definition mcxt.c:160
char * pnstrdup(const char *in, Size len)
Definition mcxt.c:1792
MemoryContext CacheMemoryContext
Definition mcxt.c:169
void MemoryContextDelete(MemoryContext context)
Definition mcxt.c:472
#define AllocSetContextCreate
Definition memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition memutils.h:160
#define SECURITY_LOCAL_USERID_CHANGE
Definition miscadmin.h:318
void GetUserIdAndSecContext(Oid *userid, int *sec_context)
Definition miscinit.c:613
Oid GetUserId(void)
Definition miscinit.c:470
BackendType MyBackendType
Definition miscinit.c:65
char * GetUserNameFromId(Oid roleid, bool noerr)
Definition miscinit.c:989
void SetUserIdAndSecContext(Oid userid, int sec_context)
Definition miscinit.c:620
Datum namein(PG_FUNCTION_ARGS)
Definition name.c:48
bool isTempNamespace(Oid namespaceId)
Definition namespace.c:3721
Oid LookupCreationNamespace(const char *nspname)
Definition namespace.c:3500
List * fetch_search_path(bool includeImplicit)
Definition namespace.c:4891
Oid get_namespace_oid(const char *nspname, bool missing_ok)
Definition namespace.c:3607
#define IsA(nodeptr, _type_)
Definition nodes.h:164
#define makeNode(_type_)
Definition nodes.h:161
int ParseLoc
Definition nodes.h:250
static char * errmsg
#define InvokeObjectPostCreateHook(classId, objectId, subId)
#define InvokeObjectPostAlterHook(classId, objectId, subId)
void check_object_ownership(Oid roleid, ObjectType objtype, ObjectAddress address, Node *object, Relation relation)
char * getObjectDescription(const ObjectAddress *object, bool missing_ok)
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)
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:124
@ OBJECT_SCHEMA
@ OBJECT_TABLESPACE
@ OBJECT_ROLE
@ OBJECT_EXTENSION
@ OBJECT_INDEX
@ OBJECT_DATABASE
@ OBJECT_PUBLICATION
@ OBJECT_SUBSCRIPTION
@ OBJECT_STATISTIC_EXT
#define CURSOR_OPT_PARALLEL_OK
#define ACL_CREATE
Definition parsenodes.h:85
#define MAXPGPATH
const void size_t len
Oid getExtensionType(Oid extensionOid, const char *typname)
Definition pg_depend.c:832
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition pg_depend.c:47
long changeDependencyFor(Oid classId, Oid objectId, Oid refClassId, Oid oldRefObjectId, Oid newRefObjectId)
Definition pg_depend.c:459
long deleteDependencyRecordsForClass(Oid classId, Oid objectId, Oid refclassId, char deptype)
Definition pg_depend.c:353
Oid getExtensionOfObject(Oid classId, Oid objectId)
Definition pg_depend.c:734
END_CATALOG_STRUCT typedef FormData_pg_depend * Form_pg_depend
Definition pg_depend.h:76
static char * filename
Definition pg_dumpall.c:133
END_CATALOG_STRUCT typedef FormData_pg_extension * Form_pg_extension
#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:518
#define foreach_ptr(type, var, lst)
Definition pg_list.h:469
#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)
static char buf[DEFAULT_XLOG_SEG_SIZE]
NameData typname
Definition pg_type.h:43
#define pg_valid_server_encoding
Definition pg_wchar.h:631
#define ERRCODE_UNDEFINED_TABLE
Definition pgbench.c:79
void get_share_path(const char *my_exec_path, char *ret_path)
Definition path.c:902
#define is_absolute_path(filename)
Definition port.h:104
char * last_dir_separator(const char *filename)
Definition path.c:145
char * first_path_var_separator(const char *pathlist)
Definition path.c:127
void canonicalize_path(char *path)
Definition path.c:337
#define snprintf
Definition port.h:260
char * first_dir_separator(const char *filename)
Definition path.c:110
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition strlcpy.c:45
List * pg_parse_query(const char *query_string)
Definition postgres.c:604
List * pg_plan_queries(List *querytrees, const char *query_string, int cursorOptions, ParamListInfo boundParams)
Definition postgres.c:975
List * pg_analyze_and_rewrite_fixedparams(RawStmt *parsetree, const char *query_string, const Oid *paramTypes, int numParams, QueryEnvironment *queryEnv)
Definition postgres.c:670
static Datum PointerGetDatum(const void *X)
Definition postgres.h:342
static Datum BoolGetDatum(bool X)
Definition postgres.h:112
static Datum ObjectIdGetDatum(Oid X)
Definition postgres.h:252
uint64_t Datum
Definition postgres.h:70
static Datum CStringGetDatum(const char *X)
Definition postgres.h:370
#define InvalidOid
unsigned int Oid
void FreeQueryDesc(QueryDesc *qdesc)
Definition pquery.c:106
QueryDesc * CreateQueryDesc(PlannedStmt *plannedstmt, const char *sourceText, Snapshot snapshot, Snapshot crosscheck_snapshot, DestReceiver *dest, ParamListInfo params, QueryEnvironment *queryEnv, int instrument_options)
Definition pquery.c:68
static int fb(int x)
char * psprintf(const char *fmt,...)
Definition psprintf.c:43
const char * CleanQuerytext(const char *query, int *location, int *len)
Datum textregexreplace(PG_FUNCTION_ARGS)
Definition regexp.c:658
#define RelationGetDescr(relation)
Definition rel.h:540
const char * quote_identifier(const char *ident)
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:272
void PushActiveSnapshot(Snapshot snapshot)
Definition snapmgr.c:682
void PopActiveSnapshot(void)
Definition snapmgr.c:775
Snapshot GetActiveSnapshot(void)
Definition snapmgr.c:800
void relation_close(Relation relation, LOCKMODE lockmode)
Definition relation.c:205
#define BTEqualStrategyNumber
Definition stratnum.h:31
#define ERRCODE_DUPLICATE_OBJECT
Definition streamutil.c:30
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition stringinfo.c:145
void appendStringInfoString(StringInfo str, const char *s)
Definition stringinfo.c:230
void initStringInfo(StringInfo str)
Definition stringinfo.c:97
char * name
Definition guc.h:141
struct ConfigVariable * next
Definition guc.h:148
char * value
Definition guc.h:142
Definition dirent.c:26
struct ErrorContextCallback * previous
Definition elog.h:297
List *List * no_relocate
Definition extension.c:103
struct ExtensionSiblingCache * next
Definition extension.c:153
const char * typname
Definition extension.c:156
struct ExtensionVersionInfo * previous
Definition extension.c:118
ItemPointerData t_self
Definition htup.h:65
Definition pg_list.h:54
Definition nodes.h:135
ParseLoc stmt_location
ParseLoc stmt_len
TupleDesc rd_att
Definition rel.h:112
Definition value.h:64
Definition c.h:832
Definition c.h:778
bool superuser(void)
Definition superuser.c:47
void ReleaseSysCache(HeapTuple tuple)
Definition syscache.c:264
HeapTuple SearchSysCache1(SysCacheIdentifier cacheId, Datum key1)
Definition syscache.c:220
#define GetSysCacheHashValue1(cacheId, key1)
Definition syscache.h:118
#define GetSysCacheOid1(cacheId, oidcol, key1)
Definition syscache.h:109
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, const Datum *values, const bool *isnull)
Definition tuplestore.c:785
void ProcessUtility(PlannedStmt *pstmt, const char *queryString, bool readOnlyTree, ProcessUtilityContext context, ParamListInfo params, QueryEnvironment *queryEnv, DestReceiver *dest, QueryCompletion *qc)
Definition utility.c:504
@ PROCESS_UTILITY_QUERY
Definition utility.h:23
String * makeString(char *str)
Definition value.c:63
#define strVal(v)
Definition value.h:82
bool SplitIdentifierString(char *rawstring, char separator, List **namelist)
Definition varlena.c:2777
char * text_to_cstring(const text *t)
Definition varlena.c:217
Datum replace_text(PG_FUNCTION_ARGS)
Definition varlena.c:3125
#define stat
Definition win32_port.h:74
void CommandCounterIncrement(void)
Definition xact.c:1102
int MyXactFlags
Definition xact.c:138
#define XACT_FLAGS_ACCESSEDTEMPNAMESPACE
Definition xact.h:103