aboutsummaryrefslogtreecommitdiff
path: root/src/backend/commands/tsearchcmds.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/commands/tsearchcmds.c')
-rw-r--r--src/backend/commands/tsearchcmds.c296
1 files changed, 185 insertions, 111 deletions
diff --git a/src/backend/commands/tsearchcmds.c b/src/backend/commands/tsearchcmds.c
index e3d877e03f9..ceb5fba0e6a 100644
--- a/src/backend/commands/tsearchcmds.c
+++ b/src/backend/commands/tsearchcmds.c
@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/tsearchcmds.c,v 1.11 2008/03/26 21:10:38 alvherre Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/tsearchcmds.c,v 1.12 2008/06/14 18:04:33 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -271,40 +271,59 @@ DefineTSParser(List *names, List *parameters)
* DROP TEXT SEARCH PARSER
*/
void
-RemoveTSParser(List *names, DropBehavior behavior, bool missing_ok)
+RemoveTSParsers(DropStmt *drop)
{
- Oid prsOid;
- ObjectAddress object;
+ ObjectAddresses *objects;
+ ListCell *cell;
if (!superuser())
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser to drop text search parsers")));
- prsOid = TSParserGetPrsid(names, true);
- if (!OidIsValid(prsOid))
+ /*
+ * 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)
{
- if (!missing_ok)
+ List *names = (List *) lfirst(cell);
+ Oid prsOid;
+ ObjectAddress object;
+
+ prsOid = TSParserGetPrsid(names, true);
+
+ if (!OidIsValid(prsOid))
{
- ereport(ERROR,
- (errcode(ERRCODE_UNDEFINED_OBJECT),
- errmsg("text search parser \"%s\" does not exist",
+ 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;
}
- else
- {
- ereport(NOTICE,
- (errmsg("text search parser \"%s\" does not exist, skipping",
- NameListToString(names))));
- }
- return;
+
+ object.classId = TSParserRelationId;
+ object.objectId = prsOid;
+ object.objectSubId = 0;
+
+ add_exact_object_address(&object, objects);
}
- object.classId = TSParserRelationId;
- object.objectId = prsOid;
- object.objectSubId = 0;
+ performMultipleDeletions(objects, drop->behavior);
- performDeletion(&object, behavior);
+ free_object_addresses(objects);
}
/*
@@ -613,54 +632,72 @@ RenameTSDictionary(List *oldname, const char *newname)
* DROP TEXT SEARCH DICTIONARY
*/
void
-RemoveTSDictionary(List *names, DropBehavior behavior, bool missing_ok)
+RemoveTSDictionaries(DropStmt *drop)
{
- Oid dictOid;
- ObjectAddress object;
- HeapTuple tup;
- Oid namespaceId;
+ 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();
- dictOid = TSDictionaryGetDictid(names, true);
- if (!OidIsValid(dictOid))
+ foreach(cell, drop->objects)
{
- if (!missing_ok)
- {
- ereport(ERROR,
- (errcode(ERRCODE_UNDEFINED_OBJECT),
- errmsg("text search dictionary \"%s\" does not exist",
- NameListToString(names))));
- }
- else
+ List *names = (List *) lfirst(cell);
+ Oid dictOid;
+ ObjectAddress object;
+ HeapTuple tup;
+ Oid namespaceId;
+
+ dictOid = TSDictionaryGetDictid(names, true);
+
+ if (!OidIsValid(dictOid))
{
- ereport(NOTICE,
- (errmsg("text search dictionary \"%s\" does not exist, skipping",
- NameListToString(names))));
+ 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;
}
- return;
- }
- tup = SearchSysCache(TSDICTOID,
- ObjectIdGetDatum(dictOid),
- 0, 0, 0);
+ 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);
- 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));
- /* 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;
- ReleaseSysCache(tup);
+ add_exact_object_address(&object, objects);
- object.classId = TSDictionaryRelationId;
- object.objectId = dictOid;
- object.objectSubId = 0;
+ ReleaseSysCache(tup);
+ }
+
+ performMultipleDeletions(objects, drop->behavior);
- performDeletion(&object, behavior);
+ free_object_addresses(objects);
}
/*
@@ -1086,40 +1123,59 @@ RenameTSTemplate(List *oldname, const char *newname)
* DROP TEXT SEARCH TEMPLATE
*/
void
-RemoveTSTemplate(List *names, DropBehavior behavior, bool missing_ok)
+RemoveTSTemplates(DropStmt *drop)
{
- Oid tmplOid;
- ObjectAddress object;
+ ObjectAddresses *objects;
+ ListCell *cell;
if (!superuser())
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser to drop text search templates")));
- tmplOid = TSTemplateGetTmplid(names, true);
- if (!OidIsValid(tmplOid))
+ /*
+ * 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)
{
- if (!missing_ok)
- {
- ereport(ERROR,
- (errcode(ERRCODE_UNDEFINED_OBJECT),
- errmsg("text search template \"%s\" does not exist",
- NameListToString(names))));
- }
- else
+ List *names = (List *) lfirst(cell);
+ Oid tmplOid;
+ ObjectAddress object;
+
+ tmplOid = TSTemplateGetTmplid(names, true);
+
+ if (!OidIsValid(tmplOid))
{
- ereport(NOTICE,
- (errmsg("text search template \"%s\" does not exist, skipping",
- NameListToString(names))));
+ 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;
}
- return;
+
+ object.classId = TSTemplateRelationId;
+ object.objectId = tmplOid;
+ object.objectSubId = 0;
+
+ add_exact_object_address(&object, objects);
}
- object.classId = TSTemplateRelationId;
- object.objectId = tmplOid;
- object.objectSubId = 0;
+ performMultipleDeletions(objects, drop->behavior);
- performDeletion(&object, behavior);
+ free_object_addresses(objects);
}
/*
@@ -1474,48 +1530,66 @@ RenameTSConfiguration(List *oldname, const char *newname)
* DROP TEXT SEARCH CONFIGURATION
*/
void
-RemoveTSConfiguration(List *names, DropBehavior behavior, bool missing_ok)
+RemoveTSConfigurations(DropStmt *drop)
{
- Oid cfgOid;
- Oid namespaceId;
- ObjectAddress object;
- HeapTuple tup;
+ ObjectAddresses *objects;
+ ListCell *cell;
- tup = GetTSConfigTuple(names);
+ /*
+ * 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();
- if (!HeapTupleIsValid(tup))
+ foreach(cell, drop->objects)
{
- if (!missing_ok)
- {
- ereport(ERROR,
- (errcode(ERRCODE_UNDEFINED_OBJECT),
- errmsg("text search configuration \"%s\" does not exist",
- NameListToString(names))));
- }
- else
+ List *names = (List *) lfirst(cell);
+ Oid cfgOid;
+ Oid namespaceId;
+ ObjectAddress object;
+ HeapTuple tup;
+
+ tup = GetTSConfigTuple(names);
+
+ if (!HeapTupleIsValid(tup))
{
- ereport(NOTICE,
- (errmsg("text search configuration \"%s\" does not exist, skipping",
- NameListToString(names))));
+ 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;
}
- 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));
+ /* 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;
+
+ add_exact_object_address(&object, objects);
+
+ ReleaseSysCache(tup);
+ }
- object.classId = TSConfigRelationId;
- object.objectId = cfgOid;
- object.objectSubId = 0;
+ performMultipleDeletions(objects, drop->behavior);
- performDeletion(&object, behavior);
+ free_object_addresses(objects);
}
/*