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/xlogrecovery.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_collation.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 "common/file_perm.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/relmapper.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
 
struct  CreateDBRelInfo
 

Typedefs

typedef enum CreateDBStrategy CreateDBStrategy
 
typedef struct CreateDBRelInfo CreateDBRelInfo
 

Enumerations

enum  CreateDBStrategy { CREATEDB_WAL_LOG , CREATEDB_FILE_COPY }
 

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, bool *dbHasLoginEvtP, TransactionId *dbFrozenXidP, MultiXactId *dbMinMultiP, Oid *dbTablespace, char **dbCollate, char **dbCtype, char **dbLocale, char **dbIcurules, char *dbLocProvider, char **dbCollversion)
 
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)
 
static void CreateDatabaseUsingWalLog (Oid src_dboid, Oid dst_dboid, Oid src_tsid, Oid dst_tsid)
 
static ListScanSourceDatabasePgClass (Oid tbid, Oid dbid, char *srcpath)
 
static ListScanSourceDatabasePgClassPage (Page page, Buffer buf, Oid tbid, Oid dbid, char *srcpath, List *rlocatorlist, Snapshot snapshot)
 
static CreateDBRelInfoScanSourceDatabasePgClassTuple (HeapTupleData *tuple, Oid tbid, Oid dbid, char *srcpath)
 
static void CreateDirAndVersionFile (char *dbpath, Oid dbid, Oid tsid, bool isRedo)
 
static void CreateDatabaseUsingFileCopy (Oid src_dboid, Oid dst_dboid, Oid src_tsid, Oid dst_tsid)
 
static void recovery_create_dbdir (char *path, bool only_tblspc)
 
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)
 
ObjectAddress AlterDatabaseRefreshColl (AlterDatabaseRefreshCollStmt *stmt)
 
Oid AlterDatabaseSet (AlterDatabaseSetStmt *stmt)
 
ObjectAddress AlterDatabaseOwner (const char *dbname, Oid newOwnerId)
 
Datum pg_database_collation_actual_version (PG_FUNCTION_ARGS)
 
bool have_createdb_privilege (void)
 
Oid get_database_oid (const char *dbname, bool missing_ok)
 
char * get_database_name (Oid dbid)
 
bool database_is_invalid_form (Form_pg_database datform)
 
bool database_is_invalid_oid (Oid dboid)
 
void dbase_redo (XLogReaderState *record)
 

Typedef Documentation

◆ CreateDBRelInfo

◆ CreateDBStrategy

Enumeration Type Documentation

◆ CreateDBStrategy

Enumerator
CREATEDB_WAL_LOG 
CREATEDB_FILE_COPY 

Definition at line 82 of file dbcommands.c.

83 {
CreateDBStrategy
Definition: dbcommands.c:83
@ CREATEDB_FILE_COPY
Definition: dbcommands.c:85
@ CREATEDB_WAL_LOG
Definition: dbcommands.c:84

Function Documentation

◆ AlterDatabase()

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

Definition at line 2341 of file dbcommands.c.

2342 {
2343  Relation rel;
2344  Oid dboid;
2345  HeapTuple tuple,
2346  newtuple;
2347  Form_pg_database datform;
2348  ScanKeyData scankey;
2349  SysScanDesc scan;
2350  ListCell *option;
2351  bool dbistemplate = false;
2352  bool dballowconnections = true;
2353  int dbconnlimit = DATCONNLIMIT_UNLIMITED;
2354  DefElem *distemplate = NULL;
2355  DefElem *dallowconnections = NULL;
2356  DefElem *dconnlimit = NULL;
2357  DefElem *dtablespace = NULL;
2358  Datum new_record[Natts_pg_database] = {0};
2359  bool new_record_nulls[Natts_pg_database] = {0};
2360  bool new_record_repl[Natts_pg_database] = {0};
2361 
2362  /* Extract options from the statement node tree */
2363  foreach(option, stmt->options)
2364  {
2365  DefElem *defel = (DefElem *) lfirst(option);
2366 
2367  if (strcmp(defel->defname, "is_template") == 0)
2368  {
2369  if (distemplate)
2370  errorConflictingDefElem(defel, pstate);
2371  distemplate = defel;
2372  }
2373  else if (strcmp(defel->defname, "allow_connections") == 0)
2374  {
2375  if (dallowconnections)
2376  errorConflictingDefElem(defel, pstate);
2377  dallowconnections = defel;
2378  }
2379  else if (strcmp(defel->defname, "connection_limit") == 0)
2380  {
2381  if (dconnlimit)
2382  errorConflictingDefElem(defel, pstate);
2383  dconnlimit = defel;
2384  }
2385  else if (strcmp(defel->defname, "tablespace") == 0)
2386  {
2387  if (dtablespace)
2388  errorConflictingDefElem(defel, pstate);
2389  dtablespace = defel;
2390  }
2391  else
2392  ereport(ERROR,
2393  (errcode(ERRCODE_SYNTAX_ERROR),
2394  errmsg("option \"%s\" not recognized", defel->defname),
2395  parser_errposition(pstate, defel->location)));
2396  }
2397 
2398  if (dtablespace)
2399  {
2400  /*
2401  * While the SET TABLESPACE syntax doesn't allow any other options,
2402  * somebody could write "WITH TABLESPACE ...". Forbid any other
2403  * options from being specified in that case.
2404  */
2405  if (list_length(stmt->options) != 1)
2406  ereport(ERROR,
2407  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2408  errmsg("option \"%s\" cannot be specified with other options",
2409  dtablespace->defname),
2410  parser_errposition(pstate, dtablespace->location)));
2411  /* this case isn't allowed within a transaction block */
2412  PreventInTransactionBlock(isTopLevel, "ALTER DATABASE SET TABLESPACE");
2413  movedb(stmt->dbname, defGetString(dtablespace));
2414  return InvalidOid;
2415  }
2416 
2417  if (distemplate && distemplate->arg)
2418  dbistemplate = defGetBoolean(distemplate);
2419  if (dallowconnections && dallowconnections->arg)
2420  dballowconnections = defGetBoolean(dallowconnections);
2421  if (dconnlimit && dconnlimit->arg)
2422  {
2423  dbconnlimit = defGetInt32(dconnlimit);
2424  if (dbconnlimit < DATCONNLIMIT_UNLIMITED)
2425  ereport(ERROR,
2426  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2427  errmsg("invalid connection limit: %d", dbconnlimit)));
2428  }
2429 
2430  /*
2431  * Get the old tuple. We don't need a lock on the database per se,
2432  * because we're not going to do anything that would mess up incoming
2433  * connections.
2434  */
2435  rel = table_open(DatabaseRelationId, RowExclusiveLock);
2436  ScanKeyInit(&scankey,
2437  Anum_pg_database_datname,
2438  BTEqualStrategyNumber, F_NAMEEQ,
2439  CStringGetDatum(stmt->dbname));
2440  scan = systable_beginscan(rel, DatabaseNameIndexId, true,
2441  NULL, 1, &scankey);
2442  tuple = systable_getnext(scan);
2443  if (!HeapTupleIsValid(tuple))
2444  ereport(ERROR,
2445  (errcode(ERRCODE_UNDEFINED_DATABASE),
2446  errmsg("database \"%s\" does not exist", stmt->dbname)));
2447  LockTuple(rel, &tuple->t_self, InplaceUpdateTupleLock);
2448 
2449  datform = (Form_pg_database) GETSTRUCT(tuple);
2450  dboid = datform->oid;
2451 
2452  if (database_is_invalid_form(datform))
2453  {
2454  ereport(FATAL,
2455  errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
2456  errmsg("cannot alter invalid database \"%s\"", stmt->dbname),
2457  errhint("Use DROP DATABASE to drop invalid databases."));
2458  }
2459 
2460  if (!object_ownercheck(DatabaseRelationId, dboid, GetUserId()))
2462  stmt->dbname);
2463 
2464  /*
2465  * In order to avoid getting locked out and having to go through
2466  * standalone mode, we refuse to disallow connections to the database
2467  * we're currently connected to. Lockout can still happen with concurrent
2468  * sessions but the likeliness of that is not high enough to worry about.
2469  */
2470  if (!dballowconnections && dboid == MyDatabaseId)
2471  ereport(ERROR,
2472  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2473  errmsg("cannot disallow connections for current database")));
2474 
2475  /*
2476  * Build an updated tuple, perusing the information just obtained
2477  */
2478  if (distemplate)
2479  {
2480  new_record[Anum_pg_database_datistemplate - 1] = BoolGetDatum(dbistemplate);
2481  new_record_repl[Anum_pg_database_datistemplate - 1] = true;
2482  }
2483  if (dallowconnections)
2484  {
2485  new_record[Anum_pg_database_datallowconn - 1] = BoolGetDatum(dballowconnections);
2486  new_record_repl[Anum_pg_database_datallowconn - 1] = true;
2487  }
2488  if (dconnlimit)
2489  {
2490  new_record[Anum_pg_database_datconnlimit - 1] = Int32GetDatum(dbconnlimit);
2491  new_record_repl[Anum_pg_database_datconnlimit - 1] = true;
2492  }
2493 
2494  newtuple = heap_modify_tuple(tuple, RelationGetDescr(rel), new_record,
2495  new_record_nulls, new_record_repl);
2496  CatalogTupleUpdate(rel, &tuple->t_self, newtuple);
2497  UnlockTuple(rel, &tuple->t_self, InplaceUpdateTupleLock);
2498 
2499  InvokeObjectPostAlterHook(DatabaseRelationId, dboid, 0);
2500 
2501  systable_endscan(scan);
2502 
2503  /* Close pg_database, but keep lock till commit */
2504  table_close(rel, NoLock);
2505 
2506  return dboid;
2507 }
@ ACLCHECK_NOT_OWNER
Definition: acl.h:185
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:2622
bool object_ownercheck(Oid classid, Oid objectid, Oid roleid)
Definition: aclchk.c:4064
bool database_is_invalid_form(Form_pg_database datform)
Definition: dbcommands.c:3211
static void movedb(const char *dbname, const char *tblspcname)
Definition: dbcommands.c:1977
int32 defGetInt32(DefElem *def)
Definition: define.c:162
bool defGetBoolean(DefElem *def)
Definition: define.c:107
char * defGetString(DefElem *def)
Definition: define.c:48
void errorConflictingDefElem(DefElem *defel, ParseState *pstate)
Definition: define.c:384
int errhint(const char *fmt,...)
Definition: elog.c:1317
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define FATAL
Definition: elog.h:41
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:606
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:513
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:387
Oid MyDatabaseId
Definition: globals.c:93
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, const Datum *replValues, const bool *replIsnull, const bool *doReplace)
Definition: heaptuple.c:1209
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define GETSTRUCT(TUP)
Definition: htup_details.h:653
#define stmt
Definition: indent_codes.h:59
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:313
void LockTuple(Relation relation, ItemPointer tid, LOCKMODE lockmode)
Definition: lmgr.c:557
void UnlockTuple(Relation relation, ItemPointer tid, LOCKMODE lockmode)
Definition: lmgr.c:594
#define NoLock
Definition: lockdefs.h:34
#define InplaceUpdateTupleLock
Definition: lockdefs.h:48
#define RowExclusiveLock
Definition: lockdefs.h:38
Oid GetUserId(void)
Definition: miscinit.c:524
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:197
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:106
@ OBJECT_DATABASE
Definition: parsenodes.h:2277
FormData_pg_database * Form_pg_database
Definition: pg_database.h:96
#define DATCONNLIMIT_UNLIMITED
Definition: pg_database.h:117
#define lfirst(lc)
Definition: pg_list.h:172
static int list_length(const List *l)
Definition: pg_list.h:152
uintptr_t Datum
Definition: postgres.h:64
static Datum BoolGetDatum(bool X)
Definition: postgres.h:102
static Datum CStringGetDatum(const char *X)
Definition: postgres.h:350
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:212
#define InvalidOid
Definition: postgres_ext.h:36
unsigned int Oid
Definition: postgres_ext.h:31
#define RelationGetDescr(relation)
Definition: rel.h:531
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:817
ParseLoc location
Definition: parsenodes.h:821
Node * arg
Definition: parsenodes.h:818
ItemPointerData t_self
Definition: htup.h:65
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:40
void PreventInTransactionBlock(bool isTopLevel, const char *stmtType)
Definition: xact.c:3640

References aclcheck_error(), ACLCHECK_NOT_OWNER, DefElem::arg, BoolGetDatum(), BTEqualStrategyNumber, CatalogTupleUpdate(), CStringGetDatum(), database_is_invalid_form(), DATCONNLIMIT_UNLIMITED, defGetBoolean(), defGetInt32(), defGetString(), DefElem::defname, ereport, errcode(), errhint(), errmsg(), ERROR, errorConflictingDefElem(), FATAL, GETSTRUCT, GetUserId(), heap_modify_tuple(), HeapTupleIsValid, InplaceUpdateTupleLock, Int32GetDatum(), InvalidOid, InvokeObjectPostAlterHook, lfirst, list_length(), DefElem::location, LockTuple(), movedb(), MyDatabaseId, NoLock, OBJECT_DATABASE, object_ownercheck(), parser_errposition(), PreventInTransactionBlock(), RelationGetDescr, RowExclusiveLock, ScanKeyInit(), stmt, systable_beginscan(), systable_endscan(), systable_getnext(), HeapTupleData::t_self, table_close(), table_open(), and UnlockTuple().

Referenced by standard_ProcessUtility().

◆ AlterDatabaseOwner()

ObjectAddress AlterDatabaseOwner ( const char *  dbname,
Oid  newOwnerId 
)

Definition at line 2637 of file dbcommands.c.

2638 {
2639  Oid db_id;
2640  HeapTuple tuple;
2641  Relation rel;
2642  ScanKeyData scankey;
2643  SysScanDesc scan;
2644  Form_pg_database datForm;
2645  ObjectAddress address;
2646 
2647  /*
2648  * Get the old tuple. We don't need a lock on the database per se,
2649  * because we're not going to do anything that would mess up incoming
2650  * connections.
2651  */
2652  rel = table_open(DatabaseRelationId, RowExclusiveLock);
2653  ScanKeyInit(&scankey,
2654  Anum_pg_database_datname,
2655  BTEqualStrategyNumber, F_NAMEEQ,
2657  scan = systable_beginscan(rel, DatabaseNameIndexId, true,
2658  NULL, 1, &scankey);
2659  tuple = systable_getnext(scan);
2660  if (!HeapTupleIsValid(tuple))
2661  ereport(ERROR,
2662  (errcode(ERRCODE_UNDEFINED_DATABASE),
2663  errmsg("database \"%s\" does not exist", dbname)));
2664 
2665  datForm = (Form_pg_database) GETSTRUCT(tuple);
2666  db_id = datForm->oid;
2667 
2668  /*
2669  * If the new owner is the same as the existing owner, consider the
2670  * command to have succeeded. This is to be consistent with other
2671  * objects.
2672  */
2673  if (datForm->datdba != newOwnerId)
2674  {
2675  Datum repl_val[Natts_pg_database];
2676  bool repl_null[Natts_pg_database] = {0};
2677  bool repl_repl[Natts_pg_database] = {0};
2678  Acl *newAcl;
2679  Datum aclDatum;
2680  bool isNull;
2681  HeapTuple newtuple;
2682 
2683  /* Otherwise, must be owner of the existing object */
2684  if (!object_ownercheck(DatabaseRelationId, db_id, GetUserId()))
2686  dbname);
2687 
2688  /* Must be able to become new owner */
2689  check_can_set_role(GetUserId(), newOwnerId);
2690 
2691  /*
2692  * must have createdb rights
2693  *
2694  * NOTE: This is different from other alter-owner checks in that the
2695  * current user is checked for createdb privileges instead of the
2696  * destination owner. This is consistent with the CREATE case for
2697  * databases. Because superusers will always have this right, we need
2698  * no special case for them.
2699  */
2700  if (!have_createdb_privilege())
2701  ereport(ERROR,
2702  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
2703  errmsg("permission denied to change owner of database")));
2704 
2705  LockTuple(rel, &tuple->t_self, InplaceUpdateTupleLock);
2706 
2707  repl_repl[Anum_pg_database_datdba - 1] = true;
2708  repl_val[Anum_pg_database_datdba - 1] = ObjectIdGetDatum(newOwnerId);
2709 
2710  /*
2711  * Determine the modified ACL for the new owner. This is only
2712  * necessary when the ACL is non-null.
2713  */
2714  aclDatum = heap_getattr(tuple,
2715  Anum_pg_database_datacl,
2716  RelationGetDescr(rel),
2717  &isNull);
2718  if (!isNull)
2719  {
2720  newAcl = aclnewowner(DatumGetAclP(aclDatum),
2721  datForm->datdba, newOwnerId);
2722  repl_repl[Anum_pg_database_datacl - 1] = true;
2723  repl_val[Anum_pg_database_datacl - 1] = PointerGetDatum(newAcl);
2724  }
2725 
2726  newtuple = heap_modify_tuple(tuple, RelationGetDescr(rel), repl_val, repl_null, repl_repl);
2727  CatalogTupleUpdate(rel, &newtuple->t_self, newtuple);
2728  UnlockTuple(rel, &tuple->t_self, InplaceUpdateTupleLock);
2729 
2730  heap_freetuple(newtuple);
2731 
2732  /* Update owner dependency reference */
2733  changeDependencyOnOwner(DatabaseRelationId, db_id, newOwnerId);
2734  }
2735 
2736  InvokeObjectPostAlterHook(DatabaseRelationId, db_id, 0);
2737 
2738  ObjectAddressSet(address, DatabaseRelationId, db_id);
2739 
2740  systable_endscan(scan);
2741 
2742  /* Close pg_database, but keep lock till commit */
2743  table_close(rel, NoLock);
2744 
2745  return address;
2746 }
Acl * aclnewowner(const Acl *old_acl, Oid oldOwnerId, Oid newOwnerId)
Definition: acl.c:1103
void check_can_set_role(Oid member, Oid role)
Definition: acl.c:5325
#define DatumGetAclP(X)
Definition: acl.h:120
bool have_createdb_privilege(void)
Definition: dbcommands.c:2952
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1434
static Datum heap_getattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
Definition: htup_details.h:792
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
void changeDependencyOnOwner(Oid classId, Oid objectId, Oid newOwnerId)
Definition: pg_shdepend.c:316
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:322
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
char * dbname
Definition: streamutil.c:50

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

Referenced by ExecAlterOwnerStmt().

◆ AlterDatabaseRefreshColl()

ObjectAddress AlterDatabaseRefreshColl ( AlterDatabaseRefreshCollStmt stmt)

Definition at line 2514 of file dbcommands.c.

2515 {
2516  Relation rel;
2517  ScanKeyData scankey;
2518  SysScanDesc scan;
2519  Oid db_id;
2520  HeapTuple tuple;
2521  Form_pg_database datForm;
2522  ObjectAddress address;
2523  Datum datum;
2524  bool isnull;
2525  char *oldversion;
2526  char *newversion;
2527 
2528  rel = table_open(DatabaseRelationId, RowExclusiveLock);
2529  ScanKeyInit(&scankey,
2530  Anum_pg_database_datname,
2531  BTEqualStrategyNumber, F_NAMEEQ,
2532  CStringGetDatum(stmt->dbname));
2533  scan = systable_beginscan(rel, DatabaseNameIndexId, true,
2534  NULL, 1, &scankey);
2535  tuple = systable_getnext(scan);
2536  if (!HeapTupleIsValid(tuple))
2537  ereport(ERROR,
2538  (errcode(ERRCODE_UNDEFINED_DATABASE),
2539  errmsg("database \"%s\" does not exist", stmt->dbname)));
2540 
2541  datForm = (Form_pg_database) GETSTRUCT(tuple);
2542  db_id = datForm->oid;
2543 
2544  if (!object_ownercheck(DatabaseRelationId, db_id, GetUserId()))
2546  stmt->dbname);
2547  LockTuple(rel, &tuple->t_self, InplaceUpdateTupleLock);
2548 
2549  datum = heap_getattr(tuple, Anum_pg_database_datcollversion, RelationGetDescr(rel), &isnull);
2550  oldversion = isnull ? NULL : TextDatumGetCString(datum);
2551 
2552  if (datForm->datlocprovider == COLLPROVIDER_LIBC)
2553  {
2554  datum = heap_getattr(tuple, Anum_pg_database_datcollate, RelationGetDescr(rel), &isnull);
2555  if (isnull)
2556  elog(ERROR, "unexpected null in pg_database");
2557  }
2558  else
2559  {
2560  datum = heap_getattr(tuple, Anum_pg_database_datlocale, RelationGetDescr(rel), &isnull);
2561  if (isnull)
2562  elog(ERROR, "unexpected null in pg_database");
2563  }
2564 
2565  newversion = get_collation_actual_version(datForm->datlocprovider,
2566  TextDatumGetCString(datum));
2567 
2568  /* cannot change from NULL to non-NULL or vice versa */
2569  if ((!oldversion && newversion) || (oldversion && !newversion))
2570  elog(ERROR, "invalid collation version change");
2571  else if (oldversion && newversion && strcmp(newversion, oldversion) != 0)
2572  {
2573  bool nulls[Natts_pg_database] = {0};
2574  bool replaces[Natts_pg_database] = {0};
2575  Datum values[Natts_pg_database] = {0};
2576  HeapTuple newtuple;
2577 
2578  ereport(NOTICE,
2579  (errmsg("changing version from %s to %s",
2580  oldversion, newversion)));
2581 
2582  values[Anum_pg_database_datcollversion - 1] = CStringGetTextDatum(newversion);
2583  replaces[Anum_pg_database_datcollversion - 1] = true;
2584 
2585  newtuple = heap_modify_tuple(tuple, RelationGetDescr(rel),
2586  values, nulls, replaces);
2587  CatalogTupleUpdate(rel, &tuple->t_self, newtuple);
2588  heap_freetuple(newtuple);
2589  }
2590  else
2591  ereport(NOTICE,
2592  (errmsg("version has not changed")));
2593  UnlockTuple(rel, &tuple->t_self, InplaceUpdateTupleLock);
2594 
2595  InvokeObjectPostAlterHook(DatabaseRelationId, db_id, 0);
2596 
2597  ObjectAddressSet(address, DatabaseRelationId, db_id);
2598 
2599  systable_endscan(scan);
2600 
2601  table_close(rel, NoLock);
2602 
2603  return address;
2604 }
static Datum values[MAXATTR]
Definition: bootstrap.c:151
#define CStringGetTextDatum(s)
Definition: builtins.h:97
#define TextDatumGetCString(d)
Definition: builtins.h:98
#define elog(elevel,...)
Definition: elog.h:225
#define NOTICE
Definition: elog.h:35
char * get_collation_actual_version(char collprovider, const char *collcollate)
Definition: pg_locale.c:1369

References aclcheck_error(), ACLCHECK_NOT_OWNER, BTEqualStrategyNumber, CatalogTupleUpdate(), CStringGetDatum(), CStringGetTextDatum, elog, ereport, errcode(), errmsg(), ERROR, get_collation_actual_version(), GETSTRUCT, GetUserId(), heap_freetuple(), heap_getattr(), heap_modify_tuple(), HeapTupleIsValid, InplaceUpdateTupleLock, InvokeObjectPostAlterHook, LockTuple(), NoLock, NOTICE, OBJECT_DATABASE, object_ownercheck(), ObjectAddressSet, RelationGetDescr, RowExclusiveLock, ScanKeyInit(), stmt, systable_beginscan(), systable_endscan(), systable_getnext(), HeapTupleData::t_self, table_close(), table_open(), TextDatumGetCString, UnlockTuple(), and values.

Referenced by standard_ProcessUtility().

◆ AlterDatabaseSet()

Oid AlterDatabaseSet ( AlterDatabaseSetStmt stmt)

Definition at line 2611 of file dbcommands.c.

2612 {
2613  Oid datid = get_database_oid(stmt->dbname, false);
2614 
2615  /*
2616  * Obtain a lock on the database and make sure it didn't go away in the
2617  * meantime.
2618  */
2619  shdepLockAndCheckObject(DatabaseRelationId, datid);
2620 
2621  if (!object_ownercheck(DatabaseRelationId, datid, GetUserId()))
2623  stmt->dbname);
2624 
2625  AlterSetting(datid, InvalidOid, stmt->setstmt);
2626 
2627  UnlockSharedObject(DatabaseRelationId, datid, 0, AccessShareLock);
2628 
2629  return datid;
2630 }
Oid get_database_oid(const char *dbname, bool missing_ok)
Definition: dbcommands.c:3140
void UnlockSharedObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition: lmgr.c:1131
#define AccessShareLock
Definition: lockdefs.h:36
void AlterSetting(Oid databaseid, Oid roleid, VariableSetStmt *setstmt)
void shdepLockAndCheckObject(Oid classId, Oid objectId)
Definition: pg_shdepend.c:1211

References AccessShareLock, aclcheck_error(), ACLCHECK_NOT_OWNER, AlterSetting(), get_database_oid(), GetUserId(), InvalidOid, OBJECT_DATABASE, object_ownercheck(), shdepLockAndCheckObject(), stmt, and UnlockSharedObject().

Referenced by standard_ProcessUtility().

◆ check_db_file_conflict()

static bool check_db_file_conflict ( Oid  db_id)
static

Definition at line 3067 of file dbcommands.c.

3068 {
3069  bool result = false;
3070  Relation rel;
3071  TableScanDesc scan;
3072  HeapTuple tuple;
3073 
3074  rel = table_open(TableSpaceRelationId, AccessShareLock);
3075  scan = table_beginscan_catalog(rel, 0, NULL);
3076  while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
3077  {
3078  Form_pg_tablespace spcform = (Form_pg_tablespace) GETSTRUCT(tuple);
3079  Oid dsttablespace = spcform->oid;
3080  char *dstpath;
3081  struct stat st;
3082 
3083  /* Don't mess with the global tablespace */
3084  if (dsttablespace == GLOBALTABLESPACE_OID)
3085  continue;
3086 
3087  dstpath = GetDatabasePath(db_id, dsttablespace);
3088 
3089  if (lstat(dstpath, &st) == 0)
3090  {
3091  /* Found a conflicting file (or directory, whatever) */
3092  pfree(dstpath);
3093  result = true;
3094  break;
3095  }
3096 
3097  pfree(dstpath);
3098  }
3099 
3100  table_endscan(scan);
3102 
3103  return result;
3104 }
static char dstpath[MAXPGPATH]
Definition: file_ops.c:32
HeapTuple heap_getnext(TableScanDesc sscan, ScanDirection direction)
Definition: heapam.c:1243
void pfree(void *pointer)
Definition: mcxt.c:1521
FormData_pg_tablespace * Form_pg_tablespace
Definition: pg_tablespace.h:48
char * GetDatabasePath(Oid dbOid, Oid spcOid)
Definition: relpath.c:110
@ ForwardScanDirection
Definition: sdir.h:28
TableScanDesc table_beginscan_catalog(Relation relation, int nkeys, struct ScanKeyData *key)
Definition: tableam.c:112
static void table_endscan(TableScanDesc scan)
Definition: tableam.h:1028
#define lstat(path, sb)
Definition: win32_port.h:285

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 1570 of file dbcommands.c.

1571 {
1572  int ctype_encoding = pg_get_encoding_from_locale(ctype, true);
1573  int collate_encoding = pg_get_encoding_from_locale(collate, true);
1574 
1575  if (!(ctype_encoding == encoding ||
1576  ctype_encoding == PG_SQL_ASCII ||
1577  ctype_encoding == -1 ||
1578 #ifdef WIN32
1579  encoding == PG_UTF8 ||
1580 #endif
1581  (encoding == PG_SQL_ASCII && superuser())))
1582  ereport(ERROR,
1583  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1584  errmsg("encoding \"%s\" does not match locale \"%s\"",
1586  ctype),
1587  errdetail("The chosen LC_CTYPE setting requires encoding \"%s\".",
1588  pg_encoding_to_char(ctype_encoding))));
1589 
1590  if (!(collate_encoding == encoding ||
1591  collate_encoding == PG_SQL_ASCII ||
1592  collate_encoding == -1 ||
1593 #ifdef WIN32
1594  encoding == PG_UTF8 ||
1595 #endif
1596  (encoding == PG_SQL_ASCII && superuser())))
1597  ereport(ERROR,
1598  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1599  errmsg("encoding \"%s\" does not match locale \"%s\"",
1601  collate),
1602  errdetail("The chosen LC_COLLATE setting requires encoding \"%s\".",
1603  pg_encoding_to_char(collate_encoding))));
1604 }
int errdetail(const char *fmt,...)
Definition: elog.c:1203
int32 encoding
Definition: pg_database.h:41
@ PG_SQL_ASCII
Definition: pg_wchar.h:226
@ PG_UTF8
Definition: pg_wchar.h:232
#define pg_encoding_to_char
Definition: pg_wchar.h:630
int pg_get_encoding_from_locale(const char *ctype, bool write_message)
Definition: chklocale.c:301
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().

◆ CreateDatabaseUsingFileCopy()

static void CreateDatabaseUsingFileCopy ( Oid  src_dboid,
Oid  dst_dboid,
Oid  src_tsid,
Oid  dst_tsid 
)
static

Definition at line 550 of file dbcommands.c.

552 {
553  TableScanDesc scan;
554  Relation rel;
555  HeapTuple tuple;
556 
557  /*
558  * Force a checkpoint before starting the copy. This will force all dirty
559  * buffers, including those of unlogged tables, out to disk, to ensure
560  * source database is up-to-date on disk for the copy.
561  * FlushDatabaseBuffers() would suffice for that, but we also want to
562  * process any pending unlink requests. Otherwise, if a checkpoint
563  * happened while we're copying files, a file might be deleted just when
564  * we're about to copy it, causing the lstat() call in copydir() to fail
565  * with ENOENT.
566  *
567  * In binary upgrade mode, we can skip this checkpoint because pg_upgrade
568  * is careful to ensure that template0 is fully written to disk prior to
569  * any CREATE DATABASE commands.
570  */
571  if (!IsBinaryUpgrade)
574 
575  /*
576  * Iterate through all tablespaces of the template database, and copy each
577  * one to the new database.
578  */
579  rel = table_open(TableSpaceRelationId, AccessShareLock);
580  scan = table_beginscan_catalog(rel, 0, NULL);
581  while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
582  {
583  Form_pg_tablespace spaceform = (Form_pg_tablespace) GETSTRUCT(tuple);
584  Oid srctablespace = spaceform->oid;
585  Oid dsttablespace;
586  char *srcpath;
587  char *dstpath;
588  struct stat st;
589 
590  /* No need to copy global tablespace */
591  if (srctablespace == GLOBALTABLESPACE_OID)
592  continue;
593 
594  srcpath = GetDatabasePath(src_dboid, srctablespace);
595 
596  if (stat(srcpath, &st) < 0 || !S_ISDIR(st.st_mode) ||
597  directory_is_empty(srcpath))
598  {
599  /* Assume we can ignore it */
600  pfree(srcpath);
601  continue;
602  }
603 
604  if (srctablespace == src_tsid)
605  dsttablespace = dst_tsid;
606  else
607  dsttablespace = srctablespace;
608 
609  dstpath = GetDatabasePath(dst_dboid, dsttablespace);
610 
611  /*
612  * Copy this subdirectory to the new location
613  *
614  * We don't need to copy subdirectories
615  */
616  copydir(srcpath, dstpath, false);
617 
618  /* Record the filesystem change in XLOG */
619  {
621 
622  xlrec.db_id = dst_dboid;
623  xlrec.tablespace_id = dsttablespace;
624  xlrec.src_db_id = src_dboid;
625  xlrec.src_tablespace_id = srctablespace;
626 
627  XLogBeginInsert();
628  XLogRegisterData((char *) &xlrec,
630 
631  (void) XLogInsert(RM_DBASE_ID,
633  }
634  pfree(srcpath);
635  pfree(dstpath);
636  }
637  table_endscan(scan);
639 
640  /*
641  * We force a checkpoint before committing. This effectively means that
642  * committed XLOG_DBASE_CREATE_FILE_COPY operations will never need to be
643  * replayed (at least not in ordinary crash recovery; we still have to
644  * make the XLOG entry for the benefit of PITR operations). This avoids
645  * two nasty scenarios:
646  *
647  * #1: At wal_level=minimal, we don't XLOG the contents of newly created
648  * relfilenodes; therefore the drop-and-recreate-whole-directory behavior
649  * of DBASE_CREATE replay would lose such files created in the new
650  * database between our commit and the next checkpoint.
651  *
652  * #2: Since we have to recopy the source database during DBASE_CREATE
653  * replay, we run the risk of copying changes in it that were committed
654  * after the original CREATE DATABASE command but before the system crash
655  * that led to the replay. This is at least unexpected and at worst could
656  * lead to inconsistencies, eg duplicate table names.
657  *
658  * (Both of these were real bugs in releases 8.0 through 8.0.3.)
659  *
660  * In PITR replay, the first of these isn't an issue, and the second is
661  * only a risk if the CREATE DATABASE and subsequent template database
662  * change both occur while a base backup is being taken. There doesn't
663  * seem to be much we can do about that except document it as a
664  * limitation.
665  *
666  * In binary upgrade mode, we can skip this checkpoint because neither of
667  * these problems applies: we don't ever replay the WAL generated during
668  * pg_upgrade, and we don't support taking base backups during pg_upgrade
669  * (not to mention that we don't concurrently modify template0, either).
670  *
671  * See CreateDatabaseUsingWalLog() for a less cheesy CREATE DATABASE
672  * strategy that avoids these problems.
673  */
674  if (!IsBinaryUpgrade)
677 }
bool directory_is_empty(const char *path)
Definition: tablespace.c:853
void RequestCheckpoint(int flags)
Definition: checkpointer.c:952
void copydir(const char *fromdir, const char *todir, bool recurse)
Definition: copydir.c:37
#define XLOG_DBASE_CREATE_FILE_COPY
bool IsBinaryUpgrade
Definition: globals.c:120
#define stat
Definition: win32_port.h:284
#define S_ISDIR(m)
Definition: win32_port.h:325
#define CHECKPOINT_FLUSH_ALL
Definition: xlog.h:143
#define CHECKPOINT_FORCE
Definition: xlog.h:142
#define CHECKPOINT_WAIT
Definition: xlog.h:145
#define CHECKPOINT_IMMEDIATE
Definition: xlog.h:141
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:474
void XLogRegisterData(const char *data, uint32 len)
Definition: xloginsert.c:364
void XLogBeginInsert(void)
Definition: xloginsert.c:149
#define XLR_SPECIAL_REL_UPDATE
Definition: xlogrecord.h:82

References AccessShareLock, CHECKPOINT_FLUSH_ALL, CHECKPOINT_FORCE, CHECKPOINT_IMMEDIATE, CHECKPOINT_WAIT, copydir(), xl_dbase_create_file_copy_rec::db_id, directory_is_empty(), dstpath, ForwardScanDirection, GetDatabasePath(), GETSTRUCT, heap_getnext(), IsBinaryUpgrade, pfree(), RequestCheckpoint(), S_ISDIR, xl_dbase_create_file_copy_rec::src_db_id, xl_dbase_create_file_copy_rec::src_tablespace_id, stat::st_mode, stat, table_beginscan_catalog(), table_close(), table_endscan(), table_open(), xl_dbase_create_file_copy_rec::tablespace_id, XLOG_DBASE_CREATE_FILE_COPY, XLogBeginInsert(), XLogInsert(), XLogRegisterData(), and XLR_SPECIAL_REL_UPDATE.

Referenced by createdb().

◆ CreateDatabaseUsingWalLog()

static void CreateDatabaseUsingWalLog ( Oid  src_dboid,
Oid  dst_dboid,
Oid  src_tsid,
Oid  dst_tsid 
)
static

Definition at line 148 of file dbcommands.c.

150 {
151  char *srcpath;
152  char *dstpath;
153  List *rlocatorlist = NULL;
154  ListCell *cell;
155  LockRelId srcrelid;
156  LockRelId dstrelid;
157  RelFileLocator srcrlocator;
158  RelFileLocator dstrlocator;
159  CreateDBRelInfo *relinfo;
160 
161  /* Get source and destination database paths. */
162  srcpath = GetDatabasePath(src_dboid, src_tsid);
163  dstpath = GetDatabasePath(dst_dboid, dst_tsid);
164 
165  /* Create database directory and write PG_VERSION file. */
166  CreateDirAndVersionFile(dstpath, dst_dboid, dst_tsid, false);
167 
168  /* Copy relmap file from source database to the destination database. */
169  RelationMapCopy(dst_dboid, dst_tsid, srcpath, dstpath);
170 
171  /* Get list of relfilelocators to copy from the source database. */
172  rlocatorlist = ScanSourceDatabasePgClass(src_tsid, src_dboid, srcpath);
173  Assert(rlocatorlist != NIL);
174 
175  /*
176  * Database IDs will be the same for all relations so set them before
177  * entering the loop.
178  */
179  srcrelid.dbId = src_dboid;
180  dstrelid.dbId = dst_dboid;
181 
182  /* Loop over our list of relfilelocators and copy each one. */
183  foreach(cell, rlocatorlist)
184  {
185  relinfo = lfirst(cell);
186  srcrlocator = relinfo->rlocator;
187 
188  /*
189  * If the relation is from the source db's default tablespace then we
190  * need to create it in the destination db's default tablespace.
191  * Otherwise, we need to create in the same tablespace as it is in the
192  * source database.
193  */
194  if (srcrlocator.spcOid == src_tsid)
195  dstrlocator.spcOid = dst_tsid;
196  else
197  dstrlocator.spcOid = srcrlocator.spcOid;
198 
199  dstrlocator.dbOid = dst_dboid;
200  dstrlocator.relNumber = srcrlocator.relNumber;
201 
202  /*
203  * Acquire locks on source and target relations before copying.
204  *
205  * We typically do not read relation data into shared_buffers without
206  * holding a relation lock. It's unclear what could go wrong if we
207  * skipped it in this case, because nobody can be modifying either the
208  * source or destination database at this point, and we have locks on
209  * both databases, too, but let's take the conservative route.
210  */
211  dstrelid.relId = srcrelid.relId = relinfo->reloid;
212  LockRelationId(&srcrelid, AccessShareLock);
213  LockRelationId(&dstrelid, AccessShareLock);
214 
215  /* Copy relation storage from source to the destination. */
216  CreateAndCopyRelationData(srcrlocator, dstrlocator, relinfo->permanent);
217 
218  /* Release the relation locks. */
219  UnlockRelationId(&srcrelid, AccessShareLock);
220  UnlockRelationId(&dstrelid, AccessShareLock);
221  }
222 
223  pfree(srcpath);
224  pfree(dstpath);
225  list_free_deep(rlocatorlist);
226 }
void CreateAndCopyRelationData(RelFileLocator src_rlocator, RelFileLocator dst_rlocator, bool permanent)
Definition: bufmgr.c:4798
#define Assert(condition)
Definition: c.h:812
static void CreateDirAndVersionFile(char *dbpath, Oid dbid, Oid tsid, bool isRedo)
Definition: dbcommands.c:456
static List * ScanSourceDatabasePgClass(Oid tbid, Oid dbid, char *srcpath)
Definition: dbcommands.c:250
void list_free_deep(List *list)
Definition: list.c:1560
void UnlockRelationId(LockRelId *relid, LOCKMODE lockmode)
Definition: lmgr.c:211
void LockRelationId(LockRelId *relid, LOCKMODE lockmode)
Definition: lmgr.c:183
#define NIL
Definition: pg_list.h:68
void RelationMapCopy(Oid dbid, Oid tsid, char *srcdbpath, char *dstdbpath)
Definition: relmapper.c:292
RelFileLocator rlocator
Definition: dbcommands.c:106
Definition: pg_list.h:54
Definition: rel.h:39
Oid relId
Definition: rel.h:40
Oid dbId
Definition: rel.h:41
RelFileNumber relNumber

References AccessShareLock, Assert, CreateAndCopyRelationData(), CreateDirAndVersionFile(), LockRelId::dbId, RelFileLocator::dbOid, dstpath, GetDatabasePath(), lfirst, list_free_deep(), LockRelationId(), NIL, CreateDBRelInfo::permanent, pfree(), RelationMapCopy(), LockRelId::relId, RelFileLocator::relNumber, CreateDBRelInfo::reloid, CreateDBRelInfo::rlocator, ScanSourceDatabasePgClass(), RelFileLocator::spcOid, and UnlockRelationId().

Referenced by createdb().

◆ createdb()

Oid createdb ( ParseState pstate,
const CreatedbStmt stmt 
)

Definition at line 683 of file dbcommands.c.

684 {
685  Oid src_dboid;
686  Oid src_owner;
687  int src_encoding = -1;
688  char *src_collate = NULL;
689  char *src_ctype = NULL;
690  char *src_locale = NULL;
691  char *src_icurules = NULL;
692  char src_locprovider = '\0';
693  char *src_collversion = NULL;
694  bool src_istemplate;
695  bool src_hasloginevt = false;
696  bool src_allowconn;
697  TransactionId src_frozenxid = InvalidTransactionId;
698  MultiXactId src_minmxid = InvalidMultiXactId;
699  Oid src_deftablespace;
700  volatile Oid dst_deftablespace;
701  Relation pg_database_rel;
702  HeapTuple tuple;
703  Datum new_record[Natts_pg_database] = {0};
704  bool new_record_nulls[Natts_pg_database] = {0};
705  Oid dboid = InvalidOid;
706  Oid datdba;
707  ListCell *option;
708  DefElem *tablespacenameEl = NULL;
709  DefElem *ownerEl = NULL;
710  DefElem *templateEl = NULL;
711  DefElem *encodingEl = NULL;
712  DefElem *localeEl = NULL;
713  DefElem *builtinlocaleEl = NULL;
714  DefElem *collateEl = NULL;
715  DefElem *ctypeEl = NULL;
716  DefElem *iculocaleEl = NULL;
717  DefElem *icurulesEl = NULL;
718  DefElem *locproviderEl = NULL;
719  DefElem *istemplateEl = NULL;
720  DefElem *allowconnectionsEl = NULL;
721  DefElem *connlimitEl = NULL;
722  DefElem *collversionEl = NULL;
723  DefElem *strategyEl = NULL;
724  char *dbname = stmt->dbname;
725  char *dbowner = NULL;
726  const char *dbtemplate = NULL;
727  char *dbcollate = NULL;
728  char *dbctype = NULL;
729  const char *dblocale = NULL;
730  char *dbicurules = NULL;
731  char dblocprovider = '\0';
732  char *canonname;
733  int encoding = -1;
734  bool dbistemplate = false;
735  bool dballowconnections = true;
736  int dbconnlimit = DATCONNLIMIT_UNLIMITED;
737  char *dbcollversion = NULL;
738  int notherbackends;
739  int npreparedxacts;
740  CreateDBStrategy dbstrategy = CREATEDB_WAL_LOG;
742 
743  /* Extract options from the statement node tree */
744  foreach(option, stmt->options)
745  {
746  DefElem *defel = (DefElem *) lfirst(option);
747 
748  if (strcmp(defel->defname, "tablespace") == 0)
749  {
750  if (tablespacenameEl)
751  errorConflictingDefElem(defel, pstate);
752  tablespacenameEl = defel;
753  }
754  else if (strcmp(defel->defname, "owner") == 0)
755  {
756  if (ownerEl)
757  errorConflictingDefElem(defel, pstate);
758  ownerEl = defel;
759  }
760  else if (strcmp(defel->defname, "template") == 0)
761  {
762  if (templateEl)
763  errorConflictingDefElem(defel, pstate);
764  templateEl = defel;
765  }
766  else if (strcmp(defel->defname, "encoding") == 0)
767  {
768  if (encodingEl)
769  errorConflictingDefElem(defel, pstate);
770  encodingEl = defel;
771  }
772  else if (strcmp(defel->defname, "locale") == 0)
773  {
774  if (localeEl)
775  errorConflictingDefElem(defel, pstate);
776  localeEl = defel;
777  }
778  else if (strcmp(defel->defname, "builtin_locale") == 0)
779  {
780  if (builtinlocaleEl)
781  errorConflictingDefElem(defel, pstate);
782  builtinlocaleEl = defel;
783  }
784  else if (strcmp(defel->defname, "lc_collate") == 0)
785  {
786  if (collateEl)
787  errorConflictingDefElem(defel, pstate);
788  collateEl = defel;
789  }
790  else if (strcmp(defel->defname, "lc_ctype") == 0)
791  {
792  if (ctypeEl)
793  errorConflictingDefElem(defel, pstate);
794  ctypeEl = defel;
795  }
796  else if (strcmp(defel->defname, "icu_locale") == 0)
797  {
798  if (iculocaleEl)
799  errorConflictingDefElem(defel, pstate);
800  iculocaleEl = defel;
801  }
802  else if (strcmp(defel->defname, "icu_rules") == 0)
803  {
804  if (icurulesEl)
805  errorConflictingDefElem(defel, pstate);
806  icurulesEl = defel;
807  }
808  else if (strcmp(defel->defname, "locale_provider") == 0)
809  {
810  if (locproviderEl)
811  errorConflictingDefElem(defel, pstate);
812  locproviderEl = defel;
813  }
814  else if (strcmp(defel->defname, "is_template") == 0)
815  {
816  if (istemplateEl)
817  errorConflictingDefElem(defel, pstate);
818  istemplateEl = defel;
819  }
820  else if (strcmp(defel->defname, "allow_connections") == 0)
821  {
822  if (allowconnectionsEl)
823  errorConflictingDefElem(defel, pstate);
824  allowconnectionsEl = defel;
825  }
826  else if (strcmp(defel->defname, "connection_limit") == 0)
827  {
828  if (connlimitEl)
829  errorConflictingDefElem(defel, pstate);
830  connlimitEl = defel;
831  }
832  else if (strcmp(defel->defname, "collation_version") == 0)
833  {
834  if (collversionEl)
835  errorConflictingDefElem(defel, pstate);
836  collversionEl = defel;
837  }
838  else if (strcmp(defel->defname, "location") == 0)
839  {
841  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
842  errmsg("LOCATION is not supported anymore"),
843  errhint("Consider using tablespaces instead."),
844  parser_errposition(pstate, defel->location)));
845  }
846  else if (strcmp(defel->defname, "oid") == 0)
847  {
848  dboid = defGetObjectId(defel);
849 
850  /*
851  * We don't normally permit new databases to be created with
852  * system-assigned OIDs. pg_upgrade tries to preserve database
853  * OIDs, so we can't allow any database to be created with an OID
854  * that might be in use in a freshly-initialized cluster created
855  * by some future version. We assume all such OIDs will be from
856  * the system-managed OID range.
857  *
858  * As an exception, however, we permit any OID to be assigned when
859  * allow_system_table_mods=on (so that initdb can assign system
860  * OIDs to template0 and postgres) or when performing a binary
861  * upgrade (so that pg_upgrade can preserve whatever OIDs it finds
862  * in the source cluster).
863  */
864  if (dboid < FirstNormalObjectId &&
866  ereport(ERROR,
867  (errcode(ERRCODE_INVALID_PARAMETER_VALUE)),
868  errmsg("OIDs less than %u are reserved for system objects", FirstNormalObjectId));
869  }
870  else if (strcmp(defel->defname, "strategy") == 0)
871  {
872  if (strategyEl)
873  errorConflictingDefElem(defel, pstate);
874  strategyEl = defel;
875  }
876  else
877  ereport(ERROR,
878  (errcode(ERRCODE_SYNTAX_ERROR),
879  errmsg("option \"%s\" not recognized", defel->defname),
880  parser_errposition(pstate, defel->location)));
881  }
882 
883  if (ownerEl && ownerEl->arg)
884  dbowner = defGetString(ownerEl);
885  if (templateEl && templateEl->arg)
886  dbtemplate = defGetString(templateEl);
887  if (encodingEl && encodingEl->arg)
888  {
889  const char *encoding_name;
890 
891  if (IsA(encodingEl->arg, Integer))
892  {
893  encoding = defGetInt32(encodingEl);
894  encoding_name = pg_encoding_to_char(encoding);
895  if (strcmp(encoding_name, "") == 0 ||
896  pg_valid_server_encoding(encoding_name) < 0)
897  ereport(ERROR,
898  (errcode(ERRCODE_UNDEFINED_OBJECT),
899  errmsg("%d is not a valid encoding code",
900  encoding),
901  parser_errposition(pstate, encodingEl->location)));
902  }
903  else
904  {
905  encoding_name = defGetString(encodingEl);
906  encoding = pg_valid_server_encoding(encoding_name);
907  if (encoding < 0)
908  ereport(ERROR,
909  (errcode(ERRCODE_UNDEFINED_OBJECT),
910  errmsg("%s is not a valid encoding name",
911  encoding_name),
912  parser_errposition(pstate, encodingEl->location)));
913  }
914  }
915  if (localeEl && localeEl->arg)
916  {
917  dbcollate = defGetString(localeEl);
918  dbctype = defGetString(localeEl);
919  dblocale = defGetString(localeEl);
920  }
921  if (builtinlocaleEl && builtinlocaleEl->arg)
922  dblocale = defGetString(builtinlocaleEl);
923  if (collateEl && collateEl->arg)
924  dbcollate = defGetString(collateEl);
925  if (ctypeEl && ctypeEl->arg)
926  dbctype = defGetString(ctypeEl);
927  if (iculocaleEl && iculocaleEl->arg)
928  dblocale = defGetString(iculocaleEl);
929  if (icurulesEl && icurulesEl->arg)
930  dbicurules = defGetString(icurulesEl);
931  if (locproviderEl && locproviderEl->arg)
932  {
933  char *locproviderstr = defGetString(locproviderEl);
934 
935  if (pg_strcasecmp(locproviderstr, "builtin") == 0)
936  dblocprovider = COLLPROVIDER_BUILTIN;
937  else if (pg_strcasecmp(locproviderstr, "icu") == 0)
938  dblocprovider = COLLPROVIDER_ICU;
939  else if (pg_strcasecmp(locproviderstr, "libc") == 0)
940  dblocprovider = COLLPROVIDER_LIBC;
941  else
942  ereport(ERROR,
943  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
944  errmsg("unrecognized locale provider: %s",
945  locproviderstr)));
946  }
947  if (istemplateEl && istemplateEl->arg)
948  dbistemplate = defGetBoolean(istemplateEl);
949  if (allowconnectionsEl && allowconnectionsEl->arg)
950  dballowconnections = defGetBoolean(allowconnectionsEl);
951  if (connlimitEl && connlimitEl->arg)
952  {
953  dbconnlimit = defGetInt32(connlimitEl);
954  if (dbconnlimit < DATCONNLIMIT_UNLIMITED)
955  ereport(ERROR,
956  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
957  errmsg("invalid connection limit: %d", dbconnlimit)));
958  }
959  if (collversionEl)
960  dbcollversion = defGetString(collversionEl);
961 
962  /* obtain OID of proposed owner */
963  if (dbowner)
964  datdba = get_role_oid(dbowner, false);
965  else
966  datdba = GetUserId();
967 
968  /*
969  * To create a database, must have createdb privilege and must be able to
970  * become the target role (this does not imply that the target role itself
971  * must have createdb privilege). The latter provision guards against
972  * "giveaway" attacks. Note that a superuser will always have both of
973  * these privileges a fortiori.
974  */
976  ereport(ERROR,
977  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
978  errmsg("permission denied to create database")));
979 
980  check_can_set_role(GetUserId(), datdba);
981 
982  /*
983  * Lookup database (template) to be cloned, and obtain share lock on it.
984  * ShareLock allows two CREATE DATABASEs to work from the same template
985  * concurrently, while ensuring no one is busy dropping it in parallel
986  * (which would be Very Bad since we'd likely get an incomplete copy
987  * without knowing it). This also prevents any new connections from being
988  * made to the source until we finish copying it, so we can be sure it
989  * won't change underneath us.
990  */
991  if (!dbtemplate)
992  dbtemplate = "template1"; /* Default template database name */
993 
994  if (!get_db_info(dbtemplate, ShareLock,
995  &src_dboid, &src_owner, &src_encoding,
996  &src_istemplate, &src_allowconn, &src_hasloginevt,
997  &src_frozenxid, &src_minmxid, &src_deftablespace,
998  &src_collate, &src_ctype, &src_locale, &src_icurules, &src_locprovider,
999  &src_collversion))
1000  ereport(ERROR,
1001  (errcode(ERRCODE_UNDEFINED_DATABASE),
1002  errmsg("template database \"%s\" does not exist",
1003  dbtemplate)));
1004 
1005  /*
1006  * If the source database was in the process of being dropped, we can't
1007  * use it as a template.
1008  */
1009  if (database_is_invalid_oid(src_dboid))
1010  ereport(ERROR,
1011  errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1012  errmsg("cannot use invalid database \"%s\" as template", dbtemplate),
1013  errhint("Use DROP DATABASE to drop invalid databases."));
1014 
1015  /*
1016  * Permission check: to copy a DB that's not marked datistemplate, you
1017  * must be superuser or the owner thereof.
1018  */
1019  if (!src_istemplate)
1020  {
1021  if (!object_ownercheck(DatabaseRelationId, src_dboid, GetUserId()))
1022  ereport(ERROR,
1023  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1024  errmsg("permission denied to copy database \"%s\"",
1025  dbtemplate)));
1026  }
1027 
1028  /* Validate the database creation strategy. */
1029  if (strategyEl && strategyEl->arg)
1030  {
1031  char *strategy;
1032 
1033  strategy = defGetString(strategyEl);
1034  if (pg_strcasecmp(strategy, "wal_log") == 0)
1035  dbstrategy = CREATEDB_WAL_LOG;
1036  else if (pg_strcasecmp(strategy, "file_copy") == 0)
1037  dbstrategy = CREATEDB_FILE_COPY;
1038  else
1039  ereport(ERROR,
1040  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1041  errmsg("invalid create database strategy \"%s\"", strategy),
1042  errhint("Valid strategies are \"wal_log\" and \"file_copy\".")));
1043  }
1044 
1045  /* If encoding or locales are defaulted, use source's setting */
1046  if (encoding < 0)
1047  encoding = src_encoding;
1048  if (dbcollate == NULL)
1049  dbcollate = src_collate;
1050  if (dbctype == NULL)
1051  dbctype = src_ctype;
1052  if (dblocprovider == '\0')
1053  dblocprovider = src_locprovider;
1054  if (dblocale == NULL)
1055  dblocale = src_locale;
1056  if (dbicurules == NULL)
1057  dbicurules = src_icurules;
1058 
1059  /* Some encodings are client only */
1061  ereport(ERROR,
1062  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1063  errmsg("invalid server encoding %d", encoding)));
1064 
1065  /* Check that the chosen locales are valid, and get canonical spellings */
1066  if (!check_locale(LC_COLLATE, dbcollate, &canonname))
1067  ereport(ERROR,
1068  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1069  errmsg("invalid LC_COLLATE locale name: \"%s\"", dbcollate),
1070  errhint("If the locale name is specific to ICU, use ICU_LOCALE.")));
1071  dbcollate = canonname;
1072  if (!check_locale(LC_CTYPE, dbctype, &canonname))
1073  ereport(ERROR,
1074  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1075  errmsg("invalid LC_CTYPE locale name: \"%s\"", dbctype),
1076  errhint("If the locale name is specific to ICU, use ICU_LOCALE.")));
1077  dbctype = canonname;
1078 
1079  check_encoding_locale_matches(encoding, dbcollate, dbctype);
1080 
1081  /* validate provider-specific parameters */
1082  if (dblocprovider != COLLPROVIDER_BUILTIN)
1083  {
1084  if (builtinlocaleEl)
1085  ereport(ERROR,
1086  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1087  errmsg("BUILTIN_LOCALE cannot be specified unless locale provider is builtin")));
1088  }
1089 
1090  if (dblocprovider != COLLPROVIDER_ICU)
1091  {
1092  if (iculocaleEl)
1093  ereport(ERROR,
1094  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1095  errmsg("ICU locale cannot be specified unless locale provider is ICU")));
1096 
1097  if (dbicurules)
1098  ereport(ERROR,
1099  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
1100  errmsg("ICU rules cannot be specified unless locale provider is ICU")));
1101  }
1102 
1103  /* validate and canonicalize locale for the provider */
1104  if (dblocprovider == COLLPROVIDER_BUILTIN)
1105  {
1106  /*
1107  * This would happen if template0 uses the libc provider but the new
1108  * database uses builtin.
1109  */
1110  if (!dblocale)
1111  ereport(ERROR,
1112  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1113  errmsg("LOCALE or BUILTIN_LOCALE must be specified")));
1114 
1115  dblocale = builtin_validate_locale(encoding, dblocale);
1116  }
1117  else if (dblocprovider == COLLPROVIDER_ICU)
1118  {
1120  ereport(ERROR,
1121  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1122  errmsg("encoding \"%s\" is not supported with ICU provider",
1124 
1125  /*
1126  * This would happen if template0 uses the libc provider but the new
1127  * database uses icu.
1128  */
1129  if (!dblocale)
1130  ereport(ERROR,
1131  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1132  errmsg("LOCALE or ICU_LOCALE must be specified")));
1133 
1134  /*
1135  * During binary upgrade, or when the locale came from the template
1136  * database, preserve locale string. Otherwise, canonicalize to a
1137  * language tag.
1138  */
1139  if (!IsBinaryUpgrade && dblocale != src_locale)
1140  {
1141  char *langtag = icu_language_tag(dblocale,
1143 
1144  if (langtag && strcmp(dblocale, langtag) != 0)
1145  {
1146  ereport(NOTICE,
1147  (errmsg("using standard form \"%s\" for ICU locale \"%s\"",
1148  langtag, dblocale)));
1149 
1150  dblocale = langtag;
1151  }
1152  }
1153 
1154  icu_validate_locale(dblocale);
1155  }
1156 
1157  /* for libc, locale comes from datcollate and datctype */
1158  if (dblocprovider == COLLPROVIDER_LIBC)
1159  dblocale = NULL;
1160 
1161  /*
1162  * Check that the new encoding and locale settings match the source
1163  * database. We insist on this because we simply copy the source data ---
1164  * any non-ASCII data would be wrongly encoded, and any indexes sorted
1165  * according to the source locale would be wrong.
1166  *
1167  * However, we assume that template0 doesn't contain any non-ASCII data
1168  * nor any indexes that depend on collation or ctype, so template0 can be
1169  * used as template for creating a database with any encoding or locale.
1170  */
1171  if (strcmp(dbtemplate, "template0") != 0)
1172  {
1173  if (encoding != src_encoding)
1174  ereport(ERROR,
1175  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1176  errmsg("new encoding (%s) is incompatible with the encoding of the template database (%s)",
1178  pg_encoding_to_char(src_encoding)),
1179  errhint("Use the same encoding as in the template database, or use template0 as template.")));
1180 
1181  if (strcmp(dbcollate, src_collate) != 0)
1182  ereport(ERROR,
1183  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1184  errmsg("new collation (%s) is incompatible with the collation of the template database (%s)",
1185  dbcollate, src_collate),
1186  errhint("Use the same collation as in the template database, or use template0 as template.")));
1187 
1188  if (strcmp(dbctype, src_ctype) != 0)
1189  ereport(ERROR,
1190  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1191  errmsg("new LC_CTYPE (%s) is incompatible with the LC_CTYPE of the template database (%s)",
1192  dbctype, src_ctype),
1193  errhint("Use the same LC_CTYPE as in the template database, or use template0 as template.")));
1194 
1195  if (dblocprovider != src_locprovider)
1196  ereport(ERROR,
1197  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1198  errmsg("new locale provider (%s) does not match locale provider of the template database (%s)",
1199  collprovider_name(dblocprovider), collprovider_name(src_locprovider)),
1200  errhint("Use the same locale provider as in the template database, or use template0 as template.")));
1201 
1202  if (dblocprovider == COLLPROVIDER_ICU)
1203  {
1204  char *val1;
1205  char *val2;
1206 
1207  Assert(dblocale);
1208  Assert(src_locale);
1209  if (strcmp(dblocale, src_locale) != 0)
1210  ereport(ERROR,
1211  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1212  errmsg("new ICU locale (%s) is incompatible with the ICU locale of the template database (%s)",
1213  dblocale, src_locale),
1214  errhint("Use the same ICU locale as in the template database, or use template0 as template.")));
1215 
1216  val1 = dbicurules;
1217  if (!val1)
1218  val1 = "";
1219  val2 = src_icurules;
1220  if (!val2)
1221  val2 = "";
1222  if (strcmp(val1, val2) != 0)
1223  ereport(ERROR,
1224  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1225  errmsg("new ICU collation rules (%s) are incompatible with the ICU collation rules of the template database (%s)",
1226  val1, val2),
1227  errhint("Use the same ICU collation rules as in the template database, or use template0 as template.")));
1228  }
1229  }
1230 
1231  /*
1232  * If we got a collation version for the template database, check that it
1233  * matches the actual OS collation version. Otherwise error; the user
1234  * needs to fix the template database first. Don't complain if a
1235  * collation version was specified explicitly as a statement option; that
1236  * is used by pg_upgrade to reproduce the old state exactly.
1237  *
1238  * (If the template database has no collation version, then either the
1239  * platform/provider does not support collation versioning, or it's
1240  * template0, for which we stipulate that it does not contain
1241  * collation-using objects.)
1242  */
1243  if (src_collversion && !collversionEl)
1244  {
1245  char *actual_versionstr;
1246  const char *locale;
1247 
1248  if (dblocprovider == COLLPROVIDER_LIBC)
1249  locale = dbcollate;
1250  else
1251  locale = dblocale;
1252 
1253  actual_versionstr = get_collation_actual_version(dblocprovider, locale);
1254  if (!actual_versionstr)
1255  ereport(ERROR,
1256  (errmsg("template database \"%s\" has a collation version, but no actual collation version could be determined",
1257  dbtemplate)));
1258 
1259  if (strcmp(actual_versionstr, src_collversion) != 0)
1260  ereport(ERROR,
1261  (errmsg("template database \"%s\" has a collation version mismatch",
1262  dbtemplate),
1263  errdetail("The template database was created using collation version %s, "
1264  "but the operating system provides version %s.",
1265  src_collversion, actual_versionstr),
1266  errhint("Rebuild all objects in the template database that use the default collation and run "
1267  "ALTER DATABASE %s REFRESH COLLATION VERSION, "
1268  "or build PostgreSQL with the right library version.",
1269  quote_identifier(dbtemplate))));
1270  }
1271 
1272  if (dbcollversion == NULL)
1273  dbcollversion = src_collversion;
1274 
1275  /*
1276  * Normally, we copy the collation version from the template database.
1277  * This last resort only applies if the template database does not have a
1278  * collation version, which is normally only the case for template0.
1279  */
1280  if (dbcollversion == NULL)
1281  {
1282  const char *locale;
1283 
1284  if (dblocprovider == COLLPROVIDER_LIBC)
1285  locale = dbcollate;
1286  else
1287  locale = dblocale;
1288 
1289  dbcollversion = get_collation_actual_version(dblocprovider, locale);
1290  }
1291 
1292  /* Resolve default tablespace for new database */
1293  if (tablespacenameEl && tablespacenameEl->arg)
1294  {
1295  char *tablespacename;
1296  AclResult aclresult;
1297 
1298  tablespacename = defGetString(tablespacenameEl);
1299  dst_deftablespace = get_tablespace_oid(tablespacename, false);
1300  /* check permissions */
1301  aclresult = object_aclcheck(TableSpaceRelationId, dst_deftablespace, GetUserId(),
1302  ACL_CREATE);
1303  if (aclresult != ACLCHECK_OK)
1304  aclcheck_error(aclresult, OBJECT_TABLESPACE,
1305  tablespacename);
1306 
1307  /* pg_global must never be the default tablespace */
1308  if (dst_deftablespace == GLOBALTABLESPACE_OID)
1309  ereport(ERROR,
1310  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1311  errmsg("pg_global cannot be used as default tablespace")));
1312 
1313  /*
1314  * If we are trying to change the default tablespace of the template,
1315  * we require that the template not have any files in the new default
1316  * tablespace. This is necessary because otherwise the copied
1317  * database would contain pg_class rows that refer to its default
1318  * tablespace both explicitly (by OID) and implicitly (as zero), which
1319  * would cause problems. For example another CREATE DATABASE using
1320  * the copied database as template, and trying to change its default
1321  * tablespace again, would yield outright incorrect results (it would
1322  * improperly move tables to the new default tablespace that should
1323  * stay in the same tablespace).
1324  */
1325  if (dst_deftablespace != src_deftablespace)
1326  {
1327  char *srcpath;
1328  struct stat st;
1329 
1330  srcpath = GetDatabasePath(src_dboid, dst_deftablespace);
1331 
1332  if (stat(srcpath, &st) == 0 &&
1333  S_ISDIR(st.st_mode) &&
1334  !directory_is_empty(srcpath))
1335  ereport(ERROR,
1336  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1337  errmsg("cannot assign new default tablespace \"%s\"",
1338  tablespacename),
1339  errdetail("There is a conflict because database \"%s\" already has some tables in this tablespace.",
1340  dbtemplate)));
1341  pfree(srcpath);
1342  }
1343  }
1344  else
1345  {
1346  /* Use template database's default tablespace */
1347  dst_deftablespace = src_deftablespace;
1348  /* Note there is no additional permission check in this path */
1349  }
1350 
1351  /*
1352  * If built with appropriate switch, whine when regression-testing
1353  * conventions for database names are violated. But don't complain during
1354  * initdb.
1355  */
1356 #ifdef ENFORCE_REGRESSION_TEST_NAME_RESTRICTIONS
1357  if (IsUnderPostmaster && strstr(dbname, "regression") == NULL)
1358  elog(WARNING, "databases created by regression test cases should have names including \"regression\"");
1359 #endif
1360 
1361  /*
1362  * Check for db name conflict. This is just to give a more friendly error
1363  * message than "unique index violation". There's a race condition but
1364  * we're willing to accept the less friendly message in that case.
1365  */
1366  if (OidIsValid(get_database_oid(dbname, true)))
1367  ereport(ERROR,
1368  (errcode(ERRCODE_DUPLICATE_DATABASE),
1369  errmsg("database \"%s\" already exists", dbname)));
1370 
1371  /*
1372  * The source DB can't have any active backends, except this one
1373  * (exception is to allow CREATE DB while connected to template1).
1374  * Otherwise we might copy inconsistent data.
1375  *
1376  * This should be last among the basic error checks, because it involves
1377  * potential waiting; we may as well throw an error first if we're gonna
1378  * throw one.
1379  */
1380  if (CountOtherDBBackends(src_dboid, &notherbackends, &npreparedxacts))
1381  ereport(ERROR,
1382  (errcode(ERRCODE_OBJECT_IN_USE),
1383  errmsg("source database \"%s\" is being accessed by other users",
1384  dbtemplate),
1385  errdetail_busy_db(notherbackends, npreparedxacts)));
1386 
1387  /*
1388  * Select an OID for the new database, checking that it doesn't have a
1389  * filename conflict with anything already existing in the tablespace
1390  * directories.
1391  */
1392  pg_database_rel = table_open(DatabaseRelationId, RowExclusiveLock);
1393 
1394  /*
1395  * If database OID is configured, check if the OID is already in use or
1396  * data directory already exists.
1397  */
1398  if (OidIsValid(dboid))
1399  {
1400  char *existing_dbname = get_database_name(dboid);
1401 
1402  if (existing_dbname != NULL)
1403  ereport(ERROR,
1404  (errcode(ERRCODE_INVALID_PARAMETER_VALUE)),
1405  errmsg("database OID %u is already in use by database \"%s\"",
1406  dboid, existing_dbname));
1407 
1408  if (check_db_file_conflict(dboid))
1409  ereport(ERROR,
1410  (errcode(ERRCODE_INVALID_PARAMETER_VALUE)),
1411  errmsg("data directory with the specified OID %u already exists", dboid));
1412  }
1413  else
1414  {
1415  /* Select an OID for the new database if is not explicitly configured. */
1416  do
1417  {
1418  dboid = GetNewOidWithIndex(pg_database_rel, DatabaseOidIndexId,
1419  Anum_pg_database_oid);
1420  } while (check_db_file_conflict(dboid));
1421  }
1422 
1423  /*
1424  * Insert a new tuple into pg_database. This establishes our ownership of
1425  * the new database name (anyone else trying to insert the same name will
1426  * block on the unique index, and fail after we commit).
1427  */
1428 
1429  Assert((dblocprovider != COLLPROVIDER_LIBC && dblocale) ||
1430  (dblocprovider == COLLPROVIDER_LIBC && !dblocale));
1431 
1432  /* Form tuple */
1433  new_record[Anum_pg_database_oid - 1] = ObjectIdGetDatum(dboid);
1434  new_record[Anum_pg_database_datname - 1] =
1436  new_record[Anum_pg_database_datdba - 1] = ObjectIdGetDatum(datdba);
1437  new_record[Anum_pg_database_encoding - 1] = Int32GetDatum(encoding);
1438  new_record[Anum_pg_database_datlocprovider - 1] = CharGetDatum(dblocprovider);
1439  new_record[Anum_pg_database_datistemplate - 1] = BoolGetDatum(dbistemplate);
1440  new_record[Anum_pg_database_datallowconn - 1] = BoolGetDatum(dballowconnections);
1441  new_record[Anum_pg_database_dathasloginevt - 1] = BoolGetDatum(src_hasloginevt);
1442  new_record[Anum_pg_database_datconnlimit - 1] = Int32GetDatum(dbconnlimit);
1443  new_record[Anum_pg_database_datfrozenxid - 1] = TransactionIdGetDatum(src_frozenxid);
1444  new_record[Anum_pg_database_datminmxid - 1] = TransactionIdGetDatum(src_minmxid);
1445  new_record[Anum_pg_database_dattablespace - 1] = ObjectIdGetDatum(dst_deftablespace);
1446  new_record[Anum_pg_database_datcollate - 1] = CStringGetTextDatum(dbcollate);
1447  new_record[Anum_pg_database_datctype - 1] = CStringGetTextDatum(dbctype);
1448  if (dblocale)
1449  new_record[Anum_pg_database_datlocale - 1] = CStringGetTextDatum(dblocale);
1450  else
1451  new_record_nulls[Anum_pg_database_datlocale - 1] = true;
1452  if (dbicurules)
1453  new_record[Anum_pg_database_daticurules - 1] = CStringGetTextDatum(dbicurules);
1454  else
1455  new_record_nulls[Anum_pg_database_daticurules - 1] = true;
1456  if (dbcollversion)
1457  new_record[Anum_pg_database_datcollversion - 1] = CStringGetTextDatum(dbcollversion);
1458  else
1459  new_record_nulls[Anum_pg_database_datcollversion - 1] = true;
1460 
1461  /*
1462  * We deliberately set datacl to default (NULL), rather than copying it
1463  * from the template database. Copying it would be a bad idea when the
1464  * owner is not the same as the template's owner.
1465  */
1466  new_record_nulls[Anum_pg_database_datacl - 1] = true;
1467 
1468  tuple = heap_form_tuple(RelationGetDescr(pg_database_rel),
1469  new_record, new_record_nulls);
1470 
1471  CatalogTupleInsert(pg_database_rel, tuple);
1472 
1473  /*
1474  * Now generate additional catalog entries associated with the new DB
1475  */
1476 
1477  /* Register owner dependency */
1478  recordDependencyOnOwner(DatabaseRelationId, dboid, datdba);
1479 
1480  /* Create pg_shdepend entries for objects within database */
1481  copyTemplateDependencies(src_dboid, dboid);
1482 
1483  /* Post creation hook for new database */
1484  InvokeObjectPostCreateHook(DatabaseRelationId, dboid, 0);
1485 
1486  /*
1487  * If we're going to be reading data for the to-be-created database into
1488  * shared_buffers, take a lock on it. Nobody should know that this
1489  * database exists yet, but it's good to maintain the invariant that an
1490  * AccessExclusiveLock on the database is sufficient to drop all of its
1491  * buffers without worrying about more being read later.
1492  *
1493  * Note that we need to do this before entering the
1494  * PG_ENSURE_ERROR_CLEANUP block below, because createdb_failure_callback
1495  * expects this lock to be held already.
1496  */
1497  if (dbstrategy == CREATEDB_WAL_LOG)
1498  LockSharedObject(DatabaseRelationId, dboid, 0, AccessShareLock);
1499 
1500  /*
1501  * Once we start copying subdirectories, we need to be able to clean 'em
1502  * up if we fail. Use an ENSURE block to make sure this happens. (This
1503  * is not a 100% solution, because of the possibility of failure during
1504  * transaction commit after we leave this routine, but it should handle
1505  * most scenarios.)
1506  */
1507  fparms.src_dboid = src_dboid;
1508  fparms.dest_dboid = dboid;
1509  fparms.strategy = dbstrategy;
1510 
1512  PointerGetDatum(&fparms));
1513  {
1514  /*
1515  * If the user has asked to create a database with WAL_LOG strategy
1516  * then call CreateDatabaseUsingWalLog, which will copy the database
1517  * at the block level and it will WAL log each copied block.
1518  * Otherwise, call CreateDatabaseUsingFileCopy that will copy the
1519  * database file by file.
1520  */
1521  if (dbstrategy == CREATEDB_WAL_LOG)
1522  CreateDatabaseUsingWalLog(src_dboid, dboid, src_deftablespace,
1523  dst_deftablespace);
1524  else
1525  CreateDatabaseUsingFileCopy(src_dboid, dboid, src_deftablespace,
1526  dst_deftablespace);
1527 
1528  /*
1529  * Close pg_database, but keep lock till commit.
1530  */
1531  table_close(pg_database_rel, NoLock);
1532 
1533  /*
1534  * Force synchronous commit, thus minimizing the window between
1535  * creation of the database files and committal of the transaction. If
1536  * we crash before committing, we'll have a DB that's taking up disk
1537  * space but is not in pg_database, which is not good.
1538  */
1539  ForceSyncCommit();
1540  }
1542  PointerGetDatum(&fparms));
1543 
1544  return dboid;
1545 }
Oid get_role_oid(const char *rolname, bool missing_ok)
Definition: acl.c:5554
AclResult
Definition: acl.h:182
@ ACLCHECK_OK
Definition: acl.h:183
AclResult object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode)
Definition: aclchk.c:3810
Oid get_tablespace_oid(const char *tablespacename, bool missing_ok)
Definition: tablespace.c:1426
TransactionId MultiXactId
Definition: c.h:616
uint32 TransactionId
Definition: c.h:606
#define OidIsValid(objectId)
Definition: c.h:729
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:419
char * get_database_name(Oid dbid)
Definition: dbcommands.c:3187
static void CreateDatabaseUsingWalLog(Oid src_dboid, Oid dst_dboid, Oid src_tsid, Oid dst_tsid)
Definition: dbcommands.c:148
void check_encoding_locale_matches(int encoding, const char *collate, const char *ctype)
Definition: dbcommands.c:1570
static int errdetail_busy_db(int notherbackends, int npreparedxacts)
Definition: dbcommands.c:3110
static bool check_db_file_conflict(Oid db_id)
Definition: dbcommands.c:3067
static void CreateDatabaseUsingFileCopy(Oid src_dboid, Oid dst_dboid, Oid src_tsid, Oid dst_tsid)
Definition: dbcommands.c:550
static bool get_db_info(const char *name, LOCKMODE lockmode, Oid *dbIdP, Oid *ownerIdP, int *encodingP, bool *dbIsTemplateP, bool *dbAllowConnP, bool *dbHasLoginEvtP, TransactionId *dbFrozenXidP, MultiXactId *dbMinMultiP, Oid *dbTablespace, char **dbCollate, char **dbCtype, char **dbLocale, char **dbIcurules, char *dbLocProvider, char **dbCollversion)
Definition: dbcommands.c:2794
static void createdb_failure_callback(int code, Datum arg)
Definition: dbcommands.c:1608
bool database_is_invalid_oid(Oid dboid)
Definition: dbcommands.c:3221
Oid defGetObjectId(DefElem *def)
Definition: define.c:219
#define WARNING
Definition: elog.h:36
bool is_encoding_supported_by_icu(int encoding)
Definition: encnames.c:461
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:641
bool IsUnderPostmaster
Definition: globals.c:119
bool allowSystemTableMods
Definition: globals.c:129
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
Definition: heaptuple.c:1116
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:233
static char * locale
Definition: initdb.c:140
#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
void LockSharedObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition: lmgr.c:1072
#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:158
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:173
@ OBJECT_TABLESPACE
Definition: parsenodes.h:2310
#define ACL_CREATE
Definition: parsenodes.h:85
int icu_validation_level
Definition: pg_locale.c:125
void icu_validate_locale(const char *loc_str)
Definition: pg_locale.c:1806
char * icu_language_tag(const char *loc_str, int elevel)
Definition: pg_locale.c:1748
const char * builtin_validate_locale(int encoding, const char *locale)
Definition: pg_locale.c:1710
bool check_locale(int category, const char *locale, char **canonname)
Definition: pg_locale.c:305
void copyTemplateDependencies(Oid templateDbId, Oid newDbId)
Definition: pg_shdepend.c:895
void recordDependencyOnOwner(Oid classId, Oid objectId, Oid owner)
Definition: pg_shdepend.c:168
#define PG_VALID_BE_ENCODING(_enc)
Definition: pg_wchar.h:281
#define pg_valid_server_encoding
Definition: pg_wchar.h:631
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
static Datum TransactionIdGetDatum(TransactionId X)
Definition: postgres.h:272
static Datum CharGetDatum(char X)
Definition: postgres.h:122
bool CountOtherDBBackends(Oid databaseId, int *nbackends, int *nprepared)
Definition: procarray.c:3750
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:12868
Definition: value.h:29
CreateDBStrategy strategy
Definition: dbcommands.c:92
#define InvalidTransactionId
Definition: transam.h:31
#define FirstNormalObjectId
Definition: transam.h:197
void ForceSyncCommit(void)
Definition: xact.c:1151

References AccessShareLock, ACL_CREATE, aclcheck_error(), ACLCHECK_OK, allowSystemTableMods, DefElem::arg, Assert, BoolGetDatum(), builtin_validate_locale(), CatalogTupleInsert(), CharGetDatum(), check_can_set_role(), check_db_file_conflict(), check_encoding_locale_matches(), check_locale(), copyTemplateDependencies(), CountOtherDBBackends(), CreateDatabaseUsingFileCopy(), CreateDatabaseUsingWalLog(), createdb_failure_callback(), CREATEDB_FILE_COPY, CREATEDB_WAL_LOG, CStringGetDatum(), CStringGetTextDatum, database_is_invalid_oid(), DATCONNLIMIT_UNLIMITED, dbname, defGetBoolean(), defGetInt32(), defGetObjectId(), defGetString(), DefElem::defname, createdb_failure_params::dest_dboid, DirectFunctionCall1, directory_is_empty(), elog, encoding, ereport, errcode(), errdetail(), errdetail_busy_db(), errhint(), errmsg(), ERROR, errorConflictingDefElem(), FirstNormalObjectId, ForceSyncCommit(), get_collation_actual_version(), get_database_name(), get_database_oid(), get_db_info(), get_role_oid(), get_tablespace_oid(), GetDatabasePath(), GetNewOidWithIndex(), GetUserId(), have_createdb_privilege(), heap_form_tuple(), icu_language_tag(), icu_validate_locale(), icu_validation_level, Int32GetDatum(), InvalidMultiXactId, InvalidOid, InvalidTransactionId, InvokeObjectPostCreateHook, is_encoding_supported_by_icu(), IsA, IsBinaryUpgrade, IsUnderPostmaster, lfirst, locale, DefElem::location, LockSharedObject(), namein(), NoLock, NOTICE, object_aclcheck(), object_ownercheck(), OBJECT_TABLESPACE, ObjectIdGetDatum(), OidIsValid, parser_errposition(), pfree(), pg_encoding_to_char, PG_END_ENSURE_ERROR_CLEANUP, PG_ENSURE_ERROR_CLEANUP, pg_strcasecmp(), PG_VALID_BE_ENCODING, pg_valid_server_encoding, PointerGetDatum(), quote_identifier(), recordDependencyOnOwner(), RelationGetDescr, RowExclusiveLock, S_ISDIR, ShareLock, createdb_failure_params::src_dboid, stat::st_mode, stat, stmt, createdb_failure_params::strategy, table_close(), table_open(), TransactionIdGetDatum(), and WARNING.

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

◆ createdb_failure_callback()

static void createdb_failure_callback ( int  code,
Datum  arg 
)
static

Definition at line 1608 of file dbcommands.c.

1609 {
1611 
1612  /*
1613  * If we were copying database at block levels then drop pages for the
1614  * destination database that are in the shared buffer cache. And tell
1615  * checkpointer to forget any pending fsync and unlink requests for files
1616  * in the database. The reasoning behind doing this is same as explained
1617  * in dropdb function. But unlike dropdb we don't need to call
1618  * pgstat_drop_database because this database is still not created so
1619  * there should not be any stat for this.
1620  */
1621  if (fparms->strategy == CREATEDB_WAL_LOG)
1622  {
1625 
1626  /* Release lock on the target database. */
1627  UnlockSharedObject(DatabaseRelationId, fparms->dest_dboid, 0,
1628  AccessShareLock);
1629  }
1630 
1631  /*
1632  * Release lock on source database before doing recursive remove. This is
1633  * not essential but it seems desirable to release the lock as soon as
1634  * possible.
1635  */
1636  UnlockSharedObject(DatabaseRelationId, fparms->src_dboid, 0, ShareLock);
1637 
1638  /* Throw away any successfully copied subdirectories */
1640 }
void DropDatabaseBuffers(Oid dbid)
Definition: bufmgr.c:4386
static void remove_dbtablespaces(Oid db_id)
Definition: dbcommands.c:2977
void ForgetDatabaseSyncRequests(Oid dbid)
Definition: md.c:1441
void * arg
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:312

References AccessShareLock, arg, CREATEDB_WAL_LOG, DatumGetPointer(), createdb_failure_params::dest_dboid, DropDatabaseBuffers(), ForgetDatabaseSyncRequests(), remove_dbtablespaces(), ShareLock, createdb_failure_params::src_dboid, createdb_failure_params::strategy, and UnlockSharedObject().

Referenced by createdb().

◆ CreateDirAndVersionFile()

static void CreateDirAndVersionFile ( char *  dbpath,
Oid  dbid,
Oid  tsid,
bool  isRedo 
)
static

Definition at line 456 of file dbcommands.c.

457 {
458  int fd;
459  int nbytes;
460  char versionfile[MAXPGPATH];
461  char buf[16];
462 
463  /*
464  * Note that we don't have to copy version data from the source database;
465  * there's only one legal value.
466  */
467  sprintf(buf, "%s\n", PG_MAJORVERSION);
468  nbytes = strlen(PG_MAJORVERSION) + 1;
469 
470  /* Create database directory. */
471  if (MakePGDirectory(dbpath) < 0)
472  {
473  /* Failure other than already exists or not in WAL replay? */
474  if (errno != EEXIST || !isRedo)
475  ereport(ERROR,
477  errmsg("could not create directory \"%s\": %m", dbpath)));
478  }
479 
480  /*
481  * Create PG_VERSION file in the database path. If the file already
482  * exists and we are in WAL replay then try again to open it in write
483  * mode.
484  */
485  snprintf(versionfile, sizeof(versionfile), "%s/%s", dbpath, "PG_VERSION");
486 
487  fd = OpenTransientFile(versionfile, O_WRONLY | O_CREAT | O_EXCL | PG_BINARY);
488  if (fd < 0 && errno == EEXIST && isRedo)
489  fd = OpenTransientFile(versionfile, O_WRONLY | O_TRUNC | PG_BINARY);
490 
491  if (fd < 0)
492  ereport(ERROR,
494  errmsg("could not create file \"%s\": %m", versionfile)));
495 
496  /* Write PG_MAJORVERSION in the PG_VERSION file. */
497  pgstat_report_wait_start(WAIT_EVENT_VERSION_FILE_WRITE);
498  errno = 0;
499  if ((int) write(fd, buf, nbytes) != nbytes)
500  {
501  /* If write didn't set errno, assume problem is no disk space. */
502  if (errno == 0)
503  errno = ENOSPC;
504  ereport(ERROR,
506  errmsg("could not write to file \"%s\": %m", versionfile)));
507  }
509 
510  pgstat_report_wait_start(WAIT_EVENT_VERSION_FILE_SYNC);
511  if (pg_fsync(fd) != 0)
514  errmsg("could not fsync file \"%s\": %m", versionfile)));
515  fsync_fname(dbpath, true);
517 
518  /* Close the version file. */
520 
521  /* If we are not in WAL replay then write the WAL. */
522  if (!isRedo)
523  {
525 
527 
528  xlrec.db_id = dbid;
529  xlrec.tablespace_id = tsid;
530 
531  XLogBeginInsert();
532  XLogRegisterData((char *) (&xlrec),
534 
535  (void) XLogInsert(RM_DBASE_ID, XLOG_DBASE_CREATE_WAL_LOG);
536 
538  }
539 }
#define PG_BINARY
Definition: c.h:1227
#define XLOG_DBASE_CREATE_WAL_LOG
int errcode_for_file_access(void)
Definition: elog.c:876
int MakePGDirectory(const char *directoryName)
Definition: fd.c:3936
int CloseTransientFile(int fd)
Definition: fd.c:2831
void fsync_fname(const char *fname, bool isdir)
Definition: fd.c:755
int data_sync_elevel(int elevel)
Definition: fd.c:3959
int pg_fsync(int fd)
Definition: fd.c:385
int OpenTransientFile(const char *fileName, int fileFlags)
Definition: fd.c:2655
#define write(a, b, c)
Definition: win32.h:14
#define START_CRIT_SECTION()
Definition: miscadmin.h:149
#define END_CRIT_SECTION()
Definition: miscadmin.h:151
#define MAXPGPATH
static char * buf
Definition: pg_test_fsync.c:72
#define sprintf
Definition: port.h:240
#define snprintf
Definition: port.h:238
static int fd(const char *x, int i)
Definition: preproc-init.c:105
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: wait_event.h:85
static void pgstat_report_wait_end(void)
Definition: wait_event.h:101

References buf, CloseTransientFile(), data_sync_elevel(), xl_dbase_create_wal_log_rec::db_id, END_CRIT_SECTION, ereport, errcode_for_file_access(), errmsg(), ERROR, fd(), fsync_fname(), MakePGDirectory(), MAXPGPATH, OpenTransientFile(), PG_BINARY, pg_fsync(), pgstat_report_wait_end(), pgstat_report_wait_start(), snprintf, sprintf, START_CRIT_SECTION, xl_dbase_create_wal_log_rec::tablespace_id, write, XLOG_DBASE_CREATE_WAL_LOG, XLogBeginInsert(), XLogInsert(), and XLogRegisterData().

Referenced by CreateDatabaseUsingWalLog(), and dbase_redo().

◆ database_is_invalid_form()

bool database_is_invalid_form ( Form_pg_database  datform)

Definition at line 3211 of file dbcommands.c.

3212 {
3213  return datform->datconnlimit == DATCONNLIMIT_INVALID_DB;
3214 }
#define DATCONNLIMIT_INVALID_DB
Definition: pg_database.h:124

References DATCONNLIMIT_INVALID_DB.

Referenced by AlterDatabase(), database_is_invalid_oid(), get_database_list(), InitPostgres(), and vac_truncate_clog().

◆ database_is_invalid_oid()

bool database_is_invalid_oid ( Oid  dboid)

Definition at line 3221 of file dbcommands.c.

3222 {
3223  HeapTuple dbtup;
3224  Form_pg_database dbform;
3225  bool invalid;
3226 
3227  dbtup = SearchSysCache1(DATABASEOID, ObjectIdGetDatum(dboid));
3228  if (!HeapTupleIsValid(dbtup))
3229  elog(ERROR, "cache lookup failed for database %u", dboid);
3230  dbform = (Form_pg_database) GETSTRUCT(dbtup);
3231 
3233 
3234  ReleaseSysCache(dbtup);
3235 
3236  return invalid;
3237 }
invalidindex index d is invalid
Definition: isn.c:133
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:269
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:221

References database_is_invalid_form(), elog, ERROR, GETSTRUCT, HeapTupleIsValid, invalid, ObjectIdGetDatum(), ReleaseSysCache(), and SearchSysCache1().

Referenced by createdb().

◆ dbase_redo()

void dbase_redo ( XLogReaderState record)

Definition at line 3283 of file dbcommands.c.

3284 {
3285  uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
3286 
3287  /* Backup blocks are not used in dbase records */
3288  Assert(!XLogRecHasAnyBlockRefs(record));
3289 
3290  if (info == XLOG_DBASE_CREATE_FILE_COPY)
3291  {
3294  char *src_path;
3295  char *dst_path;
3296  char *parent_path;
3297  struct stat st;
3298 
3299  src_path = GetDatabasePath(xlrec->src_db_id, xlrec->src_tablespace_id);
3300  dst_path = GetDatabasePath(xlrec->db_id, xlrec->tablespace_id);
3301 
3302  /*
3303  * Our theory for replaying a CREATE is to forcibly drop the target
3304  * subdirectory if present, then re-copy the source data. This may be
3305  * more work than needed, but it is simple to implement.
3306  */
3307  if (stat(dst_path, &st) == 0 && S_ISDIR(st.st_mode))
3308  {
3309  if (!rmtree(dst_path, true))
3310  /* If this failed, copydir() below is going to error. */
3311  ereport(WARNING,
3312  (errmsg("some useless files may be left behind in old database directory \"%s\"",
3313  dst_path)));
3314  }
3315 
3316  /*
3317  * If the parent of the target path doesn't exist, create it now. This
3318  * enables us to create the target underneath later.
3319  */
3320  parent_path = pstrdup(dst_path);
3321  get_parent_directory(parent_path);
3322  if (stat(parent_path, &st) < 0)
3323  {
3324  if (errno != ENOENT)
3325  ereport(FATAL,
3326  errmsg("could not stat directory \"%s\": %m",
3327  dst_path));
3328 
3329  /* create the parent directory if needed and valid */
3330  recovery_create_dbdir(parent_path, true);
3331  }
3332  pfree(parent_path);
3333 
3334  /*
3335  * There's a case where the copy source directory is missing for the
3336  * same reason above. Create the empty source directory so that
3337  * copydir below doesn't fail. The directory will be dropped soon by
3338  * recovery.
3339  */
3340  if (stat(src_path, &st) < 0 && errno == ENOENT)
3341  recovery_create_dbdir(src_path, false);
3342 
3343  /*
3344  * Force dirty buffers out to disk, to ensure source database is
3345  * up-to-date for the copy.
3346  */
3348 
3349  /* Close all smgr fds in all backends. */
3351 
3352  /*
3353  * Copy this subdirectory to the new location
3354  *
3355  * We don't need to copy subdirectories
3356  */
3357  copydir(src_path, dst_path, false);
3358 
3359  pfree(src_path);
3360  pfree(dst_path);
3361  }
3362  else if (info == XLOG_DBASE_CREATE_WAL_LOG)
3363  {
3366  char *dbpath;
3367  char *parent_path;
3368 
3369  dbpath = GetDatabasePath(xlrec->db_id, xlrec->tablespace_id);
3370 
3371  /* create the parent directory if needed and valid */
3372  parent_path = pstrdup(dbpath);
3373  get_parent_directory(parent_path);
3374  recovery_create_dbdir(parent_path, true);
3375 
3376  /* Create the database directory with the version file. */
3377  CreateDirAndVersionFile(dbpath, xlrec->db_id, xlrec->tablespace_id,
3378  true);
3379  pfree(dbpath);
3380  }
3381  else if (info == XLOG_DBASE_DROP)
3382  {
3383  xl_dbase_drop_rec *xlrec = (xl_dbase_drop_rec *) XLogRecGetData(record);
3384  char *dst_path;
3385  int i;
3386 
3387  if (InHotStandby)
3388  {
3389  /*
3390  * Lock database while we resolve conflicts to ensure that
3391  * InitPostgres() cannot fully re-execute concurrently. This
3392  * avoids backends re-connecting automatically to same database,
3393  * which can happen in some cases.
3394  *
3395  * This will lock out walsenders trying to connect to db-specific
3396  * slots for logical decoding too, so it's safe for us to drop
3397  * slots.
3398  */
3399  LockSharedObjectForSession(DatabaseRelationId, xlrec->db_id, 0, AccessExclusiveLock);
3401  }
3402 
3403  /* Drop any database-specific replication slots */
3405 
3406  /* Drop pages for this database that are in the shared buffer cache */
3407  DropDatabaseBuffers(xlrec->db_id);
3408 
3409  /* Also, clean out any fsync requests that might be pending in md.c */
3411 
3412  /* Clean out the xlog relcache too */
3413  XLogDropDatabase(xlrec->db_id);
3414 
3415  /* Close all smgr fds in all backends. */
3417 
3418  for (i = 0; i < xlrec->ntablespaces; i++)
3419  {
3420  dst_path = GetDatabasePath(xlrec->db_id, xlrec->tablespace_ids[i]);
3421 
3422  /* And remove the physical files */
3423  if (!rmtree(dst_path, true))
3424  ereport(WARNING,
3425  (errmsg("some useless files may be left behind in old database directory \"%s\"",
3426  dst_path)));
3427  pfree(dst_path);
3428  }
3429 
3430  if (InHotStandby)
3431  {
3432  /*
3433  * Release locks prior to commit. XXX There is a race condition
3434  * here that may allow backends to reconnect, but the window for
3435  * this is small because the gap between here and commit is mostly
3436  * fairly small and it is unlikely that people will be dropping
3437  * databases that we are trying to connect to anyway.
3438  */
3439  UnlockSharedObjectForSession(DatabaseRelationId, xlrec->db_id, 0, AccessExclusiveLock);
3440  }
3441  }
3442  else
3443  elog(PANIC, "dbase_redo: unknown op code %u", info);
3444 }
void FlushDatabaseBuffers(Oid dbid)
Definition: bufmgr.c:4862
uint8_t uint8
Definition: c.h:483
static void recovery_create_dbdir(char *path, bool only_tblspc)
Definition: dbcommands.c:3254
#define XLOG_DBASE_DROP
#define PANIC
Definition: elog.h:42
int i
Definition: isn.c:72
void UnlockSharedObjectForSession(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition: lmgr.c:1170
void LockSharedObjectForSession(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition: lmgr.c:1152
#define AccessExclusiveLock
Definition: lockdefs.h:43
char * pstrdup(const char *in)
Definition: mcxt.c:1696
void get_parent_directory(char *path)
Definition: path.c:991
void WaitForProcSignalBarrier(uint64 generation)
Definition: procsignal.c:421
uint64 EmitProcSignalBarrier(ProcSignalBarrierType type)
Definition: procsignal.c:353
@ PROCSIGNAL_BARRIER_SMGRRELEASE
Definition: procsignal.h:56
bool rmtree(const char *path, bool rmtopdir)
Definition: rmtree.c:50
void ReplicationSlotsDropDBSlots(Oid dboid)
Definition: slot.c:1298
void ResolveRecoveryConflictWithDatabase(Oid dbid)
Definition: standby.c:568
Oid tablespace_ids[FLEXIBLE_ARRAY_MEMBER]
#define XLogRecGetInfo(decoder)
Definition: xlogreader.h:410
#define XLogRecGetData(decoder)
Definition: xlogreader.h:415
#define XLogRecHasAnyBlockRefs(decoder)
Definition: xlogreader.h:417
#define XLR_INFO_MASK
Definition: xlogrecord.h:62
void XLogDropDatabase(Oid dbid)
Definition: xlogutils.c:652
#define InHotStandby
Definition: xlogutils.h:60

References AccessExclusiveLock, Assert, copydir(), CreateDirAndVersionFile(), xl_dbase_create_file_copy_rec::db_id, xl_dbase_create_wal_log_rec::db_id, xl_dbase_drop_rec::db_id, DropDatabaseBuffers(), elog, EmitProcSignalBarrier(), ereport, errmsg(), FATAL, FlushDatabaseBuffers(), ForgetDatabaseSyncRequests(), get_parent_directory(), GetDatabasePath(), i, InHotStandby, LockSharedObjectForSession(), xl_dbase_drop_rec::ntablespaces, PANIC, pfree(), PROCSIGNAL_BARRIER_SMGRRELEASE, pstrdup(), recovery_create_dbdir(), ReplicationSlotsDropDBSlots(), ResolveRecoveryConflictWithDatabase(), rmtree(), S_ISDIR, xl_dbase_create_file_copy_rec::src_db_id, xl_dbase_create_file_copy_rec::src_tablespace_id, stat::st_mode, stat, xl_dbase_create_file_copy_rec::tablespace_id, xl_dbase_create_wal_log_rec::tablespace_id, xl_dbase_drop_rec::tablespace_ids, UnlockSharedObjectForSession(), WaitForProcSignalBarrier(), WARNING, XLOG_DBASE_CREATE_FILE_COPY, XLOG_DBASE_CREATE_WAL_LOG, XLOG_DBASE_DROP, XLogDropDatabase(), XLogRecGetData, XLogRecGetInfo, XLogRecHasAnyBlockRefs, and XLR_INFO_MASK.

◆ DropDatabase()

void DropDatabase ( ParseState pstate,
DropdbStmt stmt 
)

Definition at line 2316 of file dbcommands.c.

2317 {
2318  bool force = false;
2319  ListCell *lc;
2320 
2321  foreach(lc, stmt->options)
2322  {
2323  DefElem *opt = (DefElem *) lfirst(lc);
2324 
2325  if (strcmp(opt->defname, "force") == 0)
2326  force = true;
2327  else
2328  ereport(ERROR,
2329  (errcode(ERRCODE_SYNTAX_ERROR),
2330  errmsg("unrecognized DROP DATABASE option \"%s\"", opt->defname),
2331  parser_errposition(pstate, opt->location)));
2332  }
2333 
2334  dropdb(stmt->dbname, stmt->missing_ok, force);
2335 }
void dropdb(const char *dbname, bool missing_ok, bool force)
Definition: dbcommands.c:1647

References DefElem::defname, dropdb(), ereport, errcode(), errmsg(), ERROR, lfirst, DefElem::location, parser_errposition(), and stmt.

Referenced by standard_ProcessUtility().

◆ dropdb()

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

Definition at line 1647 of file dbcommands.c.

1648 {
1649  Oid db_id;
1650  bool db_istemplate;
1651  Relation pgdbrel;
1652  HeapTuple tup;
1653  ScanKeyData scankey;
1654  void *inplace_state;
1655  Form_pg_database datform;
1656  int notherbackends;
1657  int npreparedxacts;
1658  int nslots,
1659  nslots_active;
1660  int nsubscriptions;
1661 
1662  /*
1663  * Look up the target database's OID, and get exclusive lock on it. We
1664  * need this to ensure that no new backend starts up in the target
1665  * database while we are deleting it (see postinit.c), and that no one is
1666  * using it as a CREATE DATABASE template or trying to delete it for
1667  * themselves.
1668  */
1669  pgdbrel = table_open(DatabaseRelationId, RowExclusiveLock);
1670 
1671  if (!get_db_info(dbname, AccessExclusiveLock, &db_id, NULL, NULL,
1672  &db_istemplate, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL))
1673  {
1674  if (!missing_ok)
1675  {
1676  ereport(ERROR,
1677  (errcode(ERRCODE_UNDEFINED_DATABASE),
1678  errmsg("database \"%s\" does not exist", dbname)));
1679  }
1680  else
1681  {
1682  /* Close pg_database, release the lock, since we changed nothing */
1683  table_close(pgdbrel, RowExclusiveLock);
1684  ereport(NOTICE,
1685  (errmsg("database \"%s\" does not exist, skipping",
1686  dbname)));
1687  return;
1688  }
1689  }
1690 
1691  /*
1692  * Permission checks
1693  */
1694  if (!object_ownercheck(DatabaseRelationId, db_id, GetUserId()))
1696  dbname);
1697 
1698  /* DROP hook for the database being removed */
1699  InvokeObjectDropHook(DatabaseRelationId, db_id, 0);
1700 
1701  /*
1702  * Disallow dropping a DB that is marked istemplate. This is just to
1703  * prevent people from accidentally dropping template0 or template1; they
1704  * can do so if they're really determined ...
1705  */
1706  if (db_istemplate)
1707  ereport(ERROR,
1708  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1709  errmsg("cannot drop a template database")));
1710 
1711  /* Obviously can't drop my own database */
1712  if (db_id == MyDatabaseId)
1713  ereport(ERROR,
1714  (errcode(ERRCODE_OBJECT_IN_USE),
1715  errmsg("cannot drop the currently open database")));
1716 
1717  /*
1718  * Check whether there are active logical slots that refer to the
1719  * to-be-dropped database. The database lock we are holding prevents the
1720  * creation of new slots using the database or existing slots becoming
1721  * active.
1722  */
1723  (void) ReplicationSlotsCountDBSlots(db_id, &nslots, &nslots_active);
1724  if (nslots_active)
1725  {
1726  ereport(ERROR,
1727  (errcode(ERRCODE_OBJECT_IN_USE),
1728  errmsg("database \"%s\" is used by an active logical replication slot",
1729  dbname),
1730  errdetail_plural("There is %d active slot.",
1731  "There are %d active slots.",
1732  nslots_active, nslots_active)));
1733  }
1734 
1735  /*
1736  * Check if there are subscriptions defined in the target database.
1737  *
1738  * We can't drop them automatically because they might be holding
1739  * resources in other databases/instances.
1740  */
1741  if ((nsubscriptions = CountDBSubscriptions(db_id)) > 0)
1742  ereport(ERROR,
1743  (errcode(ERRCODE_OBJECT_IN_USE),
1744  errmsg("database \"%s\" is being used by logical replication subscription",
1745  dbname),
1746  errdetail_plural("There is %d subscription.",
1747  "There are %d subscriptions.",
1748  nsubscriptions, nsubscriptions)));
1749 
1750 
1751  /*
1752  * Attempt to terminate all existing connections to the target database if
1753  * the user has requested to do so.
1754  */
1755  if (force)
1756  TerminateOtherDBBackends(db_id);
1757 
1758  /*
1759  * Check for other backends in the target database. (Because we hold the
1760  * database lock, no new ones can start after this.)
1761  *
1762  * As in CREATE DATABASE, check this after other error conditions.
1763  */
1764  if (CountOtherDBBackends(db_id, &notherbackends, &npreparedxacts))
1765  ereport(ERROR,
1766  (errcode(ERRCODE_OBJECT_IN_USE),
1767  errmsg("database \"%s\" is being accessed by other users",
1768  dbname),
1769  errdetail_busy_db(notherbackends, npreparedxacts)));
1770 
1771  /*
1772  * Delete any comments or security labels associated with the database.
1773  */
1774  DeleteSharedComments(db_id, DatabaseRelationId);
1775  DeleteSharedSecurityLabel(db_id, DatabaseRelationId);
1776 
1777  /*
1778  * Remove settings associated with this database
1779  */
1780  DropSetting(db_id, InvalidOid);
1781 
1782  /*
1783  * Remove shared dependency references for the database.
1784  */
1785  dropDatabaseDependencies(db_id);
1786 
1787  /*
1788  * Tell the cumulative stats system to forget it immediately, too.
1789  */
1790  pgstat_drop_database(db_id);
1791 
1792  /*
1793  * Except for the deletion of the catalog row, subsequent actions are not
1794  * transactional (consider DropDatabaseBuffers() discarding modified
1795  * buffers). But we might crash or get interrupted below. To prevent
1796  * accesses to a database with invalid contents, mark the database as
1797  * invalid using an in-place update.
1798  *
1799  * We need to flush the WAL before continuing, to guarantee the
1800  * modification is durable before performing irreversible filesystem
1801  * operations.
1802  */
1803  ScanKeyInit(&scankey,
1804  Anum_pg_database_datname,
1805  BTEqualStrategyNumber, F_NAMEEQ,
1807  systable_inplace_update_begin(pgdbrel, DatabaseNameIndexId, true,
1808  NULL, 1, &scankey, &tup, &inplace_state);
1809  if (!HeapTupleIsValid(tup))
1810  elog(ERROR, "cache lookup failed for database %u", db_id);
1811  datform = (Form_pg_database) GETSTRUCT(tup);
1812  datform->datconnlimit = DATCONNLIMIT_INVALID_DB;
1813  systable_inplace_update_finish(inplace_state, tup);
1815 
1816  /*
1817  * Also delete the tuple - transactionally. If this transaction commits,
1818  * the row will be gone, but if we fail, dropdb() can be invoked again.
1819  */
1820  CatalogTupleDelete(pgdbrel, &tup->t_self);
1821  heap_freetuple(tup);
1822 
1823  /*
1824  * Drop db-specific replication slots.
1825  */
1827 
1828  /*
1829  * Drop pages for this database that are in the shared buffer cache. This
1830  * is important to ensure that no remaining backend tries to write out a
1831  * dirty buffer to the dead database later...
1832  */
1833  DropDatabaseBuffers(db_id);
1834 
1835  /*
1836  * Tell checkpointer to forget any pending fsync and unlink requests for
1837  * files in the database; else the fsyncs will fail at next checkpoint, or
1838  * worse, it will delete files that belong to a newly created database
1839  * with the same OID.
1840  */
1842 
1843  /*
1844  * Force a checkpoint to make sure the checkpointer has received the
1845  * message sent by ForgetDatabaseSyncRequests.
1846  */
1848 
1849  /* Close all smgr fds in all backends. */
1851 
1852  /*
1853  * Remove all tablespace subdirs belonging to the database.
1854  */
1855  remove_dbtablespaces(db_id);
1856 
1857  /*
1858  * Close pg_database, but keep lock till commit.
1859  */
1860  table_close(pgdbrel, NoLock);
1861 
1862  /*
1863  * Force synchronous commit, thus minimizing the window between removal of
1864  * the database files and committal of the transaction. If we crash before
1865  * committing, we'll have a DB that's gone on disk but still there
1866  * according to pg_database, which is not good.
1867  */
1868  ForceSyncCommit();
1869 }
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:1295
void systable_inplace_update_begin(Relation relation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, const ScanKeyData *key, HeapTuple *oldtupcopy, void **state)
Definition: genam.c:810
void systable_inplace_update_finish(void *state, HeapTuple tuple)
Definition: genam.c:886
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:365
#define InvokeObjectDropHook(classId, objectId, subId)
Definition: objectaccess.h:182
void DropSetting(Oid databaseid, Oid roleid)
void dropDatabaseDependencies(Oid databaseId)
Definition: pg_shdepend.c:999
int CountDBSubscriptions(Oid dbid)
void pgstat_drop_database(Oid databaseid)
void TerminateOtherDBBackends(Oid databaseId)
Definition: procarray.c:3828
void DeleteSharedSecurityLabel(Oid objectId, Oid classId)
Definition: seclabel.c:491
bool ReplicationSlotsCountDBSlots(Oid dboid, int *nslots, int *nactive)
Definition: slot.c:1240
XLogRecPtr XactLastRecEnd
Definition: xlog.c:254
void XLogFlush(XLogRecPtr record)
Definition: xlog.c:2802

References AccessExclusiveLock, aclcheck_error(), ACLCHECK_NOT_OWNER, BTEqualStrategyNumber, CatalogTupleDelete(), CHECKPOINT_FORCE, CHECKPOINT_IMMEDIATE, CHECKPOINT_WAIT, CountDBSubscriptions(), CountOtherDBBackends(), CStringGetDatum(), DATCONNLIMIT_INVALID_DB, dbname, DeleteSharedComments(), DeleteSharedSecurityLabel(), DropDatabaseBuffers(), dropDatabaseDependencies(), DropSetting(), elog, EmitProcSignalBarrier(), ereport, errcode(), errdetail_busy_db(), errdetail_plural(), errmsg(), ERROR, ForceSyncCommit(), ForgetDatabaseSyncRequests(), get_db_info(), GETSTRUCT, GetUserId(), heap_freetuple(), HeapTupleIsValid, InvalidOid, InvokeObjectDropHook, MyDatabaseId, NoLock, NOTICE, OBJECT_DATABASE, object_ownercheck(), pgstat_drop_database(), PROCSIGNAL_BARRIER_SMGRRELEASE, remove_dbtablespaces(), ReplicationSlotsCountDBSlots(), ReplicationSlotsDropDBSlots(), RequestCheckpoint(), RowExclusiveLock, ScanKeyInit(), systable_inplace_update_begin(), systable_inplace_update_finish(), HeapTupleData::t_self, table_close(), table_open(), TerminateOtherDBBackends(), WaitForProcSignalBarrier(), XactLastRecEnd, and XLogFlush().

Referenced by DropDatabase().

◆ errdetail_busy_db()

static int errdetail_busy_db ( int  notherbackends,
int  npreparedxacts 
)
static

Definition at line 3110 of file dbcommands.c.

3111 {
3112  if (notherbackends > 0 && npreparedxacts > 0)
3113 
3114  /*
3115  * We don't deal with singular versus plural here, since gettext
3116  * doesn't support multiple plurals in one string.
3117  */
3118  errdetail("There are %d other session(s) and %d prepared transaction(s) using the database.",
3119  notherbackends, npreparedxacts);
3120  else if (notherbackends > 0)
3121  errdetail_plural("There is %d other session using the database.",
3122  "There are %d other sessions using the database.",
3123  notherbackends,
3124  notherbackends);
3125  else
3126  errdetail_plural("There is %d prepared transaction using the database.",
3127  "There are %d prepared transactions using the database.",
3128  npreparedxacts,
3129  npreparedxacts);
3130  return 0; /* just to keep ereport macro happy */
3131 }

References errdetail(), and errdetail_plural().

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

◆ get_database_name()

char* get_database_name ( Oid  dbid)

Definition at line 3187 of file dbcommands.c.

3188 {
3189  HeapTuple dbtuple;
3190  char *result;
3191 
3192  dbtuple = SearchSysCache1(DATABASEOID, ObjectIdGetDatum(dbid));
3193  if (HeapTupleIsValid(dbtuple))
3194  {
3195  result = pstrdup(NameStr(((Form_pg_database) GETSTRUCT(dbtuple))->datname));
3196  ReleaseSysCache(dbtuple);
3197  }
3198  else
3199  result = NULL;
3200 
3201  return result;
3202 }
#define NameStr(name)
Definition: c.h:700
NameData datname
Definition: pg_database.h:35

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

Referenced by AfterTriggerSetState(), AlterObjectRename_internal(), AlterPublicationOwner_internal(), AlterSchemaOwner_internal(), AlterSubscriptionOwner_internal(), calculate_database_size(), createdb(), CreatePublication(), CreateSchemaCommand(), CreateSubscription(), 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(), 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 3140 of file dbcommands.c.

3141 {
3142  Relation pg_database;
3143  ScanKeyData entry[1];
3144  SysScanDesc scan;
3145  HeapTuple dbtuple;
3146  Oid oid;
3147 
3148  /*
3149  * There's no syscache for pg_database indexed by name, so we must look
3150  * the hard way.
3151  */
3152  pg_database = table_open(DatabaseRelationId, AccessShareLock);
3153  ScanKeyInit(&entry[0],
3154  Anum_pg_database_datname,
3155  BTEqualStrategyNumber, F_NAMEEQ,
3157  scan = systable_beginscan(pg_database, DatabaseNameIndexId, true,
3158  NULL, 1, entry);
3159 
3160  dbtuple = systable_getnext(scan);
3161 
3162  /* We assume that there can be at most one matching tuple */
3163  if (HeapTupleIsValid(dbtuple))
3164  oid = ((Form_pg_database) GETSTRUCT(dbtuple))->oid;
3165  else
3166  oid = InvalidOid;
3167 
3168  systable_endscan(scan);
3169  table_close(pg_database, AccessShareLock);
3170 
3171  if (!OidIsValid(oid) && !missing_ok)
3172  ereport(ERROR,
3173  (errcode(ERRCODE_UNDEFINED_DATABASE),
3174  errmsg("database \"%s\" does not exist",
3175  dbname)));
3176 
3177  return oid;
3178 }

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(), pg_database_size_name(), RenameDatabase(), sepgsql_database_post_create(), synchronize_slots(), and worker_spi_launch().

◆ get_db_info()

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

Definition at line 2794 of file dbcommands.c.

2802 {
2803  bool result = false;
2804  Relation relation;
2805 
2806  Assert(name);
2807 
2808  /* Caller may wish to grab a better lock on pg_database beforehand... */
2809  relation = table_open(DatabaseRelationId, AccessShareLock);
2810 
2811  /*
2812  * Loop covers the rare case where the database is renamed before we can
2813  * lock it. We try again just in case we can find a new one of the same
2814  * name.
2815  */
2816  for (;;)
2817  {
2818  ScanKeyData scanKey;
2819  SysScanDesc scan;
2820  HeapTuple tuple;
2821  Oid dbOid;
2822 
2823  /*
2824  * there's no syscache for database-indexed-by-name, so must do it the
2825  * hard way
2826  */
2827  ScanKeyInit(&scanKey,
2828  Anum_pg_database_datname,
2829  BTEqualStrategyNumber, F_NAMEEQ,
2831 
2832  scan = systable_beginscan(relation, DatabaseNameIndexId, true,
2833  NULL, 1, &scanKey);
2834 
2835  tuple = systable_getnext(scan);
2836 
2837  if (!HeapTupleIsValid(tuple))
2838  {
2839  /* definitely no database of that name */
2840  systable_endscan(scan);
2841  break;
2842  }
2843 
2844  dbOid = ((Form_pg_database) GETSTRUCT(tuple))->oid;
2845 
2846  systable_endscan(scan);
2847 
2848  /*
2849  * Now that we have a database OID, we can try to lock the DB.
2850  */
2851  if (lockmode != NoLock)
2852  LockSharedObject(DatabaseRelationId, dbOid, 0, lockmode);
2853 
2854  /*
2855  * And now, re-fetch the tuple by OID. If it's still there and still
2856  * the same name, we win; else, drop the lock and loop back to try
2857  * again.
2858  */
2859  tuple = SearchSysCache1(DATABASEOID, ObjectIdGetDatum(dbOid));
2860  if (HeapTupleIsValid(tuple))
2861  {
2862  Form_pg_database dbform = (Form_pg_database) GETSTRUCT(tuple);
2863 
2864  if (strcmp(name, NameStr(dbform->datname)) == 0)
2865  {
2866  Datum datum;
2867  bool isnull;
2868 
2869  /* oid of the database */
2870  if (dbIdP)
2871  *dbIdP = dbOid;
2872  /* oid of the owner */
2873  if (ownerIdP)
2874  *ownerIdP = dbform->datdba;
2875  /* character encoding */
2876  if (encodingP)
2877  *encodingP = dbform->encoding;
2878  /* allowed as template? */
2879  if (dbIsTemplateP)
2880  *dbIsTemplateP = dbform->datistemplate;
2881  /* Has on login event trigger? */
2882  if (dbHasLoginEvtP)
2883  *dbHasLoginEvtP = dbform->dathasloginevt;
2884  /* allowing connections? */
2885  if (dbAllowConnP)
2886  *dbAllowConnP = dbform->datallowconn;
2887  /* limit of frozen XIDs */
2888  if (dbFrozenXidP)
2889  *dbFrozenXidP = dbform->datfrozenxid;
2890  /* minimum MultiXactId */
2891  if (dbMinMultiP)
2892  *dbMinMultiP = dbform->datminmxid;
2893  /* default tablespace for this database */
2894  if (dbTablespace)
2895  *dbTablespace = dbform->dattablespace;
2896  /* default locale settings for this database */
2897  if (dbLocProvider)
2898  *dbLocProvider = dbform->datlocprovider;
2899  if (dbCollate)
2900  {
2901  datum = SysCacheGetAttrNotNull(DATABASEOID, tuple, Anum_pg_database_datcollate);
2902  *dbCollate = TextDatumGetCString(datum);
2903  }
2904  if (dbCtype)
2905  {
2906  datum = SysCacheGetAttrNotNull(DATABASEOID, tuple, Anum_pg_database_datctype);
2907  *dbCtype = TextDatumGetCString(datum);
2908  }
2909  if (dbLocale)
2910  {
2911  datum = SysCacheGetAttr(DATABASEOID, tuple, Anum_pg_database_datlocale, &isnull);
2912  if (isnull)
2913  *dbLocale = NULL;
2914  else
2915  *dbLocale = TextDatumGetCString(datum);
2916  }
2917  if (dbIcurules)
2918  {
2919  datum = SysCacheGetAttr(DATABASEOID, tuple, Anum_pg_database_daticurules, &isnull);
2920  if (isnull)
2921  *dbIcurules = NULL;
2922  else
2923  *dbIcurules = TextDatumGetCString(datum);
2924  }
2925  if (dbCollversion)
2926  {
2927  datum = SysCacheGetAttr(DATABASEOID, tuple, Anum_pg_database_datcollversion, &isnull);
2928  if (isnull)
2929  *dbCollversion = NULL;
2930  else
2931  *dbCollversion = TextDatumGetCString(datum);
2932  }
2933  ReleaseSysCache(tuple);
2934  result = true;
2935  break;
2936  }
2937  /* can only get here if it was just renamed */
2938  ReleaseSysCache(tuple);
2939  }
2940 
2941  if (lockmode != NoLock)
2942  UnlockSharedObject(DatabaseRelationId, dbOid, 0, lockmode);
2943  }
2944 
2945  table_close(relation, AccessShareLock);
2946 
2947  return result;
2948 }
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:600
Datum SysCacheGetAttrNotNull(int cacheId, HeapTuple tup, AttrNumber attributeNumber)
Definition: syscache.c:631
const char * name

References AccessShareLock, Assert, BTEqualStrategyNumber, CStringGetDatum(), GETSTRUCT, HeapTupleIsValid, LockSharedObject(), name, NameStr, NoLock, ObjectIdGetDatum(), ReleaseSysCache(), ScanKeyInit(), SearchSysCache1(), SysCacheGetAttr(), SysCacheGetAttrNotNull(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), table_open(), TextDatumGetCString, and UnlockSharedObject().

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

◆ have_createdb_privilege()

bool have_createdb_privilege ( void  )

Definition at line 2952 of file dbcommands.c.

2953 {
2954  bool result = false;
2955  HeapTuple utup;
2956 
2957  /* Superusers can always do everything */
2958  if (superuser())
2959  return true;
2960 
2961  utup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(GetUserId()));
2962  if (HeapTupleIsValid(utup))
2963  {
2964  result = ((Form_pg_authid) GETSTRUCT(utup))->rolcreatedb;
2965  ReleaseSysCache(utup);
2966  }
2967  return result;
2968 }
FormData_pg_authid * Form_pg_authid
Definition: pg_authid.h:56
bool rolcreatedb
Definition: pg_authid.h:38

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

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

◆ movedb()

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

Definition at line 1977 of file dbcommands.c.

1978 {
1979  Oid db_id;
1980  Relation pgdbrel;
1981  int notherbackends;
1982  int npreparedxacts;
1983  HeapTuple oldtuple,
1984  newtuple;
1985  Oid src_tblspcoid,
1986  dst_tblspcoid;
1987  ScanKeyData scankey;
1988  SysScanDesc sysscan;
1989  AclResult aclresult;
1990  char *src_dbpath;
1991  char *dst_dbpath;
1992  DIR *dstdir;
1993  struct dirent *xlde;
1994  movedb_failure_params fparms;
1995 
1996  /*
1997  * Look up the target database's OID, and get exclusive lock on it. We
1998  * need this to ensure that no new backend starts up in the database while
1999  * we are moving it, and that no one is using it as a CREATE DATABASE
2000  * template or trying to delete it.
2001  */
2002  pgdbrel = table_open(DatabaseRelationId, RowExclusiveLock);
2003 
2004  if (!get_db_info(dbname, AccessExclusiveLock, &db_id, NULL, NULL, NULL,
2005  NULL, NULL, NULL, NULL, &src_tblspcoid, NULL, NULL, NULL, NULL, NULL, NULL))
2006  ereport(ERROR,
2007  (errcode(ERRCODE_UNDEFINED_DATABASE),
2008  errmsg("database \"%s\" does not exist", dbname)));
2009 
2010  /*
2011  * We actually need a session lock, so that the lock will persist across
2012  * the commit/restart below. (We could almost get away with letting the
2013  * lock be released at commit, except that someone could try to move
2014  * relations of the DB back into the old directory while we rmtree() it.)
2015  */
2016  LockSharedObjectForSession(DatabaseRelationId, db_id, 0,
2018 
2019  /*
2020  * Permission checks
2021  */
2022  if (!object_ownercheck(DatabaseRelationId, db_id, GetUserId()))
2024  dbname);
2025 
2026  /*
2027  * Obviously can't move the tables of my own database
2028  */
2029  if (db_id == MyDatabaseId)
2030  ereport(ERROR,
2031  (errcode(ERRCODE_OBJECT_IN_USE),
2032  errmsg("cannot change the tablespace of the currently open database")));
2033 
2034  /*
2035  * Get tablespace's oid
2036  */
2037  dst_tblspcoid = get_tablespace_oid(tblspcname, false);
2038 
2039  /*
2040  * Permission checks
2041  */
2042  aclresult = object_aclcheck(TableSpaceRelationId, dst_tblspcoid, GetUserId(),
2043  ACL_CREATE);
2044  if (aclresult != ACLCHECK_OK)
2045  aclcheck_error(aclresult, OBJECT_TABLESPACE,
2046  tblspcname);
2047 
2048  /*
2049  * pg_global must never be the default tablespace
2050  */
2051  if (dst_tblspcoid == GLOBALTABLESPACE_OID)
2052  ereport(ERROR,
2053  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2054  errmsg("pg_global cannot be used as default tablespace")));
2055 
2056  /*
2057  * No-op if same tablespace
2058  */
2059  if (src_tblspcoid == dst_tblspcoid)
2060  {
2061  table_close(pgdbrel, NoLock);
2062  UnlockSharedObjectForSession(DatabaseRelationId, db_id, 0,
2064  return;
2065  }
2066 
2067  /*
2068  * Check for other backends in the target database. (Because we hold the
2069  * database lock, no new ones can start after this.)
2070  *
2071  * As in CREATE DATABASE, check this after other error conditions.
2072  */
2073  if (CountOtherDBBackends(db_id, &notherbackends, &npreparedxacts))
2074  ereport(ERROR,
2075  (errcode(ERRCODE_OBJECT_IN_USE),
2076  errmsg("database \"%s\" is being accessed by other users",
2077  dbname),
2078  errdetail_busy_db(notherbackends, npreparedxacts)));
2079 
2080  /*
2081  * Get old and new database paths
2082  */
2083  src_dbpath = GetDatabasePath(db_id, src_tblspcoid);
2084  dst_dbpath = GetDatabasePath(db_id, dst_tblspcoid);
2085 
2086  /*
2087  * Force a checkpoint before proceeding. This will force all dirty
2088  * buffers, including those of unlogged tables, out to disk, to ensure
2089  * source database is up-to-date on disk for the copy.
2090  * FlushDatabaseBuffers() would suffice for that, but we also want to
2091  * process any pending unlink requests. Otherwise, the check for existing
2092  * files in the target directory might fail unnecessarily, not to mention
2093  * that the copy might fail due to source files getting deleted under it.
2094  * On Windows, this also ensures that background procs don't hold any open
2095  * files, which would cause rmdir() to fail.
2096  */
2099 
2100  /* Close all smgr fds in all backends. */
2102 
2103  /*
2104  * Now drop all buffers holding data of the target database; they should
2105  * no longer be dirty so DropDatabaseBuffers is safe.
2106  *
2107  * It might seem that we could just let these buffers age out of shared
2108  * buffers naturally, since they should not get referenced anymore. The
2109  * problem with that is that if the user later moves the database back to
2110  * its original tablespace, any still-surviving buffers would appear to
2111  * contain valid data again --- but they'd be missing any changes made in
2112  * the database while it was in the new tablespace. In any case, freeing
2113  * buffers that should never be used again seems worth the cycles.
2114  *
2115  * Note: it'd be sufficient to get rid of buffers matching db_id and
2116  * src_tblspcoid, but bufmgr.c presently provides no API for that.
2117  */
2118  DropDatabaseBuffers(db_id);
2119 
2120  /*
2121  * Check for existence of files in the target directory, i.e., objects of
2122  * this database that are already in the target tablespace. We can't
2123  * allow the move in such a case, because we would need to change those
2124  * relations' pg_class.reltablespace entries to zero, and we don't have
2125  * access to the DB's pg_class to do so.
2126  */
2127  dstdir = AllocateDir(dst_dbpath);
2128  if (dstdir != NULL)
2129  {
2130  while ((xlde = ReadDir(dstdir, dst_dbpath)) != NULL)
2131  {
2132  if (strcmp(xlde->d_name, ".") == 0 ||
2133  strcmp(xlde->d_name, "..") == 0)
2134  continue;
2135 
2136  ereport(ERROR,
2137  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
2138  errmsg("some relations of database \"%s\" are already in tablespace \"%s\"",
2139  dbname, tblspcname),
2140  errhint("You must move them back to the database's default tablespace before using this command.")));
2141  }
2142 
2143  FreeDir(dstdir);
2144 
2145  /*
2146  * The directory exists but is empty. We must remove it before using
2147  * the copydir function.
2148  */
2149  if (rmdir(dst_dbpath) != 0)
2150  elog(ERROR, "could not remove directory \"%s\": %m",
2151  dst_dbpath);
2152  }
2153 
2154  /*
2155  * Use an ENSURE block to make sure we remove the debris if the copy fails
2156  * (eg, due to out-of-disk-space). This is not a 100% solution, because
2157  * of the possibility of failure during transaction commit, but it should
2158  * handle most scenarios.
2159  */
2160  fparms.dest_dboid = db_id;
2161  fparms.dest_tsoid = dst_tblspcoid;
2163  PointerGetDatum(&fparms));
2164  {
2165  Datum new_record[Natts_pg_database] = {0};
2166  bool new_record_nulls[Natts_pg_database] = {0};
2167  bool new_record_repl[Natts_pg_database] = {0};
2168 
2169  /*
2170  * Copy files from the old tablespace to the new one
2171  */
2172  copydir(src_dbpath, dst_dbpath, false);
2173 
2174  /*
2175  * Record the filesystem change in XLOG
2176  */
2177  {
2179 
2180  xlrec.db_id = db_id;
2181  xlrec.tablespace_id = dst_tblspcoid;
2182  xlrec.src_db_id = db_id;
2183  xlrec.src_tablespace_id = src_tblspcoid;
2184 
2185  XLogBeginInsert();
2186  XLogRegisterData((char *) &xlrec,
2188 
2189  (void) XLogInsert(RM_DBASE_ID,
2191  }
2192 
2193  /*
2194  * Update the database's pg_database tuple
2195  */
2196  ScanKeyInit(&scankey,
2197  Anum_pg_database_datname,
2198  BTEqualStrategyNumber, F_NAMEEQ,
2200  sysscan = systable_beginscan(pgdbrel, DatabaseNameIndexId, true,
2201  NULL, 1, &scankey);
2202  oldtuple = systable_getnext(sysscan);
2203  if (!HeapTupleIsValid(oldtuple)) /* shouldn't happen... */
2204  ereport(ERROR,
2205  (errcode(ERRCODE_UNDEFINED_DATABASE),
2206  errmsg("database \"%s\" does not exist", dbname)));
2207  LockTuple(pgdbrel, &oldtuple->t_self, InplaceUpdateTupleLock);
2208 
2209  new_record[Anum_pg_database_dattablespace - 1] = ObjectIdGetDatum(dst_tblspcoid);
2210  new_record_repl[Anum_pg_database_dattablespace - 1] = true;
2211 
2212  newtuple = heap_modify_tuple(oldtuple, RelationGetDescr(pgdbrel),
2213  new_record,
2214  new_record_nulls, new_record_repl);
2215  CatalogTupleUpdate(pgdbrel, &oldtuple->t_self, newtuple);
2216  UnlockTuple(pgdbrel, &oldtuple->t_self, InplaceUpdateTupleLock);
2217 
2218  InvokeObjectPostAlterHook(DatabaseRelationId, db_id, 0);
2219 
2220  systable_endscan(sysscan);
2221 
2222  /*
2223  * Force another checkpoint here. As in CREATE DATABASE, this is to
2224  * ensure that we don't have to replay a committed
2225  * XLOG_DBASE_CREATE_FILE_COPY operation, which would cause us to lose
2226  * any unlogged operations done in the new DB tablespace before the
2227  * next checkpoint.
2228  */
2230 
2231  /*
2232  * Force synchronous commit, thus minimizing the window between
2233  * copying the database files and committal of the transaction. If we
2234  * crash before committing, we'll leave an orphaned set of files on
2235  * disk, which is not fatal but not good either.
2236  */
2237  ForceSyncCommit();
2238 
2239  /*
2240  * Close pg_database, but keep lock till commit.
2241  */
2242  table_close(pgdbrel, NoLock);
2243  }
2245  PointerGetDatum(&fparms));
2246 
2247  /*
2248  * Commit the transaction so that the pg_database update is committed. If
2249  * we crash while removing files, the database won't be corrupt, we'll
2250  * just leave some orphaned files in the old directory.
2251  *
2252  * (This is OK because we know we aren't inside a transaction block.)
2253  *
2254  * XXX would it be safe/better to do this inside the ensure block? Not
2255  * convinced it's a good idea; consider elog just after the transaction
2256  * really commits.
2257  */
2260 
2261  /* Start new transaction for the remaining work; don't need a snapshot */
2263 
2264  /*
2265  * Remove files from the old tablespace
2266  */
2267  if (!rmtree(src_dbpath, true))
2268  ereport(WARNING,
2269  (errmsg("some useless files may be left behind in old database directory \"%s\"",
2270  src_dbpath)));
2271 
2272  /*
2273  * Record the filesystem change in XLOG
2274  */
2275  {
2276  xl_dbase_drop_rec xlrec;
2277 
2278  xlrec.db_id = db_id;
2279  xlrec.ntablespaces = 1;
2280 
2281  XLogBeginInsert();
2282  XLogRegisterData((char *) &xlrec, sizeof(xl_dbase_drop_rec));
2283  XLogRegisterData((char *) &src_tblspcoid, sizeof(Oid));
2284 
2285  (void) XLogInsert(RM_DBASE_ID,
2287  }
2288 
2289  /* Now it's safe to release the database lock */
2290  UnlockSharedObjectForSession(DatabaseRelationId, db_id, 0,
2292 
2293  pfree(src_dbpath);
2294  pfree(dst_dbpath);
2295 }
static void movedb_failure_callback(int code, Datum arg)
Definition: dbcommands.c:2299
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2931
int FreeDir(DIR *dir)
Definition: fd.c:2983
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2865
void PopActiveSnapshot(void)
Definition: snapmgr.c:707
Definition: dirent.c:26
Definition: dirent.h:10
char d_name[MAX_PATH]
Definition: dirent.h:15
void StartTransactionCommand(void)
Definition: xact.c:3051
void CommitTransactionCommand(void)
Definition: xact.c:3149

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_file_copy_rec::db_id, xl_dbase_drop_rec::db_id, dbname, movedb_failure_params::dest_dboid, movedb_failure_params::dest_tsoid, DropDatabaseBuffers(), elog, EmitProcSignalBarrier(), ereport, errcode(), errdetail_busy_db(), errhint(), errmsg(), ERROR, ForceSyncCommit(), FreeDir(), get_db_info(), get_tablespace_oid(), GetDatabasePath(), GetUserId(), heap_modify_tuple(), HeapTupleIsValid, InplaceUpdateTupleLock, InvokeObjectPostAlterHook, LockSharedObjectForSession(), LockTuple(), movedb_failure_callback(), MyDatabaseId, NoLock, xl_dbase_drop_rec::ntablespaces, object_aclcheck(), OBJECT_DATABASE, object_ownercheck(), OBJECT_TABLESPACE, ObjectIdGetDatum(), pfree(), PG_END_ENSURE_ERROR_CLEANUP, PG_ENSURE_ERROR_CLEANUP, PointerGetDatum(), PopActiveSnapshot(), PROCSIGNAL_BARRIER_SMGRRELEASE, ReadDir(), RelationGetDescr, RequestCheckpoint(), rmtree(), RowExclusiveLock, ScanKeyInit(), xl_dbase_create_file_copy_rec::src_db_id, xl_dbase_create_file_copy_rec::src_tablespace_id, StartTransactionCommand(), systable_beginscan(), systable_endscan(), systable_getnext(), HeapTupleData::t_self, table_close(), table_open(), xl_dbase_create_file_copy_rec::tablespace_id, UnlockSharedObjectForSession(), UnlockTuple(), WaitForProcSignalBarrier(), WARNING, XLOG_DBASE_CREATE_FILE_COPY, 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 2299 of file dbcommands.c.

2300 {
2302  char *dstpath;
2303 
2304  /* Get rid of anything we managed to copy to the target directory */
2305  dstpath = GetDatabasePath(fparms->dest_dboid, fparms->dest_tsoid);
2306 
2307  (void) rmtree(dstpath, true);
2308 
2309  pfree(dstpath);
2310 }

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

Referenced by movedb().

◆ pg_database_collation_actual_version()

Datum pg_database_collation_actual_version ( PG_FUNCTION_ARGS  )

Definition at line 2750 of file dbcommands.c.

2751 {
2752  Oid dbid = PG_GETARG_OID(0);
2753  HeapTuple tp;
2754  char datlocprovider;
2755  Datum datum;
2756  char *version;
2757 
2758  tp = SearchSysCache1(DATABASEOID, ObjectIdGetDatum(dbid));
2759  if (!HeapTupleIsValid(tp))
2760  ereport(ERROR,
2761  (errcode(ERRCODE_UNDEFINED_OBJECT),
2762  errmsg("database with OID %u does not exist", dbid)));
2763 
2765 
2766  if (datlocprovider == COLLPROVIDER_LIBC)
2767  datum = SysCacheGetAttrNotNull(DATABASEOID, tp, Anum_pg_database_datcollate);
2768  else
2769  datum = SysCacheGetAttrNotNull(DATABASEOID, tp, Anum_pg_database_datlocale);
2770 
2772  TextDatumGetCString(datum));
2773 
2774  ReleaseSysCache(tp);
2775 
2776  if (version)
2778  else
2779  PG_RETURN_NULL();
2780 }
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
#define PG_RETURN_NULL()
Definition: fmgr.h:345
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:372
char datlocprovider
Definition: pg_database.h:44
text * cstring_to_text(const char *s)
Definition: varlena.c:184

References cstring_to_text(), datlocprovider, ereport, errcode(), errmsg(), ERROR, get_collation_actual_version(), GETSTRUCT, HeapTupleIsValid, ObjectIdGetDatum(), PG_GETARG_OID, PG_RETURN_NULL, PG_RETURN_TEXT_P, ReleaseSysCache(), SearchSysCache1(), SysCacheGetAttrNotNull(), and TextDatumGetCString.

◆ recovery_create_dbdir()

static void recovery_create_dbdir ( char *  path,
bool  only_tblspc 
)
static

Definition at line 3254 of file dbcommands.c.

3255 {
3256  struct stat st;
3257 
3259 
3260  if (stat(path, &st) == 0)
3261  return;
3262 
3263  if (only_tblspc && strstr(path, PG_TBLSPC_DIR_SLASH) == NULL)
3264  elog(PANIC, "requested to created invalid directory: %s", path);
3265 
3267  ereport(PANIC,
3268  errmsg("missing directory \"%s\"", path));
3269 
3271  "creating missing directory: %s", path);
3272 
3273  if (pg_mkdir_p(path, pg_dir_create_mode) != 0)
3274  ereport(PANIC,
3275  errmsg("could not create missing directory \"%s\": %m", path));
3276 }
bool allow_in_place_tablespaces
Definition: tablespace.c:85
#define DEBUG1
Definition: elog.h:30
int pg_dir_create_mode
Definition: file_perm.c:18
int pg_mkdir_p(char *path, int omode)
Definition: pgmkdirp.c:57
#define PG_TBLSPC_DIR_SLASH
Definition: relpath.h:42
bool RecoveryInProgress(void)
Definition: xlog.c:6334
bool reachedConsistency
Definition: xlogrecovery.c:294

References allow_in_place_tablespaces, Assert, DEBUG1, elog, ereport, errmsg(), PANIC, pg_dir_create_mode, pg_mkdir_p(), PG_TBLSPC_DIR_SLASH, reachedConsistency, RecoveryInProgress(), stat, and WARNING.

Referenced by dbase_redo().

◆ remove_dbtablespaces()

static void remove_dbtablespaces ( Oid  db_id)
static

Definition at line 2977 of file dbcommands.c.

2978 {
2979  Relation rel;
2980  TableScanDesc scan;
2981  HeapTuple tuple;
2982  List *ltblspc = NIL;
2983  ListCell *cell;
2984  int ntblspc;
2985  int i;
2986  Oid *tablespace_ids;
2987 
2988  rel = table_open(TableSpaceRelationId, AccessShareLock);
2989  scan = table_beginscan_catalog(rel, 0, NULL);
2990  while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
2991  {
2992  Form_pg_tablespace spcform = (Form_pg_tablespace) GETSTRUCT(tuple);
2993  Oid dsttablespace = spcform->oid;
2994  char *dstpath;
2995  struct stat st;
2996 
2997  /* Don't mess with the global tablespace */
2998  if (dsttablespace == GLOBALTABLESPACE_OID)
2999  continue;
3000 
3001  dstpath = GetDatabasePath(db_id, dsttablespace);
3002 
3003  if (lstat(dstpath, &st) < 0 || !S_ISDIR(st.st_mode))
3004  {
3005  /* Assume we can ignore it */
3006  pfree(dstpath);
3007  continue;
3008  }
3009 
3010  if (!rmtree(dstpath, true))
3011  ereport(WARNING,
3012  (errmsg("some useless files may be left behind in old database directory \"%s\"",
3013  dstpath)));
3014 
3015  ltblspc = lappend_oid(ltblspc, dsttablespace);
3016  pfree(dstpath);
3017  }
3018 
3019  ntblspc = list_length(ltblspc);
3020  if (ntblspc == 0)
3021  {
3022  table_endscan(scan);
3024  return;
3025  }
3026 
3027  tablespace_ids = (Oid *) palloc(ntblspc * sizeof(Oid));
3028  i = 0;
3029  foreach(cell, ltblspc)
3030  tablespace_ids[i++] = lfirst_oid(cell);
3031 
3032  /* Record the filesystem change in XLOG */
3033  {
3034  xl_dbase_drop_rec xlrec;
3035 
3036  xlrec.db_id = db_id;
3037  xlrec.ntablespaces = ntblspc;
3038 
3039  XLogBeginInsert();
3040  XLogRegisterData((char *) &xlrec, MinSizeOfDbaseDropRec);
3041  XLogRegisterData((char *) tablespace_ids, ntblspc * sizeof(Oid));
3042 
3043  (void) XLogInsert(RM_DBASE_ID,
3045  }
3046 
3047  list_free(ltblspc);
3048  pfree(tablespace_ids);
3049 
3050  table_endscan(scan);
3052 }
#define MinSizeOfDbaseDropRec
List * lappend_oid(List *list, Oid datum)
Definition: list.c:375
void list_free(List *list)
Definition: list.c:1546
void * palloc(Size size)
Definition: mcxt.c:1317
#define lfirst_oid(lc)
Definition: pg_list.h:174

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 1876 of file dbcommands.c.

1877 {
1878  Oid db_id;
1879  HeapTuple newtup;
1880  ItemPointerData otid;
1881  Relation rel;
1882  int notherbackends;
1883  int npreparedxacts;
1884  ObjectAddress address;
1885 
1886  /*
1887  * Look up the target database's OID, and get exclusive lock on it. We
1888  * need this for the same reasons as DROP DATABASE.
1889  */
1890  rel = table_open(DatabaseRelationId, RowExclusiveLock);
1891 
1892  if (!get_db_info(oldname, AccessExclusiveLock, &db_id, NULL, NULL, NULL,
1893  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL))
1894  ereport(ERROR,
1895  (errcode(ERRCODE_UNDEFINED_DATABASE),
1896  errmsg("database \"%s\" does not exist", oldname)));
1897 
1898  /* must be owner */
1899  if (!object_ownercheck(DatabaseRelationId, db_id, GetUserId()))
1901  oldname);
1902 
1903  /* must have createdb rights */
1904  if (!have_createdb_privilege())
1905  ereport(ERROR,
1906  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1907  errmsg("permission denied to rename database")));
1908 
1909  /*
1910  * If built with appropriate switch, whine when regression-testing
1911  * conventions for database names are violated.
1912  */
1913 #ifdef ENFORCE_REGRESSION_TEST_NAME_RESTRICTIONS
1914  if (strstr(newname, "regression") == NULL)
1915  elog(WARNING, "databases created by regression test cases should have names including \"regression\"");
1916 #endif
1917 
1918  /*
1919  * Make sure the new name doesn't exist. See notes for same error in
1920  * CREATE DATABASE.
1921  */
1922  if (OidIsValid(get_database_oid(newname, true)))
1923  ereport(ERROR,
1924  (errcode(ERRCODE_DUPLICATE_DATABASE),
1925  errmsg("database \"%s\" already exists", newname)));
1926 
1927  /*
1928  * XXX Client applications probably store the current database somewhere,
1929  * so renaming it could cause confusion. On the other hand, there may not
1930  * be an actual problem besides a little confusion, so think about this
1931  * and decide.
1932  */
1933  if (db_id == MyDatabaseId)
1934  ereport(ERROR,
1935  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1936  errmsg("current database cannot be renamed")));
1937 
1938  /*
1939  * Make sure the database does not have active sessions. This is the same
1940  * concern as above, but applied to other sessions.
1941  *
1942  * As in CREATE DATABASE, check this after other error conditions.
1943  */
1944  if (CountOtherDBBackends(db_id, &notherbackends, &npreparedxacts))
1945  ereport(ERROR,
1946  (errcode(ERRCODE_OBJECT_IN_USE),
1947  errmsg("database \"%s\" is being accessed by other users",
1948  oldname),
1949  errdetail_busy_db(notherbackends, npreparedxacts)));
1950 
1951  /* rename */
1952  newtup = SearchSysCacheLockedCopy1(DATABASEOID, ObjectIdGetDatum(db_id));
1953  if (!HeapTupleIsValid(newtup))
1954  elog(ERROR, "cache lookup failed for database %u", db_id);
1955  otid = newtup->t_self;
1956  namestrcpy(&(((Form_pg_database) GETSTRUCT(newtup))->datname), newname);
1957  CatalogTupleUpdate(rel, &otid, newtup);
1958  UnlockTuple(rel, &otid, InplaceUpdateTupleLock);
1959 
1960  InvokeObjectPostAlterHook(DatabaseRelationId, db_id, 0);
1961 
1962  ObjectAddressSet(address, DatabaseRelationId, db_id);
1963 
1964  /*
1965  * Close pg_database, but keep lock till commit.
1966  */
1967  table_close(rel, NoLock);
1968 
1969  return address;
1970 }
void namestrcpy(Name name, const char *str)
Definition: name.c:233
HeapTuple SearchSysCacheLockedCopy1(int cacheId, Datum key1)
Definition: syscache.c:404

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

Referenced by ExecRenameStmt().

◆ ScanSourceDatabasePgClass()

static List * ScanSourceDatabasePgClass ( Oid  tbid,
Oid  dbid,
char *  srcpath 
)
static

Definition at line 250 of file dbcommands.c.

251 {
252  RelFileLocator rlocator;
253  BlockNumber nblocks;
254  BlockNumber blkno;
255  Buffer buf;
256  RelFileNumber relfilenumber;
257  Page page;
258  List *rlocatorlist = NIL;
259  LockRelId relid;
260  Snapshot snapshot;
261  SMgrRelation smgr;
262  BufferAccessStrategy bstrategy;
263 
264  /* Get pg_class relfilenumber. */
265  relfilenumber = RelationMapOidToFilenumberForDatabase(srcpath,
266  RelationRelationId);
267 
268  /* Don't read data into shared_buffers without holding a relation lock. */
269  relid.dbId = dbid;
270  relid.relId = RelationRelationId;
272 
273  /* Prepare a RelFileLocator for the pg_class relation. */
274  rlocator.spcOid = tbid;
275  rlocator.dbOid = dbid;
276  rlocator.relNumber = relfilenumber;
277 
278  smgr = smgropen(rlocator, INVALID_PROC_NUMBER);
279  nblocks = smgrnblocks(smgr, MAIN_FORKNUM);
280  smgrclose(smgr);
281 
282  /* Use a buffer access strategy since this is a bulk read operation. */
283  bstrategy = GetAccessStrategy(BAS_BULKREAD);
284 
285  /*
286  * As explained in the function header comments, we need a snapshot that
287  * will see all committed transactions as committed, and our transaction
288  * snapshot - or the active snapshot - might not be new enough for that,
289  * but the return value of GetLatestSnapshot() should work fine.
290  */
291  snapshot = GetLatestSnapshot();
292 
293  /* Process the relation block by block. */
294  for (blkno = 0; blkno < nblocks; blkno++)
295  {
297 
298  buf = ReadBufferWithoutRelcache(rlocator, MAIN_FORKNUM, blkno,
299  RBM_NORMAL, bstrategy, true);
300 
302  page = BufferGetPage(buf);
303  if (PageIsNew(page) || PageIsEmpty(page))
304  {
306  continue;
307  }
308 
309  /* Append relevant pg_class tuples for current page to rlocatorlist. */
310  rlocatorlist = ScanSourceDatabasePgClassPage(page, buf, tbid, dbid,
311  srcpath, rlocatorlist,
312  snapshot);
313 
315  }
316 
317  /* Release relation lock. */
319 
320  return rlocatorlist;
321 }
uint32 BlockNumber
Definition: block.h:31
int Buffer
Definition: buf.h:23
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:4941
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:5158
Buffer ReadBufferWithoutRelcache(RelFileLocator rlocator, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy, bool permanent)
Definition: bufmgr.c:830
@ BAS_BULKREAD
Definition: bufmgr.h:36
#define BUFFER_LOCK_SHARE
Definition: bufmgr.h:190
static Page BufferGetPage(Buffer buffer)
Definition: bufmgr.h:400
@ RBM_NORMAL
Definition: bufmgr.h:45
static bool PageIsEmpty(Page page)
Definition: bufpage.h:223
Pointer Page
Definition: bufpage.h:81
static bool PageIsNew(Page page)
Definition: bufpage.h:233
static List * ScanSourceDatabasePgClassPage(Page page, Buffer buf, Oid tbid, Oid dbid, char *srcpath, List *rlocatorlist, Snapshot snapshot)
Definition: dbcommands.c:328
BufferAccessStrategy GetAccessStrategy(BufferAccessStrategyType btype)
Definition: freelist.c:541
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:122
#define INVALID_PROC_NUMBER
Definition: procnumber.h:26
RelFileNumber RelationMapOidToFilenumberForDatabase(char *dbpath, Oid relationId)
Definition: relmapper.c:265
Oid RelFileNumber
Definition: relpath.h:25
@ MAIN_FORKNUM
Definition: relpath.h:58
BlockNumber smgrnblocks(SMgrRelation reln, ForkNumber forknum)
Definition: smgr.c:677
SMgrRelation smgropen(RelFileLocator rlocator, ProcNumber backend)
Definition: smgr.c:201
void smgrclose(SMgrRelation reln)
Definition: smgr.c:323
Snapshot GetLatestSnapshot(void)
Definition: snapmgr.c:287

References AccessShareLock, BAS_BULKREAD, buf, BUFFER_LOCK_SHARE, BufferGetPage(), CHECK_FOR_INTERRUPTS, LockRelId::dbId, RelFileLocator::dbOid, GetAccessStrategy(), GetLatestSnapshot(), INVALID_PROC_NUMBER, LockBuffer(), LockRelationId(), MAIN_FORKNUM, NIL, PageIsEmpty(), PageIsNew(), RBM_NORMAL, ReadBufferWithoutRelcache(), RelationMapOidToFilenumberForDatabase(), LockRelId::relId, RelFileLocator::relNumber, ScanSourceDatabasePgClassPage(), smgrclose(), smgrnblocks(), smgropen(), RelFileLocator::spcOid, UnlockRelationId(), and UnlockReleaseBuffer().

Referenced by CreateDatabaseUsingWalLog().

◆ ScanSourceDatabasePgClassPage()

static List * ScanSourceDatabasePgClassPage ( Page  page,
Buffer  buf,
Oid  tbid,
Oid  dbid,
char *  srcpath,
List rlocatorlist,
Snapshot  snapshot 
)
static

Definition at line 328 of file dbcommands.c.

331 {
333  OffsetNumber offnum;
334  OffsetNumber maxoff;
335  HeapTupleData tuple;
336 
337  maxoff = PageGetMaxOffsetNumber(page);
338 
339  /* Loop over offsets. */
340  for (offnum = FirstOffsetNumber;
341  offnum <= maxoff;
342  offnum = OffsetNumberNext(offnum))
343  {
344  ItemId itemid;
345 
346  itemid = PageGetItemId(page, offnum);
347 
348  /* Nothing to do if slot is empty or already dead. */
349  if (!ItemIdIsUsed(itemid) || ItemIdIsDead(itemid) ||
350  ItemIdIsRedirected(itemid))
351  continue;
352 
353  Assert(ItemIdIsNormal(itemid));
354  ItemPointerSet(&(tuple.t_self), blkno, offnum);
355 
356  /* Initialize a HeapTupleData structure. */
357  tuple.t_data = (HeapTupleHeader) PageGetItem(page, itemid);
358  tuple.t_len = ItemIdGetLength(itemid);
359  tuple.t_tableOid = RelationRelationId;
360 
361  /* Skip tuples that are not visible to this snapshot. */
362  if (HeapTupleSatisfiesVisibility(&tuple, snapshot, buf))
363  {
364  CreateDBRelInfo *relinfo;
365 
366  /*
367  * ScanSourceDatabasePgClassTuple is in charge of constructing a
368  * CreateDBRelInfo object for this tuple, but can also decide that
369  * this tuple isn't something we need to copy. If we do need to
370  * copy the relation, add it to the list.
371  */
372  relinfo = ScanSourceDatabasePgClassTuple(&tuple, tbid, dbid,
373  srcpath);
374  if (relinfo != NULL)
375  rlocatorlist = lappend(rlocatorlist, relinfo);
376  }
377  }
378 
379  return rlocatorlist;
380 }
BlockNumber BufferGetBlockNumber(Buffer buffer)
Definition: bufmgr.c:3724
static Item PageGetItem(Page page, ItemId itemId)
Definition: bufpage.h:354
static ItemId PageGetItemId(Page page, OffsetNumber offsetNumber)
Definition: bufpage.h:243
static OffsetNumber PageGetMaxOffsetNumber(Page page)
Definition: bufpage.h:372
static CreateDBRelInfo * ScanSourceDatabasePgClassTuple(HeapTupleData *tuple, Oid tbid, Oid dbid, char *srcpath)
Definition: dbcommands.c:391
bool HeapTupleSatisfiesVisibility(HeapTuple htup, Snapshot snapshot, Buffer buffer)
HeapTupleHeaderData * HeapTupleHeader
Definition: htup.h:23
#define ItemIdGetLength(itemId)
Definition: itemid.h:59
#define ItemIdIsNormal(itemId)
Definition: itemid.h:99
#define ItemIdIsDead(itemId)
Definition: itemid.h:113
#define ItemIdIsUsed(itemId)
Definition: itemid.h:92
#define ItemIdIsRedirected(itemId)
Definition: itemid.h:106
static void ItemPointerSet(ItemPointerData *pointer, BlockNumber blockNumber, OffsetNumber offNum)
Definition: itemptr.h:135
List * lappend(List *list, void *datum)
Definition: list.c:339
#define OffsetNumberNext(offsetNumber)
Definition: off.h:52
uint16 OffsetNumber
Definition: off.h:24
#define FirstOffsetNumber
Definition: off.h:27
uint32 t_len
Definition: htup.h:64
HeapTupleHeader t_data
Definition: htup.h:68
Oid t_tableOid
Definition: htup.h:66

References Assert, buf, BufferGetBlockNumber(), FirstOffsetNumber, HeapTupleSatisfiesVisibility(), ItemIdGetLength, ItemIdIsDead, ItemIdIsNormal, ItemIdIsRedirected, ItemIdIsUsed, ItemPointerSet(), lappend(), OffsetNumberNext, PageGetItem(), PageGetItemId(), PageGetMaxOffsetNumber(), ScanSourceDatabasePgClassTuple(), HeapTupleData::t_data, HeapTupleData::t_len, HeapTupleData::t_self, and HeapTupleData::t_tableOid.

Referenced by ScanSourceDatabasePgClass().

◆ ScanSourceDatabasePgClassTuple()

CreateDBRelInfo * ScanSourceDatabasePgClassTuple ( HeapTupleData tuple,
Oid  tbid,
Oid  dbid,
char *  srcpath 
)
static

Definition at line 391 of file dbcommands.c.

393 {
394  CreateDBRelInfo *relinfo;
395  Form_pg_class classForm;
396  RelFileNumber relfilenumber = InvalidRelFileNumber;
397 
398  classForm = (Form_pg_class) GETSTRUCT(tuple);
399 
400  /*
401  * Return NULL if this object does not need to be copied.
402  *
403  * Shared objects don't need to be copied, because they are shared.
404  * Objects without storage can't be copied, because there's nothing to
405  * copy. Temporary relations don't need to be copied either, because they
406  * are inaccessible outside of the session that created them, which must
407  * be gone already, and couldn't connect to a different database if it
408  * still existed. autovacuum will eventually remove the pg_class entries
409  * as well.
410  */
411  if (classForm->reltablespace == GLOBALTABLESPACE_OID ||
412  !RELKIND_HAS_STORAGE(classForm->relkind) ||
413  classForm->relpersistence == RELPERSISTENCE_TEMP)
414  return NULL;
415 
416  /*
417  * If relfilenumber is valid then directly use it. Otherwise, consult the
418  * relmap.
419  */
420  if (RelFileNumberIsValid(classForm->relfilenode))
421  relfilenumber = classForm->relfilenode;
422  else
423  relfilenumber = RelationMapOidToFilenumberForDatabase(srcpath,
424  classForm->oid);
425 
426  /* We must have a valid relfilenumber. */
427  if (!RelFileNumberIsValid(relfilenumber))
428  elog(ERROR, "relation with OID %u does not have a valid relfilenumber",
429  classForm->oid);
430 
431  /* Prepare a rel info element and add it to the list. */
432  relinfo = (CreateDBRelInfo *) palloc(sizeof(CreateDBRelInfo));
433  if (OidIsValid(classForm->reltablespace))
434  relinfo->rlocator.spcOid = classForm->reltablespace;
435  else
436  relinfo->rlocator.spcOid = tbid;
437 
438  relinfo->rlocator.dbOid = dbid;
439  relinfo->rlocator.relNumber = relfilenumber;
440  relinfo->reloid = classForm->oid;
441 
442  /* Temporary relations were rejected above. */
443  Assert(classForm->relpersistence != RELPERSISTENCE_TEMP);
444  relinfo->permanent =
445  (classForm->relpersistence == RELPERSISTENCE_PERMANENT) ? true : false;
446 
447  return relinfo;
448 }
FormData_pg_class * Form_pg_class
Definition: pg_class.h:153
#define InvalidRelFileNumber
Definition: relpath.h:26
#define RelFileNumberIsValid(relnumber)
Definition: relpath.h:27

References Assert, RelFileLocator::dbOid, elog, ERROR, GETSTRUCT, InvalidRelFileNumber, OidIsValid, palloc(), CreateDBRelInfo::permanent, RelationMapOidToFilenumberForDatabase(), RelFileNumberIsValid, RelFileLocator::relNumber, CreateDBRelInfo::reloid, CreateDBRelInfo::rlocator, and RelFileLocator::spcOid.

Referenced by ScanSourceDatabasePgClassPage().