PostgreSQL Source Code  git master
dbcommands.c File Reference
#include "postgres.h"
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include "access/genam.h"
#include "access/heapam.h"
#include "access/htup_details.h"
#include "access/multixact.h"
#include "access/tableam.h"
#include "access/xact.h"
#include "access/xloginsert.h"
#include "access/xlogutils.h"
#include "catalog/catalog.h"
#include "catalog/dependency.h"
#include "catalog/indexing.h"
#include "catalog/objectaccess.h"
#include "catalog/pg_authid.h"
#include "catalog/pg_database.h"
#include "catalog/pg_db_role_setting.h"
#include "catalog/pg_subscription.h"
#include "catalog/pg_tablespace.h"
#include "commands/comment.h"
#include "commands/dbcommands.h"
#include "commands/dbcommands_xlog.h"
#include "commands/defrem.h"
#include "commands/seclabel.h"
#include "commands/tablespace.h"
#include "mb/pg_wchar.h"
#include "miscadmin.h"
#include "pgstat.h"
#include "postmaster/bgwriter.h"
#include "replication/slot.h"
#include "storage/copydir.h"
#include "storage/fd.h"
#include "storage/ipc.h"
#include "storage/lmgr.h"
#include "storage/md.h"
#include "storage/procarray.h"
#include "storage/smgr.h"
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/pg_locale.h"
#include "utils/snapmgr.h"
#include "utils/syscache.h"
Include dependency graph for dbcommands.c:

Go to the source code of this file.

Data Structures

struct  createdb_failure_params
 
struct  movedb_failure_params
 

Functions

static void createdb_failure_callback (int code, Datum arg)
 
static void movedb (const char *dbname, const char *tblspcname)
 
static void movedb_failure_callback (int code, Datum arg)
 
static bool get_db_info (const char *name, LOCKMODE lockmode, Oid *dbIdP, Oid *ownerIdP, int *encodingP, bool *dbIsTemplateP, bool *dbAllowConnP, TransactionId *dbFrozenXidP, MultiXactId *dbMinMultiP, Oid *dbTablespace, char **dbCollate, char **dbCtype)
 
static bool have_createdb_privilege (void)
 
static void remove_dbtablespaces (Oid db_id)
 
static bool check_db_file_conflict (Oid db_id)
 
static int errdetail_busy_db (int notherbackends, int npreparedxacts)
 
Oid createdb (ParseState *pstate, const CreatedbStmt *stmt)
 
void check_encoding_locale_matches (int encoding, const char *collate, const char *ctype)
 
void dropdb (const char *dbname, bool missing_ok, bool force)
 
ObjectAddress RenameDatabase (const char *oldname, const char *newname)
 
void DropDatabase (ParseState *pstate, DropdbStmt *stmt)
 
Oid AlterDatabase (ParseState *pstate, AlterDatabaseStmt *stmt, bool isTopLevel)
 
Oid AlterDatabaseSet (AlterDatabaseSetStmt *stmt)
 
ObjectAddress AlterDatabaseOwner (const char *dbname, Oid newOwnerId)
 
Oid get_database_oid (const char *dbname, bool missing_ok)
 
char * get_database_name (Oid dbid)
 
void dbase_redo (XLogReaderState *record)
 

Function Documentation

◆ AlterDatabase()

Oid AlterDatabase ( ParseState pstate,
AlterDatabaseStmt stmt,
bool  isTopLevel 
)

Definition at line 1485 of file dbcommands.c.

1486 {
1487  Relation rel;
1488  Oid dboid;
1489  HeapTuple tuple,
1490  newtuple;
1491  Form_pg_database datform;
1492  ScanKeyData scankey;
1493  SysScanDesc scan;
1494  ListCell *option;
1495  bool dbistemplate = false;
1496  bool dballowconnections = true;
1497  int dbconnlimit = -1;
1498  DefElem *distemplate = NULL;
1499  DefElem *dallowconnections = NULL;
1500  DefElem *dconnlimit = NULL;
1501  DefElem *dtablespace = NULL;
1502  Datum new_record[Natts_pg_database];
1503  bool new_record_nulls[Natts_pg_database];
1504  bool new_record_repl[Natts_pg_database];
1505 
1506  /* Extract options from the statement node tree */
1507  foreach(option, stmt->options)
1508  {
1509  DefElem *defel = (DefElem *) lfirst(option);
1510 
1511  if (strcmp(defel->defname, "is_template") == 0)
1512  {
1513  if (distemplate)
1514  errorConflictingDefElem(defel, pstate);
1515  distemplate = defel;
1516  }
1517  else if (strcmp(defel->defname, "allow_connections") == 0)
1518  {
1519  if (dallowconnections)
1520  errorConflictingDefElem(defel, pstate);
1521  dallowconnections = defel;
1522  }
1523  else if (strcmp(defel->defname, "connection_limit") == 0)
1524  {
1525  if (dconnlimit)
1526  errorConflictingDefElem(defel, pstate);
1527  dconnlimit = defel;
1528  }
1529  else if (strcmp(defel->defname, "tablespace") == 0)
1530  {
1531  if (dtablespace)
1532  errorConflictingDefElem(defel, pstate);
1533  dtablespace = defel;
1534  }
1535  else
1536  ereport(ERROR,
1537  (errcode(ERRCODE_SYNTAX_ERROR),
1538  errmsg("option \"%s\" not recognized", defel->defname),
1539  parser_errposition(pstate, defel->location)));
1540  }
1541 
1542  if (dtablespace)
1543  {
1544  /*
1545  * While the SET TABLESPACE syntax doesn't allow any other options,
1546  * somebody could write "WITH TABLESPACE ...". Forbid any other
1547  * options from being specified in that case.
1548  */
1549  if (list_length(stmt->options) != 1)
1550  ereport(ERROR,
1551  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1552  errmsg("option \"%s\" cannot be specified with other options",
1553  dtablespace->defname),
1554  parser_errposition(pstate, dtablespace->location)));
1555  /* this case isn't allowed within a transaction block */
1556  PreventInTransactionBlock(isTopLevel, "ALTER DATABASE SET TABLESPACE");
1557  movedb(stmt->dbname, defGetString(dtablespace));
1558  return InvalidOid;
1559  }
1560 
1561  if (distemplate && distemplate->arg)
1562  dbistemplate = defGetBoolean(distemplate);
1563  if (dallowconnections && dallowconnections->arg)
1564  dballowconnections = defGetBoolean(dallowconnections);
1565  if (dconnlimit && dconnlimit->arg)
1566  {
1567  dbconnlimit = defGetInt32(dconnlimit);
1568  if (dbconnlimit < -1)
1569  ereport(ERROR,
1570  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1571  errmsg("invalid connection limit: %d", dbconnlimit)));
1572  }
1573 
1574  /*
1575  * Get the old tuple. We don't need a lock on the database per se,
1576  * because we're not going to do anything that would mess up incoming
1577  * connections.
1578  */
1579  rel = table_open(DatabaseRelationId, RowExclusiveLock);
1580  ScanKeyInit(&scankey,
1581  Anum_pg_database_datname,
1582  BTEqualStrategyNumber, F_NAMEEQ,
1583  CStringGetDatum(stmt->dbname));
1584  scan = systable_beginscan(rel, DatabaseNameIndexId, true,
1585  NULL, 1, &scankey);
1586  tuple = systable_getnext(scan);
1587  if (!HeapTupleIsValid(tuple))
1588  ereport(ERROR,
1589  (errcode(ERRCODE_UNDEFINED_DATABASE),
1590  errmsg("database \"%s\" does not exist", stmt->dbname)));
1591 
1592  datform = (Form_pg_database) GETSTRUCT(tuple);
1593  dboid = datform->oid;
1594 
1595  if (!pg_database_ownercheck(dboid, GetUserId()))
1597  stmt->dbname);
1598 
1599  /*
1600  * In order to avoid getting locked out and having to go through
1601  * standalone mode, we refuse to disallow connections to the database
1602  * we're currently connected to. Lockout can still happen with concurrent
1603  * sessions but the likeliness of that is not high enough to worry about.
1604  */
1605  if (!dballowconnections && dboid == MyDatabaseId)
1606  ereport(ERROR,
1607  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1608  errmsg("cannot disallow connections for current database")));
1609 
1610  /*
1611  * Build an updated tuple, perusing the information just obtained
1612  */
1613  MemSet(new_record, 0, sizeof(new_record));
1614  MemSet(new_record_nulls, false, sizeof(new_record_nulls));
1615  MemSet(new_record_repl, false, sizeof(new_record_repl));
1616 
1617  if (distemplate)
1618  {
1619  new_record[Anum_pg_database_datistemplate - 1] = BoolGetDatum(dbistemplate);
1620  new_record_repl[Anum_pg_database_datistemplate - 1] = true;
1621  }
1622  if (dallowconnections)
1623  {
1624  new_record[Anum_pg_database_datallowconn - 1] = BoolGetDatum(dballowconnections);
1625  new_record_repl[Anum_pg_database_datallowconn - 1] = true;
1626  }
1627  if (dconnlimit)
1628  {
1629  new_record[Anum_pg_database_datconnlimit - 1] = Int32GetDatum(dbconnlimit);
1630  new_record_repl[Anum_pg_database_datconnlimit - 1] = true;
1631  }
1632 
1633  newtuple = heap_modify_tuple(tuple, RelationGetDescr(rel), new_record,
1634  new_record_nulls, new_record_repl);
1635  CatalogTupleUpdate(rel, &tuple->t_self, newtuple);
1636 
1637  InvokeObjectPostAlterHook(DatabaseRelationId, dboid, 0);
1638 
1639  systable_endscan(scan);
1640 
1641  /* Close pg_database, but keep lock till commit */
1642  table_close(rel, NoLock);
1643 
1644  return dboid;
1645 }
@ ACLCHECK_NOT_OWNER
Definition: acl.h:181
bool pg_database_ownercheck(Oid db_oid, Oid roleid)
Definition: aclchk.c:5238
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3308
#define MemSet(start, val, len)
Definition: c.h:1008
static void movedb(const char *dbname, const char *tblspcname)
Definition: dbcommands.c:1130
int32 defGetInt32(DefElem *def)
Definition: define.c:163
bool defGetBoolean(DefElem *def)
Definition: define.c:108
char * defGetString(DefElem *def)
Definition: define.c:49
void errorConflictingDefElem(DefElem *defel, ParseState *pstate)
Definition: define.c:352
int errcode(int sqlerrcode)
Definition: elog.c:693
int errmsg(const char *fmt,...)
Definition: elog.c:904
#define ERROR
Definition: elog.h:33
#define ereport(elevel,...)
Definition: elog.h:143
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:598
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:505
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:386
Oid MyDatabaseId
Definition: globals.c:88
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1113
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define GETSTRUCT(TUP)
Definition: htup_details.h:649
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
#define NoLock
Definition: lockdefs.h:34
#define RowExclusiveLock
Definition: lockdefs.h:38
Oid GetUserId(void)
Definition: miscinit.c:495
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:175
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:111
@ OBJECT_DATABASE
Definition: parsenodes.h:1798
FormData_pg_database * Form_pg_database
Definition: pg_database.h:78
#define lfirst(lc)
Definition: pg_list.h:169
static int list_length(const List *l)
Definition: pg_list.h:149
#define CStringGetDatum(X)
Definition: postgres.h:622
uintptr_t Datum
Definition: postgres.h:411
#define BoolGetDatum(X)
Definition: postgres.h:446
#define Int32GetDatum(X)
Definition: postgres.h:523
#define InvalidOid
Definition: postgres_ext.h:36
unsigned int Oid
Definition: postgres_ext.h:31
#define RelationGetDescr(relation)
Definition: rel.h:504
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define BTEqualStrategyNumber
Definition: stratnum.h:31
char * defname
Definition: parsenodes.h:758
int location
Definition: parsenodes.h:761
Node * arg
Definition: parsenodes.h:759
ItemPointerData t_self
Definition: htup.h:65
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
void PreventInTransactionBlock(bool isTopLevel, const char *stmtType)
Definition: xact.c:3450

References aclcheck_error(), ACLCHECK_NOT_OWNER, DefElem::arg, BoolGetDatum, BTEqualStrategyNumber, CatalogTupleUpdate(), CStringGetDatum, AlterDatabaseStmt::dbname, defGetBoolean(), defGetInt32(), defGetString(), DefElem::defname, ereport, errcode(), errmsg(), ERROR, errorConflictingDefElem(), GETSTRUCT, GetUserId(), heap_modify_tuple(), HeapTupleIsValid, Int32GetDatum, InvalidOid, InvokeObjectPostAlterHook, lfirst, list_length(), DefElem::location, MemSet, movedb(), MyDatabaseId, NoLock, OBJECT_DATABASE, AlterDatabaseStmt::options, parser_errposition(), pg_database_ownercheck(), PreventInTransactionBlock(), RelationGetDescr, RowExclusiveLock, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), HeapTupleData::t_self, table_close(), and table_open().

Referenced by standard_ProcessUtility().

◆ AlterDatabaseOwner()

ObjectAddress AlterDatabaseOwner ( const char *  dbname,
Oid  newOwnerId 
)

Definition at line 1678 of file dbcommands.c.

1679 {
1680  Oid db_id;
1681  HeapTuple tuple;
1682  Relation rel;
1683  ScanKeyData scankey;
1684  SysScanDesc scan;
1685  Form_pg_database datForm;
1686  ObjectAddress address;
1687 
1688  /*
1689  * Get the old tuple. We don't need a lock on the database per se,
1690  * because we're not going to do anything that would mess up incoming
1691  * connections.
1692  */
1693  rel = table_open(DatabaseRelationId, RowExclusiveLock);
1694  ScanKeyInit(&scankey,
1695  Anum_pg_database_datname,
1696  BTEqualStrategyNumber, F_NAMEEQ,
1698  scan = systable_beginscan(rel, DatabaseNameIndexId, true,
1699  NULL, 1, &scankey);
1700  tuple = systable_getnext(scan);
1701  if (!HeapTupleIsValid(tuple))
1702  ereport(ERROR,
1703  (errcode(ERRCODE_UNDEFINED_DATABASE),
1704  errmsg("database \"%s\" does not exist", dbname)));
1705 
1706  datForm = (Form_pg_database) GETSTRUCT(tuple);
1707  db_id = datForm->oid;
1708 
1709  /*
1710  * If the new owner is the same as the existing owner, consider the
1711  * command to have succeeded. This is to be consistent with other
1712  * objects.
1713  */
1714  if (datForm->datdba != newOwnerId)
1715  {
1716  Datum repl_val[Natts_pg_database];
1717  bool repl_null[Natts_pg_database];
1718  bool repl_repl[Natts_pg_database];
1719  Acl *newAcl;
1720  Datum aclDatum;
1721  bool isNull;
1722  HeapTuple newtuple;
1723 
1724  /* Otherwise, must be owner of the existing object */
1725  if (!pg_database_ownercheck(db_id, GetUserId()))
1727  dbname);
1728 
1729  /* Must be able to become new owner */
1730  check_is_member_of_role(GetUserId(), newOwnerId);
1731 
1732  /*
1733  * must have createdb rights
1734  *
1735  * NOTE: This is different from other alter-owner checks in that the
1736  * current user is checked for createdb privileges instead of the
1737  * destination owner. This is consistent with the CREATE case for
1738  * databases. Because superusers will always have this right, we need
1739  * no special case for them.
1740  */
1741  if (!have_createdb_privilege())
1742  ereport(ERROR,
1743  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1744  errmsg("permission denied to change owner of database")));
1745 
1746  memset(repl_null, false, sizeof(repl_null));
1747  memset(repl_repl, false, sizeof(repl_repl));
1748 
1749  repl_repl[Anum_pg_database_datdba - 1] = true;
1750  repl_val[Anum_pg_database_datdba - 1] = ObjectIdGetDatum(newOwnerId);
1751 
1752  /*
1753  * Determine the modified ACL for the new owner. This is only
1754  * necessary when the ACL is non-null.
1755  */
1756  aclDatum = heap_getattr(tuple,
1757  Anum_pg_database_datacl,
1758  RelationGetDescr(rel),
1759  &isNull);
1760  if (!isNull)
1761  {
1762  newAcl = aclnewowner(DatumGetAclP(aclDatum),
1763  datForm->datdba, newOwnerId);
1764  repl_repl[Anum_pg_database_datacl - 1] = true;
1765  repl_val[Anum_pg_database_datacl - 1] = PointerGetDatum(newAcl);
1766  }
1767 
1768  newtuple = heap_modify_tuple(tuple, RelationGetDescr(rel), repl_val, repl_null, repl_repl);
1769  CatalogTupleUpdate(rel, &newtuple->t_self, newtuple);
1770 
1771  heap_freetuple(newtuple);
1772 
1773  /* Update owner dependency reference */
1774  changeDependencyOnOwner(DatabaseRelationId, db_id, newOwnerId);
1775  }
1776 
1777  InvokeObjectPostAlterHook(DatabaseRelationId, db_id, 0);
1778 
1779  ObjectAddressSet(address, DatabaseRelationId, db_id);
1780 
1781  systable_endscan(scan);
1782 
1783  /* Close pg_database, but keep lock till commit */
1784  table_close(rel, NoLock);
1785 
1786  return address;
1787 }
Acl * aclnewowner(const Acl *old_acl, Oid oldOwnerId, Oid newOwnerId)
Definition: acl.c:1037
void check_is_member_of_role(Oid member, Oid role)
Definition: acl.c:4893
#define DatumGetAclP(X)
Definition: acl.h:120
static bool have_createdb_privilege(void)
Definition: dbcommands.c:1918
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:756
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
void changeDependencyOnOwner(Oid classId, Oid objectId, Oid newOwnerId)
Definition: pg_shdepend.c:312
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define PointerGetDatum(X)
Definition: postgres.h:600
char * dbname
Definition: streamutil.c:51

References aclcheck_error(), ACLCHECK_NOT_OWNER, aclnewowner(), BTEqualStrategyNumber, CatalogTupleUpdate(), changeDependencyOnOwner(), check_is_member_of_role(), CStringGetDatum, DatumGetAclP, dbname, ereport, errcode(), errmsg(), ERROR, GETSTRUCT, GetUserId(), have_createdb_privilege(), heap_freetuple(), heap_getattr, heap_modify_tuple(), HeapTupleIsValid, InvokeObjectPostAlterHook, NoLock, OBJECT_DATABASE, ObjectAddressSet, ObjectIdGetDatum, pg_database_ownercheck(), PointerGetDatum, RelationGetDescr, RowExclusiveLock, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), HeapTupleData::t_self, table_close(), and table_open().

Referenced by ExecAlterOwnerStmt().

◆ AlterDatabaseSet()

Oid AlterDatabaseSet ( AlterDatabaseSetStmt stmt)

Definition at line 1652 of file dbcommands.c.

1653 {
1654  Oid datid = get_database_oid(stmt->dbname, false);
1655 
1656  /*
1657  * Obtain a lock on the database and make sure it didn't go away in the
1658  * meantime.
1659  */
1660  shdepLockAndCheckObject(DatabaseRelationId, datid);
1661 
1662  if (!pg_database_ownercheck(datid, GetUserId()))
1664  stmt->dbname);
1665 
1666  AlterSetting(datid, InvalidOid, stmt->setstmt);
1667 
1668  UnlockSharedObject(DatabaseRelationId, datid, 0, AccessShareLock);
1669 
1670  return datid;
1671 }
Oid get_database_oid(const char *dbname, bool missing_ok)
Definition: dbcommands.c:2106
void UnlockSharedObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition: lmgr.c:1039
#define AccessShareLock
Definition: lockdefs.h:36
void AlterSetting(Oid databaseid, Oid roleid, VariableSetStmt *setstmt)
void shdepLockAndCheckObject(Oid classId, Oid objectId)
Definition: pg_shdepend.c:1165
VariableSetStmt * setstmt
Definition: parsenodes.h:3312

References AccessShareLock, aclcheck_error(), ACLCHECK_NOT_OWNER, AlterSetting(), AlterDatabaseSetStmt::dbname, get_database_oid(), GetUserId(), InvalidOid, OBJECT_DATABASE, pg_database_ownercheck(), AlterDatabaseSetStmt::setstmt, shdepLockAndCheckObject(), and UnlockSharedObject().

Referenced by standard_ProcessUtility().

◆ check_db_file_conflict()

static bool check_db_file_conflict ( Oid  db_id)
static

Definition at line 2033 of file dbcommands.c.

2034 {
2035  bool result = false;
2036  Relation rel;
2037  TableScanDesc scan;
2038  HeapTuple tuple;
2039 
2040  rel = table_open(TableSpaceRelationId, AccessShareLock);
2041  scan = table_beginscan_catalog(rel, 0, NULL);
2042  while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
2043  {
2044  Form_pg_tablespace spcform = (Form_pg_tablespace) GETSTRUCT(tuple);
2045  Oid dsttablespace = spcform->oid;
2046  char *dstpath;
2047  struct stat st;
2048 
2049  /* Don't mess with the global tablespace */
2050  if (dsttablespace == GLOBALTABLESPACE_OID)
2051  continue;
2052 
2053  dstpath = GetDatabasePath(db_id, dsttablespace);
2054 
2055  if (lstat(dstpath, &st) == 0)
2056  {
2057  /* Found a conflicting file (or directory, whatever) */
2058  pfree(dstpath);
2059  result = true;
2060  break;
2061  }
2062 
2063  pfree(dstpath);
2064  }
2065 
2066  table_endscan(scan);
2068 
2069  return result;
2070 }
static char dstpath[MAXPGPATH]
Definition: file_ops.c:32
HeapTuple heap_getnext(TableScanDesc sscan, ScanDirection direction)
Definition: heapam.c:1340
void pfree(void *pointer)
Definition: mcxt.c:1169
FormData_pg_tablespace * Form_pg_tablespace
Definition: pg_tablespace.h:48
char * GetDatabasePath(Oid dbNode, Oid spcNode)
Definition: relpath.c:110
@ ForwardScanDirection
Definition: sdir.h:26
TableScanDesc table_beginscan_catalog(Relation relation, int nkeys, struct ScanKeyData *key)
Definition: tableam.c:112
static void table_endscan(TableScanDesc scan)
Definition: tableam.h:993
#define lstat(path, sb)
Definition: win32_port.h:284

References AccessShareLock, dstpath, ForwardScanDirection, GetDatabasePath(), GETSTRUCT, heap_getnext(), lstat, pfree(), table_beginscan_catalog(), table_close(), table_endscan(), and table_open().

Referenced by createdb().

◆ check_encoding_locale_matches()

void check_encoding_locale_matches ( int  encoding,
const char *  collate,
const char *  ctype 
)

Definition at line 769 of file dbcommands.c.

770 {
771  int ctype_encoding = pg_get_encoding_from_locale(ctype, true);
772  int collate_encoding = pg_get_encoding_from_locale(collate, true);
773 
774  if (!(ctype_encoding == encoding ||
775  ctype_encoding == PG_SQL_ASCII ||
776  ctype_encoding == -1 ||
777 #ifdef WIN32
778  encoding == PG_UTF8 ||
779 #endif
780  (encoding == PG_SQL_ASCII && superuser())))
781  ereport(ERROR,
782  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
783  errmsg("encoding \"%s\" does not match locale \"%s\"",
785  ctype),
786  errdetail("The chosen LC_CTYPE setting requires encoding \"%s\".",
787  pg_encoding_to_char(ctype_encoding))));
788 
789  if (!(collate_encoding == encoding ||
790  collate_encoding == PG_SQL_ASCII ||
791  collate_encoding == -1 ||
792 #ifdef WIN32
793  encoding == PG_UTF8 ||
794 #endif
795  (encoding == PG_SQL_ASCII && superuser())))
796  ereport(ERROR,
797  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
798  errmsg("encoding \"%s\" does not match locale \"%s\"",
800  collate),
801  errdetail("The chosen LC_COLLATE setting requires encoding \"%s\".",
802  pg_encoding_to_char(collate_encoding))));
803 }
int errdetail(const char *fmt,...)
Definition: elog.c:1037
const char * pg_encoding_to_char(int encoding)
Definition: encnames.c:588
int32 encoding
Definition: pg_database.h:41
@ PG_SQL_ASCII
Definition: pg_wchar.h:224
@ PG_UTF8
Definition: pg_wchar.h:230
int pg_get_encoding_from_locale(const char *ctype, bool write_message)
Definition: chklocale.c:452
bool superuser(void)
Definition: superuser.c:46

References encoding, ereport, errcode(), errdetail(), errmsg(), ERROR, pg_encoding_to_char(), pg_get_encoding_from_locale(), PG_SQL_ASCII, PG_UTF8, and superuser().

Referenced by createdb(), and DefineCollation().

◆ createdb()

Oid createdb ( ParseState pstate,
const CreatedbStmt stmt 
)

Definition at line 99 of file dbcommands.c.

100 {
101  TableScanDesc scan;
102  Relation rel;
103  Oid src_dboid;
104  Oid src_owner;
105  int src_encoding = -1;
106  char *src_collate = NULL;
107  char *src_ctype = NULL;
108  bool src_istemplate;
109  bool src_allowconn;
110  TransactionId src_frozenxid = InvalidTransactionId;
111  MultiXactId src_minmxid = InvalidMultiXactId;
112  Oid src_deftablespace;
113  volatile Oid dst_deftablespace;
114  Relation pg_database_rel;
115  HeapTuple tuple;
116  Datum new_record[Natts_pg_database];
117  bool new_record_nulls[Natts_pg_database];
118  Oid dboid = InvalidOid;
119  Oid datdba;
120  ListCell *option;
121  DefElem *dtablespacename = NULL;
122  DefElem *downer = NULL;
123  DefElem *dtemplate = NULL;
124  DefElem *dencoding = NULL;
125  DefElem *dlocale = NULL;
126  DefElem *dcollate = NULL;
127  DefElem *dctype = NULL;
128  DefElem *distemplate = NULL;
129  DefElem *dallowconnections = NULL;
130  DefElem *dconnlimit = NULL;
131  char *dbname = stmt->dbname;
132  char *dbowner = NULL;
133  const char *dbtemplate = NULL;
134  char *dbcollate = NULL;
135  char *dbctype = NULL;
136  char *canonname;
137  int encoding = -1;
138  bool dbistemplate = false;
139  bool dballowconnections = true;
140  int dbconnlimit = -1;
141  int notherbackends;
142  int npreparedxacts;
144 
145  /* Extract options from the statement node tree */
146  foreach(option, stmt->options)
147  {
148  DefElem *defel = (DefElem *) lfirst(option);
149 
150  if (strcmp(defel->defname, "tablespace") == 0)
151  {
152  if (dtablespacename)
153  errorConflictingDefElem(defel, pstate);
154  dtablespacename = defel;
155  }
156  else if (strcmp(defel->defname, "owner") == 0)
157  {
158  if (downer)
159  errorConflictingDefElem(defel, pstate);
160  downer = defel;
161  }
162  else if (strcmp(defel->defname, "template") == 0)
163  {
164  if (dtemplate)
165  errorConflictingDefElem(defel, pstate);
166  dtemplate = defel;
167  }
168  else if (strcmp(defel->defname, "encoding") == 0)
169  {
170  if (dencoding)
171  errorConflictingDefElem(defel, pstate);
172  dencoding = defel;
173  }
174  else if (strcmp(defel->defname, "locale") == 0)
175  {
176  if (dlocale)
177  errorConflictingDefElem(defel, pstate);
178  dlocale = defel;
179  }
180  else if (strcmp(defel->defname, "lc_collate") == 0)
181  {
182  if (dcollate)
183  errorConflictingDefElem(defel, pstate);
184  dcollate = defel;
185  }
186  else if (strcmp(defel->defname, "lc_ctype") == 0)
187  {
188  if (dctype)
189  errorConflictingDefElem(defel, pstate);
190  dctype = defel;
191  }
192  else if (strcmp(defel->defname, "is_template") == 0)
193  {
194  if (distemplate)
195  errorConflictingDefElem(defel, pstate);
196  distemplate = defel;
197  }
198  else if (strcmp(defel->defname, "allow_connections") == 0)
199  {
200  if (dallowconnections)
201  errorConflictingDefElem(defel, pstate);
202  dallowconnections = defel;
203  }
204  else if (strcmp(defel->defname, "connection_limit") == 0)
205  {
206  if (dconnlimit)
207  errorConflictingDefElem(defel, pstate);
208  dconnlimit = defel;
209  }
210  else if (strcmp(defel->defname, "location") == 0)
211  {
213  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
214  errmsg("LOCATION is not supported anymore"),
215  errhint("Consider using tablespaces instead."),
216  parser_errposition(pstate, defel->location)));
217  }
218  else if (strcmp(defel->defname, "oid") == 0)
219  {
220  dboid = defGetInt32(defel);
221 
222  /*
223  * We don't normally permit new databases to be created with
224  * system-assigned OIDs. pg_upgrade tries to preserve database
225  * OIDs, so we can't allow any database to be created with an
226  * OID that might be in use in a freshly-initialized cluster
227  * created by some future version. We assume all such OIDs will
228  * be from the system-managed OID range.
229  *
230  * As an exception, however, we permit any OID to be assigned when
231  * allow_system_table_mods=on (so that initdb can assign system
232  * OIDs to template0 and postgres) or when performing a binary
233  * upgrade (so that pg_upgrade can preserve whatever OIDs it finds
234  * in the source cluster).
235  */
236  if (dboid < FirstNormalObjectId &&
238  ereport(ERROR,
239  (errcode(ERRCODE_INVALID_PARAMETER_VALUE)),
240  errmsg("OIDs less than %u are reserved for system objects", FirstNormalObjectId));
241  }
242  else
243  ereport(ERROR,
244  (errcode(ERRCODE_SYNTAX_ERROR),
245  errmsg("option \"%s\" not recognized", defel->defname),
246  parser_errposition(pstate, defel->location)));
247  }
248 
249  if (dlocale && (dcollate || dctype))
250  ereport(ERROR,
251  (errcode(ERRCODE_SYNTAX_ERROR),
252  errmsg("conflicting or redundant options"),
253  errdetail("LOCALE cannot be specified together with LC_COLLATE or LC_CTYPE.")));
254 
255  if (downer && downer->arg)
256  dbowner = defGetString(downer);
257  if (dtemplate && dtemplate->arg)
258  dbtemplate = defGetString(dtemplate);
259  if (dencoding && dencoding->arg)
260  {
261  const char *encoding_name;
262 
263  if (IsA(dencoding->arg, Integer))
264  {
265  encoding = defGetInt32(dencoding);
266  encoding_name = pg_encoding_to_char(encoding);
267  if (strcmp(encoding_name, "") == 0 ||
268  pg_valid_server_encoding(encoding_name) < 0)
269  ereport(ERROR,
270  (errcode(ERRCODE_UNDEFINED_OBJECT),
271  errmsg("%d is not a valid encoding code",
272  encoding),
273  parser_errposition(pstate, dencoding->location)));
274  }
275  else
276  {
277  encoding_name = defGetString(dencoding);
278  encoding = pg_valid_server_encoding(encoding_name);
279  if (encoding < 0)
280  ereport(ERROR,
281  (errcode(ERRCODE_UNDEFINED_OBJECT),
282  errmsg("%s is not a valid encoding name",
283  encoding_name),
284  parser_errposition(pstate, dencoding->location)));
285  }
286  }
287  if (dlocale && dlocale->arg)
288  {
289  dbcollate = defGetString(dlocale);
290  dbctype = defGetString(dlocale);
291  }
292  if (dcollate && dcollate->arg)
293  dbcollate = defGetString(dcollate);
294  if (dctype && dctype->arg)
295  dbctype = defGetString(dctype);
296  if (distemplate && distemplate->arg)
297  dbistemplate = defGetBoolean(distemplate);
298  if (dallowconnections && dallowconnections->arg)
299  dballowconnections = defGetBoolean(dallowconnections);
300  if (dconnlimit && dconnlimit->arg)
301  {
302  dbconnlimit = defGetInt32(dconnlimit);
303  if (dbconnlimit < -1)
304  ereport(ERROR,
305  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
306  errmsg("invalid connection limit: %d", dbconnlimit)));
307  }
308 
309  /* obtain OID of proposed owner */
310  if (dbowner)
311  datdba = get_role_oid(dbowner, false);
312  else
313  datdba = GetUserId();
314 
315  /*
316  * To create a database, must have createdb privilege and must be able to
317  * become the target role (this does not imply that the target role itself
318  * must have createdb privilege). The latter provision guards against
319  * "giveaway" attacks. Note that a superuser will always have both of
320  * these privileges a fortiori.
321  */
323  ereport(ERROR,
324  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
325  errmsg("permission denied to create database")));
326 
328 
329  /*
330  * Lookup database (template) to be cloned, and obtain share lock on it.
331  * ShareLock allows two CREATE DATABASEs to work from the same template
332  * concurrently, while ensuring no one is busy dropping it in parallel
333  * (which would be Very Bad since we'd likely get an incomplete copy
334  * without knowing it). This also prevents any new connections from being
335  * made to the source until we finish copying it, so we can be sure it
336  * won't change underneath us.
337  */
338  if (!dbtemplate)
339  dbtemplate = "template1"; /* Default template database name */
340 
341  if (!get_db_info(dbtemplate, ShareLock,
342  &src_dboid, &src_owner, &src_encoding,
343  &src_istemplate, &src_allowconn,
344  &src_frozenxid, &src_minmxid, &src_deftablespace,
345  &src_collate, &src_ctype))
346  ereport(ERROR,
347  (errcode(ERRCODE_UNDEFINED_DATABASE),
348  errmsg("template database \"%s\" does not exist",
349  dbtemplate)));
350 
351  /*
352  * Permission check: to copy a DB that's not marked datistemplate, you
353  * must be superuser or the owner thereof.
354  */
355  if (!src_istemplate)
356  {
357  if (!pg_database_ownercheck(src_dboid, GetUserId()))
358  ereport(ERROR,
359  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
360  errmsg("permission denied to copy database \"%s\"",
361  dbtemplate)));
362  }
363 
364  /* If encoding or locales are defaulted, use source's setting */
365  if (encoding < 0)
366  encoding = src_encoding;
367  if (dbcollate == NULL)
368  dbcollate = src_collate;
369  if (dbctype == NULL)
370  dbctype = src_ctype;
371 
372  /* Some encodings are client only */
374  ereport(ERROR,
375  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
376  errmsg("invalid server encoding %d", encoding)));
377 
378  /* Check that the chosen locales are valid, and get canonical spellings */
379  if (!check_locale(LC_COLLATE, dbcollate, &canonname))
380  ereport(ERROR,
381  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
382  errmsg("invalid locale name: \"%s\"", dbcollate)));
383  dbcollate = canonname;
384  if (!check_locale(LC_CTYPE, dbctype, &canonname))
385  ereport(ERROR,
386  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
387  errmsg("invalid locale name: \"%s\"", dbctype)));
388  dbctype = canonname;
389 
390  check_encoding_locale_matches(encoding, dbcollate, dbctype);
391 
392  /*
393  * Check that the new encoding and locale settings match the source
394  * database. We insist on this because we simply copy the source data ---
395  * any non-ASCII data would be wrongly encoded, and any indexes sorted
396  * according to the source locale would be wrong.
397  *
398  * However, we assume that template0 doesn't contain any non-ASCII data
399  * nor any indexes that depend on collation or ctype, so template0 can be
400  * used as template for creating a database with any encoding or locale.
401  */
402  if (strcmp(dbtemplate, "template0") != 0)
403  {
404  if (encoding != src_encoding)
405  ereport(ERROR,
406  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
407  errmsg("new encoding (%s) is incompatible with the encoding of the template database (%s)",
409  pg_encoding_to_char(src_encoding)),
410  errhint("Use the same encoding as in the template database, or use template0 as template.")));
411 
412  if (strcmp(dbcollate, src_collate) != 0)
413  ereport(ERROR,
414  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
415  errmsg("new collation (%s) is incompatible with the collation of the template database (%s)",
416  dbcollate, src_collate),
417  errhint("Use the same collation as in the template database, or use template0 as template.")));
418 
419  if (strcmp(dbctype, src_ctype) != 0)
420  ereport(ERROR,
421  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
422  errmsg("new LC_CTYPE (%s) is incompatible with the LC_CTYPE of the template database (%s)",
423  dbctype, src_ctype),
424  errhint("Use the same LC_CTYPE as in the template database, or use template0 as template.")));
425  }
426 
427  /* Resolve default tablespace for new database */
428  if (dtablespacename && dtablespacename->arg)
429  {
430  char *tablespacename;
431  AclResult aclresult;
432 
433  tablespacename = defGetString(dtablespacename);
434  dst_deftablespace = get_tablespace_oid(tablespacename, false);
435  /* check permissions */
436  aclresult = pg_tablespace_aclcheck(dst_deftablespace, GetUserId(),
437  ACL_CREATE);
438  if (aclresult != ACLCHECK_OK)
440  tablespacename);
441 
442  /* pg_global must never be the default tablespace */
443  if (dst_deftablespace == GLOBALTABLESPACE_OID)
444  ereport(ERROR,
445  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
446  errmsg("pg_global cannot be used as default tablespace")));
447 
448  /*
449  * If we are trying to change the default tablespace of the template,
450  * we require that the template not have any files in the new default
451  * tablespace. This is necessary because otherwise the copied
452  * database would contain pg_class rows that refer to its default
453  * tablespace both explicitly (by OID) and implicitly (as zero), which
454  * would cause problems. For example another CREATE DATABASE using
455  * the copied database as template, and trying to change its default
456  * tablespace again, would yield outright incorrect results (it would
457  * improperly move tables to the new default tablespace that should
458  * stay in the same tablespace).
459  */
460  if (dst_deftablespace != src_deftablespace)
461  {
462  char *srcpath;
463  struct stat st;
464 
465  srcpath = GetDatabasePath(src_dboid, dst_deftablespace);
466 
467  if (stat(srcpath, &st) == 0 &&
468  S_ISDIR(st.st_mode) &&
469  !directory_is_empty(srcpath))
470  ereport(ERROR,
471  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
472  errmsg("cannot assign new default tablespace \"%s\"",
473  tablespacename),
474  errdetail("There is a conflict because database \"%s\" already has some tables in this tablespace.",
475  dbtemplate)));
476  pfree(srcpath);
477  }
478  }
479  else
480  {
481  /* Use template database's default tablespace */
482  dst_deftablespace = src_deftablespace;
483  /* Note there is no additional permission check in this path */
484  }
485 
486  /*
487  * If built with appropriate switch, whine when regression-testing
488  * conventions for database names are violated. But don't complain during
489  * initdb.
490  */
491 #ifdef ENFORCE_REGRESSION_TEST_NAME_RESTRICTIONS
492  if (IsUnderPostmaster && strstr(dbname, "regression") == NULL)
493  elog(WARNING, "databases created by regression test cases should have names including \"regression\"");
494 #endif
495 
496  /*
497  * Check for db name conflict. This is just to give a more friendly error
498  * message than "unique index violation". There's a race condition but
499  * we're willing to accept the less friendly message in that case.
500  */
501  if (OidIsValid(get_database_oid(dbname, true)))
502  ereport(ERROR,
503  (errcode(ERRCODE_DUPLICATE_DATABASE),
504  errmsg("database \"%s\" already exists", dbname)));
505 
506  /*
507  * The source DB can't have any active backends, except this one
508  * (exception is to allow CREATE DB while connected to template1).
509  * Otherwise we might copy inconsistent data.
510  *
511  * This should be last among the basic error checks, because it involves
512  * potential waiting; we may as well throw an error first if we're gonna
513  * throw one.
514  */
515  if (CountOtherDBBackends(src_dboid, &notherbackends, &npreparedxacts))
516  ereport(ERROR,
517  (errcode(ERRCODE_OBJECT_IN_USE),
518  errmsg("source database \"%s\" is being accessed by other users",
519  dbtemplate),
520  errdetail_busy_db(notherbackends, npreparedxacts)));
521 
522  /*
523  * Select an OID for the new database, checking that it doesn't have a
524  * filename conflict with anything already existing in the tablespace
525  * directories.
526  */
527  pg_database_rel = table_open(DatabaseRelationId, RowExclusiveLock);
528 
529  /*
530  * If database OID is configured, check if the OID is already in use or
531  * data directory already exists.
532  */
533  if (OidIsValid(dboid))
534  {
535  char *existing_dbname = get_database_name(dboid);
536 
537  if (existing_dbname != NULL)
538  ereport(ERROR,
539  (errcode(ERRCODE_INVALID_PARAMETER_VALUE)),
540  errmsg("database OID %u is already in use by database \"%s\"",
541  dboid, existing_dbname));
542 
543  if (check_db_file_conflict(dboid))
544  ereport(ERROR,
545  (errcode(ERRCODE_INVALID_PARAMETER_VALUE)),
546  errmsg("data directory with the specified OID %u already exists", dboid));
547  }
548  else
549  {
550  /* Select an OID for the new database if is not explicitly configured. */
551  do
552  {
553  dboid = GetNewOidWithIndex(pg_database_rel, DatabaseOidIndexId,
554  Anum_pg_database_oid);
555  } while (check_db_file_conflict(dboid));
556  }
557 
558  /*
559  * Insert a new tuple into pg_database. This establishes our ownership of
560  * the new database name (anyone else trying to insert the same name will
561  * block on the unique index, and fail after we commit).
562  */
563 
564  /* Form tuple */
565  MemSet(new_record, 0, sizeof(new_record));
566  MemSet(new_record_nulls, false, sizeof(new_record_nulls));
567 
568  new_record[Anum_pg_database_oid - 1] = ObjectIdGetDatum(dboid);
569  new_record[Anum_pg_database_datname - 1] =
571  new_record[Anum_pg_database_datdba - 1] = ObjectIdGetDatum(datdba);
572  new_record[Anum_pg_database_encoding - 1] = Int32GetDatum(encoding);
573  new_record[Anum_pg_database_datcollate - 1] =
575  new_record[Anum_pg_database_datctype - 1] =
577  new_record[Anum_pg_database_datistemplate - 1] = BoolGetDatum(dbistemplate);
578  new_record[Anum_pg_database_datallowconn - 1] = BoolGetDatum(dballowconnections);
579  new_record[Anum_pg_database_datconnlimit - 1] = Int32GetDatum(dbconnlimit);
580  new_record[Anum_pg_database_datfrozenxid - 1] = TransactionIdGetDatum(src_frozenxid);
581  new_record[Anum_pg_database_datminmxid - 1] = TransactionIdGetDatum(src_minmxid);
582  new_record[Anum_pg_database_dattablespace - 1] = ObjectIdGetDatum(dst_deftablespace);
583 
584  /*
585  * We deliberately set datacl to default (NULL), rather than copying it
586  * from the template database. Copying it would be a bad idea when the
587  * owner is not the same as the template's owner.
588  */
589  new_record_nulls[Anum_pg_database_datacl - 1] = true;
590 
591  tuple = heap_form_tuple(RelationGetDescr(pg_database_rel),
592  new_record, new_record_nulls);
593 
594  CatalogTupleInsert(pg_database_rel, tuple);
595 
596  /*
597  * Now generate additional catalog entries associated with the new DB
598  */
599 
600  /* Register owner dependency */
601  recordDependencyOnOwner(DatabaseRelationId, dboid, datdba);
602 
603  /* Create pg_shdepend entries for objects within database */
604  copyTemplateDependencies(src_dboid, dboid);
605 
606  /* Post creation hook for new database */
607  InvokeObjectPostCreateHook(DatabaseRelationId, dboid, 0);
608 
609  /*
610  * Force a checkpoint before starting the copy. This will force all dirty
611  * buffers, including those of unlogged tables, out to disk, to ensure
612  * source database is up-to-date on disk for the copy.
613  * FlushDatabaseBuffers() would suffice for that, but we also want to
614  * process any pending unlink requests. Otherwise, if a checkpoint
615  * happened while we're copying files, a file might be deleted just when
616  * we're about to copy it, causing the lstat() call in copydir() to fail
617  * with ENOENT.
618  */
621 
622  /*
623  * Once we start copying subdirectories, we need to be able to clean 'em
624  * up if we fail. Use an ENSURE block to make sure this happens. (This
625  * is not a 100% solution, because of the possibility of failure during
626  * transaction commit after we leave this routine, but it should handle
627  * most scenarios.)
628  */
629  fparms.src_dboid = src_dboid;
630  fparms.dest_dboid = dboid;
632  PointerGetDatum(&fparms));
633  {
634  /*
635  * Iterate through all tablespaces of the template database, and copy
636  * each one to the new database.
637  */
638  rel = table_open(TableSpaceRelationId, AccessShareLock);
639  scan = table_beginscan_catalog(rel, 0, NULL);
640  while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
641  {
642  Form_pg_tablespace spaceform = (Form_pg_tablespace) GETSTRUCT(tuple);
643  Oid srctablespace = spaceform->oid;
644  Oid dsttablespace;
645  char *srcpath;
646  char *dstpath;
647  struct stat st;
648 
649  /* No need to copy global tablespace */
650  if (srctablespace == GLOBALTABLESPACE_OID)
651  continue;
652 
653  srcpath = GetDatabasePath(src_dboid, srctablespace);
654 
655  if (stat(srcpath, &st) < 0 || !S_ISDIR(st.st_mode) ||
656  directory_is_empty(srcpath))
657  {
658  /* Assume we can ignore it */
659  pfree(srcpath);
660  continue;
661  }
662 
663  if (srctablespace == src_deftablespace)
664  dsttablespace = dst_deftablespace;
665  else
666  dsttablespace = srctablespace;
667 
668  dstpath = GetDatabasePath(dboid, dsttablespace);
669 
670  /*
671  * Copy this subdirectory to the new location
672  *
673  * We don't need to copy subdirectories
674  */
675  copydir(srcpath, dstpath, false);
676 
677  /* Record the filesystem change in XLOG */
678  {
679  xl_dbase_create_rec xlrec;
680 
681  xlrec.db_id = dboid;
682  xlrec.tablespace_id = dsttablespace;
683  xlrec.src_db_id = src_dboid;
684  xlrec.src_tablespace_id = srctablespace;
685 
686  XLogBeginInsert();
687  XLogRegisterData((char *) &xlrec, sizeof(xl_dbase_create_rec));
688 
689  (void) XLogInsert(RM_DBASE_ID,
691  }
692  }
693  table_endscan(scan);
695 
696  /*
697  * We force a checkpoint before committing. This effectively means
698  * that committed XLOG_DBASE_CREATE operations will never need to be
699  * replayed (at least not in ordinary crash recovery; we still have to
700  * make the XLOG entry for the benefit of PITR operations). This
701  * avoids two nasty scenarios:
702  *
703  * #1: When PITR is off, we don't XLOG the contents of newly created
704  * indexes; therefore the drop-and-recreate-whole-directory behavior
705  * of DBASE_CREATE replay would lose such indexes.
706  *
707  * #2: Since we have to recopy the source database during DBASE_CREATE
708  * replay, we run the risk of copying changes in it that were
709  * committed after the original CREATE DATABASE command but before the
710  * system crash that led to the replay. This is at least unexpected
711  * and at worst could lead to inconsistencies, eg duplicate table
712  * names.
713  *
714  * (Both of these were real bugs in releases 8.0 through 8.0.3.)
715  *
716  * In PITR replay, the first of these isn't an issue, and the second
717  * is only a risk if the CREATE DATABASE and subsequent template
718  * database change both occur while a base backup is being taken.
719  * There doesn't seem to be much we can do about that except document
720  * it as a limitation.
721  *
722  * Perhaps if we ever implement CREATE DATABASE in a less cheesy way,
723  * we can avoid this.
724  */
726 
727  /*
728  * Close pg_database, but keep lock till commit.
729  */
730  table_close(pg_database_rel, NoLock);
731 
732  /*
733  * Force synchronous commit, thus minimizing the window between
734  * creation of the database files and committal of the transaction. If
735  * we crash before committing, we'll have a DB that's taking up disk
736  * space but is not in pg_database, which is not good.
737  */
738  ForceSyncCommit();
739  }
741  PointerGetDatum(&fparms));
742 
743  return dboid;
744 }
Oid get_role_oid(const char *rolname, bool missing_ok)
Definition: acl.c:5094
AclResult
Definition: acl.h:178
@ ACLCHECK_OK
Definition: acl.h:179
AclResult pg_tablespace_aclcheck(Oid spc_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4770
bool directory_is_empty(const char *path)
Definition: tablespace.c:890
Oid get_tablespace_oid(const char *tablespacename, bool missing_ok)
Definition: tablespace.c:1465
TransactionId MultiXactId
Definition: c.h:597
uint32 TransactionId
Definition: c.h:587
#define OidIsValid(objectId)
Definition: c.h:710
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:381
void RequestCheckpoint(int flags)
Definition: checkpointer.c:920
void copydir(char *fromdir, char *todir, bool recurse)
Definition: copydir.c:37
char * get_database_name(Oid dbid)
Definition: dbcommands.c:2153
static bool get_db_info(const char *name, LOCKMODE lockmode, Oid *dbIdP, Oid *ownerIdP, int *encodingP, bool *dbIsTemplateP, bool *dbAllowConnP, TransactionId *dbFrozenXidP, MultiXactId *dbMinMultiP, Oid *dbTablespace, char **dbCollate, char **dbCtype)
Definition: dbcommands.c:1801
void check_encoding_locale_matches(int encoding, const char *collate, const char *ctype)
Definition: dbcommands.c:769
static int errdetail_busy_db(int notherbackends, int npreparedxacts)
Definition: dbcommands.c:2076
static bool check_db_file_conflict(Oid db_id)
Definition: dbcommands.c:2033
static void createdb_failure_callback(int code, Datum arg)
Definition: dbcommands.c:807
#define XLOG_DBASE_CREATE
int errhint(const char *fmt,...)
Definition: elog.c:1151
#define WARNING
Definition: elog.h:30
#define elog(elevel,...)
Definition: elog.h:218
int pg_valid_server_encoding(const char *name)
Definition: encnames.c:500
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:631
bool IsBinaryUpgrade
Definition: globals.c:113
bool IsUnderPostmaster
Definition: globals.c:112
bool allowSystemTableMods
Definition: globals.c:123
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:221
#define PG_ENSURE_ERROR_CLEANUP(cleanup_function, arg)
Definition: ipc.h:47
#define PG_END_ENSURE_ERROR_CLEANUP(cleanup_function, arg)
Definition: ipc.h:52
#define ShareLock
Definition: lockdefs.h:40
#define InvalidMultiXactId
Definition: multixact.h:24
Datum namein(PG_FUNCTION_ARGS)
Definition: name.c:48
#define IsA(nodeptr, _type_)
Definition: nodes.h:589
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:151
@ OBJECT_TABLESPACE
Definition: parsenodes.h:1830
#define ACL_CREATE
Definition: parsenodes.h:91
bool check_locale(int category, const char *locale, char **canonname)
Definition: pg_locale.c:246
void copyTemplateDependencies(Oid templateDbId, Oid newDbId)
Definition: pg_shdepend.c:849
void recordDependencyOnOwner(Oid classId, Oid objectId, Oid owner)
Definition: pg_shdepend.c:164
#define PG_VALID_BE_ENCODING(_enc)
Definition: pg_wchar.h:279
#define TransactionIdGetDatum(X)
Definition: postgres.h:565
bool CountOtherDBBackends(Oid databaseId, int *nbackends, int *nprepared)
Definition: procarray.c:3695
List * options
Definition: parsenodes.h:3294
char * dbname
Definition: parsenodes.h:3293
Definition: value.h:29
#define InvalidTransactionId
Definition: transam.h:31
#define FirstNormalObjectId
Definition: transam.h:197
#define stat
Definition: win32_port.h:283
#define S_ISDIR(m)
Definition: win32_port.h:324
void ForceSyncCommit(void)
Definition: xact.c:1123
#define CHECKPOINT_FLUSH_ALL
Definition: xlog.h:198
#define CHECKPOINT_FORCE
Definition: xlog.h:197
#define CHECKPOINT_WAIT
Definition: xlog.h:200
#define CHECKPOINT_IMMEDIATE
Definition: xlog.h:196
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:429
void XLogBeginInsert(void)
Definition: xloginsert.c:136
void XLogRegisterData(char *data, int len)
Definition: xloginsert.c:337
#define XLR_SPECIAL_REL_UPDATE
Definition: xlogrecord.h:71

References AccessShareLock, ACL_CREATE, aclcheck_error(), ACLCHECK_OK, allowSystemTableMods, DefElem::arg, BoolGetDatum, CatalogTupleInsert(), check_db_file_conflict(), check_encoding_locale_matches(), check_is_member_of_role(), check_locale(), CHECKPOINT_FLUSH_ALL, CHECKPOINT_FORCE, CHECKPOINT_IMMEDIATE, CHECKPOINT_WAIT, copydir(), copyTemplateDependencies(), CountOtherDBBackends(), createdb_failure_callback(), CStringGetDatum, xl_dbase_create_rec::db_id, dbname, CreatedbStmt::dbname, defGetBoolean(), defGetInt32(), defGetString(), DefElem::defname, createdb_failure_params::dest_dboid, DirectFunctionCall1, directory_is_empty(), dstpath, elog, encoding, ereport, errcode(), errdetail(), errdetail_busy_db(), errhint(), errmsg(), ERROR, errorConflictingDefElem(), FirstNormalObjectId, ForceSyncCommit(), ForwardScanDirection, get_database_name(), get_database_oid(), get_db_info(), get_role_oid(), get_tablespace_oid(), GetDatabasePath(), GetNewOidWithIndex(), GETSTRUCT, GetUserId(), have_createdb_privilege(), heap_form_tuple(), heap_getnext(), Int32GetDatum, InvalidMultiXactId, InvalidOid, InvalidTransactionId, InvokeObjectPostCreateHook, IsA, IsBinaryUpgrade, IsUnderPostmaster, lfirst, DefElem::location, MemSet, namein(), NoLock, OBJECT_TABLESPACE, ObjectIdGetDatum, OidIsValid, CreatedbStmt::options, parser_errposition(), pfree(), pg_database_ownercheck(), pg_encoding_to_char(), PG_END_ENSURE_ERROR_CLEANUP, PG_ENSURE_ERROR_CLEANUP, pg_tablespace_aclcheck(), PG_VALID_BE_ENCODING, pg_valid_server_encoding(), PointerGetDatum, recordDependencyOnOwner(), RelationGetDescr, RequestCheckpoint(), RowExclusiveLock, S_ISDIR, ShareLock, xl_dbase_create_rec::src_db_id, createdb_failure_params::src_dboid, xl_dbase_create_rec::src_tablespace_id, stat::st_mode, stat, table_beginscan_catalog(), table_close(), table_endscan(), table_open(), xl_dbase_create_rec::tablespace_id, TransactionIdGetDatum, WARNING, XLOG_DBASE_CREATE, XLogBeginInsert(), XLogInsert(), XLogRegisterData(), and XLR_SPECIAL_REL_UPDATE.

Referenced by CreateRole(), main(), and standard_ProcessUtility().

◆ createdb_failure_callback()

static void createdb_failure_callback ( int  code,
Datum  arg 
)
static

Definition at line 807 of file dbcommands.c.

808 {
810 
811  /*
812  * Release lock on source database before doing recursive remove. This is
813  * not essential but it seems desirable to release the lock as soon as
814  * possible.
815  */
816  UnlockSharedObject(DatabaseRelationId, fparms->src_dboid, 0, ShareLock);
817 
818  /* Throw away any successfully copied subdirectories */
820 }
static void remove_dbtablespaces(Oid db_id)
Definition: dbcommands.c:1943
void * arg
#define DatumGetPointer(X)
Definition: postgres.h:593

References arg, DatumGetPointer, createdb_failure_params::dest_dboid, remove_dbtablespaces(), ShareLock, createdb_failure_params::src_dboid, and UnlockSharedObject().

Referenced by createdb().

◆ dbase_redo()

void dbase_redo ( XLogReaderState record)

Definition at line 2174 of file dbcommands.c.

2175 {
2176  uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
2177 
2178  /* Backup blocks are not used in dbase records */
2179  Assert(!XLogRecHasAnyBlockRefs(record));
2180 
2181  if (info == XLOG_DBASE_CREATE)
2182  {
2184  char *src_path;
2185  char *dst_path;
2186  struct stat st;
2187 
2188  src_path = GetDatabasePath(xlrec->src_db_id, xlrec->src_tablespace_id);
2189  dst_path = GetDatabasePath(xlrec->db_id, xlrec->tablespace_id);
2190 
2191  /*
2192  * Our theory for replaying a CREATE is to forcibly drop the target
2193  * subdirectory if present, then re-copy the source data. This may be
2194  * more work than needed, but it is simple to implement.
2195  */
2196  if (stat(dst_path, &st) == 0 && S_ISDIR(st.st_mode))
2197  {
2198  if (!rmtree(dst_path, true))
2199  /* If this failed, copydir() below is going to error. */
2200  ereport(WARNING,
2201  (errmsg("some useless files may be left behind in old database directory \"%s\"",
2202  dst_path)));
2203  }
2204 
2205  /*
2206  * Force dirty buffers out to disk, to ensure source database is
2207  * up-to-date for the copy.
2208  */
2210 
2211  /*
2212  * Copy this subdirectory to the new location
2213  *
2214  * We don't need to copy subdirectories
2215  */
2216  copydir(src_path, dst_path, false);
2217  }
2218  else if (info == XLOG_DBASE_DROP)
2219  {
2220  xl_dbase_drop_rec *xlrec = (xl_dbase_drop_rec *) XLogRecGetData(record);
2221  char *dst_path;
2222  int i;
2223 
2224  if (InHotStandby)
2225  {
2226  /*
2227  * Lock database while we resolve conflicts to ensure that
2228  * InitPostgres() cannot fully re-execute concurrently. This
2229  * avoids backends re-connecting automatically to same database,
2230  * which can happen in some cases.
2231  *
2232  * This will lock out walsenders trying to connect to db-specific
2233  * slots for logical decoding too, so it's safe for us to drop
2234  * slots.
2235  */
2236  LockSharedObjectForSession(DatabaseRelationId, xlrec->db_id, 0, AccessExclusiveLock);
2238  }
2239 
2240  /* Drop any database-specific replication slots */
2242 
2243  /* Drop pages for this database that are in the shared buffer cache */
2244  DropDatabaseBuffers(xlrec->db_id);
2245 
2246  /* Also, clean out any fsync requests that might be pending in md.c */
2248 
2249  /* Clean out the xlog relcache too */
2250  XLogDropDatabase(xlrec->db_id);
2251 
2252  for (i = 0; i < xlrec->ntablespaces; i++)
2253  {
2254  dst_path = GetDatabasePath(xlrec->db_id, xlrec->tablespace_ids[i]);
2255 
2256  /* And remove the physical files */
2257  if (!rmtree(dst_path, true))
2258  ereport(WARNING,
2259  (errmsg("some useless files may be left behind in old database directory \"%s\"",
2260  dst_path)));
2261  pfree(dst_path);
2262  }
2263 
2264  if (InHotStandby)
2265  {
2266  /*
2267  * Release locks prior to commit. XXX There is a race condition
2268  * here that may allow backends to reconnect, but the window for
2269  * this is small because the gap between here and commit is mostly
2270  * fairly small and it is unlikely that people will be dropping
2271  * databases that we are trying to connect to anyway.
2272  */
2273  UnlockSharedObjectForSession(DatabaseRelationId, xlrec->db_id, 0, AccessExclusiveLock);
2274  }
2275  }
2276  else
2277  elog(PANIC, "dbase_redo: unknown op code %u", info);
2278 }
void DropDatabaseBuffers(Oid dbid)
Definition: bufmgr.c:3397
void FlushDatabaseBuffers(Oid dbid)
Definition: bufmgr.c:3694
unsigned char uint8
Definition: c.h:439
#define XLOG_DBASE_DROP
#define PANIC
Definition: elog.h:36
int i
Definition: isn.c:73
Assert(fmt[strlen(fmt) - 1] !='\n')
void UnlockSharedObjectForSession(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition: lmgr.c:1078
void LockSharedObjectForSession(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition: lmgr.c:1060
#define AccessExclusiveLock
Definition: lockdefs.h:43
void ForgetDatabaseSyncRequests(Oid dbid)
Definition: md.c:1032
bool rmtree(const char *path, bool rmtopdir)
Definition: rmtree.c:42
void ReplicationSlotsDropDBSlots(Oid dboid)
Definition: slot.c:968
void ResolveRecoveryConflictWithDatabase(Oid dbid)
Definition: standby.c:529
Oid tablespace_ids[FLEXIBLE_ARRAY_MEMBER]
#define XLogRecGetInfo(decoder)
Definition: xlogreader.h:315
#define XLogRecGetData(decoder)
Definition: xlogreader.h:320
#define XLogRecHasAnyBlockRefs(decoder)
Definition: xlogreader.h:322
#define XLR_INFO_MASK
Definition: xlogrecord.h:62
void XLogDropDatabase(Oid dbid)
Definition: xlogutils.c:643
#define InHotStandby
Definition: xlogutils.h:57

References AccessExclusiveLock, Assert(), copydir(), xl_dbase_create_rec::db_id, xl_dbase_drop_rec::db_id, DropDatabaseBuffers(), elog, ereport, errmsg(), FlushDatabaseBuffers(), ForgetDatabaseSyncRequests(), GetDatabasePath(), i, InHotStandby, LockSharedObjectForSession(), xl_dbase_drop_rec::ntablespaces, PANIC, pfree(), ReplicationSlotsDropDBSlots(), ResolveRecoveryConflictWithDatabase(), rmtree(), S_ISDIR, xl_dbase_create_rec::src_db_id, xl_dbase_create_rec::src_tablespace_id, stat::st_mode, stat, xl_dbase_create_rec::tablespace_id, xl_dbase_drop_rec::tablespace_ids, UnlockSharedObjectForSession(), WARNING, XLOG_DBASE_CREATE, XLOG_DBASE_DROP, XLogDropDatabase(), XLogRecGetData, XLogRecGetInfo, XLogRecHasAnyBlockRefs, and XLR_INFO_MASK.

◆ DropDatabase()

void DropDatabase ( ParseState pstate,
DropdbStmt stmt 
)

Definition at line 1460 of file dbcommands.c.

1461 {
1462  bool force = false;
1463  ListCell *lc;
1464 
1465  foreach(lc, stmt->options)
1466  {
1467  DefElem *opt = (DefElem *) lfirst(lc);
1468 
1469  if (strcmp(opt->defname, "force") == 0)
1470  force = true;
1471  else
1472  ereport(ERROR,
1473  (errcode(ERRCODE_SYNTAX_ERROR),
1474  errmsg("unrecognized DROP DATABASE option \"%s\"", opt->defname),
1475  parser_errposition(pstate, opt->location)));
1476  }
1477 
1478  dropdb(stmt->dbname, stmt->missing_ok, force);
1479 }
void dropdb(const char *dbname, bool missing_ok, bool force)
Definition: dbcommands.c:827
List * options
Definition: parsenodes.h:3324
char * dbname
Definition: parsenodes.h:3322
bool missing_ok
Definition: parsenodes.h:3323

References DropdbStmt::dbname, DefElem::defname, dropdb(), ereport, errcode(), errmsg(), ERROR, lfirst, DefElem::location, DropdbStmt::missing_ok, DropdbStmt::options, and parser_errposition().

Referenced by standard_ProcessUtility().

◆ dropdb()

void dropdb ( const char *  dbname,
bool  missing_ok,
bool  force 
)

Definition at line 827 of file dbcommands.c.

828 {
829  Oid db_id;
830  bool db_istemplate;
831  Relation pgdbrel;
832  HeapTuple tup;
833  int notherbackends;
834  int npreparedxacts;
835  int nslots,
836  nslots_active;
837  int nsubscriptions;
838 
839  /*
840  * Look up the target database's OID, and get exclusive lock on it. We
841  * need this to ensure that no new backend starts up in the target
842  * database while we are deleting it (see postinit.c), and that no one is
843  * using it as a CREATE DATABASE template or trying to delete it for
844  * themselves.
845  */
846  pgdbrel = table_open(DatabaseRelationId, RowExclusiveLock);
847 
848  if (!get_db_info(dbname, AccessExclusiveLock, &db_id, NULL, NULL,
849  &db_istemplate, NULL, NULL, NULL, NULL, NULL, NULL))
850  {
851  if (!missing_ok)
852  {
853  ereport(ERROR,
854  (errcode(ERRCODE_UNDEFINED_DATABASE),
855  errmsg("database \"%s\" does not exist", dbname)));
856  }
857  else
858  {
859  /* Close pg_database, release the lock, since we changed nothing */
860  table_close(pgdbrel, RowExclusiveLock);
861  ereport(NOTICE,
862  (errmsg("database \"%s\" does not exist, skipping",
863  dbname)));
864  return;
865  }
866  }
867 
868  /*
869  * Permission checks
870  */
871  if (!pg_database_ownercheck(db_id, GetUserId()))
873  dbname);
874 
875  /* DROP hook for the database being removed */
876  InvokeObjectDropHook(DatabaseRelationId, db_id, 0);
877 
878  /*
879  * Disallow dropping a DB that is marked istemplate. This is just to
880  * prevent people from accidentally dropping template0 or template1; they
881  * can do so if they're really determined ...
882  */
883  if (db_istemplate)
884  ereport(ERROR,
885  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
886  errmsg("cannot drop a template database")));
887 
888  /* Obviously can't drop my own database */
889  if (db_id == MyDatabaseId)
890  ereport(ERROR,
891  (errcode(ERRCODE_OBJECT_IN_USE),
892  errmsg("cannot drop the currently open database")));
893 
894  /*
895  * Check whether there are active logical slots that refer to the
896  * to-be-dropped database. The database lock we are holding prevents the
897  * creation of new slots using the database or existing slots becoming
898  * active.
899  */
900  (void) ReplicationSlotsCountDBSlots(db_id, &nslots, &nslots_active);
901  if (nslots_active)
902  {
903  ereport(ERROR,
904  (errcode(ERRCODE_OBJECT_IN_USE),
905  errmsg("database \"%s\" is used by an active logical replication slot",
906  dbname),
907  errdetail_plural("There is %d active slot.",
908  "There are %d active slots.",
909  nslots_active, nslots_active)));
910  }
911 
912  /*
913  * Check if there are subscriptions defined in the target database.
914  *
915  * We can't drop them automatically because they might be holding
916  * resources in other databases/instances.
917  */
918  if ((nsubscriptions = CountDBSubscriptions(db_id)) > 0)
919  ereport(ERROR,
920  (errcode(ERRCODE_OBJECT_IN_USE),
921  errmsg("database \"%s\" is being used by logical replication subscription",
922  dbname),
923  errdetail_plural("There is %d subscription.",
924  "There are %d subscriptions.",
925  nsubscriptions, nsubscriptions)));
926 
927 
928  /*
929  * Attempt to terminate all existing connections to the target database if
930  * the user has requested to do so.
931  */
932  if (force)
934 
935  /*
936  * Check for other backends in the target database. (Because we hold the
937  * database lock, no new ones can start after this.)
938  *
939  * As in CREATE DATABASE, check this after other error conditions.
940  */
941  if (CountOtherDBBackends(db_id, &notherbackends, &npreparedxacts))
942  ereport(ERROR,
943  (errcode(ERRCODE_OBJECT_IN_USE),
944  errmsg("database \"%s\" is being accessed by other users",
945  dbname),
946  errdetail_busy_db(notherbackends, npreparedxacts)));
947 
948  /*
949  * Remove the database's tuple from pg_database.
950  */
952  if (!HeapTupleIsValid(tup))
953  elog(ERROR, "cache lookup failed for database %u", db_id);
954 
955  CatalogTupleDelete(pgdbrel, &tup->t_self);
956 
957  ReleaseSysCache(tup);
958 
959  /*
960  * Delete any comments or security labels associated with the database.
961  */
962  DeleteSharedComments(db_id, DatabaseRelationId);
963  DeleteSharedSecurityLabel(db_id, DatabaseRelationId);
964 
965  /*
966  * Remove settings associated with this database
967  */
968  DropSetting(db_id, InvalidOid);
969 
970  /*
971  * Remove shared dependency references for the database.
972  */
974 
975  /*
976  * Drop db-specific replication slots.
977  */
979 
980  /*
981  * Drop pages for this database that are in the shared buffer cache. This
982  * is important to ensure that no remaining backend tries to write out a
983  * dirty buffer to the dead database later...
984  */
985  DropDatabaseBuffers(db_id);
986 
987  /*
988  * Tell the stats collector to forget it immediately, too.
989  */
990  pgstat_drop_database(db_id);
991 
992  /*
993  * Tell checkpointer to forget any pending fsync and unlink requests for
994  * files in the database; else the fsyncs will fail at next checkpoint, or
995  * worse, it will delete files that belong to a newly created database
996  * with the same OID.
997  */
999 
1000  /*
1001  * Force a checkpoint to make sure the checkpointer has received the
1002  * message sent by ForgetDatabaseSyncRequests. On Windows, this also
1003  * ensures that background procs don't hold any open files, which would
1004  * cause rmdir() to fail.
1005  */
1007 
1008  /*
1009  * Remove all tablespace subdirs belonging to the database.
1010  */
1011  remove_dbtablespaces(db_id);
1012 
1013  /*
1014  * Close pg_database, but keep lock till commit.
1015  */
1016  table_close(pgdbrel, NoLock);
1017 
1018  /*
1019  * Force synchronous commit, thus minimizing the window between removal of
1020  * the database files and committal of the transaction. If we crash before
1021  * committing, we'll have a DB that's gone on disk but still there
1022  * according to pg_database, which is not good.
1023  */
1024  ForceSyncCommit();
1025 }
void DeleteSharedComments(Oid oid, Oid classoid)
Definition: comment.c:374
int errdetail_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...)
Definition: elog.c:1129
#define NOTICE
Definition: elog.h:29
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:350
#define InvokeObjectDropHook(classId, objectId, subId)
Definition: objectaccess.h:160
void DropSetting(Oid databaseid, Oid roleid)
void dropDatabaseDependencies(Oid databaseId)
Definition: pg_shdepend.c:953
int CountDBSubscriptions(Oid dbid)
void pgstat_drop_database(Oid databaseid)
Definition: pgstat.c:1438
void TerminateOtherDBBackends(Oid databaseId)
Definition: procarray.c:3773
void DeleteSharedSecurityLabel(Oid objectId, Oid classId)
Definition: seclabel.c:490
bool ReplicationSlotsCountDBSlots(Oid dboid, int *nslots, int *nactive)
Definition: slot.c:912
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1198
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1150
@ DATABASEOID
Definition: syscache.h:55

References AccessExclusiveLock, aclcheck_error(), ACLCHECK_NOT_OWNER, CatalogTupleDelete(), CHECKPOINT_FORCE, CHECKPOINT_IMMEDIATE, CHECKPOINT_WAIT, CountDBSubscriptions(), CountOtherDBBackends(), DATABASEOID, dbname, DeleteSharedComments(), DeleteSharedSecurityLabel(), DropDatabaseBuffers(), dropDatabaseDependencies(), DropSetting(), elog, ereport, errcode(), errdetail_busy_db(), errdetail_plural(), errmsg(), ERROR, ForceSyncCommit(), ForgetDatabaseSyncRequests(), get_db_info(), GetUserId(), HeapTupleIsValid, InvalidOid, InvokeObjectDropHook, MyDatabaseId, NoLock, NOTICE, OBJECT_DATABASE, ObjectIdGetDatum, pg_database_ownercheck(), pgstat_drop_database(), ReleaseSysCache(), remove_dbtablespaces(), ReplicationSlotsCountDBSlots(), ReplicationSlotsDropDBSlots(), RequestCheckpoint(), RowExclusiveLock, SearchSysCache1(), HeapTupleData::t_self, table_close(), table_open(), and TerminateOtherDBBackends().

Referenced by DropDatabase().

◆ errdetail_busy_db()

static int errdetail_busy_db ( int  notherbackends,
int  npreparedxacts 
)
static

Definition at line 2076 of file dbcommands.c.

2077 {
2078  if (notherbackends > 0 && npreparedxacts > 0)
2079 
2080  /*
2081  * We don't deal with singular versus plural here, since gettext
2082  * doesn't support multiple plurals in one string.
2083  */
2084  errdetail("There are %d other session(s) and %d prepared transaction(s) using the database.",
2085  notherbackends, npreparedxacts);
2086  else if (notherbackends > 0)
2087  errdetail_plural("There is %d other session using the database.",
2088  "There are %d other sessions using the database.",
2089  notherbackends,
2090  notherbackends);
2091  else
2092  errdetail_plural("There is %d prepared transaction using the database.",
2093  "There are %d prepared transactions using the database.",
2094  npreparedxacts,
2095  npreparedxacts);
2096  return 0; /* just to keep ereport macro happy */
2097 }

References errdetail(), and errdetail_plural().

Referenced by createdb(), dropdb(), movedb(), and RenameDatabase().

◆ get_database_name()

char* get_database_name ( Oid  dbid)

Definition at line 2153 of file dbcommands.c.

2154 {
2155  HeapTuple dbtuple;
2156  char *result;
2157 
2158  dbtuple = SearchSysCache1(DATABASEOID, ObjectIdGetDatum(dbid));
2159  if (HeapTupleIsValid(dbtuple))
2160  {
2161  result = pstrdup(NameStr(((Form_pg_database) GETSTRUCT(dbtuple))->datname));
2162  ReleaseSysCache(dbtuple);
2163  }
2164  else
2165  result = NULL;
2166 
2167  return result;
2168 }
#define NameStr(name)
Definition: c.h:681
char * pstrdup(const char *in)
Definition: mcxt.c:1299
NameData datname
Definition: pg_database.h:35

References DATABASEOID, datname, GETSTRUCT, HeapTupleIsValid, NameStr, ObjectIdGetDatum, pstrdup(), ReleaseSysCache(), and SearchSysCache1().

Referenced by AfterTriggerSetState(), AlterPublicationOwner_internal(), AlterSchemaOwner_internal(), calculate_database_size(), createdb(), CreatePublication(), CreateSchemaCommand(), current_database(), database_to_xml_internal(), DeconstructQualifiedName(), do_analyze_rel(), do_autovacuum(), exec_object_restorecon(), ExpandColumnRefStar(), GetNewMultiXactId(), GetNewTransactionId(), getObjectDescription(), getObjectIdentityParts(), heap_vacuum_rel(), IdentifySystem(), InitTempTableNamespace(), lazy_check_wraparound_failsafe(), map_sql_catalog_to_xmlschema_types(), map_sql_schema_to_xmlschema_types(), map_sql_table_to_xmlschema(), map_sql_type_to_xml_name(), perform_work_item(), RangeVarGetAndCheckCreationNamespace(), RangeVarGetCreationNamespace(), RangeVarGetRelidExtended(), ReindexMultipleTables(), RenameSchema(), SetMultiXactIdLimit(), SetTransactionIdLimit(), shdepLockAndCheckObject(), TerminateOtherDBBackends(), and transformColumnRef().

◆ get_database_oid()

Oid get_database_oid ( const char *  dbname,
bool  missing_ok 
)

Definition at line 2106 of file dbcommands.c.

2107 {
2108  Relation pg_database;
2109  ScanKeyData entry[1];
2110  SysScanDesc scan;
2111  HeapTuple dbtuple;
2112  Oid oid;
2113 
2114  /*
2115  * There's no syscache for pg_database indexed by name, so we must look
2116  * the hard way.
2117  */
2118  pg_database = table_open(DatabaseRelationId, AccessShareLock);
2119  ScanKeyInit(&entry[0],
2120  Anum_pg_database_datname,
2121  BTEqualStrategyNumber, F_NAMEEQ,
2123  scan = systable_beginscan(pg_database, DatabaseNameIndexId, true,
2124  NULL, 1, entry);
2125 
2126  dbtuple = systable_getnext(scan);
2127 
2128  /* We assume that there can be at most one matching tuple */
2129  if (HeapTupleIsValid(dbtuple))
2130  oid = ((Form_pg_database) GETSTRUCT(dbtuple))->oid;
2131  else
2132  oid = InvalidOid;
2133 
2134  systable_endscan(scan);
2135  table_close(pg_database, AccessShareLock);
2136 
2137  if (!OidIsValid(oid) && !missing_ok)
2138  ereport(ERROR,
2139  (errcode(ERRCODE_UNDEFINED_DATABASE),
2140  errmsg("database \"%s\" does not exist",
2141  dbname)));
2142 
2143  return oid;
2144 }

References AccessShareLock, BTEqualStrategyNumber, CStringGetDatum, dbname, ereport, errcode(), errmsg(), ERROR, GETSTRUCT, HeapTupleIsValid, InvalidOid, OidIsValid, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by AlterDatabaseSet(), AlterRoleSet(), CommentObject(), convert_database_name(), createdb(), get_object_address_unqualified(), objectNamesToOids(), pg_database_size_name(), RenameDatabase(), and sepgsql_database_post_create().

◆ get_db_info()

static bool get_db_info ( const char *  name,
LOCKMODE  lockmode,
Oid dbIdP,
Oid ownerIdP,
int *  encodingP,
bool dbIsTemplateP,
bool dbAllowConnP,
TransactionId dbFrozenXidP,
MultiXactId dbMinMultiP,
Oid dbTablespace,
char **  dbCollate,
char **  dbCtype 
)
static

Definition at line 1801 of file dbcommands.c.

1806 {
1807  bool result = false;
1808  Relation relation;
1809 
1810  AssertArg(name);
1811 
1812  /* Caller may wish to grab a better lock on pg_database beforehand... */
1813  relation = table_open(DatabaseRelationId, AccessShareLock);
1814 
1815  /*
1816  * Loop covers the rare case where the database is renamed before we can
1817  * lock it. We try again just in case we can find a new one of the same
1818  * name.
1819  */
1820  for (;;)
1821  {
1822  ScanKeyData scanKey;
1823  SysScanDesc scan;
1824  HeapTuple tuple;
1825  Oid dbOid;
1826 
1827  /*
1828  * there's no syscache for database-indexed-by-name, so must do it the
1829  * hard way
1830  */
1831  ScanKeyInit(&scanKey,
1832  Anum_pg_database_datname,
1833  BTEqualStrategyNumber, F_NAMEEQ,
1835 
1836  scan = systable_beginscan(relation, DatabaseNameIndexId, true,
1837  NULL, 1, &scanKey);
1838 
1839  tuple = systable_getnext(scan);
1840 
1841  if (!HeapTupleIsValid(tuple))
1842  {
1843  /* definitely no database of that name */
1844  systable_endscan(scan);
1845  break;
1846  }
1847 
1848  dbOid = ((Form_pg_database) GETSTRUCT(tuple))->oid;
1849 
1850  systable_endscan(scan);
1851 
1852  /*
1853  * Now that we have a database OID, we can try to lock the DB.
1854  */
1855  if (lockmode != NoLock)
1856  LockSharedObject(DatabaseRelationId, dbOid, 0, lockmode);
1857 
1858  /*
1859  * And now, re-fetch the tuple by OID. If it's still there and still
1860  * the same name, we win; else, drop the lock and loop back to try
1861  * again.
1862  */
1863  tuple = SearchSysCache1(DATABASEOID, ObjectIdGetDatum(dbOid));
1864  if (HeapTupleIsValid(tuple))
1865  {
1866  Form_pg_database dbform = (Form_pg_database) GETSTRUCT(tuple);
1867 
1868  if (strcmp(name, NameStr(dbform->datname)) == 0)
1869  {
1870  /* oid of the database */
1871  if (dbIdP)
1872  *dbIdP = dbOid;
1873  /* oid of the owner */
1874  if (ownerIdP)
1875  *ownerIdP = dbform->datdba;
1876  /* character encoding */
1877  if (encodingP)
1878  *encodingP = dbform->encoding;
1879  /* allowed as template? */
1880  if (dbIsTemplateP)
1881  *dbIsTemplateP = dbform->datistemplate;
1882  /* allowing connections? */
1883  if (dbAllowConnP)
1884  *dbAllowConnP = dbform->datallowconn;
1885  /* limit of frozen XIDs */
1886  if (dbFrozenXidP)
1887  *dbFrozenXidP = dbform->datfrozenxid;
1888  /* minimum MultiXactId */
1889  if (dbMinMultiP)
1890  *dbMinMultiP = dbform->datminmxid;
1891  /* default tablespace for this database */
1892  if (dbTablespace)
1893  *dbTablespace = dbform->dattablespace;
1894  /* default locale settings for this database */
1895  if (dbCollate)
1896  *dbCollate = pstrdup(NameStr(dbform->datcollate));
1897  if (dbCtype)
1898  *dbCtype = pstrdup(NameStr(dbform->datctype));
1899  ReleaseSysCache(tuple);
1900  result = true;
1901  break;
1902  }
1903  /* can only get here if it was just renamed */
1904  ReleaseSysCache(tuple);
1905  }
1906 
1907  if (lockmode != NoLock)
1908  UnlockSharedObject(DatabaseRelationId, dbOid, 0, lockmode);
1909  }
1910 
1911  table_close(relation, AccessShareLock);
1912 
1913  return result;
1914 }
#define AssertArg(condition)
Definition: c.h:806
const char * name
Definition: encode.c:561
void LockSharedObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition: lmgr.c:1018

References AccessShareLock, AssertArg, BTEqualStrategyNumber, CStringGetDatum, DATABASEOID, GETSTRUCT, HeapTupleIsValid, LockSharedObject(), name, NameStr, NoLock, ObjectIdGetDatum, pstrdup(), ReleaseSysCache(), ScanKeyInit(), SearchSysCache1(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), table_open(), and UnlockSharedObject().

Referenced by createdb(), dropdb(), movedb(), and RenameDatabase().

◆ have_createdb_privilege()

static bool have_createdb_privilege ( void  )
static

Definition at line 1918 of file dbcommands.c.

1919 {
1920  bool result = false;
1921  HeapTuple utup;
1922 
1923  /* Superusers can always do everything */
1924  if (superuser())
1925  return true;
1926 
1928  if (HeapTupleIsValid(utup))
1929  {
1930  result = ((Form_pg_authid) GETSTRUCT(utup))->rolcreatedb;
1931  ReleaseSysCache(utup);
1932  }
1933  return result;
1934 }
FormData_pg_authid * Form_pg_authid
Definition: pg_authid.h:56
bool rolcreatedb
Definition: pg_authid.h:38
@ AUTHOID
Definition: syscache.h:45

References AUTHOID, GETSTRUCT, GetUserId(), HeapTupleIsValid, ObjectIdGetDatum, ReleaseSysCache(), rolcreatedb, SearchSysCache1(), and superuser().

Referenced by AlterDatabaseOwner(), createdb(), and RenameDatabase().

◆ movedb()

static void movedb ( const char *  dbname,
const char *  tblspcname 
)
static

Definition at line 1130 of file dbcommands.c.

1131 {
1132  Oid db_id;
1133  Relation pgdbrel;
1134  int notherbackends;
1135  int npreparedxacts;
1136  HeapTuple oldtuple,
1137  newtuple;
1138  Oid src_tblspcoid,
1139  dst_tblspcoid;
1140  Datum new_record[Natts_pg_database];
1141  bool new_record_nulls[Natts_pg_database];
1142  bool new_record_repl[Natts_pg_database];
1143  ScanKeyData scankey;
1144  SysScanDesc sysscan;
1145  AclResult aclresult;
1146  char *src_dbpath;
1147  char *dst_dbpath;
1148  DIR *dstdir;
1149  struct dirent *xlde;
1150  movedb_failure_params fparms;
1151 
1152  /*
1153  * Look up the target database's OID, and get exclusive lock on it. We
1154  * need this to ensure that no new backend starts up in the database while
1155  * we are moving it, and that no one is using it as a CREATE DATABASE
1156  * template or trying to delete it.
1157  */
1158  pgdbrel = table_open(DatabaseRelationId, RowExclusiveLock);
1159 
1160  if (!get_db_info(dbname, AccessExclusiveLock, &db_id, NULL, NULL,
1161  NULL, NULL, NULL, NULL, &src_tblspcoid, NULL, NULL))
1162  ereport(ERROR,
1163  (errcode(ERRCODE_UNDEFINED_DATABASE),
1164  errmsg("database \"%s\" does not exist", dbname)));
1165 
1166  /*
1167  * We actually need a session lock, so that the lock will persist across
1168  * the commit/restart below. (We could almost get away with letting the
1169  * lock be released at commit, except that someone could try to move
1170  * relations of the DB back into the old directory while we rmtree() it.)
1171  */
1172  LockSharedObjectForSession(DatabaseRelationId, db_id, 0,
1174 
1175  /*
1176  * Permission checks
1177  */
1178  if (!pg_database_ownercheck(db_id, GetUserId()))
1180  dbname);
1181 
1182  /*
1183  * Obviously can't move the tables of my own database
1184  */
1185  if (db_id == MyDatabaseId)
1186  ereport(ERROR,
1187  (errcode(ERRCODE_OBJECT_IN_USE),
1188  errmsg("cannot change the tablespace of the currently open database")));
1189 
1190  /*
1191  * Get tablespace's oid
1192  */
1193  dst_tblspcoid = get_tablespace_oid(tblspcname, false);
1194 
1195  /*
1196  * Permission checks
1197  */
1198  aclresult = pg_tablespace_aclcheck(dst_tblspcoid, GetUserId(),
1199  ACL_CREATE);
1200  if (aclresult != ACLCHECK_OK)
1201  aclcheck_error(aclresult, OBJECT_TABLESPACE,
1202  tblspcname);
1203 
1204  /*
1205  * pg_global must never be the default tablespace
1206  */
1207  if (dst_tblspcoid == GLOBALTABLESPACE_OID)
1208  ereport(ERROR,
1209  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1210  errmsg("pg_global cannot be used as default tablespace")));
1211 
1212  /*
1213  * No-op if same tablespace
1214  */
1215  if (src_tblspcoid == dst_tblspcoid)
1216  {
1217  table_close(pgdbrel, NoLock);
1218  UnlockSharedObjectForSession(DatabaseRelationId, db_id, 0,
1220  return;
1221  }
1222 
1223  /*
1224  * Check for other backends in the target database. (Because we hold the
1225  * database lock, no new ones can start after this.)
1226  *
1227  * As in CREATE DATABASE, check this after other error conditions.
1228  */
1229  if (CountOtherDBBackends(db_id, &notherbackends, &npreparedxacts))
1230  ereport(ERROR,
1231  (errcode(ERRCODE_OBJECT_IN_USE),
1232  errmsg("database \"%s\" is being accessed by other users",
1233  dbname),
1234  errdetail_busy_db(notherbackends, npreparedxacts)));
1235 
1236  /*
1237  * Get old and new database paths
1238  */
1239  src_dbpath = GetDatabasePath(db_id, src_tblspcoid);
1240  dst_dbpath = GetDatabasePath(db_id, dst_tblspcoid);
1241 
1242  /*
1243  * Force a checkpoint before proceeding. This will force all dirty
1244  * buffers, including those of unlogged tables, out to disk, to ensure
1245  * source database is up-to-date on disk for the copy.
1246  * FlushDatabaseBuffers() would suffice for that, but we also want to
1247  * process any pending unlink requests. Otherwise, the check for existing
1248  * files in the target directory might fail unnecessarily, not to mention
1249  * that the copy might fail due to source files getting deleted under it.
1250  * On Windows, this also ensures that background procs don't hold any open
1251  * files, which would cause rmdir() to fail.
1252  */
1255 
1256  /*
1257  * Now drop all buffers holding data of the target database; they should
1258  * no longer be dirty so DropDatabaseBuffers is safe.
1259  *
1260  * It might seem that we could just let these buffers age out of shared
1261  * buffers naturally, since they should not get referenced anymore. The
1262  * problem with that is that if the user later moves the database back to
1263  * its original tablespace, any still-surviving buffers would appear to
1264  * contain valid data again --- but they'd be missing any changes made in
1265  * the database while it was in the new tablespace. In any case, freeing
1266  * buffers that should never be used again seems worth the cycles.
1267  *
1268  * Note: it'd be sufficient to get rid of buffers matching db_id and
1269  * src_tblspcoid, but bufmgr.c presently provides no API for that.
1270  */
1271  DropDatabaseBuffers(db_id);
1272 
1273  /*
1274  * Check for existence of files in the target directory, i.e., objects of
1275  * this database that are already in the target tablespace. We can't
1276  * allow the move in such a case, because we would need to change those
1277  * relations' pg_class.reltablespace entries to zero, and we don't have
1278  * access to the DB's pg_class to do so.
1279  */
1280  dstdir = AllocateDir(dst_dbpath);
1281  if (dstdir != NULL)
1282  {
1283  while ((xlde = ReadDir(dstdir, dst_dbpath)) != NULL)
1284  {
1285  if (strcmp(xlde->d_name, ".") == 0 ||
1286  strcmp(xlde->d_name, "..") == 0)
1287  continue;
1288 
1289  ereport(ERROR,
1290  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1291  errmsg("some relations of database \"%s\" are already in tablespace \"%s\"",
1292  dbname, tblspcname),
1293  errhint("You must move them back to the database's default tablespace before using this command.")));
1294  }
1295 
1296  FreeDir(dstdir);
1297 
1298  /*
1299  * The directory exists but is empty. We must remove it before using
1300  * the copydir function.
1301  */
1302  if (rmdir(dst_dbpath) != 0)
1303  elog(ERROR, "could not remove directory \"%s\": %m",
1304  dst_dbpath);
1305  }
1306 
1307  /*
1308  * Use an ENSURE block to make sure we remove the debris if the copy fails
1309  * (eg, due to out-of-disk-space). This is not a 100% solution, because
1310  * of the possibility of failure during transaction commit, but it should
1311  * handle most scenarios.
1312  */
1313  fparms.dest_dboid = db_id;
1314  fparms.dest_tsoid = dst_tblspcoid;
1316  PointerGetDatum(&fparms));
1317  {
1318  /*
1319  * Copy files from the old tablespace to the new one
1320  */
1321  copydir(src_dbpath, dst_dbpath, false);
1322 
1323  /*
1324  * Record the filesystem change in XLOG
1325  */
1326  {
1327  xl_dbase_create_rec xlrec;
1328 
1329  xlrec.db_id = db_id;
1330  xlrec.tablespace_id = dst_tblspcoid;
1331  xlrec.src_db_id = db_id;
1332  xlrec.src_tablespace_id = src_tblspcoid;
1333 
1334  XLogBeginInsert();
1335  XLogRegisterData((char *) &xlrec, sizeof(xl_dbase_create_rec));
1336 
1337  (void) XLogInsert(RM_DBASE_ID,
1339  }
1340 
1341  /*
1342  * Update the database's pg_database tuple
1343  */
1344  ScanKeyInit(&scankey,
1345  Anum_pg_database_datname,
1346  BTEqualStrategyNumber, F_NAMEEQ,
1348  sysscan = systable_beginscan(pgdbrel, DatabaseNameIndexId, true,
1349  NULL, 1, &scankey);
1350  oldtuple = systable_getnext(sysscan);
1351  if (!HeapTupleIsValid(oldtuple)) /* shouldn't happen... */
1352  ereport(ERROR,
1353  (errcode(ERRCODE_UNDEFINED_DATABASE),
1354  errmsg("database \"%s\" does not exist", dbname)));
1355 
1356  MemSet(new_record, 0, sizeof(new_record));
1357  MemSet(new_record_nulls, false, sizeof(new_record_nulls));
1358  MemSet(new_record_repl, false, sizeof(new_record_repl));
1359 
1360  new_record[Anum_pg_database_dattablespace - 1] = ObjectIdGetDatum(dst_tblspcoid);
1361  new_record_repl[Anum_pg_database_dattablespace - 1] = true;
1362 
1363  newtuple = heap_modify_tuple(oldtuple, RelationGetDescr(pgdbrel),
1364  new_record,
1365  new_record_nulls, new_record_repl);
1366  CatalogTupleUpdate(pgdbrel, &oldtuple->t_self, newtuple);
1367 
1368  InvokeObjectPostAlterHook(DatabaseRelationId, db_id, 0);
1369 
1370  systable_endscan(sysscan);
1371 
1372  /*
1373  * Force another checkpoint here. As in CREATE DATABASE, this is to
1374  * ensure that we don't have to replay a committed XLOG_DBASE_CREATE
1375  * operation, which would cause us to lose any unlogged operations
1376  * done in the new DB tablespace before the next checkpoint.
1377  */
1379 
1380  /*
1381  * Force synchronous commit, thus minimizing the window between
1382  * copying the database files and committal of the transaction. If we
1383  * crash before committing, we'll leave an orphaned set of files on
1384  * disk, which is not fatal but not good either.
1385  */
1386  ForceSyncCommit();
1387 
1388  /*
1389  * Close pg_database, but keep lock till commit.
1390  */
1391  table_close(pgdbrel, NoLock);
1392  }
1394  PointerGetDatum(&fparms));
1395 
1396  /*
1397  * Commit the transaction so that the pg_database update is committed. If
1398  * we crash while removing files, the database won't be corrupt, we'll
1399  * just leave some orphaned files in the old directory.
1400  *
1401  * (This is OK because we know we aren't inside a transaction block.)
1402  *
1403  * XXX would it be safe/better to do this inside the ensure block? Not
1404  * convinced it's a good idea; consider elog just after the transaction
1405  * really commits.
1406  */
1409 
1410  /* Start new transaction for the remaining work; don't need a snapshot */
1412 
1413  /*
1414  * Remove files from the old tablespace
1415  */
1416  if (!rmtree(src_dbpath, true))
1417  ereport(WARNING,
1418  (errmsg("some useless files may be left behind in old database directory \"%s\"",
1419  src_dbpath)));
1420 
1421  /*
1422  * Record the filesystem change in XLOG
1423  */
1424  {
1425  xl_dbase_drop_rec xlrec;
1426 
1427  xlrec.db_id = db_id;
1428  xlrec.ntablespaces = 1;
1429 
1430  XLogBeginInsert();
1431  XLogRegisterData((char *) &xlrec, sizeof(xl_dbase_drop_rec));
1432  XLogRegisterData((char *) &src_tblspcoid, sizeof(Oid));
1433 
1434  (void) XLogInsert(RM_DBASE_ID,
1436  }
1437 
1438  /* Now it's safe to release the database lock */
1439  UnlockSharedObjectForSession(DatabaseRelationId, db_id, 0,
1441 }
static void movedb_failure_callback(int code, Datum arg)
Definition: dbcommands.c:1445
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2788
int FreeDir(DIR *dir)
Definition: fd.c:2840
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2722
void PopActiveSnapshot(void)
Definition: snapmgr.c:774
Definition: dirent.c:26
Definition: dirent.h:10
char d_name[MAX_PATH]
Definition: dirent.h:15
void StartTransactionCommand(void)
Definition: xact.c:2909
void CommitTransactionCommand(void)
Definition: xact.c:3010

References AccessExclusiveLock, ACL_CREATE, aclcheck_error(), ACLCHECK_NOT_OWNER, ACLCHECK_OK, AllocateDir(), BTEqualStrategyNumber, CatalogTupleUpdate(), CHECKPOINT_FLUSH_ALL, CHECKPOINT_FORCE, CHECKPOINT_IMMEDIATE, CHECKPOINT_WAIT, CommitTransactionCommand(), copydir(), CountOtherDBBackends(), CStringGetDatum, dirent::d_name, xl_dbase_create_rec::db_id, xl_dbase_drop_rec::db_id, dbname, movedb_failure_params::dest_dboid, movedb_failure_params::dest_tsoid, DropDatabaseBuffers(), elog, ereport, errcode(), errdetail_busy_db(), errhint(), errmsg(), ERROR, ForceSyncCommit(), FreeDir(), get_db_info(), get_tablespace_oid(), GetDatabasePath(), GetUserId(), heap_modify_tuple(), HeapTupleIsValid, InvokeObjectPostAlterHook, LockSharedObjectForSession(), MemSet, movedb_failure_callback(), MyDatabaseId, NoLock, xl_dbase_drop_rec::ntablespaces, OBJECT_DATABASE, OBJECT_TABLESPACE, ObjectIdGetDatum, pg_database_ownercheck(), PG_END_ENSURE_ERROR_CLEANUP, PG_ENSURE_ERROR_CLEANUP, pg_tablespace_aclcheck(), PointerGetDatum, PopActiveSnapshot(), ReadDir(), RelationGetDescr, RequestCheckpoint(), rmtree(), RowExclusiveLock, ScanKeyInit(), xl_dbase_create_rec::src_db_id, xl_dbase_create_rec::src_tablespace_id, StartTransactionCommand(), systable_beginscan(), systable_endscan(), systable_getnext(), HeapTupleData::t_self, table_close(), table_open(), xl_dbase_create_rec::tablespace_id, UnlockSharedObjectForSession(), WARNING, XLOG_DBASE_CREATE, XLOG_DBASE_DROP, XLogBeginInsert(), XLogInsert(), XLogRegisterData(), and XLR_SPECIAL_REL_UPDATE.

Referenced by AlterDatabase().

◆ movedb_failure_callback()

static void movedb_failure_callback ( int  code,
Datum  arg 
)
static

Definition at line 1445 of file dbcommands.c.

1446 {
1448  char *dstpath;
1449 
1450  /* Get rid of anything we managed to copy to the target directory */
1451  dstpath = GetDatabasePath(fparms->dest_dboid, fparms->dest_tsoid);
1452 
1453  (void) rmtree(dstpath, true);
1454 }

References arg, DatumGetPointer, movedb_failure_params::dest_dboid, movedb_failure_params::dest_tsoid, dstpath, GetDatabasePath(), and rmtree().

Referenced by movedb().

◆ remove_dbtablespaces()

static void remove_dbtablespaces ( Oid  db_id)
static

Definition at line 1943 of file dbcommands.c.

1944 {
1945  Relation rel;
1946  TableScanDesc scan;
1947  HeapTuple tuple;
1948  List *ltblspc = NIL;
1949  ListCell *cell;
1950  int ntblspc;
1951  int i;
1952  Oid *tablespace_ids;
1953 
1954  rel = table_open(TableSpaceRelationId, AccessShareLock);
1955  scan = table_beginscan_catalog(rel, 0, NULL);
1956  while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
1957  {
1958  Form_pg_tablespace spcform = (Form_pg_tablespace) GETSTRUCT(tuple);
1959  Oid dsttablespace = spcform->oid;
1960  char *dstpath;
1961  struct stat st;
1962 
1963  /* Don't mess with the global tablespace */
1964  if (dsttablespace == GLOBALTABLESPACE_OID)
1965  continue;
1966 
1967  dstpath = GetDatabasePath(db_id, dsttablespace);
1968 
1969  if (lstat(dstpath, &st) < 0 || !S_ISDIR(st.st_mode))
1970  {
1971  /* Assume we can ignore it */
1972  pfree(dstpath);
1973  continue;
1974  }
1975 
1976  if (!rmtree(dstpath, true))
1977  ereport(WARNING,
1978  (errmsg("some useless files may be left behind in old database directory \"%s\"",
1979  dstpath)));
1980 
1981  ltblspc = lappend_oid(ltblspc, dsttablespace);
1982  pfree(dstpath);
1983  }
1984 
1985  ntblspc = list_length(ltblspc);
1986  if (ntblspc == 0)
1987  {
1988  table_endscan(scan);
1990  return;
1991  }
1992 
1993  tablespace_ids = (Oid *) palloc(ntblspc * sizeof(Oid));
1994  i = 0;
1995  foreach(cell, ltblspc)
1996  tablespace_ids[i++] = lfirst_oid(cell);
1997 
1998  /* Record the filesystem change in XLOG */
1999  {
2000  xl_dbase_drop_rec xlrec;
2001 
2002  xlrec.db_id = db_id;
2003  xlrec.ntablespaces = ntblspc;
2004 
2005  XLogBeginInsert();
2006  XLogRegisterData((char *) &xlrec, MinSizeOfDbaseDropRec);
2007  XLogRegisterData((char *) tablespace_ids, ntblspc * sizeof(Oid));
2008 
2009  (void) XLogInsert(RM_DBASE_ID,
2011  }
2012 
2013  list_free(ltblspc);
2014  pfree(tablespace_ids);
2015 
2016  table_endscan(scan);
2018 }
#define MinSizeOfDbaseDropRec
List * lappend_oid(List *list, Oid datum)
Definition: list.c:372
void list_free(List *list)
Definition: list.c:1505
void * palloc(Size size)
Definition: mcxt.c:1062
#define NIL
Definition: pg_list.h:65
#define lfirst_oid(lc)
Definition: pg_list.h:171
Definition: pg_list.h:51

References AccessShareLock, xl_dbase_drop_rec::db_id, dstpath, ereport, errmsg(), ForwardScanDirection, GetDatabasePath(), GETSTRUCT, heap_getnext(), i, lappend_oid(), lfirst_oid, list_free(), list_length(), lstat, MinSizeOfDbaseDropRec, NIL, xl_dbase_drop_rec::ntablespaces, palloc(), pfree(), rmtree(), S_ISDIR, stat::st_mode, table_beginscan_catalog(), table_close(), table_endscan(), table_open(), WARNING, XLOG_DBASE_DROP, XLogBeginInsert(), XLogInsert(), XLogRegisterData(), and XLR_SPECIAL_REL_UPDATE.

Referenced by createdb_failure_callback(), and dropdb().

◆ RenameDatabase()

ObjectAddress RenameDatabase ( const char *  oldname,
const char *  newname 
)

Definition at line 1032 of file dbcommands.c.

1033 {
1034  Oid db_id;
1035  HeapTuple newtup;
1036  Relation rel;
1037  int notherbackends;
1038  int npreparedxacts;
1039  ObjectAddress address;
1040 
1041  /*
1042  * Look up the target database's OID, and get exclusive lock on it. We
1043  * need this for the same reasons as DROP DATABASE.
1044  */
1045  rel = table_open(DatabaseRelationId, RowExclusiveLock);
1046 
1047  if (!get_db_info(oldname, AccessExclusiveLock, &db_id, NULL, NULL,
1048  NULL, NULL, NULL, NULL, NULL, NULL, NULL))
1049  ereport(ERROR,
1050  (errcode(ERRCODE_UNDEFINED_DATABASE),
1051  errmsg("database \"%s\" does not exist", oldname)));
1052 
1053  /* must be owner */
1054  if (!pg_database_ownercheck(db_id, GetUserId()))
1056  oldname);
1057 
1058  /* must have createdb rights */
1059  if (!have_createdb_privilege())
1060  ereport(ERROR,
1061  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1062  errmsg("permission denied to rename database")));
1063 
1064  /*
1065  * If built with appropriate switch, whine when regression-testing
1066  * conventions for database names are violated.
1067  */
1068 #ifdef ENFORCE_REGRESSION_TEST_NAME_RESTRICTIONS
1069  if (strstr(newname, "regression") == NULL)
1070  elog(WARNING, "databases created by regression test cases should have names including \"regression\"");
1071 #endif
1072 
1073  /*
1074  * Make sure the new name doesn't exist. See notes for same error in
1075  * CREATE DATABASE.
1076  */
1077  if (OidIsValid(get_database_oid(newname, true)))
1078  ereport(ERROR,
1079  (errcode(ERRCODE_DUPLICATE_DATABASE),
1080  errmsg("database \"%s\" already exists", newname)));
1081 
1082  /*
1083  * XXX Client applications probably store the current database somewhere,
1084  * so renaming it could cause confusion. On the other hand, there may not
1085  * be an actual problem besides a little confusion, so think about this
1086  * and decide.
1087  */
1088  if (db_id == MyDatabaseId)
1089  ereport(ERROR,
1090  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1091  errmsg("current database cannot be renamed")));
1092 
1093  /*
1094  * Make sure the database does not have active sessions. This is the same
1095  * concern as above, but applied to other sessions.
1096  *
1097  * As in CREATE DATABASE, check this after other error conditions.
1098  */
1099  if (CountOtherDBBackends(db_id, &notherbackends, &npreparedxacts))
1100  ereport(ERROR,
1101  (errcode(ERRCODE_OBJECT_IN_USE),
1102  errmsg("database \"%s\" is being accessed by other users",
1103  oldname),
1104  errdetail_busy_db(notherbackends, npreparedxacts)));
1105 
1106  /* rename */
1108  if (!HeapTupleIsValid(newtup))
1109  elog(ERROR, "cache lookup failed for database %u", db_id);
1110  namestrcpy(&(((Form_pg_database) GETSTRUCT(newtup))->datname), newname);
1111  CatalogTupleUpdate(rel, &newtup->t_self, newtup);
1112 
1113  InvokeObjectPostAlterHook(DatabaseRelationId, db_id, 0);
1114 
1115  ObjectAddressSet(address, DatabaseRelationId, db_id);
1116 
1117  /*
1118  * Close pg_database, but keep lock till commit.
1119  */
1120  table_close(rel, NoLock);
1121 
1122  return address;
1123 }
void namestrcpy(Name name, const char *str)
Definition: name.c:233
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:177

References AccessExclusiveLock, aclcheck_error(), ACLCHECK_NOT_OWNER, CatalogTupleUpdate(), CountOtherDBBackends(), DATABASEOID, datname, elog, ereport, errcode(), errdetail_busy_db(), errmsg(), ERROR, get_database_oid(), get_db_info(), GETSTRUCT, GetUserId(), have_createdb_privilege(), HeapTupleIsValid, InvokeObjectPostAlterHook, MyDatabaseId, namestrcpy(), NoLock, OBJECT_DATABASE, ObjectAddressSet, ObjectIdGetDatum, OidIsValid, pg_database_ownercheck(), RowExclusiveLock, SearchSysCacheCopy1, HeapTupleData::t_self, table_close(), table_open(), and WARNING.

Referenced by ExecRenameStmt().