⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dbcommands.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 3 页
字号:
		if (valuestr)			a = GUCArrayAdd(a, stmt->variable, valuestr);		else			a = GUCArrayDelete(a, stmt->variable);		if (a)			repl_val[Anum_pg_database_datconfig - 1] = PointerGetDatum(a);		else			repl_null[Anum_pg_database_datconfig - 1] = 'n';	}	newtuple = heap_modifytuple(tuple, RelationGetDescr(rel), repl_val, repl_null, repl_repl);	simple_heap_update(rel, &tuple->t_self, newtuple);	/* Update indexes */	CatalogUpdateIndexes(rel, newtuple);	systable_endscan(scan);	/* Close pg_database, but keep lock till commit */	heap_close(rel, NoLock);	/*	 * We don't bother updating the flat file since ALTER DATABASE SET doesn't	 * affect it.	 */}/* * ALTER DATABASE name OWNER TO newowner */voidAlterDatabaseOwner(const char *dbname, Oid newOwnerId){	HeapTuple	tuple;	Relation	rel;	ScanKeyData scankey;	SysScanDesc scan;	Form_pg_database datForm;	/*	 * We don't need ExclusiveLock since we aren't updating the flat file.	 */	rel = heap_open(DatabaseRelationId, RowExclusiveLock);	ScanKeyInit(&scankey,				Anum_pg_database_datname,				BTEqualStrategyNumber, F_NAMEEQ,				NameGetDatum(dbname));	scan = systable_beginscan(rel, DatabaseNameIndexId, true,							  SnapshotNow, 1, &scankey);	tuple = systable_getnext(scan);	if (!HeapTupleIsValid(tuple))		ereport(ERROR,				(errcode(ERRCODE_UNDEFINED_DATABASE),				 errmsg("database \"%s\" does not exist", dbname)));	datForm = (Form_pg_database) GETSTRUCT(tuple);	/*	 * If the new owner is the same as the existing owner, consider the	 * command to have succeeded.  This is to be consistent with other	 * objects.	 */	if (datForm->datdba != newOwnerId)	{		Datum		repl_val[Natts_pg_database];		char		repl_null[Natts_pg_database];		char		repl_repl[Natts_pg_database];		Acl		   *newAcl;		Datum		aclDatum;		bool		isNull;		HeapTuple	newtuple;		/* Otherwise, must be owner of the existing object */		if (!pg_database_ownercheck(HeapTupleGetOid(tuple), GetUserId()))			aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_DATABASE,						   dbname);		/* Must be able to become new owner */		check_is_member_of_role(GetUserId(), newOwnerId);		/*		 * must have createdb rights		 *		 * NOTE: This is different from other alter-owner checks in that the		 * current user is checked for createdb privileges instead of the		 * destination owner.  This is consistent with the CREATE case for		 * databases.  Because superusers will always have this right, we need		 * no special case for them.		 */		if (!have_createdb_privilege())			ereport(ERROR,					(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),				   errmsg("permission denied to change owner of database")));		memset(repl_null, ' ', sizeof(repl_null));		memset(repl_repl, ' ', sizeof(repl_repl));		repl_repl[Anum_pg_database_datdba - 1] = 'r';		repl_val[Anum_pg_database_datdba - 1] = ObjectIdGetDatum(newOwnerId);		/*		 * Determine the modified ACL for the new owner.  This is only		 * necessary when the ACL is non-null.		 */		aclDatum = heap_getattr(tuple,								Anum_pg_database_datacl,								RelationGetDescr(rel),								&isNull);		if (!isNull)		{			newAcl = aclnewowner(DatumGetAclP(aclDatum),								 datForm->datdba, newOwnerId);			repl_repl[Anum_pg_database_datacl - 1] = 'r';			repl_val[Anum_pg_database_datacl - 1] = PointerGetDatum(newAcl);		}		newtuple = heap_modifytuple(tuple, RelationGetDescr(rel), repl_val, repl_null, repl_repl);		simple_heap_update(rel, &newtuple->t_self, newtuple);		CatalogUpdateIndexes(rel, newtuple);		heap_freetuple(newtuple);		/* Update owner dependency reference */		changeDependencyOnOwner(DatabaseRelationId, HeapTupleGetOid(tuple),								newOwnerId);	}	systable_endscan(scan);	/* Close pg_database, but keep lock till commit */	heap_close(rel, NoLock);	/*	 * We don't bother updating the flat file since ALTER DATABASE OWNER	 * doesn't affect it.	 */}/* * Helper functions */static boolget_db_info(const char *name, Oid *dbIdP, Oid *ownerIdP,			int *encodingP, bool *dbIsTemplateP, bool *dbAllowConnP,			Oid *dbLastSysOidP,			TransactionId *dbVacuumXidP, TransactionId *dbFrozenXidP,			Oid *dbTablespace){	Relation	relation;	ScanKeyData scanKey;	SysScanDesc scan;	HeapTuple	tuple;	bool		gottuple;	AssertArg(name);	/* Caller may wish to grab a better lock on pg_database beforehand... */	relation = heap_open(DatabaseRelationId, AccessShareLock);	ScanKeyInit(&scanKey,				Anum_pg_database_datname,				BTEqualStrategyNumber, F_NAMEEQ,				NameGetDatum(name));	scan = systable_beginscan(relation, DatabaseNameIndexId, true,							  SnapshotNow, 1, &scanKey);	tuple = systable_getnext(scan);	gottuple = HeapTupleIsValid(tuple);	if (gottuple)	{		Form_pg_database dbform = (Form_pg_database) GETSTRUCT(tuple);		/* oid of the database */		if (dbIdP)			*dbIdP = HeapTupleGetOid(tuple);		/* oid of the owner */		if (ownerIdP)			*ownerIdP = dbform->datdba;		/* character encoding */		if (encodingP)			*encodingP = dbform->encoding;		/* allowed as template? */		if (dbIsTemplateP)			*dbIsTemplateP = dbform->datistemplate;		/* allowing connections? */		if (dbAllowConnP)			*dbAllowConnP = dbform->datallowconn;		/* last system OID used in database */		if (dbLastSysOidP)			*dbLastSysOidP = dbform->datlastsysoid;		/* limit of vacuumed XIDs */		if (dbVacuumXidP)			*dbVacuumXidP = dbform->datvacuumxid;		/* limit of frozen XIDs */		if (dbFrozenXidP)			*dbFrozenXidP = dbform->datfrozenxid;		/* default tablespace for this database */		if (dbTablespace)			*dbTablespace = dbform->dattablespace;	}	systable_endscan(scan);	heap_close(relation, AccessShareLock);	return gottuple;}/* Check if current user has createdb privileges */static boolhave_createdb_privilege(void){	bool		result = false;	HeapTuple	utup;	/* Superusers can always do everything */	if (superuser())		return true;	utup = SearchSysCache(AUTHOID,						  ObjectIdGetDatum(GetUserId()),						  0, 0, 0);	if (HeapTupleIsValid(utup))	{		result = ((Form_pg_authid) GETSTRUCT(utup))->rolcreatedb;		ReleaseSysCache(utup);	}	return result;}/* * Remove tablespace directories * * We don't know what tablespaces db_id is using, so iterate through all * tablespaces removing <tablespace>/db_id */static voidremove_dbtablespaces(Oid db_id){	Relation	rel;	HeapScanDesc scan;	HeapTuple	tuple;	rel = heap_open(TableSpaceRelationId, AccessShareLock);	scan = heap_beginscan(rel, SnapshotNow, 0, NULL);	while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)	{		Oid			dsttablespace = HeapTupleGetOid(tuple);		char	   *dstpath;		struct stat st;		/* Don't mess with the global tablespace */		if (dsttablespace == GLOBALTABLESPACE_OID)			continue;		dstpath = GetDatabasePath(db_id, dsttablespace);		if (stat(dstpath, &st) < 0 || !S_ISDIR(st.st_mode))		{			/* Assume we can ignore it */			pfree(dstpath);			continue;		}		if (!rmtree(dstpath, true))			ereport(WARNING,					(errmsg("could not remove database directory \"%s\"",							dstpath)));		/* Record the filesystem change in XLOG */		{			xl_dbase_drop_rec xlrec;			XLogRecData rdata[1];			xlrec.db_id = db_id;			xlrec.tablespace_id = dsttablespace;			rdata[0].data = (char *) &xlrec;			rdata[0].len = sizeof(xl_dbase_drop_rec);			rdata[0].buffer = InvalidBuffer;			rdata[0].next = NULL;			(void) XLogInsert(RM_DBASE_ID, XLOG_DBASE_DROP, rdata);		}		pfree(dstpath);	}	heap_endscan(scan);	heap_close(rel, AccessShareLock);}/* * get_database_oid - given a database name, look up the OID * * Returns InvalidOid if database name not found. * * This is not actually used in this file, but is exported for use elsewhere. */Oidget_database_oid(const char *dbname){	Relation	pg_database;	ScanKeyData entry[1];	SysScanDesc scan;	HeapTuple	dbtuple;	Oid			oid;	/* There's no syscache for pg_database, so must look the hard way */	pg_database = heap_open(DatabaseRelationId, AccessShareLock);	ScanKeyInit(&entry[0],				Anum_pg_database_datname,				BTEqualStrategyNumber, F_NAMEEQ,				CStringGetDatum(dbname));	scan = systable_beginscan(pg_database, DatabaseNameIndexId, true,							  SnapshotNow, 1, entry);	dbtuple = systable_getnext(scan);	/* We assume that there can be at most one matching tuple */	if (HeapTupleIsValid(dbtuple))		oid = HeapTupleGetOid(dbtuple);	else		oid = InvalidOid;	systable_endscan(scan);	heap_close(pg_database, AccessShareLock);	return oid;}/* * get_database_name - given a database OID, look up the name * * Returns a palloc'd string, or NULL if no such database. * * This is not actually used in this file, but is exported for use elsewhere. */char *get_database_name(Oid dbid){	Relation	pg_database;	ScanKeyData entry[1];	SysScanDesc scan;	HeapTuple	dbtuple;	char	   *result;	/* There's no syscache for pg_database, so must look the hard way */	pg_database = heap_open(DatabaseRelationId, AccessShareLock);	ScanKeyInit(&entry[0],				ObjectIdAttributeNumber,				BTEqualStrategyNumber, F_OIDEQ,				ObjectIdGetDatum(dbid));	scan = systable_beginscan(pg_database, DatabaseOidIndexId, true,							  SnapshotNow, 1, entry);	dbtuple = systable_getnext(scan);	/* We assume that there can be at most one matching tuple */	if (HeapTupleIsValid(dbtuple))		result = pstrdup(NameStr(((Form_pg_database) GETSTRUCT(dbtuple))->datname));	else		result = NULL;	systable_endscan(scan);	heap_close(pg_database, AccessShareLock);	return result;}/* * DATABASE resource manager's routines */voiddbase_redo(XLogRecPtr lsn, XLogRecord *record){	uint8		info = record->xl_info & ~XLR_INFO_MASK;	if (info == XLOG_DBASE_CREATE)	{		xl_dbase_create_rec *xlrec = (xl_dbase_create_rec *) XLogRecGetData(record);		char	   *src_path;		char	   *dst_path;		struct stat st;		src_path = GetDatabasePath(xlrec->src_db_id, xlrec->src_tablespace_id);		dst_path = GetDatabasePath(xlrec->db_id, xlrec->tablespace_id);		/*		 * Our theory for replaying a CREATE is to forcibly drop the target		 * subdirectory if present, then re-copy the source data. This may be		 * more work than needed, but it is simple to implement.		 */		if (stat(dst_path, &st) == 0 && S_ISDIR(st.st_mode))		{			if (!rmtree(dst_path, true))				ereport(WARNING,						(errmsg("could not remove database directory \"%s\"",								dst_path)));		}		/*		 * Force dirty buffers out to disk, to ensure source database is		 * up-to-date for the copy.  (We really only need to flush buffers for		 * the source database, but bufmgr.c provides no API for that.)		 */		BufferSync();		/*		 * Copy this subdirectory to the new location		 *		 * We don't need to copy subdirectories		 */		copydir(src_path, dst_path, false);	}	else if (info == XLOG_DBASE_DROP)	{		xl_dbase_drop_rec *xlrec = (xl_dbase_drop_rec *) XLogRecGetData(record);		char	   *dst_path;		dst_path = GetDatabasePath(xlrec->db_id, xlrec->tablespace_id);		/*		 * Drop pages for this database that are in the shared buffer cache		 */		DropBuffers(xlrec->db_id);		if (!rmtree(dst_path, true))			ereport(WARNING,					(errmsg("could not remove database directory \"%s\"",							dst_path)));	}	else		elog(PANIC, "dbase_redo: unknown op code %u", info);}voiddbase_desc(char *buf, uint8 xl_info, char *rec){	uint8		info = xl_info & ~XLR_INFO_MASK;	if (info == XLOG_DBASE_CREATE)	{		xl_dbase_create_rec *xlrec = (xl_dbase_create_rec *) rec;		sprintf(buf + strlen(buf), "create db: copy dir %u/%u to %u/%u",				xlrec->src_db_id, xlrec->src_tablespace_id,				xlrec->db_id, xlrec->tablespace_id);	}	else if (info == XLOG_DBASE_DROP)	{		xl_dbase_drop_rec *xlrec = (xl_dbase_drop_rec *) rec;		sprintf(buf + strlen(buf), "drop db: dir %u/%u",				xlrec->db_id, xlrec->tablespace_id);	}	else		strcat(buf, "UNKNOWN");}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -