PostgreSQL Source Code  git master
dumputils.c File Reference
#include "postgres_fe.h"
#include "dumputils.h"
#include "fe_utils/string_utils.h"
Include dependency graph for dumputils.c:

Go to the source code of this file.

Macros

#define CONVERT_PRIV(code, keywd)
 

Functions

static bool parseAclItem (const char *item, const char *type, const char *name, const char *subname, int remoteVersion, PQExpBuffer grantee, PQExpBuffer grantor, PQExpBuffer privs, PQExpBuffer privswgo)
 
static char * copyAclUserName (PQExpBuffer output, char *input)
 
static void AddAcl (PQExpBuffer aclbuf, const char *keyword, const char *subname)
 
bool buildACLCommands (const char *name, const char *subname, const char *nspname, const char *type, const char *acls, const char *racls, const char *owner, const char *prefix, int remoteVersion, PQExpBuffer sql)
 
bool buildDefaultACLCommands (const char *type, const char *nspname, const char *acls, const char *racls, const char *initacls, const char *initracls, const char *owner, int remoteVersion, PQExpBuffer sql)
 
void buildShSecLabelQuery (PGconn *conn, const char *catalog_name, Oid objectId, PQExpBuffer sql)
 
void emitShSecLabels (PGconn *conn, PGresult *res, PQExpBuffer buffer, const char *objtype, const char *objname)
 
void buildACLQueries (PQExpBuffer acl_subquery, PQExpBuffer racl_subquery, PQExpBuffer init_acl_subquery, PQExpBuffer init_racl_subquery, const char *acl_column, const char *acl_owner, const char *obj_kind, bool binary_upgrade)
 
bool variable_is_guc_list_quote (const char *name)
 
void makeAlterConfigCommand (PGconn *conn, const char *configitem, const char *type, const char *name, const char *type2, const char *name2, PQExpBuffer buf)
 

Macro Definition Documentation

◆ CONVERT_PRIV

#define CONVERT_PRIV (   code,
  keywd 
)
Value:
do { \
if ((pos = strchr(eqpos + 1, code))) \
{ \
if (*(pos + 1) == '*') \
{ \
AddAcl(privswgo, keywd, subname); \
all_without_go = false; \
} \
else \
{ \
AddAcl(privs, keywd, subname); \
all_with_go = false; \
} \
} \
else \
all_with_go = all_without_go = false; \
} while (0)
NameData subname

Referenced by parseAclItem().

Function Documentation

◆ AddAcl()

static void AddAcl ( PQExpBuffer  aclbuf,
const char *  keyword,
const char *  subname 
)
static

Definition at line 666 of file dumputils.c.

References appendPQExpBuffer(), appendPQExpBufferChar(), appendPQExpBufferStr(), and PQExpBufferData::len.

667 {
668  if (aclbuf->len > 0)
669  appendPQExpBufferChar(aclbuf, ',');
670  appendPQExpBufferStr(aclbuf, keyword);
671  if (subname)
672  appendPQExpBuffer(aclbuf, "(%s)", subname);
673 }
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:385
NameData subname
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:262
void appendPQExpBufferChar(PQExpBuffer str, char ch)
Definition: pqexpbuffer.c:396

◆ buildACLCommands()

bool buildACLCommands ( const char *  name,
const char *  subname,
const char *  nspname,
const char *  type,
const char *  acls,
const char *  racls,
const char *  owner,
const char *  prefix,
int  remoteVersion,
PQExpBuffer  sql 
)

Definition at line 56 of file dumputils.c.

References appendPQExpBuffer(), appendPQExpBufferStr(), Assert, createPQExpBuffer(), PQExpBufferData::data, destroyPQExpBuffer(), fmtId(), free, grantor, i, PQExpBufferData::len, parseAclItem(), parsePGArray(), and printfPQExpBuffer().

Referenced by buildDefaultACLCommands(), dumpACL(), and dumpTablespaces().

60 {
61  bool ok = true;
62  char **aclitems = NULL;
63  char **raclitems = NULL;
64  int naclitems = 0;
65  int nraclitems = 0;
66  int i;
67  PQExpBuffer grantee,
68  grantor,
69  privs,
70  privswgo;
71  PQExpBuffer firstsql,
72  secondsql;
73  bool found_owner_privs = false;
74 
75  if (strlen(acls) == 0 && strlen(racls) == 0)
76  return true; /* object has default permissions */
77 
78  /* treat empty-string owner same as NULL */
79  if (owner && *owner == '\0')
80  owner = NULL;
81 
82  if (strlen(acls) != 0)
83  {
84  if (!parsePGArray(acls, &aclitems, &naclitems))
85  {
86  if (aclitems)
87  free(aclitems);
88  return false;
89  }
90  }
91 
92  if (strlen(racls) != 0)
93  {
94  if (!parsePGArray(racls, &raclitems, &nraclitems))
95  {
96  if (raclitems)
97  free(raclitems);
98  return false;
99  }
100  }
101 
102  grantee = createPQExpBuffer();
103  grantor = createPQExpBuffer();
104  privs = createPQExpBuffer();
105  privswgo = createPQExpBuffer();
106 
107  /*
108  * At the end, these two will be pasted together to form the result.
109  *
110  * For older systems we use these to ensure that the owner privileges go
111  * before the other ones, as a GRANT could create the default entry for
112  * the object, which generally includes all rights for the owner. In more
113  * recent versions we normally handle this because the owner rights come
114  * first in the ACLs, but older versions might have them after the PUBLIC
115  * privileges.
116  *
117  * For 9.6 and later systems, much of this changes. With 9.6, we check
118  * the default privileges for the objects at dump time and create two sets
119  * of ACLs- "racls" which are the ACLs to REVOKE from the object (as the
120  * object may have initial privileges on it, along with any default ACLs
121  * which are not part of the current set of privileges), and regular
122  * "acls", which are the ACLs to GRANT to the object. We handle the
123  * REVOKEs first, followed by the GRANTs.
124  */
125  firstsql = createPQExpBuffer();
126  secondsql = createPQExpBuffer();
127 
128  /*
129  * For pre-9.6 systems, we always start with REVOKE ALL FROM PUBLIC, as we
130  * don't wish to make any assumptions about what the default ACLs are, and
131  * we do not collect them during the dump phase (and racls will always be
132  * the empty set, see above).
133  *
134  * For 9.6 and later, if any revoke ACLs have been provided, then include
135  * them in 'firstsql'.
136  *
137  * Revoke ACLs happen when an object starts out life with a set of
138  * privileges (eg: GRANT SELECT ON pg_class TO PUBLIC;) and the user has
139  * decided to revoke those rights. Since those objects come into being
140  * with those default privileges, we have to revoke them to match what the
141  * current state of affairs is. Note that we only started explicitly
142  * tracking such initial rights in 9.6, and prior to that all initial
143  * rights are actually handled by the simple 'REVOKE ALL .. FROM PUBLIC'
144  * case, for initdb-created objects. Prior to 9.6, we didn't handle
145  * extensions correctly, but we do now by tracking their initial
146  * privileges, in the same way we track initdb initial privileges, see
147  * pg_init_privs.
148  */
149  if (remoteVersion < 90600)
150  {
151  Assert(nraclitems == 0);
152 
153  appendPQExpBuffer(firstsql, "%sREVOKE ALL", prefix);
154  if (subname)
155  appendPQExpBuffer(firstsql, "(%s)", subname);
156  appendPQExpBuffer(firstsql, " ON %s ", type);
157  if (nspname && *nspname)
158  appendPQExpBuffer(firstsql, "%s.", fmtId(nspname));
159  appendPQExpBuffer(firstsql, "%s FROM PUBLIC;\n", name);
160  }
161  else
162  {
163  /* Scan individual REVOKE ACL items */
164  for (i = 0; i < nraclitems; i++)
165  {
166  if (!parseAclItem(raclitems[i], type, name, subname, remoteVersion,
167  grantee, grantor, privs, privswgo))
168  {
169  ok = false;
170  break;
171  }
172 
173  if (privs->len > 0 || privswgo->len > 0)
174  {
175  if (privs->len > 0)
176  {
177  appendPQExpBuffer(firstsql, "%sREVOKE %s ON %s ",
178  prefix, privs->data, type);
179  if (nspname && *nspname)
180  appendPQExpBuffer(firstsql, "%s.", fmtId(nspname));
181  appendPQExpBuffer(firstsql, "%s FROM ", name);
182  if (grantee->len == 0)
183  appendPQExpBufferStr(firstsql, "PUBLIC;\n");
184  else if (strncmp(grantee->data, "group ",
185  strlen("group ")) == 0)
186  appendPQExpBuffer(firstsql, "GROUP %s;\n",
187  fmtId(grantee->data + strlen("group ")));
188  else
189  appendPQExpBuffer(firstsql, "%s;\n",
190  fmtId(grantee->data));
191  }
192  if (privswgo->len > 0)
193  {
194  appendPQExpBuffer(firstsql,
195  "%sREVOKE GRANT OPTION FOR %s ON %s ",
196  prefix, privswgo->data, type);
197  if (nspname && *nspname)
198  appendPQExpBuffer(firstsql, "%s.", fmtId(nspname));
199  appendPQExpBuffer(firstsql, "%s FROM ", name);
200  if (grantee->len == 0)
201  appendPQExpBufferStr(firstsql, "PUBLIC");
202  else if (strncmp(grantee->data, "group ",
203  strlen("group ")) == 0)
204  appendPQExpBuffer(firstsql, "GROUP %s",
205  fmtId(grantee->data + strlen("group ")));
206  else
207  appendPQExpBufferStr(firstsql, fmtId(grantee->data));
208  }
209  }
210  }
211  }
212 
213  /*
214  * We still need some hacking though to cover the case where new default
215  * public privileges are added in new versions: the REVOKE ALL will revoke
216  * them, leading to behavior different from what the old version had,
217  * which is generally not what's wanted. So add back default privs if the
218  * source database is too old to have had that particular priv.
219  */
220  if (remoteVersion < 80200 && strcmp(type, "DATABASE") == 0)
221  {
222  /* database CONNECT priv didn't exist before 8.2 */
223  appendPQExpBuffer(firstsql, "%sGRANT CONNECT ON %s %s TO PUBLIC;\n",
224  prefix, type, name);
225  }
226 
227  /* Scan individual ACL items */
228  for (i = 0; i < naclitems; i++)
229  {
230  if (!parseAclItem(aclitems[i], type, name, subname, remoteVersion,
231  grantee, grantor, privs, privswgo))
232  {
233  ok = false;
234  break;
235  }
236 
237  if (grantor->len == 0 && owner)
238  printfPQExpBuffer(grantor, "%s", owner);
239 
240  if (privs->len > 0 || privswgo->len > 0)
241  {
242  /*
243  * Prior to 9.6, we had to handle owner privileges in a special
244  * manner by first REVOKE'ing the rights and then GRANT'ing them
245  * after. With 9.6 and above, what we need to REVOKE and what we
246  * need to GRANT is figured out when we dump and stashed into
247  * "racls" and "acls", respectively. See above.
248  */
249  if (remoteVersion < 90600 && owner
250  && strcmp(grantee->data, owner) == 0
251  && strcmp(grantor->data, owner) == 0)
252  {
253  found_owner_privs = true;
254 
255  /*
256  * For the owner, the default privilege level is ALL WITH
257  * GRANT OPTION.
258  */
259  if (strcmp(privswgo->data, "ALL") != 0)
260  {
261  appendPQExpBuffer(firstsql, "%sREVOKE ALL", prefix);
262  if (subname)
263  appendPQExpBuffer(firstsql, "(%s)", subname);
264  appendPQExpBuffer(firstsql, " ON %s ", type);
265  if (nspname && *nspname)
266  appendPQExpBuffer(firstsql, "%s.", fmtId(nspname));
267  appendPQExpBuffer(firstsql, "%s FROM %s;\n",
268  name, fmtId(grantee->data));
269  if (privs->len > 0)
270  {
271  appendPQExpBuffer(firstsql,
272  "%sGRANT %s ON %s ",
273  prefix, privs->data, type);
274  if (nspname && *nspname)
275  appendPQExpBuffer(firstsql, "%s.", fmtId(nspname));
276  appendPQExpBuffer(firstsql,
277  "%s TO %s;\n",
278  name, fmtId(grantee->data));
279  }
280  if (privswgo->len > 0)
281  {
282  appendPQExpBuffer(firstsql,
283  "%sGRANT %s ON %s ",
284  prefix, privswgo->data, type);
285  if (nspname && *nspname)
286  appendPQExpBuffer(firstsql, "%s.", fmtId(nspname));
287  appendPQExpBuffer(firstsql,
288  "%s TO %s WITH GRANT OPTION;\n",
289  name, fmtId(grantee->data));
290  }
291  }
292  }
293  else
294  {
295  /*
296  * For systems prior to 9.6, we can assume we are starting
297  * from no privs at this point.
298  *
299  * For 9.6 and above, at this point we have issued REVOKE
300  * statements for all initial and default privileges which are
301  * no longer present on the object (as they were passed in as
302  * 'racls') and we can simply GRANT the rights which are in
303  * 'acls'.
304  */
305  if (grantor->len > 0
306  && (!owner || strcmp(owner, grantor->data) != 0))
307  appendPQExpBuffer(secondsql, "SET SESSION AUTHORIZATION %s;\n",
308  fmtId(grantor->data));
309 
310  if (privs->len > 0)
311  {
312  appendPQExpBuffer(secondsql, "%sGRANT %s ON %s ",
313  prefix, privs->data, type);
314  if (nspname && *nspname)
315  appendPQExpBuffer(secondsql, "%s.", fmtId(nspname));
316  appendPQExpBuffer(secondsql, "%s TO ", name);
317  if (grantee->len == 0)
318  appendPQExpBufferStr(secondsql, "PUBLIC;\n");
319  else if (strncmp(grantee->data, "group ",
320  strlen("group ")) == 0)
321  appendPQExpBuffer(secondsql, "GROUP %s;\n",
322  fmtId(grantee->data + strlen("group ")));
323  else
324  appendPQExpBuffer(secondsql, "%s;\n", fmtId(grantee->data));
325  }
326  if (privswgo->len > 0)
327  {
328  appendPQExpBuffer(secondsql, "%sGRANT %s ON %s ",
329  prefix, privswgo->data, type);
330  if (nspname && *nspname)
331  appendPQExpBuffer(secondsql, "%s.", fmtId(nspname));
332  appendPQExpBuffer(secondsql, "%s TO ", name);
333  if (grantee->len == 0)
334  appendPQExpBufferStr(secondsql, "PUBLIC");
335  else if (strncmp(grantee->data, "group ",
336  strlen("group ")) == 0)
337  appendPQExpBuffer(secondsql, "GROUP %s",
338  fmtId(grantee->data + strlen("group ")));
339  else
340  appendPQExpBufferStr(secondsql, fmtId(grantee->data));
341  appendPQExpBufferStr(secondsql, " WITH GRANT OPTION;\n");
342  }
343 
344  if (grantor->len > 0
345  && (!owner || strcmp(owner, grantor->data) != 0))
346  appendPQExpBufferStr(secondsql, "RESET SESSION AUTHORIZATION;\n");
347  }
348  }
349  }
350 
351  /*
352  * For systems prior to 9.6, if we didn't find any owner privs, the owner
353  * must have revoked 'em all.
354  *
355  * For 9.6 and above, we handle this through the 'racls'. See above.
356  */
357  if (remoteVersion < 90600 && !found_owner_privs && owner)
358  {
359  appendPQExpBuffer(firstsql, "%sREVOKE ALL", prefix);
360  if (subname)
361  appendPQExpBuffer(firstsql, "(%s)", subname);
362  appendPQExpBuffer(firstsql, " ON %s ", type);
363  if (nspname && *nspname)
364  appendPQExpBuffer(firstsql, "%s.", fmtId(nspname));
365  appendPQExpBuffer(firstsql, "%s FROM %s;\n",
366  name, fmtId(owner));
367  }
368 
369  destroyPQExpBuffer(grantee);
370  destroyPQExpBuffer(grantor);
371  destroyPQExpBuffer(privs);
372  destroyPQExpBuffer(privswgo);
373 
374  appendPQExpBuffer(sql, "%s%s", firstsql->data, secondsql->data);
375  destroyPQExpBuffer(firstsql);
376  destroyPQExpBuffer(secondsql);
377 
378  if (aclitems)
379  free(aclitems);
380 
381  if (raclitems)
382  free(raclitems);
383 
384  return ok;
385 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
bool parsePGArray(const char *atext, char ***itemarray, int *nitems)
Definition: string_utils.c:663
const char * fmtId(const char *rawid)
Definition: string_utils.c:66
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:385
NameData subname
Oid grantor
void destroyPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:113
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:262
PQExpBuffer createPQExpBuffer(void)
Definition: pqexpbuffer.c:71
#define free(a)
Definition: header.h:65
#define Assert(condition)
Definition: c.h:699
const char * name
Definition: encode.c:521
int i
static bool parseAclItem(const char *item, const char *type, const char *name, const char *subname, int remoteVersion, PQExpBuffer grantee, PQExpBuffer grantor, PQExpBuffer privs, PQExpBuffer privswgo)
Definition: dumputils.c:468

◆ buildACLQueries()

void buildACLQueries ( PQExpBuffer  acl_subquery,
PQExpBuffer  racl_subquery,
PQExpBuffer  init_acl_subquery,
PQExpBuffer  init_racl_subquery,
const char *  acl_column,
const char *  acl_owner,
const char *  obj_kind,
bool  binary_upgrade 
)

Definition at line 740 of file dumputils.c.

References printfPQExpBuffer().

Referenced by dumpTable(), getAggregates(), getBlobs(), getDefaultACLs(), getForeignDataWrappers(), getForeignServers(), getFuncs(), getNamespaces(), getProcLangs(), getTables(), and getTypes().

744 {
745  /*
746  * To get the delta from what the permissions were at creation time
747  * (either initdb or CREATE EXTENSION) vs. what they are now, we have to
748  * look at two things:
749  *
750  * What privileges have been added, which we calculate by extracting all
751  * the current privileges (using the set of default privileges for the
752  * object type if current privileges are NULL) and then removing those
753  * which existed at creation time (again, using the set of default
754  * privileges for the object type if there were no creation time
755  * privileges).
756  *
757  * What privileges have been removed, which we calculate by extracting the
758  * privileges as they were at creation time (or the default privileges, as
759  * above), and then removing the current privileges (or the default
760  * privileges, if current privileges are NULL).
761  *
762  * As a good cross-check, both directions of these checks should result in
763  * the empty set if both the current ACL and the initial privs are NULL
764  * (meaning, in practice, that the default ACLs were there at init time
765  * and is what the current privileges are).
766  *
767  * We always perform this delta on all ACLs and expect that by the time
768  * these are run the initial privileges will be in place, even in a binary
769  * upgrade situation (see below).
770  *
771  * Finally, the order in which privileges are in the ACL string (the order
772  * they been GRANT'd in, which the backend maintains) must be preserved to
773  * ensure that GRANTs WITH GRANT OPTION and subsequent GRANTs based on
774  * those are dumped in the correct order.
775  */
776  printfPQExpBuffer(acl_subquery,
777  "(SELECT pg_catalog.array_agg(acl ORDER BY row_n) FROM "
778  "(SELECT acl, row_n FROM "
779  "pg_catalog.unnest(coalesce(%s,pg_catalog.acldefault(%s,%s))) "
780  "WITH ORDINALITY AS perm(acl,row_n) "
781  "WHERE NOT EXISTS ( "
782  "SELECT 1 FROM "
783  "pg_catalog.unnest(coalesce(pip.initprivs,pg_catalog.acldefault(%s,%s))) "
784  "AS init(init_acl) WHERE acl = init_acl)) as foo)",
785  acl_column,
786  obj_kind,
787  acl_owner,
788  obj_kind,
789  acl_owner);
790 
791  printfPQExpBuffer(racl_subquery,
792  "(SELECT pg_catalog.array_agg(acl ORDER BY row_n) FROM "
793  "(SELECT acl, row_n FROM "
794  "pg_catalog.unnest(coalesce(pip.initprivs,pg_catalog.acldefault(%s,%s))) "
795  "WITH ORDINALITY AS initp(acl,row_n) "
796  "WHERE NOT EXISTS ( "
797  "SELECT 1 FROM "
798  "pg_catalog.unnest(coalesce(%s,pg_catalog.acldefault(%s,%s))) "
799  "AS permp(orig_acl) WHERE acl = orig_acl)) as foo)",
800  obj_kind,
801  acl_owner,
802  acl_column,
803  obj_kind,
804  acl_owner);
805 
806  /*
807  * In binary upgrade mode we don't run the extension script but instead
808  * dump out the objects independently and then recreate them. To preserve
809  * the initial privileges which were set on extension objects, we need to
810  * grab the set of GRANT and REVOKE commands necessary to get from the
811  * default privileges of an object to the initial privileges as recorded
812  * in pg_init_privs.
813  *
814  * These will then be run ahead of the regular ACL commands, which were
815  * calculated using the queries above, inside of a block which sets a flag
816  * to indicate that the backend should record the results of these GRANT
817  * and REVOKE statements into pg_init_privs. This is how we preserve the
818  * contents of that catalog across binary upgrades.
819  */
820  if (binary_upgrade)
821  {
822  printfPQExpBuffer(init_acl_subquery,
823  "CASE WHEN privtype = 'e' THEN "
824  "(SELECT pg_catalog.array_agg(acl ORDER BY row_n) FROM "
825  "(SELECT acl, row_n FROM pg_catalog.unnest(pip.initprivs) "
826  "WITH ORDINALITY AS initp(acl,row_n) "
827  "WHERE NOT EXISTS ( "
828  "SELECT 1 FROM "
829  "pg_catalog.unnest(pg_catalog.acldefault(%s,%s)) "
830  "AS privm(orig_acl) WHERE acl = orig_acl)) as foo) END",
831  obj_kind,
832  acl_owner);
833 
834  printfPQExpBuffer(init_racl_subquery,
835  "CASE WHEN privtype = 'e' THEN "
836  "(SELECT pg_catalog.array_agg(acl) FROM "
837  "(SELECT acl, row_n FROM "
838  "pg_catalog.unnest(pg_catalog.acldefault(%s,%s)) "
839  "WITH ORDINALITY AS privp(acl,row_n) "
840  "WHERE NOT EXISTS ( "
841  "SELECT 1 FROM pg_catalog.unnest(pip.initprivs) "
842  "AS initp(init_acl) WHERE acl = init_acl)) as foo) END",
843  obj_kind,
844  acl_owner);
845  }
846  else
847  {
848  printfPQExpBuffer(init_acl_subquery, "NULL");
849  printfPQExpBuffer(init_racl_subquery, "NULL");
850  }
851 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
static int binary_upgrade
Definition: pg_dumpall.c:65

◆ buildDefaultACLCommands()

bool buildDefaultACLCommands ( const char *  type,
const char *  nspname,
const char *  acls,
const char *  racls,
const char *  initacls,
const char *  initracls,
const char *  owner,
int  remoteVersion,
PQExpBuffer  sql 
)

Definition at line 400 of file dumputils.c.

References appendPQExpBuffer(), buildACLCommands(), createPQExpBuffer(), PQExpBufferData::data, destroyPQExpBuffer(), and fmtId().

Referenced by dumpDefaultACL().

406 {
407  PQExpBuffer prefix;
408 
409  prefix = createPQExpBuffer();
410 
411  /*
412  * We incorporate the target role directly into the command, rather than
413  * playing around with SET ROLE or anything like that. This is so that a
414  * permissions error leads to nothing happening, rather than changing
415  * default privileges for the wrong user.
416  */
417  appendPQExpBuffer(prefix, "ALTER DEFAULT PRIVILEGES FOR ROLE %s ",
418  fmtId(owner));
419  if (nspname)
420  appendPQExpBuffer(prefix, "IN SCHEMA %s ", fmtId(nspname));
421 
422  if (strlen(initacls) != 0 || strlen(initracls) != 0)
423  {
424  appendPQExpBuffer(sql, "SELECT pg_catalog.binary_upgrade_set_record_init_privs(true);\n");
425  if (!buildACLCommands("", NULL, NULL, type,
426  initacls, initracls, owner,
427  prefix->data, remoteVersion, sql))
428  {
429  destroyPQExpBuffer(prefix);
430  return false;
431  }
432  appendPQExpBuffer(sql, "SELECT pg_catalog.binary_upgrade_set_record_init_privs(false);\n");
433  }
434 
435  if (!buildACLCommands("", NULL, NULL, type,
436  acls, racls, owner,
437  prefix->data, remoteVersion, sql))
438  {
439  destroyPQExpBuffer(prefix);
440  return false;
441  }
442 
443  destroyPQExpBuffer(prefix);
444 
445  return true;
446 }
const char * fmtId(const char *rawid)
Definition: string_utils.c:66
void destroyPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:113
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:262
PQExpBuffer createPQExpBuffer(void)
Definition: pqexpbuffer.c:71
bool buildACLCommands(const char *name, const char *subname, const char *nspname, const char *type, const char *acls, const char *racls, const char *owner, const char *prefix, int remoteVersion, PQExpBuffer sql)
Definition: dumputils.c:56

◆ buildShSecLabelQuery()

void buildShSecLabelQuery ( PGconn conn,
const char *  catalog_name,
Oid  objectId,
PQExpBuffer  sql 
)

Definition at line 686 of file dumputils.c.

References appendPQExpBuffer().

Referenced by buildShSecLabels(), and dumpDatabase().

688 {
689  appendPQExpBuffer(sql,
690  "SELECT provider, label FROM pg_catalog.pg_shseclabel "
691  "WHERE classoid = 'pg_catalog.%s'::pg_catalog.regclass "
692  "AND objoid = '%u'", catalog_name, objectId);
693 }
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:262

◆ copyAclUserName()

static char * copyAclUserName ( PQExpBuffer  output,
char *  input 
)
static

Definition at line 627 of file dumputils.c.

References appendPQExpBufferChar(), and resetPQExpBuffer().

Referenced by parseAclItem().

628 {
629  resetPQExpBuffer(output);
630 
631  while (*input && *input != '=')
632  {
633  /*
634  * If user name isn't quoted, then just add it to the output buffer
635  */
636  if (*input != '"')
637  appendPQExpBufferChar(output, *input++);
638  else
639  {
640  /* Otherwise, it's a quoted username */
641  input++;
642  /* Loop until we come across an unescaped quote */
643  while (!(*input == '"' && *(input + 1) != '"'))
644  {
645  if (*input == '\0')
646  return input; /* really a syntax error... */
647 
648  /*
649  * Quoting convention is to escape " as "". Keep this code in
650  * sync with putid() in backend's acl.c.
651  */
652  if (*input == '"' && *(input + 1) == '"')
653  input++;
654  appendPQExpBufferChar(output, *input++);
655  }
656  input++;
657  }
658  }
659  return input;
660 }
void appendPQExpBufferChar(PQExpBuffer str, char ch)
Definition: pqexpbuffer.c:396
void resetPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:145

◆ emitShSecLabels()

void emitShSecLabels ( PGconn conn,
PGresult res,
PQExpBuffer  buffer,
const char *  objtype,
const char *  objname 
)

Definition at line 704 of file dumputils.c.

References appendPQExpBuffer(), appendPQExpBufferStr(), appendStringLiteralConn(), fmtId(), i, label, PQgetvalue(), PQntuples(), and provider.

Referenced by buildShSecLabels(), and dumpDatabase().

706 {
707  int i;
708 
709  for (i = 0; i < PQntuples(res); i++)
710  {
711  char *provider = PQgetvalue(res, i, 0);
712  char *label = PQgetvalue(res, i, 1);
713 
714  /* must use fmtId result before calling it again */
715  appendPQExpBuffer(buffer,
716  "SECURITY LABEL FOR %s ON %s",
717  fmtId(provider), objtype);
718  appendPQExpBuffer(buffer,
719  " %s IS ",
720  fmtId(objname));
721  appendStringLiteralConn(buffer, label, conn);
722  appendPQExpBufferStr(buffer, ";\n");
723  }
724 }
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3118
const char * fmtId(const char *rawid)
Definition: string_utils.c:66
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:385
int PQntuples(const PGresult *res)
Definition: fe-exec.c:2724
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:262
static JitProviderCallbacks provider
Definition: jit.c:46
static char * label
Definition: pg_basebackup.c:84
void appendStringLiteralConn(PQExpBuffer buf, const char *str, PGconn *conn)
Definition: string_utils.c:298
int i

◆ makeAlterConfigCommand()

void makeAlterConfigCommand ( PGconn conn,
const char *  configitem,
const char *  type,
const char *  name,
const char *  type2,
const char *  name2,
PQExpBuffer  buf 
)

Definition at line 888 of file dumputils.c.

References appendPQExpBuffer(), appendPQExpBufferStr(), appendStringLiteralConn(), fmtId(), pg_free(), pg_strdup(), and variable_is_guc_list_quote().

Referenced by dumpDatabaseConfig(), and dumpUserConfig().

892 {
893  char *mine;
894  char *pos;
895 
896  /* Parse the configitem. If we can't find an "=", silently do nothing. */
897  mine = pg_strdup(configitem);
898  pos = strchr(mine, '=');
899  if (pos == NULL)
900  {
901  pg_free(mine);
902  return;
903  }
904  *pos++ = '\0';
905 
906  /* Build the command, with suitable quoting for everything. */
907  appendPQExpBuffer(buf, "ALTER %s %s ", type, fmtId(name));
908  if (type2 != NULL && name2 != NULL)
909  appendPQExpBuffer(buf, "IN %s %s ", type2, fmtId(name2));
910  appendPQExpBuffer(buf, "SET %s TO ", fmtId(mine));
911 
912  /*
913  * Variables that are marked GUC_LIST_QUOTE were already fully quoted by
914  * flatten_set_variable_args() before they were put into the setconfig
915  * array; we mustn't re-quote them or we'll make a mess. Variables that
916  * are not so marked should just be emitted as simple string literals. If
917  * the variable is not known to variable_is_guc_list_quote(), we'll do the
918  * latter; this makes it unsafe to use GUC_LIST_QUOTE for extension
919  * variables.
920  */
921  if (variable_is_guc_list_quote(mine))
922  appendPQExpBufferStr(buf, pos);
923  else
924  appendStringLiteralConn(buf, pos, conn);
925 
926  appendPQExpBufferStr(buf, ";\n");
927 
928  pg_free(mine);
929 }
const char * fmtId(const char *rawid)
Definition: string_utils.c:66
bool variable_is_guc_list_quote(const char *name)
Definition: dumputils.c:864
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:385
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:262
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
void pg_free(void *ptr)
Definition: fe_memutils.c:105
const char * name
Definition: encode.c:521
void appendStringLiteralConn(PQExpBuffer buf, const char *str, PGconn *conn)
Definition: string_utils.c:298

◆ parseAclItem()

static bool parseAclItem ( const char *  item,
const char *  type,
const char *  name,
const char *  subname,
int  remoteVersion,
PQExpBuffer  grantee,
PQExpBuffer  grantor,
PQExpBuffer  privs,
PQExpBuffer  privswgo 
)
static

Definition at line 468 of file dumputils.c.

References appendPQExpBuffer(), buf, CONVERT_PRIV, copyAclUserName(), free, printfPQExpBuffer(), and resetPQExpBuffer().

Referenced by buildACLCommands().

472 {
473  char *buf;
474  bool all_with_go = true;
475  bool all_without_go = true;
476  char *eqpos;
477  char *slpos;
478  char *pos;
479 
480  buf = strdup(item);
481  if (!buf)
482  return false;
483 
484  /* user or group name is string up to = */
485  eqpos = copyAclUserName(grantee, buf);
486  if (*eqpos != '=')
487  {
488  free(buf);
489  return false;
490  }
491 
492  /* grantor should appear after / */
493  slpos = strchr(eqpos + 1, '/');
494  if (slpos)
495  {
496  *slpos++ = '\0';
497  slpos = copyAclUserName(grantor, slpos);
498  if (*slpos != '\0')
499  {
500  free(buf);
501  return false;
502  }
503  }
504  else
505  {
506  free(buf);
507  return false;
508  }
509 
510  /* privilege codes */
511 #define CONVERT_PRIV(code, keywd) \
512 do { \
513  if ((pos = strchr(eqpos + 1, code))) \
514  { \
515  if (*(pos + 1) == '*') \
516  { \
517  AddAcl(privswgo, keywd, subname); \
518  all_without_go = false; \
519  } \
520  else \
521  { \
522  AddAcl(privs, keywd, subname); \
523  all_with_go = false; \
524  } \
525  } \
526  else \
527  all_with_go = all_without_go = false; \
528 } while (0)
529 
530  resetPQExpBuffer(privs);
531  resetPQExpBuffer(privswgo);
532 
533  if (strcmp(type, "TABLE") == 0 || strcmp(type, "SEQUENCE") == 0 ||
534  strcmp(type, "TABLES") == 0 || strcmp(type, "SEQUENCES") == 0)
535  {
536  CONVERT_PRIV('r', "SELECT");
537 
538  if (strcmp(type, "SEQUENCE") == 0 ||
539  strcmp(type, "SEQUENCES") == 0)
540  /* sequence only */
541  CONVERT_PRIV('U', "USAGE");
542  else
543  {
544  /* table only */
545  CONVERT_PRIV('a', "INSERT");
546  CONVERT_PRIV('x', "REFERENCES");
547  /* rest are not applicable to columns */
548  if (subname == NULL)
549  {
550  CONVERT_PRIV('d', "DELETE");
551  CONVERT_PRIV('t', "TRIGGER");
552  if (remoteVersion >= 80400)
553  CONVERT_PRIV('D', "TRUNCATE");
554  }
555  }
556 
557  /* UPDATE */
558  CONVERT_PRIV('w', "UPDATE");
559  }
560  else if (strcmp(type, "FUNCTION") == 0 ||
561  strcmp(type, "FUNCTIONS") == 0)
562  CONVERT_PRIV('X', "EXECUTE");
563  else if (strcmp(type, "PROCEDURE") == 0 ||
564  strcmp(type, "PROCEDURES") == 0)
565  CONVERT_PRIV('X', "EXECUTE");
566  else if (strcmp(type, "LANGUAGE") == 0)
567  CONVERT_PRIV('U', "USAGE");
568  else if (strcmp(type, "SCHEMA") == 0 ||
569  strcmp(type, "SCHEMAS") == 0)
570  {
571  CONVERT_PRIV('C', "CREATE");
572  CONVERT_PRIV('U', "USAGE");
573  }
574  else if (strcmp(type, "DATABASE") == 0)
575  {
576  CONVERT_PRIV('C', "CREATE");
577  CONVERT_PRIV('c', "CONNECT");
578  CONVERT_PRIV('T', "TEMPORARY");
579  }
580  else if (strcmp(type, "TABLESPACE") == 0)
581  CONVERT_PRIV('C', "CREATE");
582  else if (strcmp(type, "TYPE") == 0 ||
583  strcmp(type, "TYPES") == 0)
584  CONVERT_PRIV('U', "USAGE");
585  else if (strcmp(type, "FOREIGN DATA WRAPPER") == 0)
586  CONVERT_PRIV('U', "USAGE");
587  else if (strcmp(type, "FOREIGN SERVER") == 0)
588  CONVERT_PRIV('U', "USAGE");
589  else if (strcmp(type, "FOREIGN TABLE") == 0)
590  CONVERT_PRIV('r', "SELECT");
591  else if (strcmp(type, "LARGE OBJECT") == 0)
592  {
593  CONVERT_PRIV('r', "SELECT");
594  CONVERT_PRIV('w', "UPDATE");
595  }
596  else
597  abort();
598 
599 #undef CONVERT_PRIV
600 
601  if (all_with_go)
602  {
603  resetPQExpBuffer(privs);
604  printfPQExpBuffer(privswgo, "ALL");
605  if (subname)
606  appendPQExpBuffer(privswgo, "(%s)", subname);
607  }
608  else if (all_without_go)
609  {
610  resetPQExpBuffer(privswgo);
611  printfPQExpBuffer(privs, "ALL");
612  if (subname)
613  appendPQExpBuffer(privs, "(%s)", subname);
614  }
615 
616  free(buf);
617 
618  return true;
619 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:234
NameData subname
static char * copyAclUserName(PQExpBuffer output, char *input)
Definition: dumputils.c:627
#define CONVERT_PRIV(code, keywd)
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:262
static char * buf
Definition: pg_test_fsync.c:67
#define free(a)
Definition: header.h:65
void resetPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:145

◆ variable_is_guc_list_quote()

bool variable_is_guc_list_quote ( const char *  name)

Definition at line 864 of file dumputils.c.

References pg_strcasecmp().

Referenced by dumpFunc(), and makeAlterConfigCommand().

865 {
866  if (pg_strcasecmp(name, "temp_tablespaces") == 0 ||
867  pg_strcasecmp(name, "session_preload_libraries") == 0 ||
868  pg_strcasecmp(name, "shared_preload_libraries") == 0 ||
869  pg_strcasecmp(name, "local_preload_libraries") == 0 ||
870  pg_strcasecmp(name, "search_path") == 0)
871  return true;
872  else
873  return false;
874 }
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
const char * name
Definition: encode.c:521