mirror of
				https://github.com/postgres/postgres.git
				synced 2025-10-31 00:03:57 -04:00 
			
		
		
		
	Support toasting of shared system relations, and provide toast tables for
pg_database, pg_shadow, pg_group, all of which now have potentially-long fields. Along the way, get rid of SharedSystemRelationNames list: shared rels are now identified in their include/pg_catalog/*.h files by a BKI_SHARED_RELATION macro, while indexes and toast rels inherit sharedness automatically from their parent table. Fix some bugs with failure to detoast pg_group.grolist during ALTER GROUP.
This commit is contained in:
		
							parent
							
								
									108871f4fc
								
							
						
					
					
						commit
						c06f6a6bc2
					
				| @ -1,15 +1,15 @@ | ||||
| %{ | ||||
| /*------------------------------------------------------------------------- | ||||
|  * | ||||
|  * backendparse.y | ||||
|  *	  yacc parser grammer for the "backend" initialization program. | ||||
|  * bootparse.y | ||||
|  *	  yacc parser grammar for the "backend" initialization program. | ||||
|  * | ||||
|  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group | ||||
|  * Portions Copyright (c) 1994, Regents of the University of California | ||||
|  * | ||||
|  * | ||||
|  * IDENTIFICATION | ||||
|  *	  $Header: /cvsroot/pgsql/src/backend/bootstrap/bootparse.y,v 1.45 2002/04/17 20:57:56 tgl Exp $ | ||||
|  *	  $Header: /cvsroot/pgsql/src/backend/bootstrap/bootparse.y,v 1.46 2002/04/27 21:24:33 tgl Exp $ | ||||
|  * | ||||
|  *------------------------------------------------------------------------- | ||||
|  */ | ||||
| @ -88,8 +88,9 @@ int num_columns_read = 0; | ||||
| 
 | ||||
| %type <list>  boot_index_params | ||||
| %type <ielem> boot_index_param | ||||
| %type <ival> boot_const boot_ident | ||||
| %type <ival> optbootstrap optwithoutoids boot_tuple boot_tuplelist | ||||
| %type <ival>  boot_const boot_ident | ||||
| %type <ival>  optbootstrap optsharedrelation optwithoutoids | ||||
| %type <ival>  boot_tuple boot_tuplelist | ||||
| %type <oidval> optoideq | ||||
| 
 | ||||
| %token <ival> CONST ID | ||||
| @ -97,7 +98,7 @@ int num_columns_read = 0; | ||||
| %token STRING XDEFINE | ||||
| %token XDECLARE INDEX ON USING XBUILD INDICES UNIQUE | ||||
| %token COMMA EQUALS LPAREN RPAREN | ||||
| %token OBJ_ID XBOOTSTRAP XWITHOUT_OIDS NULLVAL | ||||
| %token OBJ_ID XBOOTSTRAP XSHARED_RELATION XWITHOUT_OIDS NULLVAL | ||||
| %start TopLevel | ||||
| 
 | ||||
| %nonassoc low | ||||
| @ -150,16 +151,14 @@ Boot_CloseStmt: | ||||
| 		; | ||||
| 
 | ||||
| Boot_CreateStmt: | ||||
| 		  XCREATE optbootstrap optwithoutoids boot_ident LPAREN | ||||
| 		  XCREATE optbootstrap optsharedrelation optwithoutoids boot_ident LPAREN | ||||
| 				{ | ||||
| 					do_start(); | ||||
| 					numattr = 0; | ||||
| 					if ($2) | ||||
| 						elog(DEBUG3, "creating bootstrap relation %s...", | ||||
| 							 LexIDStr($4)); | ||||
| 					else | ||||
| 						elog(DEBUG3, "creating relation %s...", | ||||
| 							 LexIDStr($4)); | ||||
| 					elog(DEBUG3, "creating%s%s relation %s...", | ||||
| 						 $2 ? " bootstrap" : "", | ||||
| 						 $3 ? " shared" : "", | ||||
| 						 LexIDStr($5)); | ||||
| 				} | ||||
| 		  boot_typelist | ||||
| 				{ | ||||
| @ -171,21 +170,22 @@ Boot_CreateStmt: | ||||
| 
 | ||||
| 					if ($2) | ||||
| 					{ | ||||
| 						extern Relation reldesc; | ||||
| 						TupleDesc tupdesc; | ||||
| 
 | ||||
| 						if (reldesc) | ||||
| 						if (boot_reldesc) | ||||
| 						{ | ||||
| 							elog(DEBUG3, "create bootstrap: warning, open relation exists, closing first"); | ||||
| 							closerel(NULL); | ||||
| 						} | ||||
| 
 | ||||
| 						tupdesc = CreateTupleDesc(numattr, attrtypes); | ||||
| 						reldesc = heap_create(LexIDStr($4), | ||||
| 											  PG_CATALOG_NAMESPACE, | ||||
| 											  tupdesc, | ||||
| 											  true, true); | ||||
| 						reldesc->rd_rel->relhasoids = ! ($3); | ||||
| 						boot_reldesc = heap_create(LexIDStr($5), | ||||
| 												   PG_CATALOG_NAMESPACE, | ||||
| 												   tupdesc, | ||||
| 												   $3, | ||||
| 												   true, | ||||
| 												   true); | ||||
| 						boot_reldesc->rd_rel->relhasoids = ! ($4); | ||||
| 						elog(DEBUG3, "bootstrap relation created"); | ||||
| 					} | ||||
| 					else | ||||
| @ -194,11 +194,12 @@ Boot_CreateStmt: | ||||
| 						TupleDesc tupdesc; | ||||
| 
 | ||||
| 						tupdesc = CreateTupleDesc(numattr,attrtypes); | ||||
| 						id = heap_create_with_catalog(LexIDStr($4), | ||||
| 						id = heap_create_with_catalog(LexIDStr($5), | ||||
| 													  PG_CATALOG_NAMESPACE, | ||||
| 													  tupdesc, | ||||
| 													  RELKIND_RELATION, | ||||
| 													  ! ($3), | ||||
| 													  $3, | ||||
| 													  ! ($4), | ||||
| 													  true); | ||||
| 						elog(DEBUG3, "relation created with oid %u", id); | ||||
| 					} | ||||
| @ -221,7 +222,7 @@ Boot_InsertStmt: | ||||
| 					if (num_columns_read != numattr) | ||||
| 						elog(ERROR, "incorrect number of columns in row (expected %d, got %d)", | ||||
| 							 numattr, num_columns_read); | ||||
| 					if (reldesc == (Relation)NULL) | ||||
| 					if (boot_reldesc == (Relation) NULL) | ||||
| 					{ | ||||
| 						elog(ERROR, "relation not open"); | ||||
| 						err_out(); | ||||
| @ -283,6 +284,11 @@ optbootstrap: | ||||
| 		|				{ $$ = 0; } | ||||
| 		; | ||||
| 
 | ||||
| optsharedrelation: | ||||
| 			XSHARED_RELATION	{ $$ = 1; } | ||||
| 		|						{ $$ = 0; } | ||||
| 		; | ||||
| 
 | ||||
| optwithoutoids: | ||||
| 			XWITHOUT_OIDS	{ $$ = 1; } | ||||
| 		|					{ $$ = 0; } | ||||
|  | ||||
| @ -9,7 +9,7 @@ | ||||
|  * | ||||
|  * | ||||
|  * IDENTIFICATION | ||||
|  *	  $Header: /cvsroot/pgsql/src/backend/bootstrap/bootscanner.l,v 1.21 2001/08/10 18:57:33 tgl Exp $ | ||||
|  *	  $Header: /cvsroot/pgsql/src/backend/bootstrap/bootscanner.l,v 1.22 2002/04/27 21:24:33 tgl Exp $ | ||||
|  * | ||||
|  *------------------------------------------------------------------------- | ||||
|  */ | ||||
| @ -71,6 +71,8 @@ create			{ return(XCREATE); } | ||||
| 
 | ||||
| OID				{ return(OBJ_ID); } | ||||
| bootstrap		{ return(XBOOTSTRAP); } | ||||
| "shared_relation"	{ return(XSHARED_RELATION); } | ||||
| "without_oids"	{ return(XWITHOUT_OIDS); } | ||||
| _null_			{ return(NULLVAL); } | ||||
| 
 | ||||
| insert			{ return(INSERT_TUPLE); } | ||||
| @ -94,7 +96,6 @@ insert			{ return(INSERT_TUPLE); } | ||||
| "index"			{ return(INDEX); } | ||||
| "on"			{ return(ON); } | ||||
| "using"			{ return(USING); } | ||||
| "without_oids"	{ return(XWITHOUT_OIDS); } | ||||
| 
 | ||||
| {arrayid}		{ | ||||
| 					yylval.ival = EnterString(MapArrayTypeName((char*)yytext)); | ||||
|  | ||||
| @ -8,7 +8,7 @@ | ||||
|  * Portions Copyright (c) 1994, Regents of the University of California | ||||
|  * | ||||
|  * IDENTIFICATION | ||||
|  *	  $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.126 2002/04/25 02:56:55 tgl Exp $ | ||||
|  *	  $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.127 2002/04/27 21:24:33 tgl Exp $ | ||||
|  * | ||||
|  *------------------------------------------------------------------------- | ||||
|  */ | ||||
| @ -59,6 +59,9 @@ static void cleanup(void); | ||||
|  *		global variables | ||||
|  * ---------------- | ||||
|  */ | ||||
| 
 | ||||
| Relation	boot_reldesc;		/* current relation descriptor */ | ||||
| 
 | ||||
| /*
 | ||||
|  * In the lexical analyzer, we need to get the reference number quickly from | ||||
|  * the string, and the string from the reference number.  Thus we have | ||||
| @ -500,20 +503,20 @@ boot_openrel(char *relname) | ||||
| 		heap_close(rel, NoLock); | ||||
| 	} | ||||
| 
 | ||||
| 	if (reldesc != NULL) | ||||
| 	if (boot_reldesc != NULL) | ||||
| 		closerel(NULL); | ||||
| 
 | ||||
| 	elog(DEBUG3, "open relation %s, attrsize %d", relname ? relname : "(null)", | ||||
| 		 (int) ATTRIBUTE_TUPLE_SIZE); | ||||
| 
 | ||||
| 	reldesc = heap_openr(relname, NoLock); | ||||
| 	numattr = reldesc->rd_rel->relnatts; | ||||
| 	boot_reldesc = heap_openr(relname, NoLock); | ||||
| 	numattr = boot_reldesc->rd_rel->relnatts; | ||||
| 	for (i = 0; i < numattr; i++) | ||||
| 	{ | ||||
| 		if (attrtypes[i] == NULL) | ||||
| 			attrtypes[i] = AllocateAttribute(); | ||||
| 		memmove((char *) attrtypes[i], | ||||
| 				(char *) reldesc->rd_att->attrs[i], | ||||
| 				(char *) boot_reldesc->rd_att->attrs[i], | ||||
| 				ATTRIBUTE_TUPLE_SIZE); | ||||
| 
 | ||||
| 		/* Some old pg_attribute tuples might not have attisset. */ | ||||
| @ -523,8 +526,9 @@ boot_openrel(char *relname) | ||||
| 		 * defined yet. | ||||
| 		 */ | ||||
| 		if (namestrcmp(&attrtypes[i]->attname, "attisset") == 0) | ||||
| 			attrtypes[i]->attisset = get_attisset(RelationGetRelid(reldesc), | ||||
| 										 NameStr(attrtypes[i]->attname)); | ||||
| 			attrtypes[i]->attisset = | ||||
| 				get_attisset(RelationGetRelid(boot_reldesc), | ||||
| 							 NameStr(attrtypes[i]->attname)); | ||||
| 		else | ||||
| 			attrtypes[i]->attisset = false; | ||||
| 
 | ||||
| @ -547,9 +551,9 @@ closerel(char *name) | ||||
| { | ||||
| 	if (name) | ||||
| 	{ | ||||
| 		if (reldesc) | ||||
| 		if (boot_reldesc) | ||||
| 		{ | ||||
| 			if (strcmp(RelationGetRelationName(reldesc), name) != 0) | ||||
| 			if (strcmp(RelationGetRelationName(boot_reldesc), name) != 0) | ||||
| 				elog(ERROR, "closerel: close of '%s' when '%s' was expected", | ||||
| 					 name, relname ? relname : "(null)"); | ||||
| 		} | ||||
| @ -559,13 +563,13 @@ closerel(char *name) | ||||
| 
 | ||||
| 	} | ||||
| 
 | ||||
| 	if (reldesc == NULL) | ||||
| 	if (boot_reldesc == NULL) | ||||
| 		elog(ERROR, "no open relation to close"); | ||||
| 	else | ||||
| 	{ | ||||
| 		elog(DEBUG3, "close relation %s", relname ? relname : "(null)"); | ||||
| 		heap_close(reldesc, NoLock); | ||||
| 		reldesc = (Relation) NULL; | ||||
| 		heap_close(boot_reldesc, NoLock); | ||||
| 		boot_reldesc = (Relation) NULL; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| @ -585,7 +589,7 @@ DefineAttr(char *name, char *type, int attnum) | ||||
| 	int			attlen; | ||||
| 	Oid			typeoid; | ||||
| 
 | ||||
| 	if (reldesc != NULL) | ||||
| 	if (boot_reldesc != NULL) | ||||
| 	{ | ||||
| 		elog(LOG, "warning: no open relations allowed with 'create' command"); | ||||
| 		closerel(relname); | ||||
| @ -674,7 +678,7 @@ InsertOneTuple(Oid objectid) | ||||
| 
 | ||||
| 	if (objectid != (Oid) 0) | ||||
| 		tuple->t_data->t_oid = objectid; | ||||
| 	heap_insert(reldesc, tuple); | ||||
| 	heap_insert(boot_reldesc, tuple); | ||||
| 	heap_freetuple(tuple); | ||||
| 	elog(DEBUG3, "row inserted"); | ||||
| 
 | ||||
| @ -706,13 +710,13 @@ InsertOneValue(char *value, int i) | ||||
| 
 | ||||
| 		elog(DEBUG3, "Typ != NULL"); | ||||
| 		app = Typ; | ||||
| 		while (*app && (*app)->am_oid != reldesc->rd_att->attrs[i]->atttypid) | ||||
| 		while (*app && (*app)->am_oid != boot_reldesc->rd_att->attrs[i]->atttypid) | ||||
| 			++app; | ||||
| 		ap = *app; | ||||
| 		if (ap == NULL) | ||||
| 		{ | ||||
| 			elog(FATAL, "unable to find atttypid %u in Typ list", | ||||
| 				 reldesc->rd_att->attrs[i]->atttypid); | ||||
| 				 boot_reldesc->rd_att->attrs[i]->atttypid); | ||||
| 		} | ||||
| 		values[i] = OidFunctionCall3(ap->am_typ.typinput, | ||||
| 									 CStringGetDatum(value), | ||||
| @ -806,8 +810,8 @@ cleanup() | ||||
| 		elog(FATAL, "Memory manager fault: cleanup called twice.\n"); | ||||
| 		proc_exit(1); | ||||
| 	} | ||||
| 	if (reldesc != (Relation) NULL) | ||||
| 		heap_close(reldesc, NoLock); | ||||
| 	if (boot_reldesc != (Relation) NULL) | ||||
| 		heap_close(boot_reldesc, NoLock); | ||||
| 	CommitTransactionCommand(); | ||||
| 	proc_exit(Warnings); | ||||
| } | ||||
|  | ||||
| @ -1,4 +1,4 @@ | ||||
| $Header: /cvsroot/pgsql/src/backend/catalog/README,v 1.6 2002/04/15 23:46:13 momjian Exp $ | ||||
| $Header: /cvsroot/pgsql/src/backend/catalog/README,v 1.7 2002/04/27 21:24:33 tgl Exp $ | ||||
| 
 | ||||
| This directory contains .c files that manipulate the system catalogs; | ||||
| src/include/catalog contains the .h files that define the structure | ||||
| @ -69,15 +69,14 @@ manually create appropriate entries for them in the pre-loaded contents of | ||||
| pg_class, pg_attribute, and pg_type.  You'll also need to add code to function | ||||
| heap_create() in heap.c to force the correct OID to be assigned when the table | ||||
| is first referenced.  (It's near the top of the function with the comment | ||||
| beginning in 'Real ugly stuff'.)  Avoid making new catalogs be bootstrap | ||||
| beginning in "Real ugly stuff".)  Avoid making new catalogs be bootstrap | ||||
| catalogs if at all possible; generally, only tables that must be written to | ||||
| in order to create a table should be bootstrapped. | ||||
| 
 | ||||
| - Certain BOOTSTRAP tables must be at the start of the Makefile | ||||
| POSTGRES_BKI_SRCS variable, as these will not be created through standard | ||||
| function means, but will be written directly to disk.  That's how pg_class is | ||||
| created without depending on functions which depend on the existence of | ||||
| pg_class.  The list of files this currently includes is: | ||||
| POSTGRES_BKI_SRCS variable, as these will not be created through the standard | ||||
| heap_create_with_catalog process, because it needs these tables to exist | ||||
| already.  The list of files this currently includes is: | ||||
| 	pg_proc.h pg_type.h pg_attribute.h pg_class.h | ||||
| Also, indexing.h must be last, since the indexes can't be created until all | ||||
| the tables are in place.  There are reputedly some other order dependencies | ||||
|  | ||||
| @ -9,7 +9,7 @@ | ||||
|  * | ||||
|  * | ||||
|  * IDENTIFICATION | ||||
|  *	  $Header: /cvsroot/pgsql/src/backend/catalog/catalog.c,v 1.45 2002/04/12 20:38:18 tgl Exp $ | ||||
|  *	  $Header: /cvsroot/pgsql/src/backend/catalog/catalog.c,v 1.46 2002/04/27 21:24:33 tgl Exp $ | ||||
|  * | ||||
|  *------------------------------------------------------------------------- | ||||
|  */ | ||||
| @ -177,29 +177,6 @@ IsReservedName(const char *name) | ||||
| 			name[2] == '_'); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * IsSharedSystemRelationName | ||||
|  *		True iff name is the name of a shared system catalog relation. | ||||
|  * | ||||
|  *		Note: This function assumes that this is a system relation | ||||
|  *		in the first place.  If that is not known, check the namespace | ||||
|  *		(with IsSystemNamespace) before calling this function. | ||||
|  */ | ||||
| bool | ||||
| IsSharedSystemRelationName(const char *relname) | ||||
| { | ||||
| 	int			i; | ||||
| 
 | ||||
| 	i = 0; | ||||
| 	while (SharedSystemRelationNames[i] != NULL) | ||||
| 	{ | ||||
| 		if (strcmp(SharedSystemRelationNames[i], relname) == 0) | ||||
| 			return TRUE; | ||||
| 		i++; | ||||
| 	} | ||||
| 	return FALSE; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  *		newoid			- returns a unique identifier across all catalogs. | ||||
|  | ||||
| @ -10,7 +10,7 @@ | ||||
| # | ||||
| # | ||||
| # IDENTIFICATION | ||||
| #    $Header: /cvsroot/pgsql/src/backend/catalog/Attic/genbki.sh,v 1.26 2002/03/26 19:15:24 tgl Exp $ | ||||
| #    $Header: /cvsroot/pgsql/src/backend/catalog/Attic/genbki.sh,v 1.27 2002/04/27 21:24:33 tgl Exp $ | ||||
| # | ||||
| # NOTES | ||||
| #    non-essential whitespace is removed from the generated file. | ||||
| @ -217,6 +217,7 @@ BEGIN { | ||||
| 	inside = 0; | ||||
| 	raw = 0; | ||||
| 	bootstrap = ""; | ||||
| 	shared_relation = ""; | ||||
| 	without_oids = ""; | ||||
| 	nc = 0; | ||||
| 	reln_open = 0; | ||||
| @ -331,6 +332,9 @@ raw == 1 	{ print; next; } | ||||
| 	if ($0 ~ /BOOTSTRAP/) { | ||||
| 		bootstrap = "bootstrap "; | ||||
| 	} | ||||
| 	if ($0 ~ /BKI_SHARED_RELATION/) { | ||||
| 		shared_relation = "shared_relation "; | ||||
| 	} | ||||
| 	if ($0 ~ /BKI_WITHOUT_OIDS/) { | ||||
| 		without_oids = "without_oids "; | ||||
| 	} | ||||
| @ -358,7 +362,7 @@ inside == 1 { | ||||
| #  if this is the last line, then output the bki catalog stuff. | ||||
| # ---- | ||||
| 	if ($1 ~ /}/) { | ||||
| 		print "create " bootstrap without_oids catalog; | ||||
| 		print "create " bootstrap shared_relation without_oids catalog; | ||||
| 		print "\t("; | ||||
| 
 | ||||
| 		for (j=1; j<i-1; j++) { | ||||
| @ -375,6 +379,7 @@ inside == 1 { | ||||
| 		reln_open = 1; | ||||
| 		inside = 0; | ||||
| 		bootstrap = ""; | ||||
| 		shared_relation = ""; | ||||
| 		without_oids = ""; | ||||
| 		next; | ||||
| 	} | ||||
|  | ||||
| @ -8,7 +8,7 @@ | ||||
|  * | ||||
|  * | ||||
|  * IDENTIFICATION | ||||
|  *	  $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.196 2002/04/12 20:38:18 tgl Exp $ | ||||
|  *	  $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.197 2002/04/27 21:24:33 tgl Exp $ | ||||
|  * | ||||
|  * | ||||
|  * INTERFACE ROUTINES | ||||
| @ -210,11 +210,12 @@ Relation | ||||
| heap_create(const char *relname, | ||||
| 			Oid relnamespace, | ||||
| 			TupleDesc tupDesc, | ||||
| 			bool shared_relation, | ||||
| 			bool storage_create, | ||||
| 			bool allow_system_table_mods) | ||||
| { | ||||
| 	Oid			relid; | ||||
| 	Oid			dbid = MyDatabaseId; | ||||
| 	Oid			dbid = shared_relation ? InvalidOid : MyDatabaseId; | ||||
| 	bool		nailme = false; | ||||
| 	RelFileNode	rnode; | ||||
| 	Relation	rel; | ||||
| @ -225,16 +226,15 @@ heap_create(const char *relname, | ||||
| 	if (!allow_system_table_mods && | ||||
| 		(IsSystemNamespace(relnamespace) || IsToastNamespace(relnamespace)) && | ||||
| 		IsNormalProcessingMode()) | ||||
| 		elog(ERROR, "invalid relation \"%s\"; " | ||||
| 		elog(ERROR, "cannot create %s.%s: " | ||||
| 			 "system catalog modifications are currently disallowed", | ||||
| 			 relname); | ||||
| 			 get_namespace_name(relnamespace), relname); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Real ugly stuff to assign the proper relid in the relation | ||||
| 	 * descriptor follows.	Note that only "bootstrapped" relations whose | ||||
| 	 * OIDs are hard-coded in pg_class.h need be listed here.  We also | ||||
| 	 * have to take special care for those rels that should be nailed | ||||
| 	 * in cache and/or are shared across databases. | ||||
| 	 * OIDs are hard-coded in pg_class.h should be listed here.  We also | ||||
| 	 * have to recognize those rels that must be nailed in cache. | ||||
| 	 */ | ||||
| 	if (IsSystemNamespace(relnamespace)) | ||||
| 	{ | ||||
| @ -260,24 +260,19 @@ heap_create(const char *relname, | ||||
| 		} | ||||
| 		else if (strcmp(ShadowRelationName, relname) == 0) | ||||
| 		{ | ||||
| 			dbid = InvalidOid; | ||||
| 			relid = RelOid_pg_shadow; | ||||
| 		} | ||||
| 		else if (strcmp(GroupRelationName, relname) == 0) | ||||
| 		{ | ||||
| 			dbid = InvalidOid; | ||||
| 			relid = RelOid_pg_group; | ||||
| 		} | ||||
| 		else if (strcmp(DatabaseRelationName, relname) == 0) | ||||
| 		{ | ||||
| 			dbid = InvalidOid; | ||||
| 			relid = RelOid_pg_database; | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			relid = newoid(); | ||||
| 			if (IsSharedSystemRelationName(relname)) | ||||
| 				dbid = InvalidOid; | ||||
| 		} | ||||
| 	} | ||||
| 	else | ||||
| @ -651,6 +646,7 @@ heap_create_with_catalog(const char *relname, | ||||
| 						 Oid relnamespace, | ||||
| 						 TupleDesc tupdesc, | ||||
| 						 char relkind, | ||||
| 						 bool shared_relation, | ||||
| 						 bool relhasoids, | ||||
| 						 bool allow_system_table_mods) | ||||
| { | ||||
| @ -678,8 +674,12 @@ heap_create_with_catalog(const char *relname, | ||||
| 	 * necessary anymore, but we may as well avoid the cycles of creating | ||||
| 	 * and deleting the file in case we fail.) | ||||
| 	 */ | ||||
| 	new_rel_desc = heap_create(relname, relnamespace, tupdesc, | ||||
| 							   false, allow_system_table_mods); | ||||
| 	new_rel_desc = heap_create(relname, | ||||
| 							   relnamespace, | ||||
| 							   tupdesc, | ||||
| 							   shared_relation, | ||||
| 							   false, | ||||
| 							   allow_system_table_mods); | ||||
| 
 | ||||
| 	/* Fetch the relation OID assigned by heap_create */ | ||||
| 	new_rel_oid = new_rel_desc->rd_att->attrs[0]->attrelid; | ||||
|  | ||||
| @ -8,7 +8,7 @@ | ||||
|  * | ||||
|  * | ||||
|  * IDENTIFICATION | ||||
|  *	  $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.176 2002/04/12 20:38:19 tgl Exp $ | ||||
|  *	  $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.177 2002/04/27 21:24:34 tgl Exp $ | ||||
|  * | ||||
|  * | ||||
|  * INTERFACE ROUTINES | ||||
| @ -67,7 +67,6 @@ static TupleDesc BuildFuncTupleDesc(Oid funcOid, | ||||
| static TupleDesc ConstructTupleDescriptor(Relation heapRelation, | ||||
| 						 int numatts, AttrNumber *attNums, | ||||
| 						 Oid *classObjectId); | ||||
| static void ConstructIndexReldesc(Relation indexRelation, Oid amoid); | ||||
| static void UpdateRelationRelation(Relation indexRelation); | ||||
| static void InitializeAttributeOids(Relation indexRelation, | ||||
| 						int numatts, Oid indexoid); | ||||
| @ -305,26 +304,6 @@ ConstructTupleDescriptor(Relation heapRelation, | ||||
| 	return indexTupDesc; | ||||
| } | ||||
| 
 | ||||
| /* ----------------------------------------------------------------
 | ||||
|  *		ConstructIndexReldesc | ||||
|  * ---------------------------------------------------------------- | ||||
|  */ | ||||
| static void | ||||
| ConstructIndexReldesc(Relation indexRelation, Oid amoid) | ||||
| { | ||||
| 	/*
 | ||||
| 	 * Set up some additional fields of the index' pg_class entry. In | ||||
| 	 * particular, initialize knowledge of whether the index is shared. | ||||
| 	 */ | ||||
| 	indexRelation->rd_rel->relowner = GetUserId(); | ||||
| 	indexRelation->rd_rel->relam = amoid; | ||||
| 	indexRelation->rd_rel->relisshared = | ||||
| 		IsSystemNamespace(RelationGetNamespace(indexRelation)) && | ||||
| 		IsSharedSystemRelationName(RelationGetRelationName(indexRelation)); | ||||
| 	indexRelation->rd_rel->relkind = RELKIND_INDEX; | ||||
| 	indexRelation->rd_rel->relhasoids = false; | ||||
| } | ||||
| 
 | ||||
| /* ----------------------------------------------------------------
 | ||||
|  *		UpdateRelationRelation | ||||
|  * ---------------------------------------------------------------- | ||||
| @ -561,6 +540,7 @@ index_create(Oid heapRelationId, | ||||
| 	Relation	heapRelation; | ||||
| 	Relation	indexRelation; | ||||
| 	TupleDesc	indexTupDesc; | ||||
| 	bool		shared_relation; | ||||
| 	Oid			namespaceId; | ||||
| 	Oid			indexoid; | ||||
| 
 | ||||
| @ -571,7 +551,12 @@ index_create(Oid heapRelationId, | ||||
| 	 */ | ||||
| 	heapRelation = heap_open(heapRelationId, ShareLock); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * The index will be in the same namespace as its parent table, | ||||
| 	 * and is shared across databases if and only if the parent is. | ||||
| 	 */ | ||||
| 	namespaceId = RelationGetNamespace(heapRelation); | ||||
| 	shared_relation = heapRelation->rd_rel->relisshared; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * check parameters | ||||
| @ -585,6 +570,16 @@ index_create(Oid heapRelationId, | ||||
| 		IsNormalProcessingMode()) | ||||
| 		elog(ERROR, "User-defined indexes on system catalogs are not supported"); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * We cannot allow indexing a shared relation after initdb (because | ||||
| 	 * there's no way to make the entry in other databases' pg_class). | ||||
| 	 * Unfortunately we can't distinguish initdb from a manually started | ||||
| 	 * standalone backend.  However, we can at least prevent this mistake | ||||
| 	 * under normal multi-user operation. | ||||
| 	 */ | ||||
| 	if (shared_relation && IsUnderPostmaster) | ||||
| 		elog(ERROR, "Shared indexes cannot be created after initdb"); | ||||
| 
 | ||||
| 	if (get_relname_relid(indexRelationName, namespaceId)) | ||||
| 		elog(ERROR, "index named \"%s\" already exists", | ||||
| 			 indexRelationName); | ||||
| @ -607,6 +602,7 @@ index_create(Oid heapRelationId, | ||||
| 	indexRelation = heap_create(indexRelationName, | ||||
| 								namespaceId, | ||||
| 								indexTupDesc, | ||||
| 								shared_relation, | ||||
| 								false, | ||||
| 								allow_system_table_mods); | ||||
| 	indexoid = RelationGetRelid(indexRelation); | ||||
| @ -619,16 +615,18 @@ index_create(Oid heapRelationId, | ||||
| 	LockRelation(indexRelation, AccessExclusiveLock); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * construct the index relation descriptor | ||||
| 	 * Fill in fields of the index's pg_class entry that are not set | ||||
| 	 * correctly by heap_create. | ||||
| 	 * | ||||
| 	 * XXX should have a proper way to create cataloged relations | ||||
| 	 * XXX should have a cleaner way to create cataloged indexes | ||||
| 	 */ | ||||
| 	ConstructIndexReldesc(indexRelation, accessMethodObjectId); | ||||
| 	indexRelation->rd_rel->relowner = GetUserId(); | ||||
| 	indexRelation->rd_rel->relam = accessMethodObjectId; | ||||
| 	indexRelation->rd_rel->relkind = RELKIND_INDEX; | ||||
| 	indexRelation->rd_rel->relhasoids = false; | ||||
| 
 | ||||
| 	/* ----------------
 | ||||
| 	 *	  add index to catalogs | ||||
| 	 *	  (append RELATION tuple) | ||||
| 	 * ---------------- | ||||
| 	/*
 | ||||
| 	 * store index's pg_class entry | ||||
| 	 */ | ||||
| 	UpdateRelationRelation(indexRelation); | ||||
| 
 | ||||
|  | ||||
| @ -15,7 +15,7 @@ | ||||
|  * | ||||
|  * | ||||
|  * IDENTIFICATION | ||||
|  *	  $Header: /cvsroot/pgsql/src/backend/commands/cluster.c,v 1.78 2002/04/15 05:22:03 tgl Exp $ | ||||
|  *	  $Header: /cvsroot/pgsql/src/backend/commands/cluster.c,v 1.79 2002/04/27 21:24:34 tgl Exp $ | ||||
|  * | ||||
|  *------------------------------------------------------------------------- | ||||
|  */ | ||||
| @ -152,6 +152,7 @@ copy_heap(Oid OIDOldHeap, const char *NewName) | ||||
| 										  RelationGetNamespace(OldHeap), | ||||
| 										  tupdesc, | ||||
| 										  OldHeap->rd_rel->relkind, | ||||
| 										  OldHeap->rd_rel->relisshared, | ||||
| 										  OldHeap->rd_rel->relhasoids, | ||||
| 										  allowSystemTableMods); | ||||
| 
 | ||||
|  | ||||
| @ -9,7 +9,7 @@ | ||||
|  * | ||||
|  * | ||||
|  * IDENTIFICATION | ||||
|  *	  $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.87 2002/04/21 00:26:42 tgl Exp $ | ||||
|  *	  $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.88 2002/04/27 21:24:34 tgl Exp $ | ||||
|  * | ||||
|  *------------------------------------------------------------------------- | ||||
|  */ | ||||
| @ -475,11 +475,14 @@ AlterDatabaseSet(AlterDatabaseSetStmt *stmt) | ||||
| 		elog(ERROR, "permission denied"); | ||||
| 
 | ||||
| 	MemSet(repl_repl, ' ', sizeof(repl_repl)); | ||||
| 
 | ||||
| 	repl_repl[Anum_pg_database_datconfig-1] = 'r'; | ||||
| 
 | ||||
| 	if (strcmp(stmt->variable, "all")==0 && stmt->value == NULL) | ||||
| 	{ | ||||
| 		/* RESET ALL */ | ||||
| 		repl_null[Anum_pg_database_datconfig-1] = 'n'; | ||||
| 		repl_val[Anum_pg_database_datconfig-1] = (Datum) 0; | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		Datum datum; | ||||
| @ -491,16 +494,12 @@ AlterDatabaseSet(AlterDatabaseSetStmt *stmt) | ||||
| 		datum = heap_getattr(tuple, Anum_pg_database_datconfig, | ||||
| 							 RelationGetDescr(rel), &isnull); | ||||
| 
 | ||||
| 		a = isnull ? ((ArrayType *) NULL) : DatumGetArrayTypeP(datum); | ||||
| 
 | ||||
| 		if (valuestr) | ||||
| 			a = GUCArrayAdd(isnull | ||||
| 							? NULL | ||||
| 							: (ArrayType *) pg_detoast_datum((struct varlena *)datum), | ||||
| 							stmt->variable, valuestr); | ||||
| 			a = GUCArrayAdd(a, stmt->variable, valuestr); | ||||
| 		else | ||||
| 			a = GUCArrayDelete(isnull | ||||
| 							   ? NULL | ||||
| 							   : (ArrayType *) pg_detoast_datum((struct varlena *)datum), | ||||
| 							   stmt->variable); | ||||
| 			a = GUCArrayDelete(a, stmt->variable); | ||||
| 
 | ||||
| 		repl_val[Anum_pg_database_datconfig-1] = PointerGetDatum(a); | ||||
| 	} | ||||
| @ -546,8 +545,6 @@ get_db_info(const char *name, Oid *dbIdP, int4 *ownerIdP, | ||||
| 	if (gottuple) | ||||
| 	{ | ||||
| 		Form_pg_database dbform = (Form_pg_database) GETSTRUCT(tuple); | ||||
| 		text	   *tmptext; | ||||
| 		bool		isnull; | ||||
| 
 | ||||
| 		/* oid of the database */ | ||||
| 		if (dbIdP) | ||||
| @ -573,16 +570,21 @@ get_db_info(const char *name, Oid *dbIdP, int4 *ownerIdP, | ||||
| 		/* database path (as registered in pg_database) */ | ||||
| 		if (dbpath) | ||||
| 		{ | ||||
| 			tmptext = DatumGetTextP(heap_getattr(tuple, | ||||
| 												 Anum_pg_database_datpath, | ||||
| 											  RelationGetDescr(relation), | ||||
| 												 &isnull)); | ||||
| 			Datum		datum; | ||||
| 			bool		isnull; | ||||
| 
 | ||||
| 			datum = heap_getattr(tuple, | ||||
| 								 Anum_pg_database_datpath, | ||||
| 								 RelationGetDescr(relation), | ||||
| 								 &isnull); | ||||
| 			if (!isnull) | ||||
| 			{ | ||||
| 				Assert(VARSIZE(tmptext) - VARHDRSZ < MAXPGPATH); | ||||
| 				text	   *pathtext = DatumGetTextP(datum); | ||||
| 				int			pathlen = VARSIZE(pathtext) - VARHDRSZ; | ||||
| 
 | ||||
| 				strncpy(dbpath, VARDATA(tmptext), VARSIZE(tmptext) - VARHDRSZ); | ||||
| 				*(dbpath + VARSIZE(tmptext) - VARHDRSZ) = '\0'; | ||||
| 				Assert(pathlen >= 0 && pathlen < MAXPGPATH); | ||||
| 				strncpy(dbpath, VARDATA(pathtext), pathlen); | ||||
| 				*(dbpath + pathlen) = '\0'; | ||||
| 			} | ||||
| 			else | ||||
| 				strcpy(dbpath, ""); | ||||
|  | ||||
| @ -8,7 +8,7 @@ | ||||
|  * | ||||
|  * | ||||
|  * IDENTIFICATION | ||||
|  *	  $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.11 2002/04/27 03:45:01 tgl Exp $ | ||||
|  *	  $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.12 2002/04/27 21:24:34 tgl Exp $ | ||||
|  * | ||||
|  *------------------------------------------------------------------------- | ||||
|  */ | ||||
| @ -200,6 +200,7 @@ DefineRelation(CreateStmt *stmt, char relkind) | ||||
| 										  namespaceId, | ||||
| 										  descriptor, | ||||
| 										  relkind, | ||||
| 										  false, | ||||
| 										  stmt->hasoids || parentHasOids, | ||||
| 										  allowSystemTableMods); | ||||
| 
 | ||||
| @ -2840,6 +2841,7 @@ AlterTableCreateToastTable(Oid relOid, bool silent) | ||||
| 	HeapTuple	reltup; | ||||
| 	HeapTupleData classtuple; | ||||
| 	TupleDesc	tupdesc; | ||||
| 	bool		shared_relation; | ||||
| 	Relation	class_rel; | ||||
| 	Buffer		buffer; | ||||
| 	Relation	ridescs[Num_pg_class_indices]; | ||||
| @ -2856,6 +2858,7 @@ AlterTableCreateToastTable(Oid relOid, bool silent) | ||||
| 	 */ | ||||
| 	rel = heap_open(relOid, AccessExclusiveLock); | ||||
| 
 | ||||
| 	/* Check permissions */ | ||||
| 	if (rel->rd_rel->relkind != RELKIND_RELATION) | ||||
| 		elog(ERROR, "ALTER TABLE: relation \"%s\" is not a table", | ||||
| 			 RelationGetRelationName(rel)); | ||||
| @ -2863,6 +2866,19 @@ AlterTableCreateToastTable(Oid relOid, bool silent) | ||||
| 	if (!pg_class_ownercheck(relOid, GetUserId())) | ||||
| 		aclcheck_error(ACLCHECK_NOT_OWNER, RelationGetRelationName(rel)); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Toast table is shared if and only if its parent is. | ||||
| 	 * | ||||
| 	 * We cannot allow toasting a shared relation after initdb (because | ||||
| 	 * there's no way to mark it toasted in other databases' pg_class). | ||||
| 	 * Unfortunately we can't distinguish initdb from a manually started | ||||
| 	 * standalone backend.  However, we can at least prevent this mistake | ||||
| 	 * under normal multi-user operation. | ||||
| 	 */ | ||||
| 	shared_relation = rel->rd_rel->relisshared; | ||||
| 	if (shared_relation && IsUnderPostmaster) | ||||
| 		elog(ERROR, "Shared relations cannot be toasted after initdb"); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * lock the pg_class tuple for update (is that really needed?) | ||||
| 	 */ | ||||
| @ -2962,6 +2978,7 @@ AlterTableCreateToastTable(Oid relOid, bool silent) | ||||
| 										   PG_TOAST_NAMESPACE, | ||||
| 										   tupdesc, | ||||
| 										   RELKIND_TOASTVALUE, | ||||
| 										   shared_relation, | ||||
| 										   false, | ||||
| 										   true); | ||||
| 
 | ||||
|  | ||||
| @ -6,7 +6,7 @@ | ||||
|  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group | ||||
|  * Portions Copyright (c) 1994, Regents of the University of California | ||||
|  * | ||||
|  * $Header: /cvsroot/pgsql/src/backend/commands/user.c,v 1.98 2002/04/27 15:30:07 momjian Exp $ | ||||
|  * $Header: /cvsroot/pgsql/src/backend/commands/user.c,v 1.99 2002/04/27 21:24:34 tgl Exp $ | ||||
|  * | ||||
|  *------------------------------------------------------------------------- | ||||
|  */ | ||||
| @ -40,7 +40,10 @@ | ||||
| extern bool Password_encryption; | ||||
| 
 | ||||
| static void CheckPgUserAclNotNull(void); | ||||
| 
 | ||||
| static void UpdateGroupMembership(Relation group_rel, HeapTuple group_tuple, | ||||
| 								  List *members); | ||||
| static IdList *IdListToArray(List *members); | ||||
| static List *IdArrayToList(IdList *oldarray); | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
| @ -151,16 +154,11 @@ write_group_file(Relation urel, Relation grel) | ||||
| 		bool		first_user = true; | ||||
| 
 | ||||
| 		datum = heap_getattr(tuple, Anum_pg_group_groname, dsc, &isnull); | ||||
| 		if (isnull) | ||||
| 			continue;			/* ignore NULL groupnames */ | ||||
| 		groname = NameStr(*DatumGetName(datum)); | ||||
| 
 | ||||
| 		grolist_datum = heap_getattr(tuple, Anum_pg_group_grolist, dsc, &isnull); | ||||
| 		/* Ignore NULL group lists */ | ||||
| 		/* ignore NULL groupnames --- shouldn't happen */ | ||||
| 		if (isnull) | ||||
| 			continue; | ||||
| 		groname = NameStr(*DatumGetName(datum)); | ||||
| 
 | ||||
| 		grolist_p = DatumGetIdListP(grolist_datum); | ||||
| 		/*
 | ||||
| 		 * Check for illegal characters in the group name. | ||||
| 		 */ | ||||
| @ -171,8 +169,15 @@ write_group_file(Relation urel, Relation grel) | ||||
| 			continue; | ||||
| 		} | ||||
| 
 | ||||
| 		grolist_datum = heap_getattr(tuple, Anum_pg_group_grolist, dsc, &isnull); | ||||
| 		/* Ignore NULL group lists */ | ||||
| 		if (isnull) | ||||
| 			continue; | ||||
| 
 | ||||
| 		/* be sure the IdList is not toasted */ | ||||
| 		/* scan it */ | ||||
| 		grolist_p = DatumGetIdListP(grolist_datum); | ||||
| 
 | ||||
| 		/* scan grolist */ | ||||
| 		num = IDLIST_NUM(grolist_p); | ||||
| 		aidp = IDLIST_DAT(grolist_p); | ||||
| 		for (i = 0; i < num; ++i) | ||||
| @ -290,8 +295,9 @@ write_user_file(Relation urel) | ||||
| 		int			i; | ||||
| 
 | ||||
| 		datum = heap_getattr(tuple, Anum_pg_shadow_usename, dsc, &isnull); | ||||
| 		/* ignore NULL usernames (shouldn't happen) */ | ||||
| 		if (isnull) | ||||
| 			continue;			/* ignore NULL usernames */ | ||||
| 			continue; | ||||
| 		usename = NameStr(*DatumGetName(datum)); | ||||
| 
 | ||||
| 		datum = heap_getattr(tuple, Anum_pg_shadow_passwd, dsc, &isnull); | ||||
| @ -516,24 +522,19 @@ CreateUser(CreateUserStmt *stmt) | ||||
| 	while (!user_exists && !sysid_exists && | ||||
| 		   HeapTupleIsValid(tuple = heap_getnext(scan, 0))) | ||||
| 	{ | ||||
| 		Datum		datum; | ||||
| 		bool		null; | ||||
| 		Form_pg_shadow shadow_form = (Form_pg_shadow) GETSTRUCT(tuple); | ||||
| 		int32		this_sysid; | ||||
| 
 | ||||
| 		datum = heap_getattr(tuple, Anum_pg_shadow_usename, | ||||
| 							 pg_shadow_dsc, &null); | ||||
| 		Assert(!null); | ||||
| 		user_exists = (strcmp(NameStr(*DatumGetName(datum)), stmt->user) == 0); | ||||
| 		user_exists = (strcmp(NameStr(shadow_form->usename), stmt->user) == 0); | ||||
| 
 | ||||
| 		datum = heap_getattr(tuple, Anum_pg_shadow_usesysid, | ||||
| 							 pg_shadow_dsc, &null); | ||||
| 		Assert(!null); | ||||
| 		this_sysid = shadow_form->usesysid; | ||||
| 		if (havesysid)			/* customized id wanted */ | ||||
| 			sysid_exists = (DatumGetInt32(datum) == sysid); | ||||
| 			sysid_exists = (this_sysid == sysid); | ||||
| 		else | ||||
| 		{ | ||||
| 			/* pick 1 + max */ | ||||
| 			if (DatumGetInt32(datum) > max_id) | ||||
| 				max_id = DatumGetInt32(datum); | ||||
| 			if (this_sysid > max_id) | ||||
| 				max_id = this_sysid; | ||||
| 		} | ||||
| 	} | ||||
| 	heap_endscan(scan); | ||||
| @ -551,10 +552,12 @@ CreateUser(CreateUserStmt *stmt) | ||||
| 	/*
 | ||||
| 	 * Build a tuple to insert | ||||
| 	 */ | ||||
| 	MemSet(new_record, 0, sizeof(new_record)); | ||||
| 	MemSet(new_record_nulls, ' ', sizeof(new_record_nulls)); | ||||
| 
 | ||||
| 	new_record[Anum_pg_shadow_usename - 1] = | ||||
| 		DirectFunctionCall1(namein, CStringGetDatum(stmt->user)); | ||||
| 	new_record[Anum_pg_shadow_usesysid - 1] = Int32GetDatum(sysid); | ||||
| 
 | ||||
| 	AssertState(BoolIsValid(createdb)); | ||||
| 	new_record[Anum_pg_shadow_usecreatedb - 1] = BoolGetDatum(createdb); | ||||
| 	new_record[Anum_pg_shadow_usetrace - 1] = BoolGetDatum(false); | ||||
| @ -577,20 +580,14 @@ CreateUser(CreateUserStmt *stmt) | ||||
| 				DirectFunctionCall1(textin, CStringGetDatum(encrypted_password)); | ||||
| 		} | ||||
| 	} | ||||
| 	else | ||||
| 		new_record_nulls[Anum_pg_shadow_passwd - 1] = 'n'; | ||||
| 
 | ||||
| 	if (validUntil) | ||||
| 		new_record[Anum_pg_shadow_valuntil - 1] = | ||||
| 			DirectFunctionCall1(nabstimein, CStringGetDatum(validUntil)); | ||||
| 
 | ||||
| 	new_record_nulls[Anum_pg_shadow_usename - 1] = ' '; | ||||
| 	new_record_nulls[Anum_pg_shadow_usesysid - 1] = ' '; | ||||
| 
 | ||||
| 	new_record_nulls[Anum_pg_shadow_usecreatedb - 1] = ' '; | ||||
| 	new_record_nulls[Anum_pg_shadow_usetrace - 1] = ' '; | ||||
| 	new_record_nulls[Anum_pg_shadow_usesuper - 1] = ' '; | ||||
| 	new_record_nulls[Anum_pg_shadow_usecatupd - 1] = ' '; | ||||
| 
 | ||||
| 	new_record_nulls[Anum_pg_shadow_passwd - 1] = password ? ' ' : 'n'; | ||||
| 	new_record_nulls[Anum_pg_shadow_valuntil - 1] = validUntil ? ' ' : 'n'; | ||||
| 	else | ||||
| 		new_record_nulls[Anum_pg_shadow_valuntil - 1] = 'n'; | ||||
| 
 | ||||
| 	new_record_nulls[Anum_pg_shadow_useconfig - 1] = 'n'; | ||||
| 
 | ||||
| @ -651,11 +648,11 @@ AlterUser(AlterUserStmt *stmt) | ||||
| { | ||||
| 	Datum		new_record[Natts_pg_shadow]; | ||||
| 	char		new_record_nulls[Natts_pg_shadow]; | ||||
| 	char		new_record_repl[Natts_pg_shadow]; | ||||
| 	Relation	pg_shadow_rel; | ||||
| 	TupleDesc	pg_shadow_dsc; | ||||
| 	HeapTuple	tuple, | ||||
| 				new_tuple; | ||||
| 	bool		null; | ||||
| 	List	   *option; | ||||
| 	char	   *password = NULL;	/* PostgreSQL user password */ | ||||
| 	bool		encrypt_password = Password_encryption; /* encrypt password? */ | ||||
| @ -749,33 +746,23 @@ AlterUser(AlterUserStmt *stmt) | ||||
| 		elog(ERROR, "ALTER USER: user \"%s\" does not exist", stmt->user); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Build a tuple to update, perusing the information just obtained | ||||
| 	 * Build an updated tuple, perusing the information just obtained | ||||
| 	 */ | ||||
| 	MemSet(new_record, 0, sizeof(new_record)); | ||||
| 	MemSet(new_record_nulls, ' ', sizeof(new_record_nulls)); | ||||
| 	MemSet(new_record_repl, ' ', sizeof(new_record_repl)); | ||||
| 
 | ||||
| 	new_record[Anum_pg_shadow_usename - 1] = DirectFunctionCall1(namein, | ||||
| 											CStringGetDatum(stmt->user)); | ||||
| 	new_record_nulls[Anum_pg_shadow_usename - 1] = ' '; | ||||
| 
 | ||||
| 	/* sysid - leave as is */ | ||||
| 	new_record[Anum_pg_shadow_usesysid - 1] = heap_getattr(tuple, Anum_pg_shadow_usesysid, pg_shadow_dsc, &null); | ||||
| 	new_record_nulls[Anum_pg_shadow_usesysid - 1] = null ? 'n' : ' '; | ||||
| 	new_record_repl[Anum_pg_shadow_usename - 1] = 'r'; | ||||
| 
 | ||||
| 	/* createdb */ | ||||
| 	if (createdb < 0) | ||||
| 	{ | ||||
| 		/* don't change */ | ||||
| 		new_record[Anum_pg_shadow_usecreatedb - 1] = heap_getattr(tuple, Anum_pg_shadow_usecreatedb, pg_shadow_dsc, &null); | ||||
| 		new_record_nulls[Anum_pg_shadow_usecreatedb - 1] = null ? 'n' : ' '; | ||||
| 	} | ||||
| 	else | ||||
| 	if (createdb >= 0) | ||||
| 	{ | ||||
| 		new_record[Anum_pg_shadow_usecreatedb - 1] = BoolGetDatum(createdb > 0); | ||||
| 		new_record_nulls[Anum_pg_shadow_usecreatedb - 1] = ' '; | ||||
| 		new_record_repl[Anum_pg_shadow_usecreatedb - 1] = 'r'; | ||||
| 	} | ||||
| 
 | ||||
| 	/* trace - leave as is */ | ||||
| 	new_record[Anum_pg_shadow_usetrace - 1] = heap_getattr(tuple, Anum_pg_shadow_usetrace, pg_shadow_dsc, &null); | ||||
| 	new_record_nulls[Anum_pg_shadow_usetrace - 1] = null ? 'n' : ' '; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * createuser (superuser) and catupd | ||||
| 	 * | ||||
| @ -784,22 +771,13 @@ AlterUser(AlterUserStmt *stmt) | ||||
| 	 * with a situation where no existing superuser can alter the | ||||
| 	 * catalogs, including pg_shadow! | ||||
| 	 */ | ||||
| 	if (createuser < 0) | ||||
| 	{ | ||||
| 		/* don't change */ | ||||
| 		new_record[Anum_pg_shadow_usesuper - 1] = heap_getattr(tuple, Anum_pg_shadow_usesuper, pg_shadow_dsc, &null); | ||||
| 		new_record_nulls[Anum_pg_shadow_usesuper - 1] = null ? 'n' : ' '; | ||||
| 
 | ||||
| 		new_record[Anum_pg_shadow_usecatupd - 1] = heap_getattr(tuple, Anum_pg_shadow_usecatupd, pg_shadow_dsc, &null); | ||||
| 		new_record_nulls[Anum_pg_shadow_usecatupd - 1] = null ? 'n' : ' '; | ||||
| 	} | ||||
| 	else | ||||
| 	if (createuser >= 0) | ||||
| 	{ | ||||
| 		new_record[Anum_pg_shadow_usesuper - 1] = BoolGetDatum(createuser > 0); | ||||
| 		new_record_nulls[Anum_pg_shadow_usesuper - 1] = ' '; | ||||
| 		new_record_repl[Anum_pg_shadow_usesuper - 1] = 'r'; | ||||
| 
 | ||||
| 		new_record[Anum_pg_shadow_usecatupd - 1] = BoolGetDatum(createuser > 0); | ||||
| 		new_record_nulls[Anum_pg_shadow_usecatupd - 1] = ' '; | ||||
| 		new_record_repl[Anum_pg_shadow_usecatupd - 1] = 'r'; | ||||
| 	} | ||||
| 
 | ||||
| 	/* password */ | ||||
| @ -816,14 +794,7 @@ AlterUser(AlterUserStmt *stmt) | ||||
| 			new_record[Anum_pg_shadow_passwd - 1] = | ||||
| 				DirectFunctionCall1(textin, CStringGetDatum(encrypted_password)); | ||||
| 		} | ||||
| 		new_record_nulls[Anum_pg_shadow_passwd - 1] = ' '; | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		/* leave as is */ | ||||
| 		new_record[Anum_pg_shadow_passwd - 1] = | ||||
| 			heap_getattr(tuple, Anum_pg_shadow_passwd, pg_shadow_dsc, &null); | ||||
| 		new_record_nulls[Anum_pg_shadow_passwd - 1] = null ? 'n' : ' '; | ||||
| 		new_record_repl[Anum_pg_shadow_passwd - 1] = 'r'; | ||||
| 	} | ||||
| 
 | ||||
| 	/* valid until */ | ||||
| @ -831,22 +802,11 @@ AlterUser(AlterUserStmt *stmt) | ||||
| 	{ | ||||
| 		new_record[Anum_pg_shadow_valuntil - 1] = | ||||
| 			DirectFunctionCall1(nabstimein, CStringGetDatum(validUntil)); | ||||
| 		new_record_nulls[Anum_pg_shadow_valuntil - 1] = ' '; | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		/* leave as is */ | ||||
| 		new_record[Anum_pg_shadow_valuntil - 1] = | ||||
| 			heap_getattr(tuple, Anum_pg_shadow_valuntil, pg_shadow_dsc, &null); | ||||
| 		new_record_nulls[Anum_pg_shadow_valuntil - 1] = null ? 'n' : ' '; | ||||
| 		new_record_repl[Anum_pg_shadow_valuntil - 1] = 'r'; | ||||
| 	} | ||||
| 
 | ||||
| 	/* leave useconfig as is */ | ||||
| 	new_record[Anum_pg_shadow_useconfig - 1] = | ||||
| 		heap_getattr(tuple, Anum_pg_shadow_useconfig, pg_shadow_dsc, &null); | ||||
| 	new_record_nulls[Anum_pg_shadow_useconfig - 1] = null ? 'n' : ' '; | ||||
| 
 | ||||
| 	new_tuple = heap_formtuple(pg_shadow_dsc, new_record, new_record_nulls); | ||||
| 	new_tuple = heap_modifytuple(tuple, pg_shadow_rel, new_record, | ||||
| 								 new_record_nulls, new_record_repl); | ||||
| 	simple_heap_update(pg_shadow_rel, &tuple->t_self, new_tuple); | ||||
| 
 | ||||
| 	/* Update indexes */ | ||||
| @ -876,7 +836,6 @@ AlterUser(AlterUserStmt *stmt) | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * ALTER USER ... SET | ||||
|  */ | ||||
| @ -896,6 +855,10 @@ AlterUserSet(AlterUserSetStmt *stmt) | ||||
| 				? ((A_Const *) lfirst(stmt->value))->val.val.str | ||||
| 				: NULL); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * RowExclusiveLock is sufficient, because we don't need to update | ||||
| 	 * the flat password file. | ||||
| 	 */ | ||||
| 	rel = heap_openr(ShadowRelationName, RowExclusiveLock); | ||||
| 	oldtuple = SearchSysCache(SHADOWNAME, | ||||
| 							  PointerGetDatum(stmt->user), | ||||
| @ -925,16 +888,12 @@ AlterUserSet(AlterUserSetStmt *stmt) | ||||
| 		datum = SysCacheGetAttr(SHADOWNAME, oldtuple, | ||||
| 								Anum_pg_shadow_useconfig, &isnull); | ||||
| 
 | ||||
| 		array = isnull ? ((ArrayType *) NULL) : DatumGetArrayTypeP(datum); | ||||
| 
 | ||||
| 		if (valuestr) | ||||
| 			array = GUCArrayAdd(isnull | ||||
| 							? NULL | ||||
| 							: (ArrayType *) pg_detoast_datum((struct varlena *)datum), | ||||
| 							stmt->variable, valuestr); | ||||
| 			array = GUCArrayAdd(array, stmt->variable, valuestr); | ||||
| 		else | ||||
| 			array = GUCArrayDelete(isnull | ||||
| 							   ? NULL | ||||
| 							   : (ArrayType *) pg_detoast_datum((struct varlena *)datum), | ||||
| 							   stmt->variable); | ||||
| 			array = GUCArrayDelete(array, stmt->variable); | ||||
| 
 | ||||
| 		repl_val[Anum_pg_shadow_useconfig-1] = PointerGetDatum(array); | ||||
| 	} | ||||
| @ -982,16 +941,14 @@ DropUser(DropUserStmt *stmt) | ||||
| 
 | ||||
| 	foreach(item, stmt->users) | ||||
| 	{ | ||||
| 		const char *user = strVal(lfirst(item)); | ||||
| 		HeapTuple	tuple, | ||||
| 					tmp_tuple; | ||||
| 		Relation	pg_rel; | ||||
| 		TupleDesc	pg_dsc; | ||||
| 		ScanKeyData scankey; | ||||
| 		HeapScanDesc scan; | ||||
| 		Datum		datum; | ||||
| 		bool		null; | ||||
| 		int32		usesysid; | ||||
| 		const char *user = strVal(lfirst(item)); | ||||
| 
 | ||||
| 		tuple = SearchSysCache(SHADOWNAME, | ||||
| 							   PointerGetDatum(user), | ||||
| @ -1000,7 +957,7 @@ DropUser(DropUserStmt *stmt) | ||||
| 			elog(ERROR, "DROP USER: user \"%s\" does not exist%s", user, | ||||
| 				 (length(stmt->users) > 1) ? " (no users removed)" : ""); | ||||
| 
 | ||||
| 		usesysid = DatumGetInt32(heap_getattr(tuple, Anum_pg_shadow_usesysid, pg_shadow_dsc, &null)); | ||||
| 		usesysid = ((Form_pg_shadow) GETSTRUCT(tuple))->usesysid; | ||||
| 
 | ||||
| 		if (usesysid == GetUserId()) | ||||
| 			elog(ERROR, "current user cannot be dropped"); | ||||
| @ -1028,10 +985,7 @@ DropUser(DropUserStmt *stmt) | ||||
| 		{ | ||||
| 			char	   *dbname; | ||||
| 
 | ||||
| 			datum = heap_getattr(tmp_tuple, Anum_pg_database_datname, | ||||
| 								 pg_dsc, &null); | ||||
| 			Assert(!null); | ||||
| 			dbname = NameStr(*DatumGetName(datum)); | ||||
| 			dbname = NameStr(((Form_pg_database) GETSTRUCT(tmp_tuple))->datname); | ||||
| 			elog(ERROR, "DROP USER: user \"%s\" owns database \"%s\", cannot be removed%s", | ||||
| 				 user, dbname, | ||||
| 				 (length(stmt->users) > 1) ? " (no users removed)" : ""); | ||||
| @ -1066,8 +1020,7 @@ DropUser(DropUserStmt *stmt) | ||||
| 			AlterGroupStmt ags; | ||||
| 
 | ||||
| 			/* the group name from which to try to drop the user: */ | ||||
| 			datum = heap_getattr(tmp_tuple, Anum_pg_group_groname, pg_dsc, &null); | ||||
| 			ags.name = DatumGetCString(DirectFunctionCall1(nameout, datum)); | ||||
| 			ags.name = pstrdup(NameStr(((Form_pg_group) GETSTRUCT(tmp_tuple))->groname)); | ||||
| 			ags.action = -1; | ||||
| 			ags.listUsers = makeList1(makeInteger(usesysid)); | ||||
| 			AlterGroup(&ags, "DROP USER"); | ||||
| @ -1202,24 +1155,19 @@ CreateGroup(CreateGroupStmt *stmt) | ||||
| 	while (!group_exists && !sysid_exists && | ||||
| 		   HeapTupleIsValid(tuple = heap_getnext(scan, false))) | ||||
| 	{ | ||||
| 		Datum		datum; | ||||
| 		bool		null; | ||||
| 		Form_pg_group group_form = (Form_pg_group) GETSTRUCT(tuple); | ||||
| 		int32		this_sysid; | ||||
| 
 | ||||
| 		datum = heap_getattr(tuple, Anum_pg_group_groname, | ||||
| 							 pg_group_dsc, &null); | ||||
| 		Assert(!null); | ||||
| 		group_exists = (strcmp(NameStr(*DatumGetName(datum)), stmt->name) == 0); | ||||
| 		group_exists = (strcmp(NameStr(group_form->groname), stmt->name) == 0); | ||||
| 
 | ||||
| 		datum = heap_getattr(tuple, Anum_pg_group_grosysid, | ||||
| 							 pg_group_dsc, &null); | ||||
| 		Assert(!null); | ||||
| 		this_sysid = group_form->grosysid; | ||||
| 		if (havesysid)			/* customized id wanted */ | ||||
| 			sysid_exists = (DatumGetInt32(datum) == sysid); | ||||
| 			sysid_exists = (this_sysid == sysid); | ||||
| 		else | ||||
| 		{ | ||||
| 			/* pick 1 + max */ | ||||
| 			if (DatumGetInt32(datum) > max_id) | ||||
| 				max_id = DatumGetInt32(datum); | ||||
| 			if (this_sysid > max_id) | ||||
| 				max_id = this_sysid; | ||||
| 		} | ||||
| 	} | ||||
| 	heap_endscan(scan); | ||||
| @ -1231,44 +1179,30 @@ CreateGroup(CreateGroupStmt *stmt) | ||||
| 		elog(ERROR, "CREATE GROUP: group sysid %d is already assigned", | ||||
| 			 sysid); | ||||
| 
 | ||||
| 	if (!havesysid) | ||||
| 		sysid = max_id + 1; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Translate the given user names to ids | ||||
| 	 */ | ||||
| 	foreach(item, userElts) | ||||
| 	{ | ||||
| 		const char *groupuser = strVal(lfirst(item)); | ||||
| 		Value	   *v; | ||||
| 		int32		userid = get_usesysid(groupuser); | ||||
| 
 | ||||
| 		v = makeInteger(get_usesysid(groupuser)); | ||||
| 		if (!member(v, newlist)) | ||||
| 			newlist = lappend(newlist, v); | ||||
| 		if (!intMember(userid, newlist)) | ||||
| 			newlist = lappendi(newlist, userid); | ||||
| 	} | ||||
| 
 | ||||
| 	/* build an array to insert */ | ||||
| 	if (newlist) | ||||
| 	{ | ||||
| 		int			i; | ||||
| 
 | ||||
| 		userarray = palloc(ARR_OVERHEAD(1) + length(newlist) * sizeof(int32)); | ||||
| 		userarray->size = ARR_OVERHEAD(1) + length(newlist) * sizeof(int32); | ||||
| 		userarray->flags = 0; | ||||
| 		ARR_NDIM(userarray) = 1;	/* one dimensional array */ | ||||
| 		ARR_LBOUND(userarray)[0] = 1;	/* axis starts at one */ | ||||
| 		ARR_DIMS(userarray)[0] = length(newlist);		/* axis is this long */ | ||||
| 		/* fill the array */ | ||||
| 		i = 0; | ||||
| 		foreach(item, newlist) | ||||
| 			((int *) ARR_DATA_PTR(userarray))[i++] = intVal(lfirst(item)); | ||||
| 	} | ||||
| 		userarray = IdListToArray(newlist); | ||||
| 	else | ||||
| 		userarray = NULL; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Form a tuple to insert | ||||
| 	 */ | ||||
| 	if (!havesysid) | ||||
| 		sysid = max_id + 1; | ||||
| 
 | ||||
| 	new_record[Anum_pg_group_groname - 1] = | ||||
| 		DirectFunctionCall1(namein, CStringGetDatum(stmt->name)); | ||||
| 	new_record[Anum_pg_group_grosysid - 1] = Int32GetDatum(sysid); | ||||
| @ -1318,6 +1252,11 @@ AlterGroup(AlterGroupStmt *stmt, const char *tag) | ||||
| 	Relation	pg_group_rel; | ||||
| 	TupleDesc	pg_group_dsc; | ||||
| 	HeapTuple	group_tuple; | ||||
| 	IdList	   *oldarray; | ||||
| 	Datum		datum; | ||||
| 	bool		null; | ||||
| 	List	   *newlist, | ||||
| 			   *item; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Make sure the user can do this. | ||||
| @ -1337,6 +1276,14 @@ AlterGroup(AlterGroupStmt *stmt, const char *tag) | ||||
| 	if (!HeapTupleIsValid(group_tuple)) | ||||
| 		elog(ERROR, "%s: group \"%s\" does not exist", tag, stmt->name); | ||||
| 
 | ||||
| 	/* Fetch old group membership. */ | ||||
| 	datum = heap_getattr(group_tuple, Anum_pg_group_grolist, | ||||
| 						 pg_group_dsc, &null); | ||||
| 	oldarray = null ? ((IdList *) NULL) : DatumGetIdListP(datum); | ||||
| 
 | ||||
| 	/* initialize list with old array contents */ | ||||
| 	newlist = IdArrayToList(oldarray); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Now decide what to do. | ||||
| 	 */ | ||||
| @ -1345,49 +1292,18 @@ AlterGroup(AlterGroupStmt *stmt, const char *tag) | ||||
| 	if (stmt->action == +1)		/* add users, might also be invoked by
 | ||||
| 								 * create user */ | ||||
| 	{ | ||||
| 		Datum		new_record[Natts_pg_group]; | ||||
| 		char		new_record_nulls[Natts_pg_group]; | ||||
| 		ArrayType  *newarray, | ||||
| 				   *oldarray; | ||||
| 		List	   *newlist = NIL, | ||||
| 				   *item; | ||||
| 		HeapTuple	tuple; | ||||
| 		bool		null = false; | ||||
| 		Datum		datum = heap_getattr(group_tuple, Anum_pg_group_grolist, pg_group_dsc, &null); | ||||
| 		int			i; | ||||
| 
 | ||||
| 		oldarray = (ArrayType *) datum; | ||||
| 		Assert(null || ARR_NDIM(oldarray) == 1); | ||||
| 		/* first add the old array to the hitherto empty list */ | ||||
| 		if (!null) | ||||
| 			for (i = ARR_LBOUND(oldarray)[0]; i < ARR_LBOUND(oldarray)[0] + ARR_DIMS(oldarray)[0]; i++) | ||||
| 			{ | ||||
| 				int			index, | ||||
| 							arrval; | ||||
| 				Value	   *v; | ||||
| 				bool		valueNull; | ||||
| 
 | ||||
| 				index = i; | ||||
| 				arrval = DatumGetInt32(array_ref(oldarray, 1, &index, true /* by value */ , | ||||
| 											sizeof(int), 0, &valueNull)); | ||||
| 				v = makeInteger(arrval); | ||||
| 				/* filter out duplicates */ | ||||
| 				if (!member(v, newlist)) | ||||
| 					newlist = lappend(newlist, v); | ||||
| 			} | ||||
| 
 | ||||
| 		/*
 | ||||
| 		 * now convert the to be added usernames to sysids and add them to | ||||
| 		 * convert the to be added usernames to sysids and add them to | ||||
| 		 * the list | ||||
| 		 */ | ||||
| 		foreach(item, stmt->listUsers) | ||||
| 		{ | ||||
| 			Value	   *v; | ||||
| 			int32	sysid; | ||||
| 
 | ||||
| 			if (strcmp(tag, "ALTER GROUP") == 0) | ||||
| 			{ | ||||
| 				/* Get the uid of the proposed user to add. */ | ||||
| 				v = makeInteger(get_usesysid(strVal(lfirst(item)))); | ||||
| 				sysid = get_usesysid(strVal(lfirst(item))); | ||||
| 			} | ||||
| 			else if (strcmp(tag, "CREATE USER") == 0) | ||||
| 			{ | ||||
| @ -1395,16 +1311,16 @@ AlterGroup(AlterGroupStmt *stmt, const char *tag) | ||||
| 				 * in this case we already know the uid and it wouldn't be | ||||
| 				 * in the cache anyway yet | ||||
| 				 */ | ||||
| 				v = lfirst(item); | ||||
| 				sysid = intVal(lfirst(item)); | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				elog(ERROR, "AlterGroup: unknown tag %s", tag); | ||||
| 				v = NULL;		/* keep compiler quiet */ | ||||
| 				sysid = 0;		/* keep compiler quiet */ | ||||
| 			} | ||||
| 
 | ||||
| 			if (!member(v, newlist)) | ||||
| 				newlist = lappend(newlist, v); | ||||
| 			if (!intMember(sysid, newlist)) | ||||
| 				newlist = lappendi(newlist, sysid); | ||||
| 			else | ||||
| 				/*
 | ||||
| 				 * we silently assume here that this error will only come | ||||
| @ -1414,147 +1330,47 @@ AlterGroup(AlterGroupStmt *stmt, const char *tag) | ||||
| 					 tag, strVal(lfirst(item)), stmt->name); | ||||
| 		} | ||||
| 
 | ||||
| 		newarray = palloc(ARR_OVERHEAD(1) + length(newlist) * sizeof(int32)); | ||||
| 		newarray->size = ARR_OVERHEAD(1) + length(newlist) * sizeof(int32); | ||||
| 		newarray->flags = 0; | ||||
| 		ARR_NDIM(newarray) = 1; /* one dimensional array */ | ||||
| 		ARR_LBOUND(newarray)[0] = 1;	/* axis starts at one */ | ||||
| 		ARR_DIMS(newarray)[0] = length(newlist);		/* axis is this long */ | ||||
| 		/* fill the array */ | ||||
| 		i = 0; | ||||
| 		foreach(item, newlist) | ||||
| 			((int *) ARR_DATA_PTR(newarray))[i++] = intVal(lfirst(item)); | ||||
| 
 | ||||
| 		/*
 | ||||
| 		 * Form a tuple with the new array and write it back. | ||||
| 		 */ | ||||
| 		new_record[Anum_pg_group_groname - 1] = | ||||
| 			DirectFunctionCall1(namein, CStringGetDatum(stmt->name)); | ||||
| 		new_record_nulls[Anum_pg_group_groname - 1] = ' '; | ||||
| 		new_record[Anum_pg_group_grosysid - 1] = heap_getattr(group_tuple, Anum_pg_group_grosysid, pg_group_dsc, &null); | ||||
| 		new_record_nulls[Anum_pg_group_grosysid - 1] = null ? 'n' : ' '; | ||||
| 		new_record[Anum_pg_group_grolist - 1] = PointerGetDatum(newarray); | ||||
| 		new_record_nulls[Anum_pg_group_grolist - 1] = newarray ? ' ' : 'n'; | ||||
| 
 | ||||
| 		tuple = heap_formtuple(pg_group_dsc, new_record, new_record_nulls); | ||||
| 		simple_heap_update(pg_group_rel, &group_tuple->t_self, tuple); | ||||
| 
 | ||||
| 		/* Update indexes */ | ||||
| 		if (RelationGetForm(pg_group_rel)->relhasindex) | ||||
| 		{ | ||||
| 			Relation	idescs[Num_pg_group_indices]; | ||||
| 
 | ||||
| 			CatalogOpenIndices(Num_pg_group_indices, | ||||
| 							   Name_pg_group_indices, idescs); | ||||
| 			CatalogIndexInsert(idescs, Num_pg_group_indices, pg_group_rel, | ||||
| 							   tuple); | ||||
| 			CatalogCloseIndices(Num_pg_group_indices, idescs); | ||||
| 		} | ||||
| 		/* Do the update */ | ||||
| 		UpdateGroupMembership(pg_group_rel, group_tuple, newlist); | ||||
| 	}							/* endif alter group add user */ | ||||
| 
 | ||||
| 	else if (stmt->action == -1)	/* drop users from group */ | ||||
| 	{ | ||||
| 		Datum		datum; | ||||
| 		bool		null; | ||||
| 		bool		is_dropuser = strcmp(tag, "DROP USER") == 0; | ||||
| 
 | ||||
| 		datum = heap_getattr(group_tuple, Anum_pg_group_grolist, pg_group_dsc, &null); | ||||
| 		if (null) | ||||
| 		if (newlist == NIL) | ||||
| 		{ | ||||
| 			if (!is_dropuser) | ||||
| 				elog(WARNING, "ALTER GROUP: group \"%s\" does not have any members", stmt->name); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			HeapTuple	tuple; | ||||
| 			Datum		new_record[Natts_pg_group]; | ||||
| 			char		new_record_nulls[Natts_pg_group]; | ||||
| 			ArrayType  *oldarray, | ||||
| 					   *newarray; | ||||
| 			List	   *newlist = NIL, | ||||
| 					   *item; | ||||
| 			int			i; | ||||
| 
 | ||||
| 			oldarray = (ArrayType *) datum; | ||||
| 			Assert(ARR_NDIM(oldarray) == 1); | ||||
| 			/* first add the old array to the hitherto empty list */ | ||||
| 			for (i = ARR_LBOUND(oldarray)[0]; i < ARR_LBOUND(oldarray)[0] + ARR_DIMS(oldarray)[0]; i++) | ||||
| 			{ | ||||
| 				int			index, | ||||
| 							arrval; | ||||
| 				Value	   *v; | ||||
| 				bool		valueNull; | ||||
| 
 | ||||
| 				index = i; | ||||
| 				arrval = DatumGetInt32(array_ref(oldarray, 1, &index, true /* by value */ , | ||||
| 											sizeof(int), 0, &valueNull)); | ||||
| 				v = makeInteger(arrval); | ||||
| 				/* filter out duplicates */ | ||||
| 				if (!member(v, newlist)) | ||||
| 					newlist = lappend(newlist, v); | ||||
| 			} | ||||
| 
 | ||||
| 			/*
 | ||||
| 			 * now convert the to be dropped usernames to sysids and | ||||
| 			 * convert the to be dropped usernames to sysids and | ||||
| 			 * remove them from the list | ||||
| 			 */ | ||||
| 			foreach(item, stmt->listUsers) | ||||
| 			{ | ||||
| 				Value	   *v; | ||||
| 				int32		sysid; | ||||
| 
 | ||||
| 				if (!is_dropuser) | ||||
| 				{ | ||||
| 					/* Get the uid of the proposed user to drop. */ | ||||
| 					v = makeInteger(get_usesysid(strVal(lfirst(item)))); | ||||
| 					sysid = get_usesysid(strVal(lfirst(item))); | ||||
| 				} | ||||
| 				else | ||||
| 				{ | ||||
| 					/* for dropuser we already know the uid */ | ||||
| 					v = lfirst(item); | ||||
| 					sysid = intVal(lfirst(item)); | ||||
| 				} | ||||
| 				if (member(v, newlist)) | ||||
| 					newlist = LispRemove(v, newlist); | ||||
| 				if (intMember(sysid, newlist)) | ||||
| 					newlist = lremovei(sysid, newlist); | ||||
| 				else if (!is_dropuser) | ||||
| 					elog(WARNING, "ALTER GROUP: user \"%s\" is not in group \"%s\"", strVal(lfirst(item)), stmt->name); | ||||
| 			} | ||||
| 
 | ||||
| 			newarray = palloc(ARR_OVERHEAD(1) + length(newlist) * sizeof(int32)); | ||||
| 			newarray->size = ARR_OVERHEAD(1) + length(newlist) * sizeof(int32); | ||||
| 			newarray->flags = 0; | ||||
| 			ARR_NDIM(newarray) = 1;		/* one dimensional array */ | ||||
| 			ARR_LBOUND(newarray)[0] = 1;		/* axis starts at one */ | ||||
| 			ARR_DIMS(newarray)[0] = length(newlist);	/* axis is this long */ | ||||
| 			/* fill the array */ | ||||
| 			i = 0; | ||||
| 			foreach(item, newlist) | ||||
| 				((int *) ARR_DATA_PTR(newarray))[i++] = intVal(lfirst(item)); | ||||
| 
 | ||||
| 			/*
 | ||||
| 			 * Insert the new tuple with the updated user list | ||||
| 			 */ | ||||
| 			new_record[Anum_pg_group_groname - 1] = | ||||
| 				DirectFunctionCall1(namein, CStringGetDatum(stmt->name)); | ||||
| 			new_record_nulls[Anum_pg_group_groname - 1] = ' '; | ||||
| 			new_record[Anum_pg_group_grosysid - 1] = heap_getattr(group_tuple, Anum_pg_group_grosysid, pg_group_dsc, &null); | ||||
| 			new_record_nulls[Anum_pg_group_grosysid - 1] = null ? 'n' : ' '; | ||||
| 			new_record[Anum_pg_group_grolist - 1] = PointerGetDatum(newarray); | ||||
| 			new_record_nulls[Anum_pg_group_grolist - 1] = newarray ? ' ' : 'n'; | ||||
| 
 | ||||
| 			tuple = heap_formtuple(pg_group_dsc, new_record, new_record_nulls); | ||||
| 			simple_heap_update(pg_group_rel, &group_tuple->t_self, tuple); | ||||
| 
 | ||||
| 			/* Update indexes */ | ||||
| 			if (RelationGetForm(pg_group_rel)->relhasindex) | ||||
| 			{ | ||||
| 				Relation	idescs[Num_pg_group_indices]; | ||||
| 
 | ||||
| 				CatalogOpenIndices(Num_pg_group_indices, | ||||
| 								   Name_pg_group_indices, idescs); | ||||
| 				CatalogIndexInsert(idescs, Num_pg_group_indices, pg_group_rel, | ||||
| 								   tuple); | ||||
| 				CatalogCloseIndices(Num_pg_group_indices, idescs); | ||||
| 			} | ||||
| 
 | ||||
| 			/* Do the update */ | ||||
| 			UpdateGroupMembership(pg_group_rel, group_tuple, newlist); | ||||
| 		}						/* endif group not null */ | ||||
| 	}							/* endif alter group drop user */ | ||||
| 
 | ||||
| @ -1571,6 +1387,107 @@ AlterGroup(AlterGroupStmt *stmt, const char *tag) | ||||
| 	update_pg_pwd_and_pg_group(NULL); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Subroutine for AlterGroup: given a pg_group tuple and a desired new | ||||
|  * membership (expressed as an integer list), form and write an updated tuple. | ||||
|  * The pg_group relation must be open and locked already. | ||||
|  */ | ||||
| static void | ||||
| UpdateGroupMembership(Relation group_rel, HeapTuple group_tuple, | ||||
| 					  List *members) | ||||
| { | ||||
| 	IdList	   *newarray; | ||||
| 	Datum		new_record[Natts_pg_group]; | ||||
| 	char		new_record_nulls[Natts_pg_group]; | ||||
| 	char		new_record_repl[Natts_pg_group]; | ||||
| 	HeapTuple	tuple; | ||||
| 
 | ||||
| 	newarray = IdListToArray(members); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Form an updated tuple with the new array and write it back. | ||||
| 	 */ | ||||
| 	MemSet(new_record, 0, sizeof(new_record)); | ||||
| 	MemSet(new_record_nulls, ' ', sizeof(new_record_nulls)); | ||||
| 	MemSet(new_record_repl, ' ', sizeof(new_record_repl)); | ||||
| 
 | ||||
| 	new_record[Anum_pg_group_grolist - 1] = PointerGetDatum(newarray); | ||||
| 	new_record_repl[Anum_pg_group_grolist - 1] = 'r'; | ||||
| 
 | ||||
| 	tuple = heap_modifytuple(group_tuple, group_rel, | ||||
| 							 new_record, new_record_nulls, new_record_repl); | ||||
| 
 | ||||
| 	simple_heap_update(group_rel, &group_tuple->t_self, tuple); | ||||
| 
 | ||||
| 	/* Update indexes */ | ||||
| 	if (RelationGetForm(group_rel)->relhasindex) | ||||
| 	{ | ||||
| 		Relation	idescs[Num_pg_group_indices]; | ||||
| 
 | ||||
| 		CatalogOpenIndices(Num_pg_group_indices, | ||||
| 						   Name_pg_group_indices, idescs); | ||||
| 		CatalogIndexInsert(idescs, Num_pg_group_indices, group_rel, | ||||
| 						   tuple); | ||||
| 		CatalogCloseIndices(Num_pg_group_indices, idescs); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Convert an integer list of sysids to an array. | ||||
|  */ | ||||
| static IdList * | ||||
| IdListToArray(List *members) | ||||
| { | ||||
| 	int			nmembers = length(members); | ||||
| 	IdList	   *newarray; | ||||
| 	List	   *item; | ||||
| 	int			i; | ||||
| 
 | ||||
| 	newarray = palloc(ARR_OVERHEAD(1) + nmembers * sizeof(int32)); | ||||
| 	newarray->size = ARR_OVERHEAD(1) + nmembers * sizeof(int32); | ||||
| 	newarray->flags = 0; | ||||
| 	ARR_NDIM(newarray) = 1;		/* one dimensional array */ | ||||
| 	ARR_LBOUND(newarray)[0] = 1;	/* axis starts at one */ | ||||
| 	ARR_DIMS(newarray)[0] = nmembers; /* axis is this long */ | ||||
| 	i = 0; | ||||
| 	foreach(item, members) | ||||
| 	{ | ||||
| 		((int *) ARR_DATA_PTR(newarray))[i++] = lfirsti(item); | ||||
| 	} | ||||
| 
 | ||||
| 	return newarray; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Convert an array of sysids to an integer list. | ||||
|  */ | ||||
| static List * | ||||
| IdArrayToList(IdList *oldarray) | ||||
| { | ||||
| 	List	   *newlist = NIL; | ||||
| 	int			hibound, | ||||
| 				i; | ||||
| 
 | ||||
| 	if (oldarray == NULL) | ||||
| 		return NIL; | ||||
| 
 | ||||
| 	Assert(ARR_NDIM(oldarray) == 1); | ||||
| 
 | ||||
| 	hibound = ARR_DIMS(oldarray)[0]; | ||||
| 
 | ||||
| 	for (i = 0; i < hibound; i++) | ||||
| 	{ | ||||
| 		int32		sysid; | ||||
| 
 | ||||
| 		sysid = ((int *) ARR_DATA_PTR(oldarray))[i]; | ||||
| 		/* filter out any duplicates --- probably a waste of time */ | ||||
| 		if (!intMember(sysid, newlist)) | ||||
| 			newlist = lappendi(newlist, sysid); | ||||
| 	} | ||||
| 
 | ||||
| 	return newlist; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
| @ -1580,10 +1497,7 @@ void | ||||
| DropGroup(DropGroupStmt *stmt) | ||||
| { | ||||
| 	Relation	pg_group_rel; | ||||
| 	HeapScanDesc scan; | ||||
| 	HeapTuple	tuple; | ||||
| 	TupleDesc	pg_group_dsc; | ||||
| 	bool		gro_exists = false; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Make sure the user can do this. | ||||
| @ -1592,34 +1506,18 @@ DropGroup(DropGroupStmt *stmt) | ||||
| 		elog(ERROR, "DROP GROUP: permission denied"); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Scan the pg_group table and delete all matching groups. | ||||
| 	 * Drop the group. | ||||
| 	 */ | ||||
| 	pg_group_rel = heap_openr(GroupRelationName, ExclusiveLock); | ||||
| 	pg_group_dsc = RelationGetDescr(pg_group_rel); | ||||
| 	scan = heap_beginscan(pg_group_rel, false, SnapshotNow, 0, NULL); | ||||
| 
 | ||||
| 	while (HeapTupleIsValid(tuple = heap_getnext(scan, false))) | ||||
| 	{ | ||||
| 		Datum		datum; | ||||
| 		bool		null; | ||||
| 
 | ||||
| 		datum = heap_getattr(tuple, Anum_pg_group_groname, | ||||
| 							 pg_group_dsc, &null); | ||||
| 		if (!null && strcmp(NameStr(*DatumGetName(datum)), stmt->name) == 0) | ||||
| 		{ | ||||
| 			gro_exists = true; | ||||
| 			simple_heap_delete(pg_group_rel, &tuple->t_self); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	heap_endscan(scan); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Did we find any? | ||||
| 	 */ | ||||
| 	if (!gro_exists) | ||||
| 	tuple = SearchSysCacheCopy(GRONAME, | ||||
| 							   PointerGetDatum(stmt->name), | ||||
| 							   0, 0, 0); | ||||
| 	if (!HeapTupleIsValid(tuple)) | ||||
| 		elog(ERROR, "DROP GROUP: group \"%s\" does not exist", stmt->name); | ||||
| 
 | ||||
| 	simple_heap_delete(pg_group_rel, &tuple->t_self); | ||||
| 
 | ||||
| 	heap_close(pg_group_rel, NoLock); | ||||
| 
 | ||||
| 	/*
 | ||||
|  | ||||
| @ -27,7 +27,7 @@ | ||||
|  * | ||||
|  * | ||||
|  * IDENTIFICATION | ||||
|  *	  $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.159 2002/04/27 03:45:02 tgl Exp $ | ||||
|  *	  $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.160 2002/04/27 21:24:34 tgl Exp $ | ||||
|  * | ||||
|  *------------------------------------------------------------------------- | ||||
|  */ | ||||
| @ -733,6 +733,7 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate) | ||||
| 											 namespaceId, | ||||
| 											 tupdesc, | ||||
| 											 RELKIND_RELATION, | ||||
| 											 false, | ||||
| 											 true, | ||||
| 											 allowSystemTableMods); | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										23
									
								
								src/backend/utils/cache/relcache.c
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										23
									
								
								src/backend/utils/cache/relcache.c
									
									
									
									
										vendored
									
									
								
							| @ -8,7 +8,7 @@ | ||||
|  * | ||||
|  * | ||||
|  * IDENTIFICATION | ||||
|  *	  $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.162 2002/04/19 16:36:08 tgl Exp $ | ||||
|  *	  $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.163 2002/04/27 21:24:34 tgl Exp $ | ||||
|  * | ||||
|  *------------------------------------------------------------------------- | ||||
|  */ | ||||
| @ -1319,7 +1319,10 @@ LookupOpclassInfo(Oid operatorClassOid, | ||||
|  *		The relation descriptor is built just from the supplied parameters, | ||||
|  *		without actually looking at any system table entries.  We cheat | ||||
|  *		quite a lot since we only need to work for a few basic system | ||||
|  *		catalogs... | ||||
|  *		catalogs. | ||||
|  * | ||||
|  * formrdesc is currently used for: pg_class, pg_attribute, pg_proc, | ||||
|  * and pg_type (see RelationCacheInitialize). | ||||
|  * | ||||
|  * Note that these catalogs can't have constraints, default values, | ||||
|  * rules, or triggers, since we don't cope with any of that. | ||||
| @ -1374,9 +1377,10 @@ formrdesc(const char *relationName, | ||||
| 	/*
 | ||||
| 	 * It's important to distinguish between shared and non-shared | ||||
| 	 * relations, even at bootstrap time, to make sure we know where they | ||||
| 	 * are stored. | ||||
| 	 * are stored.  At present, all relations that formrdesc is used for | ||||
| 	 * are not shared. | ||||
| 	 */ | ||||
| 	relation->rd_rel->relisshared = IsSharedSystemRelationName(relationName); | ||||
| 	relation->rd_rel->relisshared = false; | ||||
| 
 | ||||
| 	relation->rd_rel->relpages = 1; | ||||
| 	relation->rd_rel->reltuples = 1; | ||||
| @ -1434,15 +1438,8 @@ formrdesc(const char *relationName, | ||||
| 	/* In bootstrap mode, we have no indexes */ | ||||
| 	if (!IsBootstrapProcessingMode()) | ||||
| 	{ | ||||
| 		/*
 | ||||
| 		 * This list is incomplete, but it only has to work for the set of | ||||
| 		 * rels that formrdesc is used for ... | ||||
| 		 */ | ||||
| 		if (strcmp(relationName, RelationRelationName) == 0 || | ||||
| 			strcmp(relationName, AttributeRelationName) == 0 || | ||||
| 			strcmp(relationName, ProcedureRelationName) == 0 || | ||||
| 			strcmp(relationName, TypeRelationName) == 0) | ||||
| 			relation->rd_rel->relhasindex = true; | ||||
| 		/* Otherwise, all the rels formrdesc is used for have indexes */ | ||||
| 		relation->rd_rel->relhasindex = true; | ||||
| 	} | ||||
| 
 | ||||
| 	/*
 | ||||
|  | ||||
| @ -8,7 +8,7 @@ | ||||
|  * | ||||
|  * | ||||
|  * IDENTIFICATION | ||||
|  *	  $Header: /cvsroot/pgsql/src/backend/utils/init/globals.c,v 1.63 2002/03/02 21:39:33 momjian Exp $ | ||||
|  *	  $Header: /cvsroot/pgsql/src/backend/utils/init/globals.c,v 1.64 2002/04/27 21:24:34 tgl Exp $ | ||||
|  * | ||||
|  * NOTES | ||||
|  *	  Globals used all over the place should be declared here and not | ||||
| @ -18,14 +18,6 @@ | ||||
|  */ | ||||
| #include "postgres.h" | ||||
| 
 | ||||
| #include <fcntl.h> | ||||
| #include <sys/file.h> | ||||
| #include <sys/types.h> | ||||
| #include <math.h> | ||||
| #include <unistd.h> | ||||
| 
 | ||||
| #include "catalog/catname.h" | ||||
| #include "catalog/indexing.h" | ||||
| #include "libpq/pqcomm.h" | ||||
| #include "miscadmin.h" | ||||
| #include "storage/backendid.h" | ||||
| @ -47,14 +39,11 @@ struct Port *MyProcPort; | ||||
| long		MyCancelKey; | ||||
| 
 | ||||
| char	   *DataDir = NULL; | ||||
| 
 | ||||
|  /*
 | ||||
|   * The PGDATA directory user says to use, or defaults to via environment | ||||
|   * variable.  NULL if no option given and no environment variable set | ||||
|   */ | ||||
| 
 | ||||
| Relation	reldesc;			/* current relation descriptor */ | ||||
| 
 | ||||
| char		OutputFileName[MAXPGPATH]; | ||||
| 
 | ||||
| char		pg_pathname[MAXPGPATH];		/* full path to postgres
 | ||||
| @ -85,27 +74,3 @@ bool		allowSystemTableMods = false; | ||||
| int			SortMem = 512; | ||||
| int			VacuumMem = 8192; | ||||
| int			NBuffers = DEF_NBUFFERS; | ||||
| 
 | ||||
| 
 | ||||
| /* ----------------
 | ||||
|  * List of relations that are shared across all databases in an installation. | ||||
|  * | ||||
|  * This used to be binary-searched, requiring that it be kept in sorted order. | ||||
|  * We just do a linear search now so there's no requirement that the list | ||||
|  * be ordered.	The list is so small it shouldn't make much difference. | ||||
|  * make sure the list is null-terminated | ||||
|  *				- jolly 8/19/95 | ||||
|  * ---------------- | ||||
|  */ | ||||
| char	   *SharedSystemRelationNames[] = { | ||||
| 	DatabaseRelationName, | ||||
| 	DatabaseNameIndex, | ||||
| 	DatabaseOidIndex, | ||||
| 	GroupRelationName, | ||||
| 	GroupNameIndex, | ||||
| 	GroupSysidIndex, | ||||
| 	ShadowRelationName, | ||||
| 	ShadowNameIndex, | ||||
| 	ShadowSysidIndex, | ||||
| 	NULL | ||||
| }; | ||||
|  | ||||
| @ -8,7 +8,7 @@ | ||||
|  * | ||||
|  * | ||||
|  * IDENTIFICATION | ||||
|  *	  $Header: /cvsroot/pgsql/src/backend/utils/init/miscinit.c,v 1.86 2002/04/04 04:25:49 momjian Exp $ | ||||
|  *	  $Header: /cvsroot/pgsql/src/backend/utils/init/miscinit.c,v 1.87 2002/04/27 21:24:34 tgl Exp $ | ||||
|  * | ||||
|  *------------------------------------------------------------------------- | ||||
|  */ | ||||
| @ -612,9 +612,8 @@ InitializeSessionUserId(const char *username) | ||||
| 							Anum_pg_shadow_useconfig, &isnull); | ||||
| 	if (!isnull) | ||||
| 	{ | ||||
| 		ArrayType *a; | ||||
| 		ArrayType *a = DatumGetArrayTypeP(datum); | ||||
| 
 | ||||
| 		a = (ArrayType *) pg_detoast_datum((struct varlena *)datum); | ||||
| 		ProcessGUCArray(a, PGC_S_USER); | ||||
| 	} | ||||
| 
 | ||||
|  | ||||
| @ -8,7 +8,7 @@ | ||||
|  * | ||||
|  * | ||||
|  * IDENTIFICATION | ||||
|  *	  $Header: /cvsroot/pgsql/src/backend/utils/init/postinit.c,v 1.102 2002/04/01 03:34:26 tgl Exp $ | ||||
|  *	  $Header: /cvsroot/pgsql/src/backend/utils/init/postinit.c,v 1.103 2002/04/27 21:24:34 tgl Exp $ | ||||
|  * | ||||
|  * | ||||
|  *------------------------------------------------------------------------- | ||||
| @ -138,7 +138,7 @@ ReverifyMyDatabase(const char *name) | ||||
| #endif | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Set up datbase-specific configuration variables. | ||||
| 	 * Set up database-specific configuration variables. | ||||
| 	 */ | ||||
| 	if (IsUnderPostmaster) | ||||
| 	{ | ||||
| @ -149,9 +149,8 @@ ReverifyMyDatabase(const char *name) | ||||
| 							 RelationGetDescr(pgdbrel), &isnull); | ||||
| 		if (!isnull) | ||||
| 		{ | ||||
| 			ArrayType *a; | ||||
| 			ArrayType *a = DatumGetArrayTypeP(datum); | ||||
| 
 | ||||
| 			a = (ArrayType *) pg_detoast_datum((struct varlena *)datum); | ||||
| 			ProcessGUCArray(a, PGC_S_DATABASE); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| @ -27,7 +27,7 @@ | ||||
| # Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group | ||||
| # Portions Copyright (c) 1994, Regents of the University of California | ||||
| # | ||||
| # $Header: /cvsroot/pgsql/src/bin/initdb/Attic/initdb.sh,v 1.151 2002/04/21 00:26:43 tgl Exp $ | ||||
| # $Header: /cvsroot/pgsql/src/bin/initdb/Attic/initdb.sh,v 1.152 2002/04/27 21:24:34 tgl Exp $ | ||||
| # | ||||
| #------------------------------------------------------------------------- | ||||
| 
 | ||||
| @ -658,10 +658,13 @@ $ECHO_N "enabling unlimited row size for system tables... "$ECHO_C | ||||
| 
 | ||||
| "$PGPATH"/postgres $PGSQL_OPT template1 >/dev/null <<EOF | ||||
| ALTER TABLE pg_attrdef CREATE TOAST TABLE; | ||||
| ALTER TABLE pg_database CREATE TOAST TABLE; | ||||
| ALTER TABLE pg_description CREATE TOAST TABLE; | ||||
| ALTER TABLE pg_group CREATE TOAST TABLE; | ||||
| ALTER TABLE pg_proc CREATE TOAST TABLE; | ||||
| ALTER TABLE pg_relcheck CREATE TOAST TABLE; | ||||
| ALTER TABLE pg_rewrite CREATE TOAST TABLE; | ||||
| ALTER TABLE pg_shadow CREATE TOAST TABLE; | ||||
| ALTER TABLE pg_statistic CREATE TOAST TABLE; | ||||
| EOF | ||||
| if [ "$?" -ne 0 ]; then | ||||
|  | ||||
| @ -7,7 +7,7 @@ | ||||
|  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group | ||||
|  * Portions Copyright (c) 1994, Regents of the University of California | ||||
|  * | ||||
|  * $Id: bootstrap.h,v 1.28 2002/03/26 19:16:20 tgl Exp $ | ||||
|  * $Id: bootstrap.h,v 1.29 2002/04/27 21:24:34 tgl Exp $ | ||||
|  * | ||||
|  *------------------------------------------------------------------------- | ||||
|  */ | ||||
| @ -31,7 +31,7 @@ typedef struct hashnode | ||||
| } hashnode; | ||||
| 
 | ||||
| 
 | ||||
| extern Relation reldesc; | ||||
| extern Relation boot_reldesc; | ||||
| extern Form_pg_attribute attrtypes[MAXATTR]; | ||||
| extern int	numattr; | ||||
| extern int	BootstrapMain(int ac, char *av[]); | ||||
|  | ||||
| @ -7,7 +7,7 @@ | ||||
|  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group | ||||
|  * Portions Copyright (c) 1994, Regents of the University of California | ||||
|  * | ||||
|  * $Id: catalog.h,v 1.23 2002/04/12 20:38:30 tgl Exp $ | ||||
|  * $Id: catalog.h,v 1.24 2002/04/27 21:24:34 tgl Exp $ | ||||
|  * | ||||
|  *------------------------------------------------------------------------- | ||||
|  */ | ||||
| @ -30,7 +30,6 @@ extern bool IsSystemNamespace(Oid namespaceId); | ||||
| extern bool IsToastNamespace(Oid namespaceId); | ||||
| 
 | ||||
| extern bool IsReservedName(const char *name); | ||||
| extern bool IsSharedSystemRelationName(const char *relname); | ||||
| 
 | ||||
| extern Oid	newoid(void); | ||||
| 
 | ||||
|  | ||||
| @ -7,7 +7,7 @@ | ||||
|  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group | ||||
|  * Portions Copyright (c) 1994, Regents of the University of California | ||||
|  * | ||||
|  * $Id: catname.h,v 1.24 2002/03/22 21:34:44 tgl Exp $ | ||||
|  * $Id: catname.h,v 1.25 2002/04/27 21:24:34 tgl Exp $ | ||||
|  * | ||||
|  *------------------------------------------------------------------------- | ||||
|  */ | ||||
| @ -42,6 +42,4 @@ | ||||
| #define  RelCheckRelationName "pg_relcheck" | ||||
| #define  TriggerRelationName "pg_trigger" | ||||
| 
 | ||||
| extern char *SharedSystemRelationNames[]; | ||||
| 
 | ||||
| #endif   /* CATNAME_H */ | ||||
|  | ||||
| @ -37,7 +37,7 @@ | ||||
|  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group | ||||
|  * Portions Copyright (c) 1994, Regents of the University of California | ||||
|  * | ||||
|  * $Id: catversion.h,v 1.127 2002/04/26 01:24:08 tgl Exp $ | ||||
|  * $Id: catversion.h,v 1.128 2002/04/27 21:24:34 tgl Exp $ | ||||
|  * | ||||
|  *------------------------------------------------------------------------- | ||||
|  */ | ||||
| @ -53,6 +53,6 @@ | ||||
|  */ | ||||
| 
 | ||||
| /*							yyyymmddN */ | ||||
| #define CATALOG_VERSION_NO	200204251 | ||||
| #define CATALOG_VERSION_NO	200204271 | ||||
| 
 | ||||
| #endif | ||||
|  | ||||
| @ -7,7 +7,7 @@ | ||||
|  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group | ||||
|  * Portions Copyright (c) 1994, Regents of the University of California | ||||
|  * | ||||
|  * $Id: heap.h,v 1.49 2002/03/31 06:26:32 tgl Exp $ | ||||
|  * $Id: heap.h,v 1.50 2002/04/27 21:24:34 tgl Exp $ | ||||
|  * | ||||
|  *------------------------------------------------------------------------- | ||||
|  */ | ||||
| @ -30,6 +30,7 @@ typedef struct RawColumnDefault | ||||
| extern Relation heap_create(const char *relname, | ||||
| 			Oid relnamespace, | ||||
| 			TupleDesc tupDesc, | ||||
| 			bool shared_relation, | ||||
| 			bool storage_create, | ||||
| 			bool allow_system_table_mods); | ||||
| 
 | ||||
| @ -39,6 +40,7 @@ extern Oid heap_create_with_catalog(const char *relname, | ||||
| 						 Oid relnamespace, | ||||
| 						 TupleDesc tupdesc, | ||||
| 						 char relkind, | ||||
| 						 bool shared_relation, | ||||
| 						 bool relhasoids, | ||||
| 						 bool allow_system_table_mods); | ||||
| 
 | ||||
|  | ||||
| @ -8,7 +8,7 @@ | ||||
|  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group | ||||
|  * Portions Copyright (c) 1994, Regents of the University of California | ||||
|  * | ||||
|  * $Id: pg_database.h,v 1.23 2002/04/21 00:26:43 tgl Exp $ | ||||
|  * $Id: pg_database.h,v 1.24 2002/04/27 21:24:34 tgl Exp $ | ||||
|  * | ||||
|  * NOTES | ||||
|  *	  the genbki.sh script reads this file and generates .bki | ||||
| @ -31,7 +31,7 @@ | ||||
|  *		typedef struct FormData_pg_database | ||||
|  * ---------------- | ||||
|  */ | ||||
| CATALOG(pg_database) BOOTSTRAP | ||||
| CATALOG(pg_database) BOOTSTRAP BKI_SHARED_RELATION | ||||
| { | ||||
| 	NameData	datname;		/* database name */ | ||||
| 	int4		datdba;			/* sysid of owner */ | ||||
|  | ||||
| @ -7,7 +7,7 @@ | ||||
|  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group | ||||
|  * Portions Copyright (c) 1994, Regents of the University of California | ||||
|  * | ||||
|  * $Id: pg_group.h,v 1.13 2001/11/05 17:46:32 momjian Exp $ | ||||
|  * $Id: pg_group.h,v 1.14 2002/04/27 21:24:34 tgl Exp $ | ||||
|  * | ||||
|  * NOTES | ||||
|  *	  the genbki.sh script reads this file and generates .bki | ||||
| @ -25,7 +25,7 @@ | ||||
|  * ---------------- | ||||
|  */ | ||||
| 
 | ||||
| CATALOG(pg_group) BOOTSTRAP BKI_WITHOUT_OIDS | ||||
| CATALOG(pg_group) BOOTSTRAP BKI_SHARED_RELATION BKI_WITHOUT_OIDS | ||||
| { | ||||
| 	NameData	groname; | ||||
| 	int4		grosysid; | ||||
|  | ||||
| @ -9,7 +9,7 @@ | ||||
|  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group | ||||
|  * Portions Copyright (c) 1994, Regents of the University of California | ||||
|  * | ||||
|  * $Id: pg_shadow.h,v 1.19 2002/04/11 05:32:03 petere Exp $ | ||||
|  * $Id: pg_shadow.h,v 1.20 2002/04/27 21:24:34 tgl Exp $ | ||||
|  * | ||||
|  * NOTES | ||||
|  *	  the genbki.sh script reads this file and generates .bki | ||||
| @ -29,7 +29,7 @@ | ||||
|  *		typedef struct FormData_pg_shadow | ||||
|  * ---------------- | ||||
|  */ | ||||
| CATALOG(pg_shadow) BOOTSTRAP BKI_WITHOUT_OIDS | ||||
| CATALOG(pg_shadow) BOOTSTRAP BKI_SHARED_RELATION BKI_WITHOUT_OIDS | ||||
| { | ||||
| 	NameData	usename; | ||||
| 	int4		usesysid; | ||||
| @ -37,8 +37,9 @@ CATALOG(pg_shadow) BOOTSTRAP BKI_WITHOUT_OIDS | ||||
| 	bool		usetrace; | ||||
| 	bool		usesuper;		/* read this field via superuser() only */ | ||||
| 	bool		usecatupd; | ||||
| 	/* remaining fields may be null; use heap_getattr to read them! */ | ||||
| 	text		passwd; | ||||
| 	int4		valuntil; | ||||
| 	int4		valuntil;		/* actually abstime */ | ||||
| 	text		useconfig[1]; | ||||
| } FormData_pg_shadow; | ||||
| 
 | ||||
|  | ||||
| @ -10,7 +10,7 @@ | ||||
|  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group | ||||
|  * Portions Copyright (c) 1995, Regents of the University of California | ||||
|  * | ||||
|  * $Id: postgres.h,v 1.56 2001/11/05 17:46:31 momjian Exp $ | ||||
|  * $Id: postgres.h,v 1.57 2002/04/27 21:24:34 tgl Exp $ | ||||
|  * | ||||
|  *------------------------------------------------------------------------- | ||||
|  */ | ||||
| @ -597,7 +597,7 @@ extern int	assertTest(int val); | ||||
| #define CATALOG(x)	typedef struct CppConcat(FormData_,x) | ||||
| 
 | ||||
| #define BOOTSTRAP | ||||
| 
 | ||||
| #define BKI_SHARED_RELATION | ||||
| #define BKI_WITHOUT_OIDS | ||||
| 
 | ||||
| /* these need to expand into some harmless, repeatable declaration */ | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user