*** pgsql/src/backend/commands/tsearchcmds.c	2008/03/26 21:10:38	1.11
--- pgsql/src/backend/commands/tsearchcmds.c	2008/06/14 18:04:33	1.12
***************
*** 9,15 ****
   *
   *
   * IDENTIFICATION
!  *	  $PostgreSQL: pgsql/src/backend/commands/tsearchcmds.c,v 1.10 2008/03/25 22:42:43 tgl Exp $
   *
   *-------------------------------------------------------------------------
   */
--- 9,15 ----
   *
   *
   * IDENTIFICATION
!  *	  $PostgreSQL: pgsql/src/backend/commands/tsearchcmds.c,v 1.11 2008/03/26 21:10:38 alvherre Exp $
   *
   *-------------------------------------------------------------------------
   */
*************** DefineTSParser(List *names, List *parame
*** 271,310 ****
   * DROP TEXT SEARCH PARSER
   */
  void
! RemoveTSParser(List *names, DropBehavior behavior, bool missing_ok)
  {
! 	Oid			prsOid;
! 	ObjectAddress object;
  
  	if (!superuser())
  		ereport(ERROR,
  				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
  				 errmsg("must be superuser to drop text search parsers")));
  
! 	prsOid = TSParserGetPrsid(names, true);
! 	if (!OidIsValid(prsOid))
  	{
! 		if (!missing_ok)
  		{
! 			ereport(ERROR,
! 					(errcode(ERRCODE_UNDEFINED_OBJECT),
! 					 errmsg("text search parser \"%s\" does not exist",
  							NameListToString(names))));
  		}
! 		else
! 		{
! 			ereport(NOTICE,
! 				(errmsg("text search parser \"%s\" does not exist, skipping",
! 						NameListToString(names))));
! 		}
! 		return;
  	}
  
! 	object.classId = TSParserRelationId;
! 	object.objectId = prsOid;
! 	object.objectSubId = 0;
  
! 	performDeletion(&object, behavior);
  }
  
  /*
--- 271,329 ----
   * DROP TEXT SEARCH PARSER
   */
  void
! RemoveTSParsers(DropStmt *drop)
  {
! 	ObjectAddresses *objects;
! 	ListCell		*cell;
  
  	if (!superuser())
  		ereport(ERROR,
  				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
  				 errmsg("must be superuser to drop text search parsers")));
  
! 	/*
! 	 * First we identify all the objects, then we delete them in a single
! 	 * performMultipleDeletions() call.  This is to avoid unwanted
! 	 * DROP RESTRICT errors if one of the objects depends on another.
! 	 */
! 	objects = new_object_addresses();
! 
! 	foreach(cell, drop->objects)
  	{
! 		List		*names = (List *) lfirst(cell);
! 		Oid			prsOid;
! 		ObjectAddress object;
! 
! 		prsOid = TSParserGetPrsid(names, true);
! 
! 		if (!OidIsValid(prsOid))
  		{
! 			if (!drop->missing_ok)
! 			{
! 				ereport(ERROR,
! 						(errcode(ERRCODE_UNDEFINED_OBJECT),
! 						 errmsg("text search parser \"%s\" does not exist",
! 								NameListToString(names))));
! 			}
! 			else
! 			{
! 				ereport(NOTICE,
! 					(errmsg("text search parser \"%s\" does not exist, skipping",
  							NameListToString(names))));
+ 			}
+ 			continue;
  		}
! 
! 		object.classId = TSParserRelationId;
! 		object.objectId = prsOid;
! 		object.objectSubId = 0;
! 
! 		add_exact_object_address(&object, objects);
  	}
  
! 	performMultipleDeletions(objects, drop->behavior);
  
! 	free_object_addresses(objects);
  }
  
  /*
*************** RenameTSDictionary(List *oldname, const
*** 613,666 ****
   * DROP TEXT SEARCH DICTIONARY
   */
  void
! RemoveTSDictionary(List *names, DropBehavior behavior, bool missing_ok)
  {
! 	Oid			dictOid;
! 	ObjectAddress object;
! 	HeapTuple	tup;
! 	Oid			namespaceId;
  
! 	dictOid = TSDictionaryGetDictid(names, true);
! 	if (!OidIsValid(dictOid))
  	{
! 		if (!missing_ok)
! 		{
! 			ereport(ERROR,
! 					(errcode(ERRCODE_UNDEFINED_OBJECT),
! 					 errmsg("text search dictionary \"%s\" does not exist",
! 							NameListToString(names))));
! 		}
! 		else
! 		{
! 			ereport(NOTICE,
! 			(errmsg("text search dictionary \"%s\" does not exist, skipping",
! 					NameListToString(names))));
  		}
- 		return;
- 	}
  
! 	tup = SearchSysCache(TSDICTOID,
! 						 ObjectIdGetDatum(dictOid),
! 						 0, 0, 0);
! 
! 	if (!HeapTupleIsValid(tup)) /* should not happen */
! 		elog(ERROR, "cache lookup failed for text search dictionary %u",
! 			 dictOid);
  
! 	/* Permission check: must own dictionary or its namespace */
! 	namespaceId = ((Form_pg_ts_dict) GETSTRUCT(tup))->dictnamespace;
! 	if (!pg_ts_dict_ownercheck(dictOid, GetUserId()) &&
! 		!pg_namespace_ownercheck(namespaceId, GetUserId()))
! 		aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TSDICTIONARY,
! 					   NameListToString(names));
  
! 	ReleaseSysCache(tup);
  
! 	object.classId = TSDictionaryRelationId;
! 	object.objectId = dictOid;
! 	object.objectSubId = 0;
  
! 	performDeletion(&object, behavior);
  }
  
  /*
--- 632,703 ----
   * DROP TEXT SEARCH DICTIONARY
   */
  void
! RemoveTSDictionaries(DropStmt *drop)
  {
! 	ObjectAddresses *objects;
! 	ListCell		*cell;
  
! 	/*
! 	 * First we identify all the objects, then we delete them in a single
! 	 * performMultipleDeletions() call.  This is to avoid unwanted
! 	 * DROP RESTRICT errors if one of the objects depends on another.
! 	 */
! 	objects = new_object_addresses();
! 
! 	foreach(cell, drop->objects)
  	{
! 		List		*names = (List *) lfirst(cell);
! 		Oid			dictOid;
! 		ObjectAddress object;
! 		HeapTuple	tup;
! 		Oid			namespaceId;
! 
! 		dictOid = TSDictionaryGetDictid(names, true);
! 
! 		if (!OidIsValid(dictOid))
! 		{
! 			if (!drop->missing_ok)
! 			{
! 				ereport(ERROR,
! 						(errcode(ERRCODE_UNDEFINED_OBJECT),
! 						 errmsg("text search dictionary \"%s\" does not exist",
! 								NameListToString(names))));
! 			}
! 			else
! 			{
! 				ereport(NOTICE,
! 				(errmsg("text search dictionary \"%s\" does not exist, skipping",
! 						NameListToString(names))));
! 			}
! 			continue;
  		}
  
! 		tup = SearchSysCache(TSDICTOID,
! 							 ObjectIdGetDatum(dictOid),
! 							 0, 0, 0);
! 		if (!HeapTupleIsValid(tup)) /* should not happen */
! 			elog(ERROR, "cache lookup failed for text search dictionary %u",
! 				 dictOid);
! 
! 		/* Permission check: must own dictionary or its namespace */
! 		namespaceId = ((Form_pg_ts_dict) GETSTRUCT(tup))->dictnamespace;
! 		if (!pg_ts_dict_ownercheck(dictOid, GetUserId()) &&
! 			!pg_namespace_ownercheck(namespaceId, GetUserId()))
! 			aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TSDICTIONARY,
! 						   NameListToString(names));
! 
! 		object.classId = TSDictionaryRelationId;
! 		object.objectId = dictOid;
! 		object.objectSubId = 0;
  
! 		add_exact_object_address(&object, objects);
  
! 		ReleaseSysCache(tup);
! 	}
  
! 	performMultipleDeletions(objects, drop->behavior);
  
! 	free_object_addresses(objects);
  }
  
  /*
*************** RenameTSTemplate(List *oldname, const ch
*** 1086,1125 ****
   * DROP TEXT SEARCH TEMPLATE
   */
  void
! RemoveTSTemplate(List *names, DropBehavior behavior, bool missing_ok)
  {
! 	Oid			tmplOid;
! 	ObjectAddress object;
  
  	if (!superuser())
  		ereport(ERROR,
  				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
  				 errmsg("must be superuser to drop text search templates")));
  
! 	tmplOid = TSTemplateGetTmplid(names, true);
! 	if (!OidIsValid(tmplOid))
  	{
! 		if (!missing_ok)
! 		{
! 			ereport(ERROR,
! 					(errcode(ERRCODE_UNDEFINED_OBJECT),
! 					 errmsg("text search template \"%s\" does not exist",
! 							NameListToString(names))));
! 		}
! 		else
  		{
! 			ereport(NOTICE,
! 			  (errmsg("text search template \"%s\" does not exist, skipping",
! 					  NameListToString(names))));
  		}
! 		return;
  	}
  
! 	object.classId = TSTemplateRelationId;
! 	object.objectId = tmplOid;
! 	object.objectSubId = 0;
  
! 	performDeletion(&object, behavior);
  }
  
  /*
--- 1123,1181 ----
   * DROP TEXT SEARCH TEMPLATE
   */
  void
! RemoveTSTemplates(DropStmt *drop)
  {
! 	ObjectAddresses *objects;
! 	ListCell		*cell;
  
  	if (!superuser())
  		ereport(ERROR,
  				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
  				 errmsg("must be superuser to drop text search templates")));
  
! 	/*
! 	 * First we identify all the objects, then we delete them in a single
! 	 * performMultipleDeletions() call.  This is to avoid unwanted
! 	 * DROP RESTRICT errors if one of the objects depends on another.
! 	 */
! 	objects = new_object_addresses();
! 
! 	foreach(cell, drop->objects)
  	{
! 		List		*names = (List *) lfirst(cell);
! 		Oid			tmplOid;
! 		ObjectAddress object;
! 
! 		tmplOid = TSTemplateGetTmplid(names, true);
! 
! 		if (!OidIsValid(tmplOid))
  		{
! 			if (!drop->missing_ok)
! 			{
! 				ereport(ERROR,
! 						(errcode(ERRCODE_UNDEFINED_OBJECT),
! 						 errmsg("text search template \"%s\" does not exist",
! 								NameListToString(names))));
! 			}
! 			else
! 			{
! 				ereport(NOTICE,
! 						(errmsg("text search template \"%s\" does not exist, skipping",
! 								NameListToString(names))));
! 			}
! 			continue;
  		}
! 
! 		object.classId = TSTemplateRelationId;
! 		object.objectId = tmplOid;
! 		object.objectSubId = 0;
! 
! 		add_exact_object_address(&object, objects);
  	}
  
! 	performMultipleDeletions(objects, drop->behavior);
  
! 	free_object_addresses(objects);
  }
  
  /*
*************** RenameTSConfiguration(List *oldname, con
*** 1474,1521 ****
   * DROP TEXT SEARCH CONFIGURATION
   */
  void
! RemoveTSConfiguration(List *names, DropBehavior behavior, bool missing_ok)
  {
! 	Oid			cfgOid;
! 	Oid			namespaceId;
! 	ObjectAddress object;
! 	HeapTuple	tup;
  
! 	tup = GetTSConfigTuple(names);
  
! 	if (!HeapTupleIsValid(tup))
  	{
! 		if (!missing_ok)
! 		{
! 			ereport(ERROR,
! 					(errcode(ERRCODE_UNDEFINED_OBJECT),
! 					 errmsg("text search configuration \"%s\" does not exist",
! 							NameListToString(names))));
! 		}
! 		else
  		{
! 			ereport(NOTICE,
! 					(errmsg("text search configuration \"%s\" does not exist, skipping",
! 							NameListToString(names))));
! 		}
! 		return;
! 	}
  
! 	/* Permission check: must own configuration or its namespace */
! 	cfgOid = HeapTupleGetOid(tup);
! 	namespaceId = ((Form_pg_ts_config) GETSTRUCT(tup))->cfgnamespace;
! 	if (!pg_ts_config_ownercheck(cfgOid, GetUserId()) &&
! 		!pg_namespace_ownercheck(namespaceId, GetUserId()))
! 		aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TSCONFIGURATION,
! 					   NameListToString(names));
  
! 	ReleaseSysCache(tup);
  
! 	object.classId = TSConfigRelationId;
! 	object.objectId = cfgOid;
! 	object.objectSubId = 0;
  
! 	performDeletion(&object, behavior);
  }
  
  /*
--- 1530,1595 ----
   * DROP TEXT SEARCH CONFIGURATION
   */
  void
! RemoveTSConfigurations(DropStmt *drop)
  {
! 	ObjectAddresses *objects;
! 	ListCell		*cell;
  
! 	/*
! 	 * First we identify all the objects, then we delete them in a single
! 	 * performMultipleDeletions() call.  This is to avoid unwanted
! 	 * DROP RESTRICT errors if one of the objects depends on another.
! 	 */
! 	objects = new_object_addresses();
  
! 	foreach(cell, drop->objects)
  	{
! 		List		*names = (List *) lfirst(cell);
! 		Oid			cfgOid;
! 		Oid			namespaceId;
! 		ObjectAddress object;
! 		HeapTuple	tup;
! 
! 		tup = GetTSConfigTuple(names);
! 
! 		if (!HeapTupleIsValid(tup))
  		{
! 			if (!drop->missing_ok)
! 			{
! 				ereport(ERROR,
! 						(errcode(ERRCODE_UNDEFINED_OBJECT),
! 						 errmsg("text search configuration \"%s\" does not exist",
! 								NameListToString(names))));
! 			}
! 			else
! 			{
! 				ereport(NOTICE,
! 						(errmsg("text search configuration \"%s\" does not exist, skipping",
! 								NameListToString(names))));
! 			}
! 			continue;
! 		}
! 
! 		/* Permission check: must own configuration or its namespace */
! 		cfgOid = HeapTupleGetOid(tup);
! 		namespaceId = ((Form_pg_ts_config) GETSTRUCT(tup))->cfgnamespace;
! 		if (!pg_ts_config_ownercheck(cfgOid, GetUserId()) &&
! 			!pg_namespace_ownercheck(namespaceId, GetUserId()))
! 			aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TSCONFIGURATION,
! 						   NameListToString(names));
! 
! 		object.classId = TSConfigRelationId;
! 		object.objectId = cfgOid;
! 		object.objectSubId = 0;
  
! 		add_exact_object_address(&object, objects);
  
! 		ReleaseSysCache(tup);
! 	}
  
! 	performMultipleDeletions(objects, drop->behavior);
  
! 	free_object_addresses(objects);
  }
  
  /*