PostgreSQL Source Code git master
Loading...
Searching...
No Matches
ddlutils.c File Reference
#include "postgres.h"
#include "access/genam.h"
#include "access/htup_details.h"
#include "access/table.h"
#include "catalog/pg_auth_members.h"
#include "catalog/pg_authid.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_database.h"
#include "catalog/pg_db_role_setting.h"
#include "catalog/pg_tablespace.h"
#include "commands/tablespace.h"
#include "common/relpath.h"
#include "funcapi.h"
#include "mb/pg_wchar.h"
#include "miscadmin.h"
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/datetime.h"
#include "utils/fmgroids.h"
#include "utils/guc.h"
#include "utils/lsyscache.h"
#include "utils/pg_locale.h"
#include "utils/rel.h"
#include "utils/ruleutils.h"
#include "utils/syscache.h"
#include "utils/timestamp.h"
#include "utils/varlena.h"
Include dependency graph for ddlutils.c:

Go to the source code of this file.

Functions

static void append_ddl_option (StringInfo buf, bool pretty, int indent, const char *fmt,...) pg_attribute_printf(4
 
static void static void append_guc_value (StringInfo buf, const char *name, const char *value)
 
static Listpg_get_role_ddl_internal (Oid roleid, bool pretty, bool memberships)
 
static Listpg_get_tablespace_ddl_internal (Oid tsid, bool pretty, bool no_owner)
 
static Datum pg_get_tablespace_ddl_srf (FunctionCallInfo fcinfo, Oid tsid)
 
static Listpg_get_database_ddl_internal (Oid dbid, bool pretty, bool no_owner, bool no_tablespace)
 
Datum pg_get_role_ddl (PG_FUNCTION_ARGS)
 
Datum pg_get_tablespace_ddl_oid (PG_FUNCTION_ARGS)
 
Datum pg_get_tablespace_ddl_name (PG_FUNCTION_ARGS)
 
Datum pg_get_database_ddl (PG_FUNCTION_ARGS)
 

Function Documentation

◆ append_ddl_option()

static void append_ddl_option ( StringInfo  buf,
bool  pretty,
int  indent,
const char fmt,
  ... 
)
static

Definition at line 65 of file ddlutils.c.

67{
68 if (pretty)
69 {
72 }
73 else
75
76 for (;;)
77 {
79 int needed;
80
81 va_start(args, fmt);
83 va_end(args);
84 if (needed == 0)
85 break;
87 }
88}
static char buf[DEFAULT_XLOG_SEG_SIZE]
static int fb(int x)
int appendStringInfoVA(StringInfo str, const char *fmt, va_list args)
Definition stringinfo.c:187
void enlargeStringInfo(StringInfo str, int needed)
Definition stringinfo.c:337
void appendStringInfoSpaces(StringInfo str, int count)
Definition stringinfo.c:260
void appendStringInfoChar(StringInfo str, char ch)
Definition stringinfo.c:242

References appendStringInfoChar(), appendStringInfoSpaces(), appendStringInfoVA(), buf, enlargeStringInfo(), and fb().

Referenced by pg_get_database_ddl_internal(), pg_get_role_ddl_internal(), and pg_get_tablespace_ddl_internal().

◆ append_guc_value()

static void append_guc_value ( StringInfo  buf,
const char name,
const char value 
)
static

Definition at line 102 of file ddlutils.c.

103{
104 char *rawval;
105
107
109 {
110 List *namelist;
111 bool first = true;
112
113 /* Parse string into list of identifiers */
114 if (!SplitGUCList(rawval, ',', &namelist))
115 {
116 /* this shouldn't fail really */
117 elog(ERROR, "invalid list syntax in setconfig item");
118 }
119 /* Special case: represent an empty list as NULL */
120 if (namelist == NIL)
123 {
124 if (first)
125 first = false;
126 else
129 }
131 }
132 else
134
135 pfree(rawval);
136}
#define ERROR
Definition elog.h:40
#define elog(elevel,...)
Definition elog.h:228
int GetConfigOptionFlags(const char *name, bool missing_ok)
Definition guc.c:4354
#define GUC_LIST_QUOTE
Definition guc.h:215
static struct @175 value
void list_free(List *list)
Definition list.c:1546
char * pstrdup(const char *in)
Definition mcxt.c:1910
void pfree(void *pointer)
Definition mcxt.c:1619
#define NIL
Definition pg_list.h:68
#define foreach_ptr(type, var, lst)
Definition pg_list.h:501
char * quote_literal_cstr(const char *rawstr)
Definition quote.c:101
void appendStringInfoString(StringInfo str, const char *s)
Definition stringinfo.c:230
Definition pg_list.h:54
bool SplitGUCList(char *rawstring, char separator, List **namelist)
Definition varlena.c:3063
const char * name

References appendStringInfoString(), buf, elog, ERROR, fb(), foreach_ptr, GetConfigOptionFlags(), GUC_LIST_QUOTE, list_free(), name, NIL, pfree(), pstrdup(), quote_literal_cstr(), SplitGUCList(), and value.

Referenced by pg_get_database_ddl_internal(), and pg_get_role_ddl_internal().

◆ pg_get_database_ddl()

Datum pg_get_database_ddl ( PG_FUNCTION_ARGS  )

Definition at line 932 of file ddlutils.c.

933{
936
937 if (SRF_IS_FIRSTCALL())
938 {
939 MemoryContext oldcontext;
940 Oid dbid;
941 bool pretty;
942 bool no_owner;
943 bool no_tablespace;
944
946 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
947
948 dbid = PG_GETARG_OID(0);
952
955 funcctx->user_fctx = statements;
956 funcctx->max_calls = list_length(statements);
957
958 MemoryContextSwitchTo(oldcontext);
959 }
960
962 statements = (List *) funcctx->user_fctx;
963
964 if (funcctx->call_cntr < funcctx->max_calls)
965 {
966 char *stmt;
967
968 stmt = list_nth(statements, funcctx->call_cntr);
969
971 }
972 else
973 {
976 }
977}
#define CStringGetTextDatum(s)
Definition builtins.h:98
static List * pg_get_database_ddl_internal(Oid dbid, bool pretty, bool no_owner, bool no_tablespace)
Definition ddlutils.c:655
#define PG_GETARG_OID(n)
Definition fmgr.h:275
#define PG_GETARG_BOOL(n)
Definition fmgr.h:274
#define SRF_IS_FIRSTCALL()
Definition funcapi.h:304
#define SRF_PERCALL_SETUP()
Definition funcapi.h:308
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition funcapi.h:310
#define SRF_FIRSTCALL_INIT()
Definition funcapi.h:306
#define SRF_RETURN_DONE(_funcctx)
Definition funcapi.h:328
#define stmt
void list_free_deep(List *list)
Definition list.c:1560
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:138
static int list_length(const List *l)
Definition pg_list.h:152
static void * list_nth(const List *list, int n)
Definition pg_list.h:331
unsigned int Oid

References CStringGetTextDatum, fb(), list_free_deep(), list_length(), list_nth(), MemoryContextSwitchTo(), pg_get_database_ddl_internal(), PG_GETARG_BOOL, PG_GETARG_OID, SRF_FIRSTCALL_INIT, SRF_IS_FIRSTCALL, SRF_PERCALL_SETUP, SRF_RETURN_DONE, SRF_RETURN_NEXT, and stmt.

◆ pg_get_database_ddl_internal()

static List * pg_get_database_ddl_internal ( Oid  dbid,
bool  pretty,
bool  no_owner,
bool  no_tablespace 
)
static

Definition at line 655 of file ddlutils.c.

657{
658 HeapTuple tuple;
661 bool isnull;
662 Datum datum;
663 const char *encoding;
664 char *dbname;
665 char *collate;
666 char *ctype;
667 Relation rel;
669 SysScanDesc scan;
672
674 if (!HeapTupleIsValid(tuple))
677 errmsg("database with OID %u does not exist", dbid)));
678
679 /* User must have connect privilege for target database. */
681 if (aclresult != ACLCHECK_OK)
683 get_database_name(dbid));
684
686 dbname = pstrdup(NameStr(dbform->datname));
687
688 /*
689 * Reject invalid databases. Deparsing a pg_database row in invalid state
690 * can produce SQL that is not executable, such as CONNECTION LIMIT = -2.
691 */
695 errmsg("cannot generate DDL for invalid database \"%s\"",
696 dbname)));
697
698 /*
699 * We don't support generating DDL for system databases. The primary
700 * reason for this is that users shouldn't be recreating them.
701 */
702 if (strcmp(dbname, "template0") == 0 || strcmp(dbname, "template1") == 0)
705 errmsg("database \"%s\" is a system database", dbname),
706 errdetail("DDL generation is not supported for template0 and template1.")));
707
709
710 /* --- Build CREATE DATABASE statement --- */
711 appendStringInfo(&buf, "CREATE DATABASE %s", quote_identifier(dbname));
712
713 /*
714 * Always use template0: the target database already contains the catalog
715 * data from whatever template was used originally, so we must start from
716 * the pristine template to avoid duplication.
717 */
718 append_ddl_option(&buf, pretty, 4, "WITH TEMPLATE = template0");
719
720 /* ENCODING */
722 if (strlen(encoding) > 0)
723 append_ddl_option(&buf, pretty, 4, "ENCODING = %s",
725
726 /* LOCALE_PROVIDER */
727 if (dbform->datlocprovider == COLLPROVIDER_BUILTIN ||
728 dbform->datlocprovider == COLLPROVIDER_ICU ||
729 dbform->datlocprovider == COLLPROVIDER_LIBC)
730 append_ddl_option(&buf, pretty, 4, "LOCALE_PROVIDER = %s",
731 collprovider_name(dbform->datlocprovider));
732 else
735 errmsg("unrecognized locale provider: %c",
736 dbform->datlocprovider)));
737
738 /* LOCALE, LC_COLLATE, LC_CTYPE */
739 datum = SysCacheGetAttr(DATABASEOID, tuple,
741 collate = isnull ? NULL : TextDatumGetCString(datum);
742 datum = SysCacheGetAttr(DATABASEOID, tuple,
744 ctype = isnull ? NULL : TextDatumGetCString(datum);
745 if (collate != NULL && ctype != NULL && strcmp(collate, ctype) == 0)
746 {
747 append_ddl_option(&buf, pretty, 4, "LOCALE = %s",
748 quote_literal_cstr(collate));
749 }
750 else
751 {
752 if (collate != NULL)
753 append_ddl_option(&buf, pretty, 4, "LC_COLLATE = %s",
754 quote_literal_cstr(collate));
755 if (ctype != NULL)
756 append_ddl_option(&buf, pretty, 4, "LC_CTYPE = %s",
757 quote_literal_cstr(ctype));
758 }
759
760 /* LOCALE (provider-specific) */
761 datum = SysCacheGetAttr(DATABASEOID, tuple,
763 if (!isnull)
764 {
765 const char *locale = TextDatumGetCString(datum);
766
767 if (dbform->datlocprovider == COLLPROVIDER_BUILTIN)
768 append_ddl_option(&buf, pretty, 4, "BUILTIN_LOCALE = %s",
769 quote_literal_cstr(locale));
770 else if (dbform->datlocprovider == COLLPROVIDER_ICU)
771 append_ddl_option(&buf, pretty, 4, "ICU_LOCALE = %s",
772 quote_literal_cstr(locale));
773 }
774
775 /* ICU_RULES */
776 datum = SysCacheGetAttr(DATABASEOID, tuple,
778 if (!isnull && dbform->datlocprovider == COLLPROVIDER_ICU)
779 append_ddl_option(&buf, pretty, 4, "ICU_RULES = %s",
781
782 /* TABLESPACE */
783 if (!no_tablespace && OidIsValid(dbform->dattablespace))
784 {
785 char *spcname = get_tablespace_name(dbform->dattablespace);
786
787 if (spcname == NULL)
790 errmsg("tablespace with OID %u does not exist",
791 dbform->dattablespace),
792 errdetail("It may have been concurrently dropped.")));
793
794 if (pg_strcasecmp(spcname, "pg_default") != 0)
795 append_ddl_option(&buf, pretty, 4, "TABLESPACE = %s",
797 }
798
801
802 /* OWNER */
803 if (!no_owner && OidIsValid(dbform->datdba))
804 {
805 char *owner = GetUserNameFromId(dbform->datdba, false);
806
808 appendStringInfo(&buf, "ALTER DATABASE %s OWNER TO %s;",
810 pfree(owner);
812 }
813
814 /* CONNECTION LIMIT */
815 if (dbform->datconnlimit != -1)
816 {
818 appendStringInfo(&buf, "ALTER DATABASE %s CONNECTION LIMIT = %d;",
819 quote_identifier(dbname), dbform->datconnlimit);
821 }
822
823 /* IS_TEMPLATE */
824 if (dbform->datistemplate)
825 {
827 appendStringInfo(&buf, "ALTER DATABASE %s IS_TEMPLATE = true;",
830 }
831
832 /* ALLOW_CONNECTIONS */
833 if (!dbform->datallowconn)
834 {
836 appendStringInfo(&buf, "ALTER DATABASE %s ALLOW_CONNECTIONS = false;",
839 }
840
841 ReleaseSysCache(tuple);
842
843 /*
844 * Now scan pg_db_role_setting for ALTER DATABASE SET configurations.
845 *
846 * It is only database-wide (setrole = 0). It generates one ALTER
847 * statement per setting.
848 */
853 ObjectIdGetDatum(dbid));
858
860 NULL, 2, scankey);
861
862 while (HeapTupleIsValid(tuple = systable_getnext(scan)))
863 {
865 Datum *settings;
866 bool *nulls;
867 int nsettings;
868
869 /*
870 * The setconfig column is a text array in "name=value" format. It
871 * should never be null for a valid row, but be defensive.
872 */
874 RelationGetDescr(rel), &isnull);
875 if (isnull)
876 continue;
877
879
881
882 for (int i = 0; i < nsettings; i++)
883 {
884 char *s,
885 *p;
886
887 if (nulls[i])
888 continue;
889
890 s = TextDatumGetCString(settings[i]);
891 p = strchr(s, '=');
892 if (p == NULL)
893 {
894 pfree(s);
895 continue;
896 }
897 *p++ = '\0';
898
900 appendStringInfo(&buf, "ALTER DATABASE %s SET %s TO ",
903
904 append_guc_value(&buf, s, p);
905
907
909
910 pfree(s);
911 }
912
913 pfree(settings);
914 pfree(nulls);
916 }
917
918 systable_endscan(scan);
920
921 pfree(buf.data);
922 pfree(dbname);
923
924 return statements;
925}
AclResult
Definition acl.h:183
@ ACLCHECK_OK
Definition acl.h:184
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition aclchk.c:2672
AclResult object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode)
Definition aclchk.c:3902
#define DatumGetArrayTypePCopy(X)
Definition array.h:262
void deconstruct_array_builtin(const ArrayType *array, Oid elmtype, Datum **elemsp, bool **nullsp, int *nelemsp)
char * get_tablespace_name(Oid spc_oid)
#define TextDatumGetCString(d)
Definition builtins.h:99
#define NameStr(name)
Definition c.h:894
#define OidIsValid(objectId)
Definition c.h:917
bool database_is_invalid_form(Form_pg_database datform)
static void append_ddl_option(StringInfo buf, bool pretty, int indent, const char *fmt,...) pg_attribute_printf(4
Definition ddlutils.c:65
static void static void append_guc_value(StringInfo buf, const char *name, const char *value)
Definition ddlutils.c:102
int errcode(int sqlerrcode)
Definition elog.c:875
int errdetail(const char *fmt,...) pg_attribute_printf(1
#define ereport(elevel,...)
Definition elog.h:152
void systable_endscan(SysScanDesc sysscan)
Definition genam.c:604
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition genam.c:515
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition genam.c:388
#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)
static char * encoding
Definition initdb.c:139
int i
Definition isn.c:77
List * lappend(List *list, void *datum)
Definition list.c:339
#define AccessShareLock
Definition lockdefs.h:36
char * get_database_name(Oid dbid)
Definition lsyscache.c:1392
Oid GetUserId(void)
Definition miscinit.c:470
char * GetUserNameFromId(Oid roleid, bool noerr)
Definition miscinit.c:990
static char * errmsg
@ OBJECT_DATABASE
#define ACL_CONNECT
Definition parsenodes.h:87
END_CATALOG_STRUCT typedef FormData_pg_database * Form_pg_database
#define pg_encoding_to_char
Definition pg_wchar.h:483
int pg_strcasecmp(const char *s1, const char *s2)
static Datum ObjectIdGetDatum(Oid X)
Definition postgres.h:252
uint64_t Datum
Definition postgres.h:70
#define InvalidOid
#define RelationGetDescr(relation)
Definition rel.h:542
const char * quote_identifier(const char *ident)
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition scankey.c:76
#define BTEqualStrategyNumber
Definition stratnum.h:31
char * dbname
Definition streamutil.c:49
void resetStringInfo(StringInfo str)
Definition stringinfo.c:126
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition stringinfo.c:145
void initStringInfo(StringInfo str)
Definition stringinfo.c:97
void ReleaseSysCache(HeapTuple tuple)
Definition syscache.c:265
HeapTuple SearchSysCache1(SysCacheIdentifier cacheId, Datum key1)
Definition syscache.c:221
Datum SysCacheGetAttr(SysCacheIdentifier cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition syscache.c:596
void table_close(Relation relation, LOCKMODE lockmode)
Definition table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition table.c:40

References AccessShareLock, ACL_CONNECT, aclcheck_error(), ACLCHECK_OK, append_ddl_option(), append_guc_value(), appendStringInfo(), appendStringInfoChar(), BTEqualStrategyNumber, buf, database_is_invalid_form(), DatumGetArrayTypePCopy, dbname, deconstruct_array_builtin(), encoding, ereport, errcode(), errdetail(), errmsg, ERROR, fb(), Form_pg_database, get_database_name(), get_tablespace_name(), GETSTRUCT(), GetUserId(), GetUserNameFromId(), heap_getattr(), HeapTupleIsValid, i, initStringInfo(), InvalidOid, lappend(), NameStr, NIL, object_aclcheck(), OBJECT_DATABASE, ObjectIdGetDatum(), OidIsValid, pfree(), pg_encoding_to_char, pg_strcasecmp(), pstrdup(), quote_identifier(), quote_literal_cstr(), RelationGetDescr, ReleaseSysCache(), resetStringInfo(), ScanKeyInit(), SearchSysCache1(), SysCacheGetAttr(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), table_open(), and TextDatumGetCString.

Referenced by pg_get_database_ddl().

◆ pg_get_role_ddl()

Datum pg_get_role_ddl ( PG_FUNCTION_ARGS  )

Definition at line 426 of file ddlutils.c.

427{
430
431 if (SRF_IS_FIRSTCALL())
432 {
433 MemoryContext oldcontext;
434 Oid roleid;
435 bool pretty;
436 bool memberships;
437
439 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
440
441 roleid = PG_GETARG_OID(0);
444
446 funcctx->user_fctx = statements;
447 funcctx->max_calls = list_length(statements);
448
449 MemoryContextSwitchTo(oldcontext);
450 }
451
453 statements = (List *) funcctx->user_fctx;
454
455 if (funcctx->call_cntr < funcctx->max_calls)
456 {
457 char *stmt;
458
459 stmt = list_nth(statements, funcctx->call_cntr);
460
462 }
463 else
464 {
467 }
468}
static List * pg_get_role_ddl_internal(Oid roleid, bool pretty, bool memberships)
Definition ddlutils.c:149

References CStringGetTextDatum, fb(), list_free_deep(), list_length(), list_nth(), MemoryContextSwitchTo(), pg_get_role_ddl_internal(), PG_GETARG_BOOL, PG_GETARG_OID, SRF_FIRSTCALL_INIT, SRF_IS_FIRSTCALL, SRF_PERCALL_SETUP, SRF_RETURN_DONE, SRF_RETURN_NEXT, and stmt.

◆ pg_get_role_ddl_internal()

static List * pg_get_role_ddl_internal ( Oid  roleid,
bool  pretty,
bool  memberships 
)
static

Definition at line 149 of file ddlutils.c.

150{
151 HeapTuple tuple;
154 char *rolname;
156 bool isnull;
157 Relation rel;
159 SysScanDesc scan;
161
162 tuple = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
163 if (!HeapTupleIsValid(tuple))
166 errmsg("role with OID %u does not exist", roleid)));
167
169 rolname = pstrdup(NameStr(roleform->rolname));
170
171 /* User must have SELECT privilege on pg_authid. */
173 {
174 ReleaseSysCache(tuple);
177 errmsg("permission denied for role %s", rolname)));
178 }
179
180 /*
181 * We don't support generating DDL for system roles. The primary reason
182 * for this is that users shouldn't be recreating them.
183 */
187 errmsg("role name \"%s\" is reserved", rolname),
188 errdetail("Role names starting with \"pg_\" are reserved for system roles.")));
189
191 appendStringInfo(&buf, "CREATE ROLE %s", quote_identifier(rolname));
192
193 /*
194 * Append role attributes. The order here follows the same sequence as
195 * you'd typically write them in a CREATE ROLE command, though any order
196 * is actually acceptable to the parser.
197 */
198 append_ddl_option(&buf, pretty, 4, "%s",
199 roleform->rolsuper ? "SUPERUSER" : "NOSUPERUSER");
200
201 append_ddl_option(&buf, pretty, 4, "%s",
202 roleform->rolinherit ? "INHERIT" : "NOINHERIT");
203
204 append_ddl_option(&buf, pretty, 4, "%s",
205 roleform->rolcreaterole ? "CREATEROLE" : "NOCREATEROLE");
206
207 append_ddl_option(&buf, pretty, 4, "%s",
208 roleform->rolcreatedb ? "CREATEDB" : "NOCREATEDB");
209
210 append_ddl_option(&buf, pretty, 4, "%s",
211 roleform->rolcanlogin ? "LOGIN" : "NOLOGIN");
212
213 append_ddl_option(&buf, pretty, 4, "%s",
214 roleform->rolreplication ? "REPLICATION" : "NOREPLICATION");
215
216 append_ddl_option(&buf, pretty, 4, "%s",
217 roleform->rolbypassrls ? "BYPASSRLS" : "NOBYPASSRLS");
218
219 /*
220 * CONNECTION LIMIT is only interesting if it's not -1 (the default,
221 * meaning no limit).
222 */
223 if (roleform->rolconnlimit >= 0)
224 append_ddl_option(&buf, pretty, 4, "CONNECTION LIMIT %d",
225 roleform->rolconnlimit);
226
229 &isnull);
230 if (!isnull)
231 {
232 TimestampTz ts;
233 int tz;
234 struct pg_tm tm;
235 fsec_t fsec;
236 const char *tzn;
237 char ts_str[MAXDATELEN + 1];
238
240 if (TIMESTAMP_NOT_FINITE(ts))
242 else if (timestamp2tm(ts, &tz, &tm, &fsec, &tzn, NULL) == 0)
243 EncodeDateTime(&tm, fsec, true, tz, tzn, USE_ISO_DATES, ts_str);
244 else
247 errmsg("timestamp out of range")));
248
249 append_ddl_option(&buf, pretty, 4, "VALID UNTIL %s",
251 }
252
253 ReleaseSysCache(tuple);
254
255 /*
256 * We intentionally omit PASSWORD. There's no way to retrieve the
257 * original password text from the stored hash, and even if we could,
258 * exposing passwords through a SQL function would be a security issue.
259 * Users must set passwords separately after recreating roles.
260 */
261
263
265
266 /*
267 * Now scan pg_db_role_setting for ALTER ROLE SET configurations.
268 *
269 * These can be role-wide (setdatabase = 0) or specific to a particular
270 * database (setdatabase = a valid DB OID). It generates one ALTER
271 * statement per setting.
272 */
277 ObjectIdGetDatum(roleid));
279 NULL, 1, &scankey);
280
281 while (HeapTupleIsValid(tuple = systable_getnext(scan)))
282 {
284 Oid datid = setting->setdatabase;
285 Datum datum;
287 Datum *settings;
288 bool *nulls;
289 int nsettings;
290 char *datname = NULL;
291
292 /*
293 * If setdatabase is valid, this is a role-in-database setting;
294 * otherwise it's a role-wide setting. Look up the database name once
295 * for all settings in this row.
296 */
297 if (OidIsValid(datid))
298 {
300 /* Database has been dropped; skip all settings in this row. */
301 if (datname == NULL)
302 continue;
303 }
304
305 /*
306 * The setconfig column is a text array in "name=value" format. It
307 * should never be null for a valid row, but be defensive.
308 */
310 RelationGetDescr(rel), &isnull);
311 if (isnull)
312 continue;
313
315
317
318 for (int i = 0; i < nsettings; i++)
319 {
320 char *s,
321 *p;
322
323 if (nulls[i])
324 continue;
325
326 s = TextDatumGetCString(settings[i]);
327 p = strchr(s, '=');
328 if (p == NULL)
329 {
330 pfree(s);
331 continue;
332 }
333 *p++ = '\0';
334
335 /* Build a fresh ALTER ROLE statement for this setting */
337 appendStringInfo(&buf, "ALTER ROLE %s", quote_identifier(rolname));
338
339 if (datname != NULL)
340 appendStringInfo(&buf, " IN DATABASE %s",
342
343 appendStringInfo(&buf, " SET %s TO ",
345
346 append_guc_value(&buf, s, p);
347
349
351
352 pfree(s);
353 }
354
355 pfree(settings);
356 pfree(nulls);
358
359 if (datname != NULL)
360 pfree(datname);
361 }
362
363 systable_endscan(scan);
365
366 /*
367 * Scan pg_auth_members for role memberships. We look for rows where
368 * member = roleid, meaning this role has been granted membership in other
369 * roles.
370 */
371 if (memberships)
372 {
377 ObjectIdGetDatum(roleid));
379 NULL, 1, &scankey);
380
381 while (HeapTupleIsValid(tuple = systable_getnext(scan)))
382 {
384 char *granted_role;
385 char *grantor;
386
387 granted_role = GetUserNameFromId(memform->roleid, false);
388 grantor = GetUserNameFromId(memform->grantor, false);
389
391 appendStringInfo(&buf, "GRANT %s TO %s",
394 appendStringInfo(&buf, " WITH ADMIN %s, INHERIT %s, SET %s",
395 memform->admin_option ? "TRUE" : "FALSE",
396 memform->inherit_option ? "TRUE" : "FALSE",
397 memform->set_option ? "TRUE" : "FALSE");
398 appendStringInfo(&buf, " GRANTED BY %s;",
399 quote_identifier(grantor));
400
402
404 pfree(grantor);
405 }
406
407 systable_endscan(scan);
409 }
410
411 pfree(buf.data);
412 pfree(rolname);
413
414 return statements;
415}
AclResult pg_class_aclcheck(Oid table_oid, Oid roleid, AclMode mode)
Definition aclchk.c:4105
void set_option(char *arg)
Definition args.c:261
void EncodeDateTime(struct pg_tm *tm, fsec_t fsec, bool print_tz, int tz, const char *tzn, int style, char *str)
Definition datetime.c:4496
void EncodeSpecialTimestamp(Timestamp dt, char *str)
Definition timestamp.c:1591
int timestamp2tm(Timestamp dt, int *tzp, struct pg_tm *tm, fsec_t *fsec, const char **tzn, pg_tz *attimezone)
Definition timestamp.c:1918
bool IsReservedName(const char *name)
Definition catalog.c:305
int64 TimestampTz
Definition timestamp.h:39
int32 fsec_t
Definition timestamp.h:41
#define TIMESTAMP_NOT_FINITE(j)
Definition timestamp.h:169
#define MAXDATELEN
Definition datetime.h:200
static struct pg_tm tm
Definition localtime.c:148
#define USE_ISO_DATES
Definition miscadmin.h:240
#define ACL_SELECT
Definition parsenodes.h:77
END_CATALOG_STRUCT typedef FormData_pg_auth_members * Form_pg_auth_members
NameData rolname
Definition pg_authid.h:36
END_CATALOG_STRUCT typedef FormData_pg_authid * Form_pg_authid
Definition pg_authid.h:60
NameData datname
Definition pg_database.h:37
END_CATALOG_STRUCT typedef FormData_pg_db_role_setting * Form_pg_db_role_setting
Definition pgtime.h:35
static TimestampTz DatumGetTimestampTz(Datum X)
Definition timestamp.h:34

References AccessShareLock, ACL_SELECT, ACLCHECK_OK, append_ddl_option(), append_guc_value(), appendStringInfo(), appendStringInfoChar(), BTEqualStrategyNumber, buf, datname, DatumGetArrayTypePCopy, DatumGetTimestampTz(), deconstruct_array_builtin(), EncodeDateTime(), EncodeSpecialTimestamp(), ereport, errcode(), errdetail(), errmsg, ERROR, fb(), Form_pg_auth_members, Form_pg_authid, Form_pg_db_role_setting, get_database_name(), GETSTRUCT(), GetUserId(), GetUserNameFromId(), heap_getattr(), HeapTupleIsValid, i, initStringInfo(), IsReservedName(), lappend(), MAXDATELEN, NameStr, NIL, ObjectIdGetDatum(), OidIsValid, pfree(), pg_class_aclcheck(), pstrdup(), quote_identifier(), quote_literal_cstr(), RelationGetDescr, ReleaseSysCache(), resetStringInfo(), rolname, ScanKeyInit(), SearchSysCache1(), SysCacheGetAttr(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), table_open(), TextDatumGetCString, timestamp2tm(), TIMESTAMP_NOT_FINITE, tm, and USE_ISO_DATES.

Referenced by pg_get_role_ddl().

◆ pg_get_tablespace_ddl_internal()

static List * pg_get_tablespace_ddl_internal ( Oid  tsid,
bool  pretty,
bool  no_owner 
)
static

Definition at line 479 of file ddlutils.c.

480{
481 HeapTuple tuple;
484 char *spcname;
485 char *spcowner;
486 char *path;
487 bool isNull;
488 Datum datum;
490
492 if (!HeapTupleIsValid(tuple))
495 errmsg("tablespace with OID %u does not exist",
496 tsid)));
497
499 spcname = pstrdup(NameStr(tspForm->spcname));
500
501 /* User must have SELECT privilege on pg_tablespace. */
503 {
504 ReleaseSysCache(tuple);
506 }
507
508 /*
509 * We don't support generating DDL for system tablespaces. The primary
510 * reason for this is that users shouldn't be recreating them.
511 */
515 errmsg("tablespace name \"%s\" is reserved", spcname),
516 errdetail("Tablespace names starting with \"pg_\" are reserved for system tablespaces.")));
517
519
520 /* Start building the CREATE TABLESPACE statement */
521 appendStringInfo(&buf, "CREATE TABLESPACE %s", quote_identifier(spcname));
522
523 /* Add OWNER clause */
524 if (!no_owner)
525 {
526 spcowner = GetUserNameFromId(tspForm->spcowner, false);
527 append_ddl_option(&buf, pretty, 4, "OWNER %s",
530 }
531
532 /* Find tablespace directory path */
533 path = get_tablespace_location(tsid);
534
535 /* Add directory LOCATION (path), if it exists */
536 if (path[0] != '\0')
537 {
538 /*
539 * Special case: if the tablespace was created with GUC
540 * "allow_in_place_tablespaces = true" and "LOCATION ''", path will
541 * begin with "pg_tblspc/". In that case, show "LOCATION ''" as the
542 * user originally specified.
543 */
545 append_ddl_option(&buf, pretty, 4, "LOCATION ''");
546 else
547 append_ddl_option(&buf, pretty, 4, "LOCATION %s",
548 quote_literal_cstr(path));
549 }
550 pfree(path);
551
554
555 /* Check for tablespace options */
556 datum = SysCacheGetAttr(TABLESPACEOID, tuple,
558 if (!isNull)
559 {
561 appendStringInfo(&buf, "ALTER TABLESPACE %s SET (",
563 get_reloptions(&buf, datum);
566 }
567
568 ReleaseSysCache(tuple);
569 pfree(spcname);
570 pfree(buf.data);
571
572 return statements;
573}
@ ACLCHECK_NO_PRIV
Definition acl.h:185
@ OBJECT_TABLESPACE
char * get_tablespace_location(Oid tablespaceOid)
END_CATALOG_STRUCT typedef FormData_pg_tablespace * Form_pg_tablespace
#define PG_TBLSPC_DIR_SLASH
Definition relpath.h:42
void get_reloptions(StringInfo buf, Datum reloptions)

References ACL_SELECT, aclcheck_error(), ACLCHECK_NO_PRIV, ACLCHECK_OK, append_ddl_option(), appendStringInfo(), appendStringInfoChar(), appendStringInfoString(), buf, ereport, errcode(), errdetail(), errmsg, ERROR, fb(), Form_pg_tablespace, get_reloptions(), get_tablespace_location(), GETSTRUCT(), GetUserId(), GetUserNameFromId(), HeapTupleIsValid, initStringInfo(), IsReservedName(), lappend(), NameStr, NIL, OBJECT_TABLESPACE, ObjectIdGetDatum(), pfree(), pg_class_aclcheck(), PG_TBLSPC_DIR_SLASH, pstrdup(), quote_identifier(), quote_literal_cstr(), ReleaseSysCache(), resetStringInfo(), SearchSysCache1(), and SysCacheGetAttr().

Referenced by pg_get_tablespace_ddl_srf().

◆ pg_get_tablespace_ddl_name()

Datum pg_get_tablespace_ddl_name ( PG_FUNCTION_ARGS  )

Definition at line 638 of file ddlutils.c.

639{
641 Oid tsid = get_tablespace_oid(NameStr(*tspname), false);
642
643 return pg_get_tablespace_ddl_srf(fcinfo, tsid);
644}
Oid get_tablespace_oid(const char *tablespacename, bool missing_ok)
static Datum pg_get_tablespace_ddl_srf(FunctionCallInfo fcinfo, Oid tsid)
Definition ddlutils.c:579
#define PG_GETARG_NAME(n)
Definition fmgr.h:279
Definition c.h:889

References fb(), get_tablespace_oid(), NameStr, pg_get_tablespace_ddl_srf(), and PG_GETARG_NAME.

◆ pg_get_tablespace_ddl_oid()

Datum pg_get_tablespace_ddl_oid ( PG_FUNCTION_ARGS  )

Definition at line 626 of file ddlutils.c.

627{
628 Oid tsid = PG_GETARG_OID(0);
629
630 return pg_get_tablespace_ddl_srf(fcinfo, tsid);
631}

References pg_get_tablespace_ddl_srf(), and PG_GETARG_OID.

◆ pg_get_tablespace_ddl_srf()

static Datum pg_get_tablespace_ddl_srf ( FunctionCallInfo  fcinfo,
Oid  tsid 
)
static

Definition at line 579 of file ddlutils.c.

580{
583
584 if (SRF_IS_FIRSTCALL())
585 {
586 MemoryContext oldcontext;
587 bool pretty;
588 bool no_owner;
589
591 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
592
595
597 funcctx->user_fctx = statements;
598 funcctx->max_calls = list_length(statements);
599
600 MemoryContextSwitchTo(oldcontext);
601 }
602
604 statements = (List *) funcctx->user_fctx;
605
606 if (funcctx->call_cntr < funcctx->max_calls)
607 {
608 char *stmt;
609
610 stmt = (char *) list_nth(statements, funcctx->call_cntr);
611
613 }
614 else
615 {
618 }
619}
static List * pg_get_tablespace_ddl_internal(Oid tsid, bool pretty, bool no_owner)
Definition ddlutils.c:479

References CStringGetTextDatum, fb(), list_free_deep(), list_length(), list_nth(), MemoryContextSwitchTo(), pg_get_tablespace_ddl_internal(), PG_GETARG_BOOL, SRF_FIRSTCALL_INIT, SRF_IS_FIRSTCALL, SRF_PERCALL_SETUP, SRF_RETURN_DONE, SRF_RETURN_NEXT, and stmt.

Referenced by pg_get_tablespace_ddl_name(), and pg_get_tablespace_ddl_oid().