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/varlena.h"
73
74
75/* GUC */
77
78/* Globally visible state variables */
79bool creating_extension = false;
81
82/*
83 * Internal data structure to hold the results of parsing a control file
84 */
86{
87 char *name; /* name of the extension */
88 char *basedir; /* base directory where control and script
89 * files are located */
90 char *control_dir; /* directory where control file was found */
91 char *directory; /* directory for script files */
92 char *default_version; /* default install target version, if any */
93 char *module_pathname; /* string to substitute for
94 * MODULE_PATHNAME */
95 char *comment; /* comment, if any */
96 char *schema; /* target schema (allowed if !relocatable) */
97 bool relocatable; /* is ALTER EXTENSION SET SCHEMA supported? */
98 bool superuser; /* must be superuser to install? */
99 bool trusted; /* allow becoming superuser on the fly? */
100 int encoding; /* encoding of the script file, or -1 */
101 List *requires; /* names of prerequisite extensions */
102 List *no_relocate; /* names of prerequisite extensions that
103 * should not be relocated */
105
106/*
107 * Internal data structure for update path information
108 */
110{
111 char *name; /* name of the starting version */
112 List *reachable; /* List of ExtensionVersionInfo's */
113 bool installable; /* does this version have an install script? */
114 /* working state for Dijkstra's algorithm: */
115 bool distance_known; /* is distance from start known yet? */
116 int distance; /* current worst-case distance estimate */
117 struct ExtensionVersionInfo *previous; /* current best predecessor */
119
120/*
121 * Information for script_error_callback()
122 */
123typedef struct
124{
125 const char *sql; /* entire script file contents */
126 const char *filename; /* script file pathname */
127 ParseLoc stmt_location; /* current stmt start loc, or -1 if unknown */
128 ParseLoc stmt_len; /* length in bytes; 0 means "rest of string" */
130
131/*
132 * A location based on the extension_control_path GUC.
133 *
134 * The macro field stores the name of a macro (for example “$system”) that
135 * the extension_control_path processing supports, and which can be replaced
136 * by a system value stored in loc.
137 *
138 * For non-system paths the macro field is NULL.
139 */
140typedef struct
141{
142 char *macro;
143 char *loc;
145
146/*
147 * Cache structure for get_function_sibling_type (and maybe later,
148 * allied lookup functions).
149 */
151{
152 struct ExtensionSiblingCache *next; /* list link */
153 /* lookup key: requesting function's OID and type name */
155 const char *typname;
156 bool valid; /* is entry currently valid? */
157 uint32 exthash; /* cache hash of owning extension's OID */
158 Oid typeoid; /* OID associated with typname */
160
161/* Head of linked list of ExtensionSiblingCache structs */
163
164/* Local functions */
165static void ext_sibling_callback(Datum arg, int cacheid, uint32 hashvalue);
169 bool reject_indirect,
170 bool reinitialize);
172 char *extensionName,
173 char *origSchemaName,
174 bool cascade,
175 List *parents,
176 bool is_create);
178 Tuplestorestate *tupstore,
179 TupleDesc tupdesc,
180 ExtensionLocation *location);
181static Datum convert_requires_to_datum(List *requires);
184 const char *initialVersion,
186 char *origSchemaName,
187 bool cascade,
188 bool is_create);
191 ObjectAddress object);
192static char *read_whole_file(const char *filename, int *length);
193static ExtensionControlFile *new_ExtensionControlFile(const char *extname);
194
195char *find_in_paths(const char *basename, List *paths);
196
197/*
198 * Return the extension location. If the current user doesn't have sufficient
199 * privilege, don't show the location.
200 */
201static char *
203{
204 /* We only want to show extension paths for superusers. */
205 if (superuser())
206 {
207 /* Return the macro value if present to avoid showing system paths. */
208 if (loc->macro != NULL)
209 return loc->macro;
210 else
211 return loc->loc;
212 }
213 else
214 {
215 /* Similar to pg_stat_activity for unprivileged users */
216 return "<insufficient privilege>";
217 }
218}
219
220/*
221 * get_extension_oid - given an extension name, look up the OID
222 *
223 * If missing_ok is false, throw an error if extension name not found. If
224 * true, just return InvalidOid.
225 */
226Oid
227get_extension_oid(const char *extname, bool missing_ok)
228{
229 Oid result;
230
232 CStringGetDatum(extname));
233
234 if (!OidIsValid(result) && !missing_ok)
237 errmsg("extension \"%s\" does not exist",
238 extname)));
239
240 return result;
241}
242
243/*
244 * get_extension_name - given an extension OID, look up the name
245 *
246 * Returns a palloc'd string, or NULL if no such extension.
247 */
248char *
250{
251 char *result;
252 HeapTuple tuple;
253
255
256 if (!HeapTupleIsValid(tuple))
257 return NULL;
258
259 result = pstrdup(NameStr(((Form_pg_extension) GETSTRUCT(tuple))->extname));
260 ReleaseSysCache(tuple);
261
262 return result;
263}
264
265/*
266 * get_extension_schema - given an extension OID, fetch its extnamespace
267 *
268 * Returns InvalidOid if no such extension.
269 */
270Oid
272{
273 Oid result;
274 HeapTuple tuple;
275
277
278 if (!HeapTupleIsValid(tuple))
279 return InvalidOid;
280
281 result = ((Form_pg_extension) GETSTRUCT(tuple))->extnamespace;
282 ReleaseSysCache(tuple);
283
284 return result;
285}
286
287/*
288 * get_function_sibling_type - find a type belonging to same extension as func
289 *
290 * Returns the type's OID, or InvalidOid if not found.
291 *
292 * This is useful in extensions, which won't have fixed object OIDs.
293 * We work from the calling function's own OID, which it can get from its
294 * FunctionCallInfo parameter, and look up the owning extension and thence
295 * a type belonging to the same extension.
296 *
297 * Notice that the type is specified by name only, without a schema.
298 * That's because this will typically be used by relocatable extensions
299 * which can't make a-priori assumptions about which schema their objects
300 * are in. As long as the extension only defines one type of this name,
301 * the answer is unique anyway.
302 *
303 * We might later add the ability to look up functions, operators, etc.
304 *
305 * This code is simply a frontend for some pg_depend lookups. Those lookups
306 * are fairly expensive, so we provide a simple cache facility. We assume
307 * that the passed typname is actually a C constant, or at least permanently
308 * allocated, so that we need not copy that string.
309 */
310Oid
312{
314 Oid extoid;
315 Oid typeoid;
316
317 /*
318 * See if we have the answer cached. Someday there may be enough callers
319 * to justify a hash table, but for now, a simple linked list is fine.
320 */
323 {
324 if (funcoid == cache_entry->reqfuncoid &&
325 strcmp(typname, cache_entry->typname) == 0)
326 break;
327 }
328 if (cache_entry && cache_entry->valid)
329 return cache_entry->typeoid;
330
331 /*
332 * Nope, so do the expensive lookups. We do not expect failures, so we do
333 * not cache negative results.
334 */
336 if (!OidIsValid(extoid))
337 return InvalidOid;
339 if (!OidIsValid(typeoid))
340 return InvalidOid;
341
342 /*
343 * Build, or revalidate, cache entry.
344 */
345 if (cache_entry == NULL)
346 {
347 /* Register invalidation hook if this is first entry */
348 if (ext_sibling_list == NULL)
351 (Datum) 0);
352
353 /* Momentarily zero the space to ensure valid flag is false */
356 sizeof(ExtensionSiblingCache));
359 }
360
362 cache_entry->typname = typname;
365 cache_entry->typeoid = typeoid;
366 /* Mark it valid only once it's fully populated */
367 cache_entry->valid = true;
368
369 return typeoid;
370}
371
372/*
373 * ext_sibling_callback
374 * Syscache inval callback function for EXTENSIONOID cache
375 *
376 * It seems sufficient to invalidate ExtensionSiblingCache entries when
377 * the owning extension's pg_extension entry is modified or deleted.
378 * Neither a requesting function's OID, nor the OID of the object it's
379 * looking for, could change without an extension update or drop/recreate.
380 */
381static void
383{
385
388 {
389 if (hashvalue == 0 ||
390 cache_entry->exthash == hashvalue)
391 cache_entry->valid = false;
392 }
393}
394
395/*
396 * Utility functions to check validity of extension and version names
397 */
398static void
400{
401 int namelen = strlen(extensionname);
402
403 /*
404 * Disallow empty names (the parser rejects empty identifiers anyway, but
405 * let's check).
406 */
407 if (namelen == 0)
410 errmsg("invalid extension name: \"%s\"", extensionname),
411 errdetail("Extension names must not be empty.")));
412
413 /*
414 * No double dashes, since that would make script filenames ambiguous.
415 */
416 if (strstr(extensionname, "--"))
419 errmsg("invalid extension name: \"%s\"", extensionname),
420 errdetail("Extension names must not contain \"--\".")));
421
422 /*
423 * No leading or trailing dash either. (We could probably allow this, but
424 * it would require much care in filename parsing and would make filenames
425 * visually if not formally ambiguous. Since there's no real-world use
426 * case, let's just forbid it.)
427 */
428 if (extensionname[0] == '-' || extensionname[namelen - 1] == '-')
431 errmsg("invalid extension name: \"%s\"", extensionname),
432 errdetail("Extension names must not begin or end with \"-\".")));
433
434 /*
435 * No directory separators either (this is sufficient to prevent ".."
436 * style attacks).
437 */
441 errmsg("invalid extension name: \"%s\"", extensionname),
442 errdetail("Extension names must not contain directory separator characters.")));
443}
444
445static void
447{
448 int namelen = strlen(versionname);
449
450 /*
451 * Disallow empty names (we could possibly allow this, but there seems
452 * little point).
453 */
454 if (namelen == 0)
457 errmsg("invalid extension version name: \"%s\"", versionname),
458 errdetail("Version names must not be empty.")));
459
460 /*
461 * No double dashes, since that would make script filenames ambiguous.
462 */
463 if (strstr(versionname, "--"))
466 errmsg("invalid extension version name: \"%s\"", versionname),
467 errdetail("Version names must not contain \"--\".")));
468
469 /*
470 * No leading or trailing dash either.
471 */
472 if (versionname[0] == '-' || versionname[namelen - 1] == '-')
475 errmsg("invalid extension version name: \"%s\"", versionname),
476 errdetail("Version names must not begin or end with \"-\".")));
477
478 /*
479 * No directory separators either (this is sufficient to prevent ".."
480 * style attacks).
481 */
485 errmsg("invalid extension version name: \"%s\"", versionname),
486 errdetail("Version names must not contain directory separator characters.")));
487}
488
489/*
490 * Utility functions to handle extension-related path names
491 */
492static bool
494{
495 const char *extension = strrchr(filename, '.');
496
497 return (extension != NULL) && (strcmp(extension, ".control") == 0);
498}
499
500static bool
502{
503 const char *extension = strrchr(filename, '.');
504
505 return (extension != NULL) && (strcmp(extension, ".sql") == 0);
506}
507
508/*
509 * Return a list of directories declared in the extension_control_path GUC.
510 */
511static List *
513{
514 char sharepath[MAXPGPATH];
515 char *system_dir;
516 char *ecp;
517 List *paths = NIL;
518
520
521 system_dir = psprintf("%s/extension", sharepath);
522
524 {
526
527 location->macro = NULL;
528 location->loc = system_dir;
529 paths = lappend(paths, location);
530 }
531 else
532 {
533 /* Duplicate the string so we can modify it */
535
536 for (;;)
537 {
538 int len;
539 char *mangled;
542
543 /* Get the length of the next path on ecp */
544 if (piece == NULL)
545 len = strlen(ecp);
546 else
547 len = piece - ecp;
548
549 /* Copy the next path found on ecp */
550 piece = palloc(len + 1);
551 strlcpy(piece, ecp, len + 1);
552
553 /*
554 * Substitute the path macro if needed or append "extension"
555 * suffix if it is a custom extension control path.
556 */
557 if (strcmp(piece, "$system") == 0)
558 {
559 location->macro = pstrdup(piece);
561 }
562 else
563 {
564 location->macro = NULL;
565 mangled = psprintf("%s/extension", piece);
566 }
567 pfree(piece);
568
569 /* Canonicalize the path based on the OS and add to the list */
571 location->loc = mangled;
572 paths = lappend(paths, location);
573
574 /* Break if ecp is empty or move to the next path on ecp */
575 if (ecp[len] == '\0')
576 break;
577 else
578 ecp += len + 1;
579 }
580 }
581
582 return paths;
583}
584
585/*
586 * Find control file for extension with name in control->name, looking in
587 * available paths. Return the full file name, or NULL if not found.
588 * If found, the directory is recorded in control->control_dir.
589 */
590static char *
592{
593 char *basename;
594 char *result;
595 List *paths;
596
597 Assert(control->name);
598
599 basename = psprintf("%s.control", control->name);
600
602 result = find_in_paths(basename, paths);
603
604 if (result)
605 {
606 const char *p;
607
608 p = strrchr(result, '/');
609 Assert(p);
610 control->control_dir = pnstrdup(result, p - result);
611 }
612
613 return result;
614}
615
616static char *
618{
619 /*
620 * The directory parameter can be omitted, absolute, or relative to the
621 * installation's base directory, which can be the sharedir or a custom
622 * path that was set via extension_control_path. It depends on where the
623 * .control file was found.
624 */
625 if (!control->directory)
626 return pstrdup(control->control_dir);
627
628 if (is_absolute_path(control->directory))
629 return pstrdup(control->directory);
630
631 Assert(control->basedir != NULL);
632 return psprintf("%s/%s", control->basedir, control->directory);
633}
634
635static char *
637 const char *version)
638{
639 char *result;
640 char *scriptdir;
641
643
644 result = (char *) palloc(MAXPGPATH);
645 snprintf(result, MAXPGPATH, "%s/%s--%s.control",
646 scriptdir, control->name, version);
647
649
650 return result;
651}
652
653static char *
655 const char *from_version, const char *version)
656{
657 char *result;
658 char *scriptdir;
659
661
662 result = (char *) palloc(MAXPGPATH);
663 if (from_version)
664 snprintf(result, MAXPGPATH, "%s/%s--%s--%s.sql",
665 scriptdir, control->name, from_version, version);
666 else
667 snprintf(result, MAXPGPATH, "%s/%s--%s.sql",
668 scriptdir, control->name, version);
669
671
672 return result;
673}
674
675
676/*
677 * Parse contents of primary or auxiliary control file, and fill in
678 * fields of *control. We parse primary file if version == NULL,
679 * else the optional auxiliary file for that version.
680 *
681 * If control->control_dir is not NULL, use that to read and parse the
682 * control file, otherwise search for the file in extension_control_path.
683 *
684 * Control files are supposed to be very short, half a dozen lines,
685 * so we don't worry about memory allocation risks here. Also we don't
686 * worry about what encoding it's in; all values are expected to be ASCII.
687 */
688static void
690 const char *version)
691{
692 char *filename;
693 FILE *file;
694 ConfigVariable *item,
695 *head = NULL,
696 *tail = NULL;
697
698 /*
699 * Locate the file to read. Auxiliary files are optional.
700 */
701 if (version)
703 else
704 {
705 /*
706 * If control_dir is already set, use it, else do a path search.
707 */
708 if (control->control_dir)
709 {
710 filename = psprintf("%s/%s.control", control->control_dir, control->name);
711 }
712 else
714 }
715
716 if (!filename)
717 {
720 errmsg("extension \"%s\" is not available", control->name),
721 errhint("The extension must first be installed on the system where PostgreSQL is running.")));
722 }
723
724 /* Assert that the control_dir ends with /extension */
725 Assert(control->control_dir != NULL);
726 Assert(strcmp(control->control_dir + strlen(control->control_dir) - strlen("/extension"), "/extension") == 0);
727
728 control->basedir = pnstrdup(
729 control->control_dir,
730 strlen(control->control_dir) - strlen("/extension"));
731
732 if ((file = AllocateFile(filename, "r")) == NULL)
733 {
734 /* no complaint for missing auxiliary file */
735 if (errno == ENOENT && version)
736 {
738 return;
739 }
740
743 errmsg("could not open extension control file \"%s\": %m",
744 filename)));
745 }
746
747 /*
748 * Parse the file content, using GUC's file parsing code. We need not
749 * check the return value since any errors will be thrown at ERROR level.
750 */
752 &head, &tail);
753
754 FreeFile(file);
755
756 /*
757 * Convert the ConfigVariable list into ExtensionControlFile entries.
758 */
759 for (item = head; item != NULL; item = item->next)
760 {
761 if (strcmp(item->name, "directory") == 0)
762 {
763 if (version)
766 errmsg("parameter \"%s\" cannot be set in a secondary extension control file",
767 item->name)));
768
769 control->directory = pstrdup(item->value);
770 }
771 else if (strcmp(item->name, "default_version") == 0)
772 {
773 if (version)
776 errmsg("parameter \"%s\" cannot be set in a secondary extension control file",
777 item->name)));
778
779 control->default_version = pstrdup(item->value);
780 }
781 else if (strcmp(item->name, "module_pathname") == 0)
782 {
783 control->module_pathname = pstrdup(item->value);
784 }
785 else if (strcmp(item->name, "comment") == 0)
786 {
787 control->comment = pstrdup(item->value);
788 }
789 else if (strcmp(item->name, "schema") == 0)
790 {
791 control->schema = pstrdup(item->value);
792 }
793 else if (strcmp(item->name, "relocatable") == 0)
794 {
795 if (!parse_bool(item->value, &control->relocatable))
798 errmsg("parameter \"%s\" requires a Boolean value",
799 item->name)));
800 }
801 else if (strcmp(item->name, "superuser") == 0)
802 {
803 if (!parse_bool(item->value, &control->superuser))
806 errmsg("parameter \"%s\" requires a Boolean value",
807 item->name)));
808 }
809 else if (strcmp(item->name, "trusted") == 0)
810 {
811 if (!parse_bool(item->value, &control->trusted))
814 errmsg("parameter \"%s\" requires a Boolean value",
815 item->name)));
816 }
817 else if (strcmp(item->name, "encoding") == 0)
818 {
819 control->encoding = pg_valid_server_encoding(item->value);
820 if (control->encoding < 0)
823 errmsg("\"%s\" is not a valid encoding name",
824 item->value)));
825 }
826 else if (strcmp(item->name, "requires") == 0)
827 {
828 /* Need a modifiable copy of string */
829 char *rawnames = pstrdup(item->value);
830
831 /* Parse string into list of identifiers */
832 if (!SplitIdentifierString(rawnames, ',', &control->requires))
833 {
834 /* syntax error in name list */
837 errmsg("parameter \"%s\" must be a list of extension names",
838 item->name)));
839 }
840 }
841 else if (strcmp(item->name, "no_relocate") == 0)
842 {
843 /* Need a modifiable copy of string */
844 char *rawnames = pstrdup(item->value);
845
846 /* Parse string into list of identifiers */
847 if (!SplitIdentifierString(rawnames, ',', &control->no_relocate))
848 {
849 /* syntax error in name list */
852 errmsg("parameter \"%s\" must be a list of extension names",
853 item->name)));
854 }
855 }
856 else
859 errmsg("unrecognized parameter \"%s\" in file \"%s\"",
860 item->name, filename)));
861 }
862
864
865 if (control->relocatable && control->schema != NULL)
868 errmsg("parameter \"schema\" cannot be specified when \"relocatable\" is true")));
869
871}
872
873/*
874 * Read the primary control file for the specified extension.
875 */
877read_extension_control_file(const char *extname)
878{
880
881 /*
882 * Parse the primary control file.
883 */
885
886 return control;
887}
888
889/*
890 * Read the auxiliary control file for the specified extension and version.
891 *
892 * Returns a new modified ExtensionControlFile struct; the original struct
893 * (reflecting just the primary control file) is not modified.
894 */
897 const char *version)
898{
900
901 /*
902 * Flat-copy the struct. Pointer fields share values with original.
903 */
906
907 /*
908 * Parse the auxiliary control file, overwriting struct fields
909 */
911
912 return acontrol;
913}
914
915/*
916 * Read an SQL script file into a string, and convert to database encoding
917 */
918static char *
920 const char *filename)
921{
922 int src_encoding;
923 char *src_str;
924 char *dest_str;
925 int len;
926
928
929 /* use database encoding if not given */
930 if (control->encoding < 0)
932 else
933 src_encoding = control->encoding;
934
935 /* make sure that source string is valid in the expected encoding */
937
938 /*
939 * Convert the encoding to the database encoding. read_whole_file
940 * null-terminated the string, so if no conversion happens the string is
941 * valid as is.
942 */
944
945 return dest_str;
946}
947
948/*
949 * error context callback for failures in script-file execution
950 */
951static void
953{
955 const char *query = callback_arg->sql;
956 int location = callback_arg->stmt_location;
957 int len = callback_arg->stmt_len;
959 const char *lastslash;
960
961 /*
962 * If there is a syntax error position, convert to internal syntax error;
963 * otherwise report the current query as an item of context stack.
964 *
965 * Note: we'll provide no context except the filename if there's neither
966 * an error position nor any known current query. That shouldn't happen
967 * though: all errors reported during raw parsing should come with an
968 * error position.
969 */
971 if (syntaxerrposition > 0)
972 {
973 /*
974 * If we do not know the bounds of the current statement (as would
975 * happen for an error occurring during initial raw parsing), we have
976 * to use a heuristic to decide how much of the script to show. We'll
977 * also use the heuristic in the unlikely case that syntaxerrposition
978 * is outside what we think the statement bounds are.
979 */
980 if (location < 0 || syntaxerrposition < location ||
981 (len > 0 && syntaxerrposition > location + len))
982 {
983 /*
984 * Our heuristic is pretty simple: look for semicolon-newline
985 * sequences, and break at the last one strictly before
986 * syntaxerrposition and the first one strictly after. It's
987 * certainly possible to fool this with semicolon-newline embedded
988 * in a string literal, but it seems better to do this than to
989 * show the entire extension script.
990 *
991 * Notice we cope with Windows-style newlines (\r\n) regardless of
992 * platform. This is because there might be such newlines in
993 * script files on other platforms.
994 */
995 int slen = strlen(query);
996
997 location = len = 0;
998 for (int loc = 0; loc < slen; loc++)
999 {
1000 if (query[loc] != ';')
1001 continue;
1002 if (query[loc + 1] == '\r')
1003 loc++;
1004 if (query[loc + 1] == '\n')
1005 {
1006 int bkpt = loc + 2;
1007
1008 if (bkpt < syntaxerrposition)
1009 location = bkpt;
1010 else if (bkpt > syntaxerrposition)
1011 {
1012 len = bkpt - location;
1013 break; /* no need to keep searching */
1014 }
1015 }
1016 }
1017 }
1018
1019 /* Trim leading/trailing whitespace, for consistency */
1020 query = CleanQuerytext(query, &location, &len);
1021
1022 /*
1023 * Adjust syntaxerrposition. It shouldn't be pointing into the
1024 * whitespace we just trimmed, but cope if it is.
1025 */
1026 syntaxerrposition -= location;
1027 if (syntaxerrposition < 0)
1029 else if (syntaxerrposition > len)
1031
1032 /* And report. */
1033 errposition(0);
1035 internalerrquery(pnstrdup(query, len));
1036 }
1037 else if (location >= 0)
1038 {
1039 /*
1040 * Since no syntax cursor will be shown, it's okay and helpful to trim
1041 * the reported query string to just the current statement.
1042 */
1043 query = CleanQuerytext(query, &location, &len);
1044 errcontext("SQL statement \"%.*s\"", len, query);
1045 }
1046
1047 /*
1048 * Trim the reported file name to remove the path. We know that
1049 * get_extension_script_filename() inserted a '/', regardless of whether
1050 * we're on Windows.
1051 */
1052 lastslash = strrchr(callback_arg->filename, '/');
1053 if (lastslash)
1054 lastslash++;
1055 else
1056 lastslash = callback_arg->filename; /* shouldn't happen, but cope */
1057
1058 /*
1059 * If we have a location (which, as said above, we really always should)
1060 * then report a line number to aid in localizing problems in big scripts.
1061 */
1062 if (location >= 0)
1063 {
1064 int linenumber = 1;
1065
1066 for (query = callback_arg->sql; *query; query++)
1067 {
1068 if (--location < 0)
1069 break;
1070 if (*query == '\n')
1071 linenumber++;
1072 }
1073 errcontext("extension script file \"%s\", near line %d",
1074 lastslash, linenumber);
1075 }
1076 else
1077 errcontext("extension script file \"%s\"", lastslash);
1078}
1079
1080/*
1081 * Execute given SQL string.
1082 *
1083 * The filename the string came from is also provided, for error reporting.
1084 *
1085 * Note: it's tempting to just use SPI to execute the string, but that does
1086 * not work very well. The really serious problem is that SPI will parse,
1087 * analyze, and plan the whole string before executing any of it; of course
1088 * this fails if there are any plannable statements referring to objects
1089 * created earlier in the script. A lesser annoyance is that SPI insists
1090 * on printing the whole string as errcontext in case of any error, and that
1091 * could be very long.
1092 */
1093static void
1094execute_sql_string(const char *sql, const char *filename)
1095{
1096 script_error_callback_arg callback_arg;
1099 DestReceiver *dest;
1100 ListCell *lc1;
1101
1102 /*
1103 * Setup error traceback support for ereport().
1104 */
1105 callback_arg.sql = sql;
1106 callback_arg.filename = filename;
1107 callback_arg.stmt_location = -1;
1108 callback_arg.stmt_len = -1;
1109
1111 scripterrcontext.arg = &callback_arg;
1114
1115 /*
1116 * Parse the SQL string into a list of raw parse trees.
1117 */
1119
1120 /* All output from SELECTs goes to the bit bucket */
1122
1123 /*
1124 * Do parse analysis, rule rewrite, planning, and execution for each raw
1125 * parsetree. We must fully execute each query before beginning parse
1126 * analysis on the next one, since there may be interdependencies.
1127 */
1128 foreach(lc1, raw_parsetree_list)
1129 {
1130 RawStmt *parsetree = lfirst_node(RawStmt, lc1);
1132 oldcontext;
1133 List *stmt_list;
1134 ListCell *lc2;
1135
1136 /* Report location of this query for error context callback */
1137 callback_arg.stmt_location = parsetree->stmt_location;
1138 callback_arg.stmt_len = parsetree->stmt_len;
1139
1140 /*
1141 * We do the work for each parsetree in a short-lived context, to
1142 * limit the memory used when there are many commands in the string.
1143 */
1146 "execute_sql_string per-statement context",
1149
1150 /* Be sure parser can see any DDL done so far */
1152
1153 stmt_list = pg_analyze_and_rewrite_fixedparams(parsetree,
1154 sql,
1155 NULL,
1156 0,
1157 NULL);
1158 stmt_list = pg_plan_queries(stmt_list, sql, CURSOR_OPT_PARALLEL_OK, NULL);
1159
1160 foreach(lc2, stmt_list)
1161 {
1163
1165
1167
1168 if (stmt->utilityStmt == NULL)
1169 {
1171
1173 sql,
1175 dest, NULL, NULL, 0);
1176
1177 ExecutorStart(qdesc, 0);
1181
1183 }
1184 else
1185 {
1186 if (IsA(stmt->utilityStmt, TransactionStmt))
1187 ereport(ERROR,
1189 errmsg("transaction control statements are not allowed within an extension script")));
1190
1192 sql,
1193 false,
1195 NULL,
1196 NULL,
1197 dest,
1198 NULL);
1199 }
1200
1202 }
1203
1204 /* Clean up per-parsetree context. */
1205 MemoryContextSwitchTo(oldcontext);
1207 }
1208
1210
1211 /* Be sure to advance the command counter after the last script command */
1213}
1214
1215/*
1216 * Policy function: is the given extension trusted for installation by a
1217 * non-superuser?
1218 *
1219 * (Update the errhint logic below if you change this.)
1220 */
1221static bool
1223{
1225
1226 /* Never trust unless extension's control file says it's okay */
1227 if (!control->trusted)
1228 return false;
1229 /* Allow if user has CREATE privilege on current database */
1231 if (aclresult == ACLCHECK_OK)
1232 return true;
1233 return false;
1234}
1235
1236/*
1237 * Execute the appropriate script file for installing or updating the extension
1238 *
1239 * If from_version isn't NULL, it's an update
1240 *
1241 * Note: requiredSchemas must be one-for-one with the control->requires list
1242 */
1243static void
1245 const char *from_version,
1246 const char *version,
1248 const char *schemaName)
1249{
1250 bool switch_to_superuser = false;
1251 char *filename;
1252 Oid save_userid = 0;
1253 int save_sec_context = 0;
1254 int save_nestlevel;
1256 ListCell *lc;
1257 ListCell *lc2;
1258
1259 /*
1260 * Enforce superuser-ness if appropriate. We postpone these checks until
1261 * here so that the control flags are correctly associated with the right
1262 * script(s) if they happen to be set in secondary control files.
1263 */
1264 if (control->superuser && !superuser())
1265 {
1266 if (extension_is_trusted(control))
1267 switch_to_superuser = true;
1268 else if (from_version == NULL)
1269 ereport(ERROR,
1271 errmsg("permission denied to create extension \"%s\"",
1272 control->name),
1273 control->trusted
1274 ? errhint("Must have CREATE privilege on current database to create this extension.")
1275 : errhint("Must be superuser to create this extension.")));
1276 else
1277 ereport(ERROR,
1279 errmsg("permission denied to update extension \"%s\"",
1280 control->name),
1281 control->trusted
1282 ? errhint("Must have CREATE privilege on current database to update this extension.")
1283 : errhint("Must be superuser to update this extension.")));
1284 }
1285
1287
1288 if (from_version == NULL)
1289 elog(DEBUG1, "executing extension script for \"%s\" version '%s'", control->name, version);
1290 else
1291 elog(DEBUG1, "executing extension script for \"%s\" update from version '%s' to '%s'", control->name, from_version, version);
1292
1293 /*
1294 * If installing a trusted extension on behalf of a non-superuser, become
1295 * the bootstrap superuser. (This switch will be cleaned up automatically
1296 * if the transaction aborts, as will the GUC changes below.)
1297 */
1299 {
1300 GetUserIdAndSecContext(&save_userid, &save_sec_context);
1302 save_sec_context | SECURITY_LOCAL_USERID_CHANGE);
1303 }
1304
1305 /*
1306 * Force client_min_messages and log_min_messages to be at least WARNING,
1307 * so that we won't spam the user with useless NOTICE messages from common
1308 * script actions like creating shell types.
1309 *
1310 * We use the equivalent of a function SET option to allow the setting to
1311 * persist for exactly the duration of the script execution. guc.c also
1312 * takes care of undoing the setting on error.
1313 *
1314 * log_min_messages can't be set by ordinary users, so for that one we
1315 * pretend to be superuser.
1316 */
1317 save_nestlevel = NewGUCNestLevel();
1318
1320 (void) set_config_option("client_min_messages", "warning",
1322 GUC_ACTION_SAVE, true, 0, false);
1324 (void) set_config_option_ext("log_min_messages", "warning",
1327 GUC_ACTION_SAVE, true, 0, false);
1328
1329 /*
1330 * Similarly disable check_function_bodies, to ensure that SQL functions
1331 * won't be parsed during creation.
1332 */
1334 (void) set_config_option("check_function_bodies", "off",
1336 GUC_ACTION_SAVE, true, 0, false);
1337
1338 /*
1339 * Set up the search path to have the target schema first, making it be
1340 * the default creation target namespace. Then add the schemas of any
1341 * prerequisite extensions, unless they are in pg_catalog which would be
1342 * searched anyway. (Listing pg_catalog explicitly in a non-first
1343 * position would be bad for security.) Finally add pg_temp to ensure
1344 * that temp objects can't take precedence over others.
1345 */
1348 foreach(lc, requiredSchemas)
1349 {
1352
1353 if (reqname && strcmp(reqname, "pg_catalog") != 0)
1355 }
1356 appendStringInfoString(&pathbuf, ", pg_temp");
1357
1358 (void) set_config_option("search_path", pathbuf.data,
1360 GUC_ACTION_SAVE, true, 0, false);
1361
1362 /*
1363 * Set creating_extension and related variables so that
1364 * recordDependencyOnCurrentExtension and other functions do the right
1365 * things. On failure, ensure we reset these variables.
1366 */
1367 creating_extension = true;
1369 PG_TRY();
1370 {
1371 char *c_sql = read_extension_script_file(control, filename);
1372 Datum t_sql;
1373
1374 /*
1375 * We filter each substitution through quote_identifier(). When the
1376 * arg contains one of the following characters, no one collection of
1377 * quoting can work inside $$dollar-quoted string literals$$,
1378 * 'single-quoted string literals', and outside of any literal. To
1379 * avoid a security snare for extension authors, error on substitution
1380 * for arguments containing these.
1381 */
1382 const char *quoting_relevant_chars = "\"$'\\";
1383
1384 /* We use various functions that want to operate on text datums */
1386
1387 /*
1388 * Reduce any lines beginning with "\echo" to empty. This allows
1389 * scripts to contain messages telling people not to run them via
1390 * psql, which has been found to be necessary due to old habits.
1391 */
1394 t_sql,
1395 CStringGetTextDatum("^\\\\echo.*$"),
1397 CStringGetTextDatum("ng"));
1398
1399 /*
1400 * If the script uses @extowner@, substitute the calling username.
1401 */
1402 if (strstr(c_sql, "@extowner@"))
1403 {
1404 Oid uid = switch_to_superuser ? save_userid : GetUserId();
1405 const char *userName = GetUserNameFromId(uid, false);
1406 const char *qUserName = quote_identifier(userName);
1407
1410 t_sql,
1411 CStringGetTextDatum("@extowner@"),
1414 ereport(ERROR,
1416 errmsg("invalid character in extension owner: must not contain any of \"%s\"",
1418 }
1419
1420 /*
1421 * If it's not relocatable, substitute the target schema name for
1422 * occurrences of @extschema@.
1423 *
1424 * For a relocatable extension, we needn't do this. There cannot be
1425 * any need for @extschema@, else it wouldn't be relocatable.
1426 */
1427 if (!control->relocatable)
1428 {
1429 Datum old = t_sql;
1431
1434 t_sql,
1435 CStringGetTextDatum("@extschema@"),
1438 ereport(ERROR,
1440 errmsg("invalid character in extension \"%s\" schema: must not contain any of \"%s\"",
1441 control->name, quoting_relevant_chars)));
1442 }
1443
1444 /*
1445 * Likewise, substitute required extensions' schema names for
1446 * occurrences of @extschema:extension_name@.
1447 */
1448 Assert(list_length(control->requires) == list_length(requiredSchemas));
1449 forboth(lc, control->requires, lc2, requiredSchemas)
1450 {
1451 Datum old = t_sql;
1452 char *reqextname = (char *) lfirst(lc);
1456 char *repltoken;
1457
1458 repltoken = psprintf("@extschema:%s@", reqextname);
1461 t_sql,
1465 ereport(ERROR,
1467 errmsg("invalid character in extension \"%s\" schema: must not contain any of \"%s\"",
1469 }
1470
1471 /*
1472 * If module_pathname was set in the control file, substitute its
1473 * value for occurrences of MODULE_PATHNAME.
1474 */
1475 if (control->module_pathname)
1476 {
1479 t_sql,
1480 CStringGetTextDatum("MODULE_PATHNAME"),
1482 }
1483
1484 /* And now back to C string */
1486
1488 }
1489 PG_FINALLY();
1490 {
1491 creating_extension = false;
1493 }
1494 PG_END_TRY();
1495
1496 /*
1497 * Restore the GUC variables we set above.
1498 */
1499 AtEOXact_GUC(true, save_nestlevel);
1500
1501 /*
1502 * Restore authentication state if needed.
1503 */
1505 SetUserIdAndSecContext(save_userid, save_sec_context);
1506}
1507
1508/*
1509 * Find or create an ExtensionVersionInfo for the specified version name
1510 *
1511 * Currently, we just use a List of the ExtensionVersionInfo's. Searching
1512 * for them therefore uses about O(N^2) time when there are N versions of
1513 * the extension. We could change the data structure to a hash table if
1514 * this ever becomes a bottleneck.
1515 */
1516static ExtensionVersionInfo *
1518{
1520 ListCell *lc;
1521
1522 foreach(lc, *evi_list)
1523 {
1525 if (strcmp(evi->name, versionname) == 0)
1526 return evi;
1527 }
1528
1530 evi->name = pstrdup(versionname);
1531 evi->reachable = NIL;
1532 evi->installable = false;
1533 /* initialize for later application of Dijkstra's algorithm */
1534 evi->distance_known = false;
1535 evi->distance = INT_MAX;
1536 evi->previous = NULL;
1537
1539
1540 return evi;
1541}
1542
1543/*
1544 * Locate the nearest unprocessed ExtensionVersionInfo
1545 *
1546 * This part of the algorithm is also about O(N^2). A priority queue would
1547 * make it much faster, but for now there's no need.
1548 */
1549static ExtensionVersionInfo *
1551{
1553 ListCell *lc;
1554
1555 foreach(lc, evi_list)
1556 {
1558
1559 /* only vertices whose distance is still uncertain are candidates */
1560 if (evi2->distance_known)
1561 continue;
1562 /* remember the closest such vertex */
1563 if (evi == NULL ||
1564 evi->distance > evi2->distance)
1565 evi = evi2;
1566 }
1567
1568 return evi;
1569}
1570
1571/*
1572 * Obtain information about the set of update scripts available for the
1573 * specified extension. The result is a List of ExtensionVersionInfo
1574 * structs, each with a subsidiary list of the ExtensionVersionInfos for
1575 * the versions that can be reached in one step from that version.
1576 */
1577static List *
1579{
1580 List *evi_list = NIL;
1581 int extnamelen = strlen(control->name);
1582 char *location;
1583 DIR *dir;
1584 struct dirent *de;
1585
1586 location = get_extension_script_directory(control);
1587 dir = AllocateDir(location);
1588 while ((de = ReadDir(dir, location)) != NULL)
1589 {
1590 char *vername;
1591 char *vername2;
1594
1595 /* must be a .sql file ... */
1596 if (!is_extension_script_filename(de->d_name))
1597 continue;
1598
1599 /* ... matching extension name followed by separator */
1600 if (strncmp(de->d_name, control->name, extnamelen) != 0 ||
1601 de->d_name[extnamelen] != '-' ||
1602 de->d_name[extnamelen + 1] != '-')
1603 continue;
1604
1605 /* extract version name(s) from 'extname--something.sql' filename */
1606 vername = pstrdup(de->d_name + extnamelen + 2);
1607 *strrchr(vername, '.') = '\0';
1608 vername2 = strstr(vername, "--");
1609 if (!vername2)
1610 {
1611 /* It's an install, not update, script; record its version name */
1613 evi->installable = true;
1614 continue;
1615 }
1616 *vername2 = '\0'; /* terminate first version */
1617 vername2 += 2; /* and point to second */
1618
1619 /* if there's a third --, it's bogus, ignore it */
1620 if (strstr(vername2, "--"))
1621 continue;
1622
1623 /* Create ExtensionVersionInfos and link them together */
1626 evi->reachable = lappend(evi->reachable, evi2);
1627 }
1628 FreeDir(dir);
1629
1630 return evi_list;
1631}
1632
1633/*
1634 * Given an initial and final version name, identify the sequence of update
1635 * scripts that have to be applied to perform that update.
1636 *
1637 * Result is a List of names of versions to transition through (the initial
1638 * version is *not* included).
1639 */
1640static List *
1642 const char *oldVersion, const char *newVersion)
1643{
1644 List *result;
1645 List *evi_list;
1648
1649 /* Extract the version update graph from the script directory */
1650 evi_list = get_ext_ver_list(control);
1651
1652 /* Initialize start and end vertices */
1655
1656 /* Find shortest path */
1657 result = find_update_path(evi_list, evi_start, evi_target, false, false);
1658
1659 if (result == NIL)
1660 ereport(ERROR,
1662 errmsg("extension \"%s\" has no update path from version \"%s\" to version \"%s\"",
1663 control->name, oldVersion, newVersion)));
1664
1665 return result;
1666}
1667
1668/*
1669 * Apply Dijkstra's algorithm to find the shortest path from evi_start to
1670 * evi_target.
1671 *
1672 * If reject_indirect is true, ignore paths that go through installable
1673 * versions. This saves work when the caller will consider starting from
1674 * all installable versions anyway.
1675 *
1676 * If reinitialize is false, assume the ExtensionVersionInfo list has not
1677 * been used for this before, and the initialization done by get_ext_ver_info
1678 * is still good. Otherwise, reinitialize all transient fields used here.
1679 *
1680 * Result is a List of names of versions to transition through (the initial
1681 * version is *not* included). Returns NIL if no such path.
1682 */
1683static List *
1687 bool reject_indirect,
1688 bool reinitialize)
1689{
1690 List *result;
1692 ListCell *lc;
1693
1694 /* Caller error if start == target */
1696 /* Caller error if reject_indirect and target is installable */
1697 Assert(!(reject_indirect && evi_target->installable));
1698
1699 if (reinitialize)
1700 {
1701 foreach(lc, evi_list)
1702 {
1704 evi->distance_known = false;
1705 evi->distance = INT_MAX;
1706 evi->previous = NULL;
1707 }
1708 }
1709
1710 evi_start->distance = 0;
1711
1713 {
1714 if (evi->distance == INT_MAX)
1715 break; /* all remaining vertices are unreachable */
1716 evi->distance_known = true;
1717 if (evi == evi_target)
1718 break; /* found shortest path to target */
1719 foreach(lc, evi->reachable)
1720 {
1722 int newdist;
1723
1724 /* if reject_indirect, treat installable versions as unreachable */
1725 if (reject_indirect && evi2->installable)
1726 continue;
1727 newdist = evi->distance + 1;
1728 if (newdist < evi2->distance)
1729 {
1730 evi2->distance = newdist;
1731 evi2->previous = evi;
1732 }
1733 else if (newdist == evi2->distance &&
1734 evi2->previous != NULL &&
1735 strcmp(evi->name, evi2->previous->name) < 0)
1736 {
1737 /*
1738 * Break ties in favor of the version name that comes first
1739 * according to strcmp(). This behavior is undocumented and
1740 * users shouldn't rely on it. We do it just to ensure that
1741 * if there is a tie, the update path that is chosen does not
1742 * depend on random factors like the order in which directory
1743 * entries get visited.
1744 */
1745 evi2->previous = evi;
1746 }
1747 }
1748 }
1749
1750 /* Return NIL if target is not reachable from start */
1751 if (!evi_target->distance_known)
1752 return NIL;
1753
1754 /* Build and return list of version names representing the update path */
1755 result = NIL;
1756 for (evi = evi_target; evi != evi_start; evi = evi->previous)
1757 result = lcons(evi->name, result);
1758
1759 return result;
1760}
1761
1762/*
1763 * Given a target version that is not directly installable, find the
1764 * best installation sequence starting from a directly-installable version.
1765 *
1766 * evi_list: previously-collected version update graph
1767 * evi_target: member of that list that we want to reach
1768 *
1769 * Returns the best starting-point version, or NULL if there is none.
1770 * On success, *best_path is set to the path from the start point.
1771 *
1772 * If there's more than one possible start point, prefer shorter update paths,
1773 * and break any ties arbitrarily on the basis of strcmp'ing the starting
1774 * versions' names.
1775 */
1776static ExtensionVersionInfo *
1778 List **best_path)
1779{
1781 ListCell *lc;
1782
1783 *best_path = NIL;
1784
1785 /*
1786 * We don't expect to be called for an installable target, but if we are,
1787 * the answer is easy: just start from there, with an empty update path.
1788 */
1789 if (evi_target->installable)
1790 return evi_target;
1791
1792 /* Consider all installable versions as start points */
1793 foreach(lc, evi_list)
1794 {
1796 List *path;
1797
1798 if (!evi1->installable)
1799 continue;
1800
1801 /*
1802 * Find shortest path from evi1 to evi_target; but no need to consider
1803 * paths going through other installable versions.
1804 */
1805 path = find_update_path(evi_list, evi1, evi_target, true, true);
1806 if (path == NIL)
1807 continue;
1808
1809 /* Remember best path */
1810 if (evi_start == NULL ||
1811 list_length(path) < list_length(*best_path) ||
1812 (list_length(path) == list_length(*best_path) &&
1813 strcmp(evi_start->name, evi1->name) < 0))
1814 {
1815 evi_start = evi1;
1816 *best_path = path;
1817 }
1818 }
1819
1820 return evi_start;
1821}
1822
1823/*
1824 * CREATE EXTENSION worker
1825 *
1826 * When CASCADE is specified, CreateExtensionInternal() recurses if required
1827 * extensions need to be installed. To sanely handle cyclic dependencies,
1828 * the "parents" list contains a list of names of extensions already being
1829 * installed, allowing us to error out if we recurse to one of those.
1830 */
1831static ObjectAddress
1833 char *schemaName,
1834 const char *versionName,
1835 bool cascade,
1836 List *parents,
1837 bool is_create)
1838{
1839 char *origSchemaName = schemaName;
1843 ExtensionControlFile *control;
1844 char *filename;
1845 struct stat fst;
1850 ObjectAddress address;
1851 ListCell *lc;
1852
1853 /*
1854 * Read the primary control file. Note we assume that it does not contain
1855 * any non-ASCII data, so there is no need to worry about encoding at this
1856 * point.
1857 */
1859
1860 /*
1861 * Determine the version to install
1862 */
1863 if (versionName == NULL)
1864 {
1865 if (pcontrol->default_version)
1866 versionName = pcontrol->default_version;
1867 else
1868 ereport(ERROR,
1870 errmsg("version to install must be specified")));
1871 }
1873
1874 /*
1875 * Figure out which script(s) we need to run to install the desired
1876 * version of the extension. If we do not have a script that directly
1877 * does what is needed, we try to find a sequence of update scripts that
1878 * will get us there.
1879 */
1881 if (stat(filename, &fst) == 0)
1882 {
1883 /* Easy, no extra scripts */
1885 }
1886 else
1887 {
1888 /* Look for best way to install this version */
1889 List *evi_list;
1892
1893 /* Extract the version update graph from the script directory */
1895
1896 /* Identify the target version */
1898
1899 /* Identify best path to reach target */
1902
1903 /* Fail if no path ... */
1904 if (evi_start == NULL)
1905 ereport(ERROR,
1907 errmsg("extension \"%s\" has no installation script nor update path for version \"%s\"",
1908 pcontrol->name, versionName)));
1909
1910 /* Otherwise, install best starting point and then upgrade */
1911 versionName = evi_start->name;
1912 }
1913
1914 /*
1915 * Fetch control parameters for installation target version
1916 */
1918
1919 /*
1920 * Determine the target schema to install the extension into
1921 */
1922 if (schemaName)
1923 {
1924 /* If the user is giving us the schema name, it must exist already. */
1926 }
1927
1928 if (control->schema != NULL)
1929 {
1930 /*
1931 * The extension is not relocatable and the author gave us a schema
1932 * for it.
1933 *
1934 * Unless CASCADE parameter was given, it's an error to give a schema
1935 * different from control->schema if control->schema is specified.
1936 */
1937 if (schemaName && strcmp(control->schema, schemaName) != 0 &&
1938 !cascade)
1939 ereport(ERROR,
1941 errmsg("extension \"%s\" must be installed in schema \"%s\"",
1942 control->name,
1943 control->schema)));
1944
1945 /* Always use the schema from control file for current extension. */
1946 schemaName = control->schema;
1947
1948 /* Find or create the schema in case it does not exist. */
1950
1951 if (!OidIsValid(schemaOid))
1952 {
1954
1955 csstmt->schemaname = schemaName;
1956 csstmt->authrole = NULL; /* will be created by current user */
1957 csstmt->schemaElts = NIL;
1958 csstmt->if_not_exists = false;
1959 CreateSchemaCommand(csstmt, "(generated CREATE SCHEMA command)",
1960 -1, -1);
1961
1962 /*
1963 * CreateSchemaCommand includes CommandCounterIncrement, so new
1964 * schema is now visible.
1965 */
1967 }
1968 }
1969 else if (!OidIsValid(schemaOid))
1970 {
1971 /*
1972 * Neither user nor author of the extension specified schema; use the
1973 * current default creation namespace, which is the first explicit
1974 * entry in the search_path.
1975 */
1976 List *search_path = fetch_search_path(false);
1977
1978 if (search_path == NIL) /* nothing valid in search_path? */
1979 ereport(ERROR,
1981 errmsg("no schema has been selected to create in")));
1982 schemaOid = linitial_oid(search_path);
1984 if (schemaName == NULL) /* recently-deleted namespace? */
1985 ereport(ERROR,
1987 errmsg("no schema has been selected to create in")));
1988
1989 list_free(search_path);
1990 }
1991
1992 /*
1993 * Make note if a temporary namespace has been accessed in this
1994 * transaction.
1995 */
1998
1999 /*
2000 * We don't check creation rights on the target namespace here. If the
2001 * extension script actually creates any objects there, it will fail if
2002 * the user doesn't have such permissions. But there are cases such as
2003 * procedural languages where it's convenient to set schema = pg_catalog
2004 * yet we don't want to restrict the command to users with ACL_CREATE for
2005 * pg_catalog.
2006 */
2007
2008 /*
2009 * Look up the prerequisite extensions, install them if necessary, and
2010 * build lists of their OIDs and the OIDs of their target schemas.
2011 */
2014 foreach(lc, control->requires)
2015 {
2016 char *curreq = (char *) lfirst(lc);
2017 Oid reqext;
2018 Oid reqschema;
2019
2023 cascade,
2024 parents,
2025 is_create);
2029 }
2030
2031 /*
2032 * Insert new tuple into pg_extension, and create dependency entries.
2033 */
2034 address = InsertExtensionTuple(control->name, extowner,
2035 schemaOid, control->relocatable,
2040 extensionOid = address.objectId;
2041
2042 /*
2043 * Apply any control-file comment on extension
2044 */
2045 if (control->comment != NULL)
2047
2048 /*
2049 * Execute the installation script file
2050 */
2054 schemaName);
2055
2056 /*
2057 * If additional update scripts have to be executed, apply the updates as
2058 * though a series of ALTER EXTENSION UPDATE commands were given
2059 */
2062 origSchemaName, cascade, is_create);
2063
2064 return address;
2065}
2066
2067/*
2068 * Get the OID of an extension listed in "requires", possibly creating it.
2069 */
2070static Oid
2072 char *extensionName,
2073 char *origSchemaName,
2074 bool cascade,
2075 List *parents,
2076 bool is_create)
2077{
2079
2082 {
2083 if (cascade)
2084 {
2085 /* Must install it. */
2086 ObjectAddress addr;
2088 ListCell *lc;
2089
2090 /* Check extension name validity before trying to cascade. */
2092
2093 /* Check for cyclic dependency between extensions. */
2094 foreach(lc, parents)
2095 {
2096 char *pname = (char *) lfirst(lc);
2097
2098 if (strcmp(pname, reqExtensionName) == 0)
2099 ereport(ERROR,
2101 errmsg("cyclic dependency detected between extensions \"%s\" and \"%s\"",
2103 }
2104
2106 (errmsg("installing required extension \"%s\"",
2108
2109 /* Add current extension to list of parents to pass down. */
2111
2112 /*
2113 * Create the required extension. We propagate the SCHEMA option
2114 * if any, and CASCADE, but no other options.
2115 */
2118 NULL,
2119 cascade,
2121 is_create);
2122
2123 /* Get its newly-assigned OID. */
2125 }
2126 else
2127 ereport(ERROR,
2129 errmsg("required extension \"%s\" is not installed",
2131 is_create ?
2132 errhint("Use CREATE EXTENSION ... CASCADE to install required extensions too.") : 0));
2133 }
2134
2135 return reqExtensionOid;
2136}
2137
2138/*
2139 * CREATE EXTENSION
2140 */
2143{
2147 char *schemaName = NULL;
2148 char *versionName = NULL;
2149 bool cascade = false;
2150 ListCell *lc;
2151
2152 /* Check extension name validity before any filesystem access */
2154
2155 /*
2156 * Check for duplicate extension name. The unique index on
2157 * pg_extension.extname would catch this anyway, and serves as a backstop
2158 * in case of race conditions; but this is a friendlier error message, and
2159 * besides we need a check to support IF NOT EXISTS.
2160 */
2161 if (get_extension_oid(stmt->extname, true) != InvalidOid)
2162 {
2163 if (stmt->if_not_exists)
2164 {
2167 errmsg("extension \"%s\" already exists, skipping",
2168 stmt->extname)));
2169 return InvalidObjectAddress;
2170 }
2171 else
2172 ereport(ERROR,
2174 errmsg("extension \"%s\" already exists",
2175 stmt->extname)));
2176 }
2177
2178 /*
2179 * We use global variables to track the extension being created, so we can
2180 * create only one extension at the same time.
2181 */
2183 ereport(ERROR,
2185 errmsg("nested CREATE EXTENSION is not supported")));
2186
2187 /* Deconstruct the statement option list */
2188 foreach(lc, stmt->options)
2189 {
2190 DefElem *defel = (DefElem *) lfirst(lc);
2191
2192 if (strcmp(defel->defname, "schema") == 0)
2193 {
2194 if (d_schema)
2196 d_schema = defel;
2198 }
2199 else if (strcmp(defel->defname, "new_version") == 0)
2200 {
2201 if (d_new_version)
2205 }
2206 else if (strcmp(defel->defname, "cascade") == 0)
2207 {
2208 if (d_cascade)
2210 d_cascade = defel;
2211 cascade = defGetBoolean(d_cascade);
2212 }
2213 else
2214 elog(ERROR, "unrecognized option: %s", defel->defname);
2215 }
2216
2217 /* Call CreateExtensionInternal to do the real work. */
2218 return CreateExtensionInternal(stmt->extname,
2219 schemaName,
2221 cascade,
2222 NIL,
2223 true);
2224}
2225
2226/*
2227 * InsertExtensionTuple
2228 *
2229 * Insert the new pg_extension row, and create extension's dependency entries.
2230 * Return the OID assigned to the new row.
2231 *
2232 * This is exported for the benefit of pg_upgrade, which has to create a
2233 * pg_extension entry (and the extension-level dependencies) without
2234 * actually running the extension's script.
2235 *
2236 * extConfig and extCondition should be arrays or PointerGetDatum(NULL).
2237 * We declare them as plain Datum to avoid needing array.h in extension.h.
2238 */
2241 Oid schemaOid, bool relocatable, const char *extVersion,
2244{
2246 Relation rel;
2248 bool nulls[Natts_pg_extension];
2249 HeapTuple tuple;
2253 ListCell *lc;
2254
2255 /*
2256 * Build and insert the pg_extension tuple
2257 */
2259
2260 memset(values, 0, sizeof(values));
2261 memset(nulls, 0, sizeof(nulls));
2262
2272
2274 nulls[Anum_pg_extension_extconfig - 1] = true;
2275 else
2277
2279 nulls[Anum_pg_extension_extcondition - 1] = true;
2280 else
2282
2283 tuple = heap_form_tuple(rel->rd_att, values, nulls);
2284
2285 CatalogTupleInsert(rel, tuple);
2286
2287 heap_freetuple(tuple);
2289
2290 /*
2291 * Record dependencies on owner, schema, and prerequisite extensions
2292 */
2294
2296
2298
2301
2302 foreach(lc, requiredExtensions)
2303 {
2306
2309 }
2310
2311 /* Record all of them (this includes duplicate elimination) */
2314
2315 /* Post creation hook for new extension */
2317
2318 return myself;
2319}
2320
2321/*
2322 * Guts of extension deletion.
2323 *
2324 * All we need do here is remove the pg_extension tuple itself. Everything
2325 * else is taken care of by the dependency infrastructure.
2326 */
2327void
2329{
2330 Relation rel;
2331 SysScanDesc scandesc;
2332 HeapTuple tuple;
2333 ScanKeyData entry[1];
2334
2335 /*
2336 * Disallow deletion of any extension that's currently open for insertion;
2337 * else subsequent executions of recordDependencyOnCurrentExtension()
2338 * could create dangling pg_depend records that refer to a no-longer-valid
2339 * pg_extension OID. This is needed not so much because we think people
2340 * might write "DROP EXTENSION foo" in foo's own script files, as because
2341 * errors in dependency management in extension script files could give
2342 * rise to cases where an extension is dropped as a result of recursing
2343 * from some contained object. Because of that, we must test for the case
2344 * here, not at some higher level of the DROP EXTENSION command.
2345 */
2347 ereport(ERROR,
2349 errmsg("cannot drop extension \"%s\" because it is being modified",
2351
2353
2354 ScanKeyInit(&entry[0],
2358 scandesc = systable_beginscan(rel, ExtensionOidIndexId, true,
2359 NULL, 1, entry);
2360
2361 tuple = systable_getnext(scandesc);
2362
2363 /* We assume that there can be at most one matching tuple */
2364 if (HeapTupleIsValid(tuple))
2365 CatalogTupleDelete(rel, &tuple->t_self);
2366
2367 systable_endscan(scandesc);
2368
2370}
2371
2372/*
2373 * This function lists the available extensions (one row per primary control
2374 * file in the control directory). We parse each control file and report the
2375 * interesting fields.
2376 *
2377 * The system view pg_available_extensions provides a user interface to this
2378 * SRF, adding information about whether the extensions are installed in the
2379 * current DB.
2380 */
2381Datum
2383{
2384 ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
2385 List *locations;
2386 DIR *dir;
2387 struct dirent *de;
2388 List *found_ext = NIL;
2389
2390 /* Build tuplestore to hold the result rows */
2391 InitMaterializedSRF(fcinfo, 0);
2392
2394
2396 {
2397 dir = AllocateDir(location->loc);
2398
2399 /*
2400 * If the control directory doesn't exist, we want to silently return
2401 * an empty set. Any other error will be reported by ReadDir.
2402 */
2403 if (dir == NULL && errno == ENOENT)
2404 {
2405 /* do nothing */
2406 }
2407 else
2408 {
2409 while ((de = ReadDir(dir, location->loc)) != NULL)
2410 {
2411 ExtensionControlFile *control;
2412 char *extname;
2414 Datum values[4];
2415 bool nulls[4];
2416
2417 if (!is_extension_control_filename(de->d_name))
2418 continue;
2419
2420 /* extract extension name from 'name.control' filename */
2421 extname = pstrdup(de->d_name);
2422 *strrchr(extname, '.') = '\0';
2423
2424 /* ignore it if it's an auxiliary control file */
2425 if (strstr(extname, "--"))
2426 continue;
2427
2428 /*
2429 * Ignore already-found names. They are not reachable by the
2430 * path search, so don't show them.
2431 */
2432 extname_str = makeString(extname);
2434 continue;
2435 else
2437
2438 control = new_ExtensionControlFile(extname);
2439 control->control_dir = pstrdup(location->loc);
2441
2442 memset(values, 0, sizeof(values));
2443 memset(nulls, 0, sizeof(nulls));
2444
2445 /* name */
2447 CStringGetDatum(control->name));
2448 /* default_version */
2449 if (control->default_version == NULL)
2450 nulls[1] = true;
2451 else
2453
2454 /* location */
2456
2457 /* comment */
2458 if (control->comment == NULL)
2459 nulls[3] = true;
2460 else
2461 values[3] = CStringGetTextDatum(control->comment);
2462
2463 tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
2464 values, nulls);
2465 }
2466
2467 FreeDir(dir);
2468 }
2469 }
2470
2471 return (Datum) 0;
2472}
2473
2474/*
2475 * This function lists the available extension versions (one row per
2476 * extension installation script). For each version, we parse the related
2477 * control file(s) and report the interesting fields.
2478 *
2479 * The system view pg_available_extension_versions provides a user interface
2480 * to this SRF, adding information about which versions are installed in the
2481 * current DB.
2482 */
2483Datum
2485{
2486 ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
2487 List *locations;
2488 DIR *dir;
2489 struct dirent *de;
2490 List *found_ext = NIL;
2491
2492 /* Build tuplestore to hold the result rows */
2493 InitMaterializedSRF(fcinfo, 0);
2494
2496
2498 {
2499 dir = AllocateDir(location->loc);
2500
2501 /*
2502 * If the control directory doesn't exist, we want to silently return
2503 * an empty set. Any other error will be reported by ReadDir.
2504 */
2505 if (dir == NULL && errno == ENOENT)
2506 {
2507 /* do nothing */
2508 }
2509 else
2510 {
2511 while ((de = ReadDir(dir, location->loc)) != NULL)
2512 {
2513 ExtensionControlFile *control;
2514 char *extname;
2516
2517 if (!is_extension_control_filename(de->d_name))
2518 continue;
2519
2520 /* extract extension name from 'name.control' filename */
2521 extname = pstrdup(de->d_name);
2522 *strrchr(extname, '.') = '\0';
2523
2524 /* ignore it if it's an auxiliary control file */
2525 if (strstr(extname, "--"))
2526 continue;
2527
2528 /*
2529 * Ignore already-found names. They are not reachable by the
2530 * path search, so don't shown them.
2531 */
2532 extname_str = makeString(extname);
2534 continue;
2535 else
2537
2538 /* read the control file */
2539 control = new_ExtensionControlFile(extname);
2540 control->control_dir = pstrdup(location->loc);
2542
2543 /* scan extension's script directory for install scripts */
2544 get_available_versions_for_extension(control, rsinfo->setResult,
2545 rsinfo->setDesc,
2546 location);
2547 }
2548
2549 FreeDir(dir);
2550 }
2551 }
2552
2553 return (Datum) 0;
2554}
2555
2556/*
2557 * Inner loop for pg_available_extension_versions:
2558 * read versions of one extension, add rows to tupstore
2559 */
2560static void
2562 Tuplestorestate *tupstore,
2563 TupleDesc tupdesc,
2564 ExtensionLocation *location)
2565{
2566 List *evi_list;
2567 ListCell *lc;
2568
2569 /* Extract the version update graph from the script directory */
2571
2572 /* For each installable version ... */
2573 foreach(lc, evi_list)
2574 {
2576 ExtensionControlFile *control;
2577 Datum values[9];
2578 bool nulls[9];
2579 ListCell *lc2;
2580
2581 if (!evi->installable)
2582 continue;
2583
2584 /*
2585 * Fetch parameters for specific version (pcontrol is not changed)
2586 */
2588
2589 memset(values, 0, sizeof(values));
2590 memset(nulls, 0, sizeof(nulls));
2591
2592 /* name */
2594 CStringGetDatum(control->name));
2595 /* version */
2596 values[1] = CStringGetTextDatum(evi->name);
2597 /* superuser */
2598 values[2] = BoolGetDatum(control->superuser);
2599 /* trusted */
2600 values[3] = BoolGetDatum(control->trusted);
2601 /* relocatable */
2602 values[4] = BoolGetDatum(control->relocatable);
2603 /* schema */
2604 if (control->schema == NULL)
2605 nulls[5] = true;
2606 else
2608 CStringGetDatum(control->schema));
2609 /* requires */
2610 if (control->requires == NIL)
2611 nulls[6] = true;
2612 else
2613 values[6] = convert_requires_to_datum(control->requires);
2614
2615 /* location */
2617
2618 /* comment */
2619 if (control->comment == NULL)
2620 nulls[8] = true;
2621 else
2622 values[8] = CStringGetTextDatum(control->comment);
2623
2624 tuplestore_putvalues(tupstore, tupdesc, values, nulls);
2625
2626 /*
2627 * Find all non-directly-installable versions that would be installed
2628 * starting from this version, and report them, inheriting the
2629 * parameters that aren't changed in updates from this version.
2630 */
2631 foreach(lc2, evi_list)
2632 {
2634 List *best_path;
2635
2636 if (evi2->installable)
2637 continue;
2639 {
2640 /*
2641 * Fetch parameters for this version (pcontrol is not changed)
2642 */
2644
2645 /* name stays the same */
2646 /* version */
2647 values[1] = CStringGetTextDatum(evi2->name);
2648 /* superuser */
2649 values[2] = BoolGetDatum(control->superuser);
2650 /* trusted */
2651 values[3] = BoolGetDatum(control->trusted);
2652 /* relocatable */
2653 values[4] = BoolGetDatum(control->relocatable);
2654 /* schema stays the same */
2655 /* requires */
2656 if (control->requires == NIL)
2657 nulls[6] = true;
2658 else
2659 {
2660 values[6] = convert_requires_to_datum(control->requires);
2661 nulls[6] = false;
2662 }
2663 /* comment and location stay the same */
2664
2665 tuplestore_putvalues(tupstore, tupdesc, values, nulls);
2666 }
2667 }
2668 }
2669}
2670
2671/*
2672 * Test whether the given extension exists (not whether it's installed)
2673 *
2674 * This checks for the existence of a matching control file in the extension
2675 * directory. That's not a bulletproof check, since the file might be
2676 * invalid, but this is only used for hints so it doesn't have to be 100%
2677 * right.
2678 */
2679bool
2681{
2682 bool result = false;
2683 List *locations;
2684 DIR *dir;
2685 struct dirent *de;
2686
2688
2690 {
2691 dir = AllocateDir(location->loc);
2692
2693 /*
2694 * If the control directory doesn't exist, we want to silently return
2695 * false. Any other error will be reported by ReadDir.
2696 */
2697 if (dir == NULL && errno == ENOENT)
2698 {
2699 /* do nothing */
2700 }
2701 else
2702 {
2703 while ((de = ReadDir(dir, location->loc)) != NULL)
2704 {
2705 char *extname;
2706
2707 if (!is_extension_control_filename(de->d_name))
2708 continue;
2709
2710 /* extract extension name from 'name.control' filename */
2711 extname = pstrdup(de->d_name);
2712 *strrchr(extname, '.') = '\0';
2713
2714 /* ignore it if it's an auxiliary control file */
2715 if (strstr(extname, "--"))
2716 continue;
2717
2718 /* done if it matches request */
2719 if (strcmp(extname, extensionName) == 0)
2720 {
2721 result = true;
2722 break;
2723 }
2724 }
2725
2726 FreeDir(dir);
2727 }
2728 if (result)
2729 break;
2730 }
2731
2732 return result;
2733}
2734
2735/*
2736 * Convert a list of extension names to a name[] Datum
2737 */
2738static Datum
2740{
2741 Datum *datums;
2742 int ndatums;
2743 ArrayType *a;
2744 ListCell *lc;
2745
2746 ndatums = list_length(requires);
2747 datums = (Datum *) palloc(ndatums * sizeof(Datum));
2748 ndatums = 0;
2749 foreach(lc, requires)
2750 {
2751 char *curreq = (char *) lfirst(lc);
2752
2753 datums[ndatums++] =
2755 }
2756 a = construct_array_builtin(datums, ndatums, NAMEOID);
2757 return PointerGetDatum(a);
2758}
2759
2760/*
2761 * This function reports the version update paths that exist for the
2762 * specified extension.
2763 */
2764Datum
2766{
2767 Name extname = PG_GETARG_NAME(0);
2768 ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
2769 List *evi_list;
2770 ExtensionControlFile *control;
2771 ListCell *lc1;
2772
2773 /* Check extension name validity before any filesystem access */
2775
2776 /* Build tuplestore to hold the result rows */
2777 InitMaterializedSRF(fcinfo, 0);
2778
2779 /* Read the extension's control file */
2780 control = read_extension_control_file(NameStr(*extname));
2781
2782 /* Extract the version update graph from the script directory */
2783 evi_list = get_ext_ver_list(control);
2784
2785 /* Iterate over all pairs of versions */
2786 foreach(lc1, evi_list)
2787 {
2789 ListCell *lc2;
2790
2791 foreach(lc2, evi_list)
2792 {
2794 List *path;
2795 Datum values[3];
2796 bool nulls[3];
2797
2798 if (evi1 == evi2)
2799 continue;
2800
2801 /* Find shortest path from evi1 to evi2 */
2802 path = find_update_path(evi_list, evi1, evi2, false, true);
2803
2804 /* Emit result row */
2805 memset(values, 0, sizeof(values));
2806 memset(nulls, 0, sizeof(nulls));
2807
2808 /* source */
2809 values[0] = CStringGetTextDatum(evi1->name);
2810 /* target */
2811 values[1] = CStringGetTextDatum(evi2->name);
2812 /* path */
2813 if (path == NIL)
2814 nulls[2] = true;
2815 else
2816 {
2818 ListCell *lcv;
2819
2821 /* The path doesn't include start vertex, but show it */
2823 foreach(lcv, path)
2824 {
2825 char *versionName = (char *) lfirst(lcv);
2826
2829 }
2831 pfree(pathbuf.data);
2832 }
2833
2834 tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
2835 values, nulls);
2836 }
2837 }
2838
2839 return (Datum) 0;
2840}
2841
2842/*
2843 * pg_extension_config_dump
2844 *
2845 * Record information about a configuration table that belongs to an
2846 * extension being created, but whose contents should be dumped in whole
2847 * or in part during pg_dump.
2848 */
2849Datum
2851{
2852 Oid tableoid = PG_GETARG_OID(0);
2854 char *tablename;
2856 ScanKeyData key[1];
2861 int arrayLength;
2862 int arrayIndex;
2863 bool isnull;
2867 ArrayType *a;
2868
2869 /*
2870 * We only allow this to be called from an extension's SQL script. We
2871 * shouldn't need any permissions check beyond that.
2872 */
2873 if (!creating_extension)
2874 ereport(ERROR,
2876 errmsg("%s can only be called from an SQL script executed by CREATE EXTENSION",
2877 "pg_extension_config_dump()")));
2878
2879 /*
2880 * Check that the table exists and is a member of the extension being
2881 * created. This ensures that we don't need to register an additional
2882 * dependency to protect the extconfig entry.
2883 */
2884 tablename = get_rel_name(tableoid);
2885 if (tablename == NULL)
2886 ereport(ERROR,
2888 errmsg("OID %u does not refer to a table", tableoid)));
2891 ereport(ERROR,
2893 errmsg("table \"%s\" is not a member of the extension being created",
2894 tablename)));
2895
2896 /*
2897 * Add the table OID and WHERE condition to the extension's extconfig and
2898 * extcondition arrays.
2899 *
2900 * If the table is already in extconfig, treat this as an update of the
2901 * WHERE condition.
2902 */
2903
2904 /* Find the pg_extension tuple */
2906
2907 ScanKeyInit(&key[0],
2911
2913 NULL, 1, key);
2914
2916
2917 if (!HeapTupleIsValid(extTup)) /* should not happen */
2918 elog(ERROR, "could not find tuple for extension %u",
2920
2921 memset(repl_val, 0, sizeof(repl_val));
2922 memset(repl_null, false, sizeof(repl_null));
2923 memset(repl_repl, false, sizeof(repl_repl));
2924
2925 /* Build or modify the extconfig value */
2926 elementDatum = ObjectIdGetDatum(tableoid);
2927
2929 RelationGetDescr(extRel), &isnull);
2930 if (isnull)
2931 {
2932 /* Previously empty extconfig, so build 1-element array */
2933 arrayLength = 0;
2934 arrayIndex = 1;
2935
2937 }
2938 else
2939 {
2940 /* Modify or extend existing extconfig array */
2941 Oid *arrayData;
2942 int i;
2943
2945
2946 arrayLength = ARR_DIMS(a)[0];
2947 if (ARR_NDIM(a) != 1 ||
2948 ARR_LBOUND(a)[0] != 1 ||
2949 arrayLength < 0 ||
2950 ARR_HASNULL(a) ||
2951 ARR_ELEMTYPE(a) != OIDOID)
2952 elog(ERROR, "extconfig is not a 1-D Oid array");
2953 arrayData = (Oid *) ARR_DATA_PTR(a);
2954
2955 arrayIndex = arrayLength + 1; /* set up to add after end */
2956
2957 for (i = 0; i < arrayLength; i++)
2958 {
2959 if (arrayData[i] == tableoid)
2960 {
2961 arrayIndex = i + 1; /* replace this element instead */
2962 break;
2963 }
2964 }
2965
2966 a = array_set(a, 1, &arrayIndex,
2968 false,
2969 -1 /* varlena array */ ,
2970 sizeof(Oid) /* OID's typlen */ ,
2971 true /* OID's typbyval */ ,
2972 TYPALIGN_INT /* OID's typalign */ );
2973 }
2976
2977 /* Build or modify the extcondition value */
2979
2981 RelationGetDescr(extRel), &isnull);
2982 if (isnull)
2983 {
2984 if (arrayLength != 0)
2985 elog(ERROR, "extconfig and extcondition arrays do not match");
2986
2988 }
2989 else
2990 {
2992
2993 if (ARR_NDIM(a) != 1 ||
2994 ARR_LBOUND(a)[0] != 1 ||
2995 ARR_HASNULL(a) ||
2997 elog(ERROR, "extcondition is not a 1-D text array");
2998 if (ARR_DIMS(a)[0] != arrayLength)
2999 elog(ERROR, "extconfig and extcondition arrays do not match");
3000
3001 /* Add or replace at same index as in extconfig */
3002 a = array_set(a, 1, &arrayIndex,
3004 false,
3005 -1 /* varlena array */ ,
3006 -1 /* TEXT's typlen */ ,
3007 false /* TEXT's typbyval */ ,
3008 TYPALIGN_INT /* TEXT's typalign */ );
3009 }
3012
3015
3017
3019
3021
3023}
3024
3025/*
3026 * pg_get_loaded_modules
3027 *
3028 * SQL-callable function to get per-loaded-module information. Modules
3029 * (shared libraries) aren't necessarily one-to-one with extensions, but
3030 * they're sufficiently closely related to make this file a good home.
3031 */
3032Datum
3034{
3035 ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
3037
3038 /* Build tuplestore to hold the result rows */
3039 InitMaterializedSRF(fcinfo, 0);
3040
3043 {
3044 const char *library_path,
3045 *module_name,
3047 const char *sep;
3048 Datum values[3] = {0};
3049 bool nulls[3] = {0};
3050
3052 &library_path,
3053 &module_name,
3055
3056 if (module_name == NULL)
3057 nulls[0] = true;
3058 else
3060 if (module_version == NULL)
3061 nulls[1] = true;
3062 else
3064
3065 /* For security reasons, we don't show the directory path */
3067 if (sep)
3068 library_path = sep + 1;
3070
3071 tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
3072 values, nulls);
3073 }
3074
3075 return (Datum) 0;
3076}
3077
3078/*
3079 * extension_config_remove
3080 *
3081 * Remove the specified table OID from extension's extconfig, if present.
3082 * This is not currently exposed as a function, but it could be;
3083 * for now, we just invoke it from ALTER EXTENSION DROP.
3084 */
3085static void
3087{
3089 ScanKeyData key[1];
3093 int arrayLength;
3094 int arrayIndex;
3095 bool isnull;
3099 ArrayType *a;
3100
3101 /* Find the pg_extension tuple */
3103
3104 ScanKeyInit(&key[0],
3108
3110 NULL, 1, key);
3111
3113
3114 if (!HeapTupleIsValid(extTup)) /* should not happen */
3115 elog(ERROR, "could not find tuple for extension %u",
3116 extensionoid);
3117
3118 /* Search extconfig for the tableoid */
3120 RelationGetDescr(extRel), &isnull);
3121 if (isnull)
3122 {
3123 /* nothing to do */
3124 a = NULL;
3125 arrayLength = 0;
3126 arrayIndex = -1;
3127 }
3128 else
3129 {
3130 Oid *arrayData;
3131 int i;
3132
3134
3135 arrayLength = ARR_DIMS(a)[0];
3136 if (ARR_NDIM(a) != 1 ||
3137 ARR_LBOUND(a)[0] != 1 ||
3138 arrayLength < 0 ||
3139 ARR_HASNULL(a) ||
3140 ARR_ELEMTYPE(a) != OIDOID)
3141 elog(ERROR, "extconfig is not a 1-D Oid array");
3142 arrayData = (Oid *) ARR_DATA_PTR(a);
3143
3144 arrayIndex = -1; /* flag for no deletion needed */
3145
3146 for (i = 0; i < arrayLength; i++)
3147 {
3148 if (arrayData[i] == tableoid)
3149 {
3150 arrayIndex = i; /* index to remove */
3151 break;
3152 }
3153 }
3154 }
3155
3156 /* If tableoid is not in extconfig, nothing to do */
3157 if (arrayIndex < 0)
3158 {
3161 return;
3162 }
3163
3164 /* Modify or delete the extconfig value */
3165 memset(repl_val, 0, sizeof(repl_val));
3166 memset(repl_null, false, sizeof(repl_null));
3167 memset(repl_repl, false, sizeof(repl_repl));
3168
3169 if (arrayLength <= 1)
3170 {
3171 /* removing only element, just set array to null */
3173 }
3174 else
3175 {
3176 /* squeeze out the target element */
3177 Datum *dvalues;
3178 int nelems;
3179 int i;
3180
3181 /* We already checked there are no nulls */
3182 deconstruct_array_builtin(a, OIDOID, &dvalues, NULL, &nelems);
3183
3184 for (i = arrayIndex; i < arrayLength - 1; i++)
3185 dvalues[i] = dvalues[i + 1];
3186
3188
3190 }
3192
3193 /* Modify or delete the extcondition value */
3195 RelationGetDescr(extRel), &isnull);
3196 if (isnull)
3197 {
3198 elog(ERROR, "extconfig and extcondition arrays do not match");
3199 }
3200 else
3201 {
3203
3204 if (ARR_NDIM(a) != 1 ||
3205 ARR_LBOUND(a)[0] != 1 ||
3206 ARR_HASNULL(a) ||
3208 elog(ERROR, "extcondition is not a 1-D text array");
3209 if (ARR_DIMS(a)[0] != arrayLength)
3210 elog(ERROR, "extconfig and extcondition arrays do not match");
3211 }
3212
3213 if (arrayLength <= 1)
3214 {
3215 /* removing only element, just set array to null */
3217 }
3218 else
3219 {
3220 /* squeeze out the target element */
3221 Datum *dvalues;
3222 int nelems;
3223 int i;
3224
3225 /* We already checked there are no nulls */
3226 deconstruct_array_builtin(a, TEXTOID, &dvalues, NULL, &nelems);
3227
3228 for (i = arrayIndex; i < arrayLength - 1; i++)
3229 dvalues[i] = dvalues[i + 1];
3230
3232
3234 }
3236
3239
3241
3243
3245}
3246
3247/*
3248 * Execute ALTER EXTENSION SET SCHEMA
3249 */
3251AlterExtensionNamespace(const char *extensionName, const char *newschema, Oid *oldschema)
3252{
3254 Oid nspOid;
3255 Oid oldNspOid;
3258 ScanKeyData key[2];
3267
3269
3270 nspOid = LookupCreationNamespace(newschema);
3271
3272 /*
3273 * Permission check: must own extension. Note that we don't bother to
3274 * check ownership of the individual member objects ...
3275 */
3279
3280 /* Permission check: must have creation rights in target namespace */
3282 if (aclresult != ACLCHECK_OK)
3284
3285 /*
3286 * If the schema is currently a member of the extension, disallow moving
3287 * the extension into the schema. That would create a dependency loop.
3288 */
3290 ereport(ERROR,
3292 errmsg("cannot move extension \"%s\" into schema \"%s\" "
3293 "because the extension contains the schema",
3294 extensionName, newschema)));
3295
3296 /* Locate the pg_extension tuple */
3298
3299 ScanKeyInit(&key[0],
3303
3305 NULL, 1, key);
3306
3308
3309 if (!HeapTupleIsValid(extTup)) /* should not happen */
3310 elog(ERROR, "could not find tuple for extension %u",
3311 extensionOid);
3312
3313 /* Copy tuple so we can modify it below */
3316
3318
3319 /*
3320 * If the extension is already in the target schema, just silently do
3321 * nothing.
3322 */
3323 if (extForm->extnamespace == nspOid)
3324 {
3326 return InvalidObjectAddress;
3327 }
3328
3329 /* Check extension is supposed to be relocatable */
3330 if (!extForm->extrelocatable)
3331 ereport(ERROR,
3333 errmsg("extension \"%s\" does not support SET SCHEMA",
3334 NameStr(extForm->extname))));
3335
3337
3338 /* store the OID of the namespace to-be-changed */
3339 oldNspOid = extForm->extnamespace;
3340
3341 /*
3342 * Scan pg_depend to find objects that depend directly on the extension,
3343 * and alter each one's schema.
3344 */
3346
3347 ScanKeyInit(&key[0],
3351 ScanKeyInit(&key[1],
3355
3357 NULL, 2, key);
3358
3360 {
3364
3365 /*
3366 * If a dependent extension has a no_relocate request for this
3367 * extension, disallow SET SCHEMA. (XXX it's a bit ugly to do this in
3368 * the same loop that's actually executing the renames: we may detect
3369 * the error condition only after having expended a fair amount of
3370 * work. However, the alternative is to do two scans of pg_depend,
3371 * which seems like optimizing for failure cases. The rename work
3372 * will all roll back cleanly enough if we do fail here.)
3373 */
3374 if (pg_depend->deptype == DEPENDENCY_NORMAL &&
3375 pg_depend->classid == ExtensionRelationId)
3376 {
3377 char *depextname = get_extension_name(pg_depend->objid);
3379 ListCell *lc;
3380
3382 foreach(lc, dcontrol->no_relocate)
3383 {
3384 char *nrextname = (char *) lfirst(lc);
3385
3386 if (strcmp(nrextname, NameStr(extForm->extname)) == 0)
3387 {
3388 ereport(ERROR,
3390 errmsg("cannot SET SCHEMA of extension \"%s\" because other extensions prevent it",
3391 NameStr(extForm->extname)),
3392 errdetail("Extension \"%s\" requests no relocation of extension \"%s\".",
3393 depextname,
3394 NameStr(extForm->extname))));
3395 }
3396 }
3397 }
3398
3399 /*
3400 * Otherwise, ignore non-membership dependencies. (Currently, the
3401 * only other case we could see here is a normal dependency from
3402 * another extension.)
3403 */
3404 if (pg_depend->deptype != DEPENDENCY_EXTENSION)
3405 continue;
3406
3407 dep.classId = pg_depend->classid;
3408 dep.objectId = pg_depend->objid;
3409 dep.objectSubId = pg_depend->objsubid;
3410
3411 if (dep.objectSubId != 0) /* should not happen */
3412 elog(ERROR, "extension should not have a sub-object dependency");
3413
3414 /* Relocate the object */
3416 dep.objectId,
3417 nspOid,
3418 objsMoved);
3419
3420 /*
3421 * If not all the objects had the same old namespace (ignoring any
3422 * that are not in namespaces or are dependent types), complain.
3423 */
3425 ereport(ERROR,
3427 errmsg("extension \"%s\" does not support SET SCHEMA",
3428 NameStr(extForm->extname)),
3429 errdetail("%s is not in the extension's schema \"%s\"",
3430 getObjectDescription(&dep, false),
3432 }
3433
3434 /* report old schema, if caller wants it */
3435 if (oldschema)
3437
3439
3441
3442 /* Now adjust pg_extension.extnamespace */
3443 extForm->extnamespace = nspOid;
3444
3446
3448
3449 /* update dependency to point to the new schema */
3452 elog(ERROR, "could not change schema dependency for extension %s",
3453 NameStr(extForm->extname));
3454
3456
3458
3459 return extAddr;
3460}
3461
3462/*
3463 * Execute ALTER EXTENSION UPDATE
3464 */
3467{
3469 char *versionName;
3470 char *oldVersionName;
3471 ExtensionControlFile *control;
3474 ScanKeyData key[1];
3478 Datum datum;
3479 bool isnull;
3480 ListCell *lc;
3481 ObjectAddress address;
3482
3483 /*
3484 * We use global variables to track the extension being created, so we can
3485 * create/update only one extension at the same time.
3486 */
3488 ereport(ERROR,
3490 errmsg("nested ALTER EXTENSION is not supported")));
3491
3492 /*
3493 * Look up the extension --- it must already exist in pg_extension
3494 */
3496
3497 ScanKeyInit(&key[0],
3500 CStringGetDatum(stmt->extname));
3501
3503 NULL, 1, key);
3504
3506
3508 ereport(ERROR,
3510 errmsg("extension \"%s\" does not exist",
3511 stmt->extname)));
3512
3514
3515 /*
3516 * Determine the existing version we are updating from
3517 */
3519 RelationGetDescr(extRel), &isnull);
3520 if (isnull)
3521 elog(ERROR, "extversion is null");
3523
3525
3527
3528 /* Permission check: must own extension */
3531 stmt->extname);
3532
3533 /*
3534 * Read the primary control file. Note we assume that it does not contain
3535 * any non-ASCII data, so there is no need to worry about encoding at this
3536 * point.
3537 */
3538 control = read_extension_control_file(stmt->extname);
3539
3540 /*
3541 * Read the statement option list
3542 */
3543 foreach(lc, stmt->options)
3544 {
3545 DefElem *defel = (DefElem *) lfirst(lc);
3546
3547 if (strcmp(defel->defname, "new_version") == 0)
3548 {
3549 if (d_new_version)
3552 }
3553 else
3554 elog(ERROR, "unrecognized option: %s", defel->defname);
3555 }
3556
3557 /*
3558 * Determine the version to update to
3559 */
3560 if (d_new_version && d_new_version->arg)
3562 else if (control->default_version)
3563 versionName = control->default_version;
3564 else
3565 {
3566 ereport(ERROR,
3568 errmsg("version to install must be specified")));
3569 versionName = NULL; /* keep compiler quiet */
3570 }
3572
3573 /*
3574 * If we're already at that version, just say so
3575 */
3577 {
3579 (errmsg("version \"%s\" of extension \"%s\" is already installed",
3580 versionName, stmt->extname)));
3581 return InvalidObjectAddress;
3582 }
3583
3584 /*
3585 * Identify the series of update script files we need to execute
3586 */
3589 versionName);
3590
3591 /*
3592 * Update the pg_extension row and execute the update scripts, one at a
3593 * time
3594 */
3597 NULL, false, false);
3598
3600
3601 return address;
3602}
3603
3604/*
3605 * Apply a series of update scripts as though individual ALTER EXTENSION
3606 * UPDATE commands had been given, including altering the pg_extension row
3607 * and dependencies each time.
3608 *
3609 * This might be more work than necessary, but it ensures that old update
3610 * scripts don't break if newer versions have different control parameters.
3611 */
3612static void
3615 const char *initialVersion,
3617 char *origSchemaName,
3618 bool cascade,
3619 bool is_create)
3620{
3621 const char *oldVersionName = initialVersion;
3622 ListCell *lcv;
3623
3624 foreach(lcv, updateVersions)
3625 {
3626 char *versionName = (char *) lfirst(lcv);
3627 ExtensionControlFile *control;
3628 char *schemaName;
3629 Oid schemaOid;
3633 ScanKeyData key[1];
3638 bool nulls[Natts_pg_extension];
3639 bool repl[Natts_pg_extension];
3641 ListCell *lc;
3642
3643 /*
3644 * Fetch parameters for specific version (pcontrol is not changed)
3645 */
3647
3648 /* Find the pg_extension tuple */
3650
3651 ScanKeyInit(&key[0],
3655
3657 NULL, 1, key);
3658
3660
3661 if (!HeapTupleIsValid(extTup)) /* should not happen */
3662 elog(ERROR, "could not find tuple for extension %u",
3663 extensionOid);
3664
3666
3667 /*
3668 * Determine the target schema (set by original install)
3669 */
3670 schemaOid = extForm->extnamespace;
3672
3673 /*
3674 * Modify extrelocatable and extversion in the pg_extension tuple
3675 */
3676 memset(values, 0, sizeof(values));
3677 memset(nulls, 0, sizeof(nulls));
3678 memset(repl, 0, sizeof(repl));
3679
3681 BoolGetDatum(control->relocatable);
3682 repl[Anum_pg_extension_extrelocatable - 1] = true;
3685 repl[Anum_pg_extension_extversion - 1] = true;
3686
3688 values, nulls, repl);
3689
3691
3693
3695
3696 /*
3697 * Look up the prerequisite extensions for this version, install them
3698 * if necessary, and build lists of their OIDs and the OIDs of their
3699 * target schemas.
3700 */
3703 foreach(lc, control->requires)
3704 {
3705 char *curreq = (char *) lfirst(lc);
3706 Oid reqext;
3707 Oid reqschema;
3708
3710 control->name,
3712 cascade,
3713 NIL,
3714 is_create);
3718 }
3719
3720 /*
3721 * Remove and recreate dependencies on prerequisite extensions
3722 */
3726
3727 myself.classId = ExtensionRelationId;
3728 myself.objectId = extensionOid;
3729 myself.objectSubId = 0;
3730
3731 foreach(lc, requiredExtensions)
3732 {
3735
3737 otherext.objectId = reqext;
3738 otherext.objectSubId = 0;
3739
3741 }
3742
3744
3745 /*
3746 * Finally, execute the update script file
3747 */
3751 schemaName);
3752
3753 /*
3754 * Update prior-version name and loop around. Since
3755 * execute_sql_string did a final CommandCounterIncrement, we can
3756 * update the pg_extension row again.
3757 */
3759 }
3760}
3761
3762/*
3763 * Execute ALTER EXTENSION ADD/DROP
3764 *
3765 * Return value is the address of the altered extension.
3766 *
3767 * objAddr is an output argument which, if not NULL, is set to the address of
3768 * the added/dropped object.
3769 */
3773{
3775 ObjectAddress object;
3776 Relation relation;
3777
3778 switch (stmt->objtype)
3779 {
3780 case OBJECT_DATABASE:
3781 case OBJECT_EXTENSION:
3782 case OBJECT_INDEX:
3783 case OBJECT_PUBLICATION:
3784 case OBJECT_ROLE:
3787 case OBJECT_TABLESPACE:
3788 ereport(ERROR,
3790 errmsg("cannot add an object of this type to an extension")));
3791 break;
3792 default:
3793 /* OK */
3794 break;
3795 }
3796
3797 /*
3798 * Find the extension and acquire a lock on it, to ensure it doesn't get
3799 * dropped concurrently. A sharable lock seems sufficient: there's no
3800 * reason not to allow other sorts of manipulations, such as add/drop of
3801 * other objects, to occur concurrently. Concurrently adding/dropping the
3802 * *same* object would be bad, but we prevent that by using a non-sharable
3803 * lock on the individual object, below.
3804 */
3806 (Node *) makeString(stmt->extname),
3807 &relation, AccessShareLock, false);
3808
3809 /* Permission check: must own extension */
3812 stmt->extname);
3813
3814 /*
3815 * Translate the parser representation that identifies the object into an
3816 * ObjectAddress. get_object_address() will throw an error if the object
3817 * does not exist, and will also acquire a lock on the object to guard
3818 * against concurrent DROP and ALTER EXTENSION ADD/DROP operations.
3819 */
3820 object = get_object_address(stmt->objtype, stmt->object,
3821 &relation, ShareUpdateExclusiveLock, false);
3822
3823 Assert(object.objectSubId == 0);
3824 if (objAddr)
3825 *objAddr = object;
3826
3827 /* Permission check: must own target object, too */
3828 check_object_ownership(GetUserId(), stmt->objtype, object,
3829 stmt->object, relation);
3830
3831 /* Do the update, recursing to any dependent objects */
3833
3834 /* Finish up */
3836
3837 /*
3838 * If get_object_address() opened the relation for us, we close it to keep
3839 * the reference count correct - but we retain any locks acquired by
3840 * get_object_address() until commit time, to guard against concurrent
3841 * activity.
3842 */
3843 if (relation != NULL)
3844 relation_close(relation, NoLock);
3845
3846 return extension;
3847}
3848
3849/*
3850 * ExecAlterExtensionContentsRecurse
3851 * Subroutine for ExecAlterExtensionContentsStmt
3852 *
3853 * Do the bare alteration of object's membership in extension,
3854 * without permission checks. Recurse to dependent objects, if any.
3855 */
3856static void
3859 ObjectAddress object)
3860{
3862
3863 /*
3864 * Check existing extension membership.
3865 */
3866 oldExtension = getExtensionOfObject(object.classId, object.objectId);
3867
3868 if (stmt->action > 0)
3869 {
3870 /*
3871 * ADD, so complain if object is already attached to some extension.
3872 */
3874 ereport(ERROR,
3876 errmsg("%s is already a member of extension \"%s\"",
3877 getObjectDescription(&object, false),
3879
3880 /*
3881 * Prevent a schema from being added to an extension if the schema
3882 * contains the extension. That would create a dependency loop.
3883 */
3884 if (object.classId == NamespaceRelationId &&
3885 object.objectId == get_extension_schema(extension.objectId))
3886 ereport(ERROR,
3888 errmsg("cannot add schema \"%s\" to extension \"%s\" "
3889 "because the schema contains the extension",
3890 get_namespace_name(object.objectId),
3891 stmt->extname)));
3892
3893 /*
3894 * OK, add the dependency.
3895 */
3897
3898 /*
3899 * Also record the initial ACL on the object, if any.
3900 *
3901 * Note that this will handle the object's ACLs, as well as any ACLs
3902 * on object subIds. (In other words, when the object is a table,
3903 * this will record the table's ACL and the ACLs for the columns on
3904 * the table, if any).
3905 */
3906 recordExtObjInitPriv(object.objectId, object.classId);
3907 }
3908 else
3909 {
3910 /*
3911 * DROP, so complain if it's not a member.
3912 */
3913 if (oldExtension != extension.objectId)
3914 ereport(ERROR,
3916 errmsg("%s is not a member of extension \"%s\"",
3917 getObjectDescription(&object, false),
3918 stmt->extname)));
3919
3920 /*
3921 * OK, drop the dependency.
3922 */
3923 if (deleteDependencyRecordsForClass(object.classId, object.objectId,
3926 elog(ERROR, "unexpected number of extension dependency records");
3927
3928 /*
3929 * If it's a relation, it might have an entry in the extension's
3930 * extconfig array, which we must remove.
3931 */
3932 if (object.classId == RelationRelationId)
3933 extension_config_remove(extension.objectId, object.objectId);
3934
3935 /*
3936 * Remove all the initial ACLs, if any.
3937 *
3938 * Note that this will remove the object's ACLs, as well as any ACLs
3939 * on object subIds. (In other words, when the object is a table,
3940 * this will remove the table's ACL and the ACLs for the columns on
3941 * the table, if any).
3942 */
3943 removeExtObjInitPriv(object.objectId, object.classId);
3944 }
3945
3946 /*
3947 * Recurse to any dependent objects; currently, this includes the array
3948 * type of a base type, the multirange type associated with a range type,
3949 * and the rowtype of a table.
3950 */
3951 if (object.classId == TypeRelationId)
3952 {
3954
3956 depobject.objectSubId = 0;
3957
3958 /* If it has an array type, update that too */
3959 depobject.objectId = get_array_type(object.objectId);
3960 if (OidIsValid(depobject.objectId))
3962
3963 /* If it is a range type, update the associated multirange too */
3964 if (type_is_range(object.objectId))
3965 {
3966 depobject.objectId = get_range_multirange(object.objectId);
3967 if (!OidIsValid(depobject.objectId))
3968 ereport(ERROR,
3970 errmsg("could not find multirange type for data type %s",
3971 format_type_be(object.objectId))));
3973 }
3974 }
3975 if (object.classId == RelationRelationId)
3976 {
3978
3980 depobject.objectSubId = 0;
3981
3982 /* It might not have a rowtype, but if it does, update that */
3983 depobject.objectId = get_rel_type_id(object.objectId);
3984 if (OidIsValid(depobject.objectId))
3986 }
3987}
3988
3989/*
3990 * Read the whole of file into memory.
3991 *
3992 * The file contents are returned as a single palloc'd chunk. For convenience
3993 * of the callers, an extra \0 byte is added to the end. That is not counted
3994 * in the length returned into *length.
3995 */
3996static char *
3997read_whole_file(const char *filename, int *length)
3998{
3999 char *buf;
4000 FILE *file;
4001 size_t bytes_to_read;
4002 struct stat fst;
4003
4004 if (stat(filename, &fst) < 0)
4005 ereport(ERROR,
4007 errmsg("could not stat file \"%s\": %m", filename)));
4008
4009 if (fst.st_size > (MaxAllocSize - 1))
4010 ereport(ERROR,
4012 errmsg("file \"%s\" is too large", filename)));
4013 bytes_to_read = (size_t) fst.st_size;
4014
4015 if ((file = AllocateFile(filename, PG_BINARY_R)) == NULL)
4016 ereport(ERROR,
4018 errmsg("could not open file \"%s\" for reading: %m",
4019 filename)));
4020
4021 buf = (char *) palloc(bytes_to_read + 1);
4022
4023 bytes_to_read = fread(buf, 1, bytes_to_read, file);
4024
4025 if (ferror(file))
4026 ereport(ERROR,
4028 errmsg("could not read file \"%s\": %m", filename)));
4029
4030 FreeFile(file);
4031
4032 buf[bytes_to_read] = '\0';
4033
4034 /*
4035 * On Windows, manually convert Windows-style newlines (\r\n) to the Unix
4036 * convention of \n only. This avoids gotchas due to script files
4037 * possibly getting converted when being transferred between platforms.
4038 * Ideally we'd do this by using text mode to read the file, but that also
4039 * causes control-Z to be treated as end-of-file. Historically we've
4040 * allowed control-Z in script files, so breaking that seems unwise.
4041 */
4042#ifdef WIN32
4043 {
4044 char *s,
4045 *d;
4046
4047 for (s = d = buf; *s; s++)
4048 {
4049 if (!(*s == '\r' && s[1] == '\n'))
4050 *d++ = *s;
4051 }
4052 *d = '\0';
4053 bytes_to_read = d - buf;
4054 }
4055#endif
4056
4057 *length = bytes_to_read;
4058 return buf;
4059}
4060
4061static ExtensionControlFile *
4062new_ExtensionControlFile(const char *extname)
4063{
4064 /*
4065 * Set up default values. Pointer fields are initially null.
4066 */
4068
4069 control->name = pstrdup(extname);
4070 control->relocatable = false;
4071 control->superuser = true;
4072 control->trusted = false;
4073 control->encoding = -1;
4074
4075 return control;
4076}
4077
4078/*
4079 * Search for the basename in the list of paths.
4080 *
4081 * Similar to find_in_path but for simplicity does not support custom error
4082 * messages and expects that paths already have all macros replaced.
4083 */
4084char *
4085find_in_paths(const char *basename, List *paths)
4086{
4087 ListCell *cell;
4088
4089 foreach(cell, paths)
4090 {
4091 ExtensionLocation *location = lfirst(cell);
4092 char *path = location->loc;
4093 char *full;
4094
4095 Assert(path != NULL);
4096
4097 path = pstrdup(path);
4098 canonicalize_path(path);
4099
4100 /* only absolute paths */
4101 if (!is_absolute_path(path))
4102 ereport(ERROR,
4104 errmsg("component in parameter \"%s\" is not an absolute path", "extension_control_path"));
4105
4106 full = psprintf("%s/%s", path, basename);
4107
4108 if (pg_file_exists(full))
4109 return full;
4110
4111 pfree(path);
4112 pfree(full);
4113 }
4114
4115 return NULL;
4116}
AclResult
Definition acl.h:182
@ ACLCHECK_OK
Definition acl.h:183
@ ACLCHECK_NOT_OWNER
Definition acl.h:185
void recordExtObjInitPriv(Oid objoid, Oid classoid)
Definition aclchk.c:4354
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition aclchk.c:2654
AclResult object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode)
Definition aclchk.c:3836
bool object_ownercheck(Oid classid, Oid objectid, Oid roleid)
Definition aclchk.c:4090
void removeExtObjInitPriv(Oid objoid, Oid classoid)
Definition aclchk.c:4518
Oid AlterObjectNamespace_oid(Oid classId, Oid objid, Oid nspOid, ObjectAddresses *objsMoved)
Definition alter.c:619
#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:155
#define CStringGetTextDatum(s)
Definition builtins.h:98
#define NameStr(name)
Definition c.h:765
#define PG_BINARY_R
Definition c.h:1289
#define Assert(condition)
Definition c.h:873
uint32_t uint32
Definition c.h:546
#define OidIsValid(objectId)
Definition c.h:788
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
int internalerrquery(const char *query)
Definition elog.c:1517
int internalerrposition(int cursorpos)
Definition elog.c:1497
int errcode_for_file_access(void)
Definition elog.c:887
int errdetail(const char *fmt,...)
Definition elog.c:1217
ErrorContextCallback * error_context_stack
Definition elog.c:95
int errhint(const char *fmt,...)
Definition elog.c:1331
int geterrposition(void)
Definition elog.c:1613
int errcode(int sqlerrcode)
Definition elog.c:864
int errmsg(const char *fmt,...)
Definition elog.c:1081
int errposition(int cursorpos)
Definition elog.c:1481
#define errcontext
Definition elog.h:198
#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
#define elog(elevel,...)
Definition elog.h:226
#define NOTICE
Definition elog.h:35
#define PG_FINALLY(...)
Definition elog.h:389
#define ereport(elevel,...)
Definition elog.h:150
void ExecutorEnd(QueryDesc *queryDesc)
Definition execMain.c:466
void ExecutorFinish(QueryDesc *queryDesc)
Definition execMain.c:406
void ExecutorStart(QueryDesc *queryDesc, int eflags)
Definition execMain.c:122
void ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count)
Definition execMain.c:297
static char * get_extension_aux_control_filename(ExtensionControlFile *control, const char *version)
Definition extension.c:636
Oid get_extension_schema(Oid ext_oid)
Definition extension.c:271
static bool is_extension_script_filename(const char *filename)
Definition extension.c:501
static char * read_whole_file(const char *filename, int *length)
Definition extension.c:3997
ObjectAddress InsertExtensionTuple(const char *extName, Oid extOwner, Oid schemaOid, bool relocatable, const char *extVersion, Datum extConfig, Datum extCondition, List *requiredExtensions)
Definition extension.c:2240
static void check_valid_extension_name(const char *extensionname)
Definition extension.c:399
Oid get_function_sibling_type(Oid funcoid, const char *typname)
Definition extension.c:311
static ExtensionVersionInfo * get_nearest_unprocessed_vertex(List *evi_list)
Definition extension.c:1550
ObjectAddress CreateExtension(ParseState *pstate, CreateExtensionStmt *stmt)
Definition extension.c:2142
static void check_valid_version_name(const char *versionname)
Definition extension.c:446
static void get_available_versions_for_extension(ExtensionControlFile *pcontrol, Tuplestorestate *tupstore, TupleDesc tupdesc, ExtensionLocation *location)
Definition extension.c:2561
static bool is_extension_control_filename(const char *filename)
Definition extension.c:493
Datum pg_get_loaded_modules(PG_FUNCTION_ARGS)
Definition extension.c:3033
static ExtensionSiblingCache * ext_sibling_list
Definition extension.c:162
static Oid get_required_extension(char *reqExtensionName, char *extensionName, char *origSchemaName, bool cascade, List *parents, bool is_create)
Definition extension.c:2071
static void script_error_callback(void *arg)
Definition extension.c:952
static ExtensionControlFile * read_extension_aux_control_file(const ExtensionControlFile *pcontrol, const char *version)
Definition extension.c:896
static char * get_extension_location(ExtensionLocation *loc)
Definition extension.c:202
char * Extension_control_path
Definition extension.c:76
static void parse_extension_control_file(ExtensionControlFile *control, const char *version)
Definition extension.c:689
bool creating_extension
Definition extension.c:79
static List * get_extension_control_directories(void)
Definition extension.c:512
Datum pg_available_extension_versions(PG_FUNCTION_ARGS)
Definition extension.c:2484
static void extension_config_remove(Oid extensionoid, Oid tableoid)
Definition extension.c:3086
static void execute_sql_string(const char *sql, const char *filename)
Definition extension.c:1094
static char * get_extension_script_directory(ExtensionControlFile *control)
Definition extension.c:617
static char * find_extension_control_filename(ExtensionControlFile *control)
Definition extension.c:591
ObjectAddress AlterExtensionNamespace(const char *extensionName, const char *newschema, Oid *oldschema)
Definition extension.c:3251
static ExtensionVersionInfo * find_install_path(List *evi_list, ExtensionVersionInfo *evi_target, List **best_path)
Definition extension.c:1777
static ExtensionControlFile * read_extension_control_file(const char *extname)
Definition extension.c:877
static void ext_sibling_callback(Datum arg, int cacheid, uint32 hashvalue)
Definition extension.c:382
ObjectAddress ExecAlterExtensionStmt(ParseState *pstate, AlterExtensionStmt *stmt)
Definition extension.c:3466
Oid CurrentExtensionObject
Definition extension.c:80
ObjectAddress ExecAlterExtensionContentsStmt(AlterExtensionContentsStmt *stmt, ObjectAddress *objAddr)
Definition extension.c:3771
Datum pg_extension_update_paths(PG_FUNCTION_ARGS)
Definition extension.c:2765
static char * read_extension_script_file(const ExtensionControlFile *control, const char *filename)
Definition extension.c:919
static void ExecAlterExtensionContentsRecurse(AlterExtensionContentsStmt *stmt, ObjectAddress extension, ObjectAddress object)
Definition extension.c:3857
Oid get_extension_oid(const char *extname, bool missing_ok)
Definition extension.c:227
Datum pg_available_extensions(PG_FUNCTION_ARGS)
Definition extension.c:2382
static ExtensionControlFile * new_ExtensionControlFile(const char *extname)
Definition extension.c:4062
Datum pg_extension_config_dump(PG_FUNCTION_ARGS)
Definition extension.c:2850
char * find_in_paths(const char *basename, List *paths)
Definition extension.c:4085
static Datum convert_requires_to_datum(List *requires)
Definition extension.c:2739
static List * identify_update_path(ExtensionControlFile *control, const char *oldVersion, const char *newVersion)
Definition extension.c:1641
static ExtensionVersionInfo * get_ext_ver_info(const char *versionname, List **evi_list)
Definition extension.c:1517
char * get_extension_name(Oid ext_oid)
Definition extension.c:249
void RemoveExtensionById(Oid extId)
Definition extension.c:2328
static List * get_ext_ver_list(ExtensionControlFile *control)
Definition extension.c:1578
static List * find_update_path(List *evi_list, ExtensionVersionInfo *evi_start, ExtensionVersionInfo *evi_target, bool reject_indirect, bool reinitialize)
Definition extension.c:1684
static char * get_extension_script_filename(ExtensionControlFile *control, const char *from_version, const char *version)
Definition extension.c:654
static void execute_extension_script(Oid extensionOid, ExtensionControlFile *control, const char *from_version, const char *version, List *requiredSchemas, const char *schemaName)
Definition extension.c:1244
bool extension_file_exists(const char *extensionName)
Definition extension.c:2680
static bool extension_is_trusted(ExtensionControlFile *control)
Definition extension.c:1222
static void ApplyExtensionUpdates(Oid extensionOid, ExtensionControlFile *pcontrol, const char *initialVersion, List *updateVersions, char *origSchemaName, bool cascade, bool is_create)
Definition extension.c:3613
static ObjectAddress CreateExtensionInternal(char *extensionName, char *schemaName, const char *versionName, bool cascade, List *parents, bool is_create)
Definition extension.c:1832
int FreeDir(DIR *dir)
Definition fd.c:3008
int FreeFile(FILE *file)
Definition fd.c:2826
bool pg_file_exists(const char *name)
Definition fd.c:503
DIR * AllocateDir(const char *dirname)
Definition fd.c:2890
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition fd.c:2956
FILE * AllocateFile(const char *name, const char *mode)
Definition fd.c:2627
#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:860
Datum DirectFunctionCall3Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2, Datum arg3)
Definition fmgr.c:835
#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:3256
int NewGUCNestLevel(void)
Definition guc.c:2110
void AtEOXact_GUC(bool isCommit, int nestLevel)
Definition guc.c:2137
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:3216
@ 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:538
int client_min_messages
Definition guc_tables.c:549
int log_min_messages[]
Definition guc_tables.c:662
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, const Datum *replValues, const bool *replIsnull, const bool *doReplace)
Definition heaptuple.c:1210
HeapTuple heap_copytuple(HeapTuple tuple)
Definition heaptuple.c:778
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
Definition heaptuple.c:1117
void heap_freetuple(HeapTuple htup)
Definition heaptuple.c:1435
#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(int 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:2078
bool type_is_range(Oid typid)
Definition lsyscache.c:2838
Oid get_rel_type_id(Oid relid)
Definition lsyscache.c:2129
Oid get_range_multirange(Oid rangeOid)
Definition lsyscache.c:3608
char * get_namespace_name(Oid nspid)
Definition lsyscache.c:3516
Oid get_array_type(Oid typid)
Definition lsyscache.c:2937
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:612
Oid GetUserId(void)
Definition miscinit.c:469
BackendType MyBackendType
Definition miscinit.c:64
char * GetUserNameFromId(Oid roleid, bool noerr)
Definition miscinit.c:988
void SetUserIdAndSecContext(Oid userid, int sec_context)
Definition miscinit.c:619
Datum namein(PG_FUNCTION_ARGS)
Definition name.c:48
bool isTempNamespace(Oid namespaceId)
Definition namespace.c:3719
Oid LookupCreationNamespace(const char *nspname)
Definition namespace.c:3498
List * fetch_search_path(bool includeImplicit)
Definition namespace.c:4889
Oid get_namespace_oid(const char *nspname, bool missing_ok)
Definition namespace.c:3605
#define IsA(nodeptr, _type_)
Definition nodes.h:164
#define makeNode(_type_)
Definition nodes.h:161
int ParseLoc
Definition nodes.h:250
#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
void * arg
#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
FormData_pg_depend * Form_pg_depend
Definition pg_depend.h:72
static char * filename
Definition pg_dumpall.c:120
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:41
#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:603
List * pg_plan_queries(List *querytrees, const char *query_string, int cursorOptions, ParamListInfo boundParams)
Definition postgres.c:974
List * pg_analyze_and_rewrite_fixedparams(RawStmt *parsetree, const char *query_string, const Oid *paramTypes, int numParams, QueryEnvironment *queryEnv)
Definition postgres.c:669
static Datum PointerGetDatum(const void *X)
Definition postgres.h:352
static Datum BoolGetDatum(bool X)
Definition postgres.h:112
static Datum ObjectIdGetDatum(Oid X)
Definition postgres.h:262
uint64_t Datum
Definition postgres.h:70
static Datum CStringGetDatum(const char *X)
Definition postgres.h:380
#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:102
struct ExtensionSiblingCache * next
Definition extension.c:152
const char * typname
Definition extension.c:155
struct ExtensionVersionInfo * previous
Definition extension.c:117
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:760
Definition c.h:706
bool superuser(void)
Definition superuser.c:46
void ReleaseSysCache(HeapTuple tuple)
Definition syscache.c:264
HeapTuple SearchSysCache1(int 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:784
void ProcessUtility(PlannedStmt *pstmt, const char *queryString, bool readOnlyTree, ProcessUtilityContext context, ParamListInfo params, QueryEnvironment *queryEnv, DestReceiver *dest, QueryCompletion *qc)
Definition utility.c:501
@ 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:2775
char * text_to_cstring(const text *t)
Definition varlena.c:215
Datum replace_text(PG_FUNCTION_ARGS)
Definition varlena.c:3123
#define stat
Definition win32_port.h:74
void CommandCounterIncrement(void)
Definition xact.c:1101
int MyXactFlags
Definition xact.c:137
#define XACT_FLAGS_ACCESSEDTEMPNAMESPACE
Definition xact.h:103