]> granicus.if.org Git - postgresql/blobdiff - src/backend/catalog/pg_conversion.c
Refactor the handling of the various DropStmt variants so that when multiple
[postgresql] / src / backend / catalog / pg_conversion.c
index 7dfd0679a22112318789cbf522baf89af2f276ed..753acb133df114b50b8e9b933c060eee487f2e84 100644 (file)
@@ -3,45 +3,45 @@
  * pg_conversion.c
  *       routines to support manipulation of the pg_conversion relation
  *
- * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/catalog/pg_conversion.c,v 1.5 2002/08/06 05:40:45 ishii Exp $
+ *       $PostgreSQL: pgsql/src/backend/catalog/pg_conversion.c,v 1.44 2008/06/14 18:04:33 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include "postgres.h"
 
 #include "access/heapam.h"
-#include "catalog/catname.h"
+#include "access/sysattr.h"
 #include "catalog/dependency.h"
 #include "catalog/indexing.h"
-#include "catalog/pg_class.h"
 #include "catalog/pg_conversion.h"
-#include "catalog/namespace.h"
-#include "utils/builtins.h"
-#include "utils/lsyscache.h"
-#include "utils/syscache.h"
-#include "utils/catcache.h"
+#include "catalog/pg_conversion_fn.h"
+#include "catalog/pg_namespace.h"
+#include "catalog/pg_proc.h"
 #include "mb/pg_wchar.h"
-#include "utils/fmgroids.h"
-#include "utils/acl.h"
 #include "miscadmin.h"
+#include "utils/acl.h"
+#include "utils/builtins.h"
+#include "utils/fmgroids.h"
+#include "utils/syscache.h"
+#include "utils/tqual.h"
 
-/* ----------------
+/*
  * ConversionCreate
  *
- * Add a new tuple to pg_coversion.
- * ---------------
+ * Add a new tuple to pg_conversion.
  */
-Oid    ConversionCreate(const char *conname, Oid connamespace,
-                                                        int32 conowner,
-                                                        int4 conforencoding, int4 contoencoding,
-                                                        Oid conproc, bool def)
+Oid
+ConversionCreate(const char *conname, Oid connamespace,
+                                Oid conowner,
+                                int32 conforencoding, int32 contoencoding,
+                                Oid conproc, bool def)
 {
-       int i;
+       int                     i;
        Relation        rel;
        TupleDesc       tupDesc;
        HeapTuple       tup;
@@ -49,33 +49,40 @@ Oid ConversionCreate(const char *conname, Oid connamespace,
        Datum           values[Natts_pg_conversion];
        NameData        cname;
        Oid                     oid;
-       ObjectAddress   myself,
-                                       referenced;
+       ObjectAddress myself,
+                               referenced;
 
        /* sanity checks */
        if (!conname)
                elog(ERROR, "no conversion name supplied");
 
        /* make sure there is no existing conversion of same name */
-       if (SearchSysCacheExists(CONNAMESP,
-                                                       PointerGetDatum(conname),
-                                                       ObjectIdGetDatum(connamespace),
-                                                        0,0))
-               elog(ERROR, "conversion name \"%s\" already exists", conname);
+       if (SearchSysCacheExists(CONNAMENSP,
+                                                        PointerGetDatum(conname),
+                                                        ObjectIdGetDatum(connamespace),
+                                                        0, 0))
+               ereport(ERROR,
+                               (errcode(ERRCODE_DUPLICATE_OBJECT),
+                                errmsg("conversion \"%s\" already exists", conname)));
 
        if (def)
        {
-               /* make sure there is no existing default
-                  <for encoding><to encoding> pair in this name space */
+               /*
+                * make sure there is no existing default <for encoding><to encoding>
+                * pair in this name space
+                */
                if (FindDefaultConversion(connamespace,
                                                                  conforencoding,
                                                                  contoencoding))
-                       elog(ERROR, "default conversion for %s to %s already exists",
-                                pg_encoding_to_char(conforencoding),pg_encoding_to_char(contoencoding));
+                       ereport(ERROR,
+                                       (errcode(ERRCODE_DUPLICATE_OBJECT),
+                                        errmsg("default conversion for %s to %s already exists",
+                                                       pg_encoding_to_char(conforencoding),
+                                                       pg_encoding_to_char(contoencoding))));
        }
 
        /* open pg_conversion */
-       rel = heap_openr(ConversionRelationName, RowExclusiveLock);
+       rel = heap_open(ConversionRelationId, RowExclusiveLock);
        tupDesc = rel->rd_att;
 
        /* initialize nulls and values */
@@ -89,14 +96,11 @@ Oid ConversionCreate(const char *conname, Oid connamespace,
        namestrcpy(&cname, conname);
        values[Anum_pg_conversion_conname - 1] = NameGetDatum(&cname);
        values[Anum_pg_conversion_connamespace - 1] = ObjectIdGetDatum(connamespace);
-       values[Anum_pg_conversion_conowner - 1] = Int32GetDatum(conowner);
+       values[Anum_pg_conversion_conowner - 1] = ObjectIdGetDatum(conowner);
        values[Anum_pg_conversion_conforencoding - 1] = Int32GetDatum(conforencoding);
        values[Anum_pg_conversion_contoencoding - 1] = Int32GetDatum(contoencoding);
        values[Anum_pg_conversion_conproc - 1] = ObjectIdGetDatum(conproc);
-       if (def == true)
-               values[Anum_pg_conversion_condefault - 1] = BoolGetDatum(def);
-       else
-               nulls[Anum_pg_conversion_condefault - 1] = 'n';
+       values[Anum_pg_conversion_condefault - 1] = BoolGetDatum(def);
 
        tup = heap_formtuple(tupDesc, values, nulls);
 
@@ -107,155 +111,95 @@ Oid      ConversionCreate(const char *conname, Oid connamespace,
        /* update the index if any */
        CatalogUpdateIndexes(rel, tup);
 
-       myself.classId = get_system_catalog_relid(ConversionRelationName);
+       myself.classId = ConversionRelationId;
        myself.objectId = HeapTupleGetOid(tup);
        myself.objectSubId = 0;
 
-       /* dependency on conversion procedure */
-       referenced.classId = RelOid_pg_proc;
+       /* create dependency on conversion procedure */
+       referenced.classId = ProcedureRelationId;
        referenced.objectId = conproc;
        referenced.objectSubId = 0;
        recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
 
+       /* create dependency on namespace */
+       referenced.classId = NamespaceRelationId;
+       referenced.objectId = connamespace;
+       referenced.objectSubId = 0;
+       recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+
+       /* create dependency on owner */
+       recordDependencyOnOwner(ConversionRelationId, HeapTupleGetOid(tup),
+                                                       conowner);
+
        heap_freetuple(tup);
        heap_close(rel, RowExclusiveLock);
 
        return oid;
 }
 
-/* ----------------
- * ConversionDrop
- *
- * Drop a conversion and do dependency check.
- * ---------------
- */
-void   ConversionDrop(const char *conname, Oid connamespace,
-                                          int32 conowner, DropBehavior behavior)
-{
-       Relation        rel;
-       TupleDesc       tupDesc;
-       HeapTuple       tuple;
-       HeapScanDesc scan;
-       ScanKeyData scanKeyData;
-       Form_pg_conversion body;
-       ObjectAddress   object;
-       Oid     myoid;
-
-       /* sanity checks */
-       if (!conname)
-               elog(ERROR, "no conversion name supplied");
-
-       ScanKeyEntryInitialize(&scanKeyData,
-                                                  0,
-                                                  Anum_pg_conversion_connamespace,
-                                                  F_OIDEQ,
-                                                  ObjectIdGetDatum(connamespace));
-
-       /* open pg_conversion */
-       rel = heap_openr(ConversionRelationName, AccessShareLock);
-       tupDesc = rel->rd_att;
-
-       scan = heap_beginscan(rel, SnapshotNow,
-                                                         1, &scanKeyData);
-
-       /* search for the target tuple */
-       while (HeapTupleIsValid(tuple = heap_getnext(scan, ForwardScanDirection)))
-       {
-               body = (Form_pg_conversion)GETSTRUCT(tuple);
-               if (!strncmp(NameStr(body->conname), conname, NAMEDATALEN))
-                       break;
-       }
-
-       if (!HeapTupleIsValid(tuple))
-       {
-               elog(ERROR, "conversion %s not found", conname);
-               return;
-       }
-
-       if (!superuser() && ((Form_pg_conversion)GETSTRUCT(tuple))->conowner != GetUserId())
-               elog(ERROR, "permission denied");
-
-       myoid = HeapTupleGetOid(tuple);
-       heap_endscan(scan);
-       heap_close(rel, AccessShareLock);
-
-       /*
-        * Do the deletion
-        */
-       object.classId = get_system_catalog_relid(ConversionRelationName);
-       object.objectId = myoid;
-       object.objectSubId = 0;
-
-       performDeletion(&object, behavior);
-}
-
-/* ----------------
+/*
  * RemoveConversionById
  *
- * Remove a tuple from pg_conversion by Oid. This function is soley
+ * Remove a tuple from pg_conversion by Oid. This function is solely
  * called inside catalog/dependency.c
- * --------------- */
+ */
 void
 RemoveConversionById(Oid conversionOid)
 {
        Relation        rel;
-       TupleDesc       tupDesc;
        HeapTuple       tuple;
        HeapScanDesc scan;
        ScanKeyData scanKeyData;
 
-       ScanKeyEntryInitialize(&scanKeyData,
-                                                  0,
-                                                  ObjectIdAttributeNumber,
-                                                  F_OIDEQ,
-                                                  ObjectIdGetDatum(conversionOid));
+       ScanKeyInit(&scanKeyData,
+                               ObjectIdAttributeNumber,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(conversionOid));
 
        /* open pg_conversion */
-       rel = heap_openr(ConversionRelationName, RowExclusiveLock);
-       tupDesc = rel->rd_att;
+       rel = heap_open(ConversionRelationId, RowExclusiveLock);
 
        scan = heap_beginscan(rel, SnapshotNow,
-                                                         1, &scanKeyData);
+                                                 1, &scanKeyData);
 
        /* search for the target tuple */
        if (HeapTupleIsValid(tuple = heap_getnext(scan, ForwardScanDirection)))
                simple_heap_delete(rel, &tuple->t_self);
        else
-               elog(ERROR, "conversion %u does not exist", conversionOid);
+               elog(ERROR, "could not find tuple for conversion %u", conversionOid);
        heap_endscan(scan);
        heap_close(rel, RowExclusiveLock);
 }
 
-/* ----------------
+/*
  * FindDefaultConversion
  *
- * Find "default" conversion proc by for_encoding and to_encoding in this name space.
- * If found, returns the procedure's oid, otherwise InvalidOid.
- * ---------------
+ * Find "default" conversion proc by for_encoding and to_encoding in the
+ * given namespace.
+ *
+ * If found, returns the procedure's oid, otherwise InvalidOid.  Note that
+ * you get the procedure's OID not the conversion's OID!
  */
-Oid FindDefaultConversion(Oid name_space, int4 for_encoding, int4 to_encoding)
+Oid
+FindDefaultConversion(Oid name_space, int32 for_encoding, int32 to_encoding)
 {
-       CatCList        *catlist;
+       CatCList   *catlist;
        HeapTuple       tuple;
        Form_pg_conversion body;
-       Oid proc = InvalidOid;
-       int     i;
-
-       /* Check we have usage rights in target namespace */
-       if (pg_namespace_aclcheck(name_space, GetUserId(), ACL_USAGE) != ACLCHECK_OK)
-               return proc;
+       Oid                     proc = InvalidOid;
+       int                     i;
 
        catlist = SearchSysCacheList(CONDEFAULT, 3,
-                                                          ObjectIdGetDatum(name_space),
-                                                          Int32GetDatum(for_encoding),
-                                                          Int32GetDatum(to_encoding),
-                                                          0);
+                                                                ObjectIdGetDatum(name_space),
+                                                                Int32GetDatum(for_encoding),
+                                                                Int32GetDatum(to_encoding),
+                                                                0);
 
        for (i = 0; i < catlist->n_members; i++)
        {
                tuple = &catlist->members[i]->tuple;
-               body = (Form_pg_conversion)GETSTRUCT(tuple);
-               if (body->condefault == TRUE)
+               body = (Form_pg_conversion) GETSTRUCT(tuple);
+               if (body->condefault)
                {
                        proc = body->conproc;
                        break;
@@ -265,29 +209,29 @@ Oid FindDefaultConversion(Oid name_space, int4 for_encoding, int4 to_encoding)
        return proc;
 }
 
-/* ----------------
- * FindConversionByName
+/*
+ * FindConversion
  *
  * Find conversion by namespace and conversion name.
- * Returns conversion oid.
- * ---------------
+ * Returns conversion OID.
  */
-Oid FindConversion(const char *conname, Oid connamespace)
+Oid
+FindConversion(const char *conname, Oid connamespace)
 {
        HeapTuple       tuple;
-       Oid procoid;
-       Oid conoid;
+       Oid                     procoid;
+       Oid                     conoid;
        AclResult       aclresult;
 
        /* search pg_conversion by connamespace and conversion name */
-       tuple = SearchSysCache(CONNAMESP,
+       tuple = SearchSysCache(CONNAMENSP,
                                                   PointerGetDatum(conname),
                                                   ObjectIdGetDatum(connamespace),
-                                                  0,0);
-
+                                                  0, 0);
        if (!HeapTupleIsValid(tuple))
                return InvalidOid;
-       procoid = ((Form_pg_conversion)GETSTRUCT(tuple))->conproc;
+
+       procoid = ((Form_pg_conversion) GETSTRUCT(tuple))->conproc;
        conoid = HeapTupleGetOid(tuple);
 
        ReleaseSysCache(tuple);
@@ -299,67 +243,3 @@ Oid FindConversion(const char *conname, Oid connamespace)
 
        return conoid;
 }
-
-/*
- * Execute SQL99's CONVERT function.
- *
- * CONVERT <left paren> <character value expression>
- * USING <form-of-use conversion name> <right paren>
- *
- * TEXT convert3(TEXT string, OID conversion_oid);
- */
-Datum
-pg_convert3(PG_FUNCTION_ARGS)
-{
-       text       *string = PG_GETARG_TEXT_P(0);
-       Oid                     convoid = PG_GETARG_OID(1);
-       HeapTuple       tuple;
-       Form_pg_conversion body;
-       text       *retval;
-       unsigned char *str;
-       unsigned char *result;
-       int len;
-
-       if (!OidIsValid(convoid))
-               elog(ERROR, "Conversion does not exist");
-
-       /* make sure that source string is null terminated */
-       len = VARSIZE(string) - VARHDRSZ;
-       str = palloc(len + 1);
-       memcpy(str, VARDATA(string), len);
-       *(str + len) = '\0';
-
-       tuple = SearchSysCache(CONOID,
-                                                  ObjectIdGetDatum(convoid),
-                                                  0,0,0);
-       if (!HeapTupleIsValid(tuple))
-               elog(ERROR, "Conversion %u search from syscache failed", convoid);
-
-       result = palloc(len * 4 + 1);
-
-       body = (Form_pg_conversion)GETSTRUCT(tuple);
-       OidFunctionCall5(body->conproc,
-                                        Int32GetDatum(body->conforencoding),
-                                        Int32GetDatum(body->contoencoding),
-                                        CStringGetDatum(str),
-                                        CStringGetDatum(result),
-                                        Int32GetDatum(len));
-
-       ReleaseSysCache(tuple);
-
-       /* build text data type structre. we cannot use textin() here,
-          since textin assumes that input string encoding is same as
-          database encoding.  */
-       len = strlen(result) + VARHDRSZ;
-       retval = palloc(len);
-       VARATT_SIZEP(retval) = len;
-       memcpy(VARDATA(retval), result, len - VARHDRSZ);
-
-       pfree(result);
-       pfree(str);
-
-       /* free memory if allocated by the toaster */
-       PG_FREE_IF_COPY(string, 0);
-
-       PG_RETURN_TEXT_P(retval);
-}