Logo Search packages:      
Sourcecode: postgresql-8.4 version File versions  Download package

pg_conversion.c
/*-------------------------------------------------------------------------
 *
 * pg_conversion.c
 *      routines to support manipulation of the pg_conversion relation
 *
 * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 *
 * IDENTIFICATION
 *      $PostgreSQL: pgsql/src/backend/catalog/pg_conversion.c,v 1.47 2009/01/01 17:23:37 momjian Exp $
 *
 *-------------------------------------------------------------------------
 */
#include "postgres.h"

#include "access/heapam.h"
#include "access/sysattr.h"
#include "catalog/dependency.h"
#include "catalog/indexing.h"
#include "catalog/pg_conversion.h"
#include "catalog/pg_conversion_fn.h"
#include "catalog/pg_namespace.h"
#include "catalog/pg_proc.h"
#include "mb/pg_wchar.h"
#include "miscadmin.h"
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/rel.h"
#include "utils/syscache.h"
#include "utils/tqual.h"

/*
 * ConversionCreate
 *
 * Add a new tuple to pg_conversion.
 */
Oid
ConversionCreate(const char *conname, Oid connamespace,
                         Oid conowner,
                         int32 conforencoding, int32 contoencoding,
                         Oid conproc, bool def)
{
      int               i;
      Relation    rel;
      TupleDesc   tupDesc;
      HeapTuple   tup;
      bool        nulls[Natts_pg_conversion];
      Datum       values[Natts_pg_conversion];
      NameData    cname;
      Oid               oid;
      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(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
             */
            if (FindDefaultConversion(connamespace,
                                                  conforencoding,
                                                  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_open(ConversionRelationId, RowExclusiveLock);
      tupDesc = rel->rd_att;

      /* initialize nulls and values */
      for (i = 0; i < Natts_pg_conversion; i++)
      {
            nulls[i] = false;
            values[i] = (Datum) NULL;
      }

      /* form a tuple */
      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] = 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);
      values[Anum_pg_conversion_condefault - 1] = BoolGetDatum(def);

      tup = heap_form_tuple(tupDesc, values, nulls);

      /* insert a new tuple */
      oid = simple_heap_insert(rel, tup);
      Assert(OidIsValid(oid));

      /* update the index if any */
      CatalogUpdateIndexes(rel, tup);

      myself.classId = ConversionRelationId;
      myself.objectId = HeapTupleGetOid(tup);
      myself.objectSubId = 0;

      /* 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;
}

/*
 * RemoveConversionById
 *
 * Remove a tuple from pg_conversion by Oid. This function is solely
 * called inside catalog/dependency.c
 */
void
RemoveConversionById(Oid conversionOid)
{
      Relation    rel;
      HeapTuple   tuple;
      HeapScanDesc scan;
      ScanKeyData scanKeyData;

      ScanKeyInit(&scanKeyData,
                        ObjectIdAttributeNumber,
                        BTEqualStrategyNumber, F_OIDEQ,
                        ObjectIdGetDatum(conversionOid));

      /* open pg_conversion */
      rel = heap_open(ConversionRelationId, RowExclusiveLock);

      scan = heap_beginscan(rel, SnapshotNow,
                                      1, &scanKeyData);

      /* search for the target tuple */
      if (HeapTupleIsValid(tuple = heap_getnext(scan, ForwardScanDirection)))
            simple_heap_delete(rel, &tuple->t_self);
      else
            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 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, int32 for_encoding, int32 to_encoding)
{
      CatCList   *catlist;
      HeapTuple   tuple;
      Form_pg_conversion body;
      Oid               proc = InvalidOid;
      int               i;

      catlist = SearchSysCacheList(CONDEFAULT, 3,
                                                 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)
            {
                  proc = body->conproc;
                  break;
            }
      }
      ReleaseSysCacheList(catlist);
      return proc;
}

/*
 * FindConversion
 *
 * Find conversion by namespace and conversion name.
 * Returns conversion OID.
 */
Oid
FindConversion(const char *conname, Oid connamespace)
{
      HeapTuple   tuple;
      Oid               procoid;
      Oid               conoid;
      AclResult   aclresult;

      /* search pg_conversion by connamespace and conversion name */
      tuple = SearchSysCache(CONNAMENSP,
                                       PointerGetDatum(conname),
                                       ObjectIdGetDatum(connamespace),
                                       0, 0);
      if (!HeapTupleIsValid(tuple))
            return InvalidOid;

      procoid = ((Form_pg_conversion) GETSTRUCT(tuple))->conproc;
      conoid = HeapTupleGetOid(tuple);

      ReleaseSysCache(tuple);

      /* Check we have execute rights for the function */
      aclresult = pg_proc_aclcheck(procoid, GetUserId(), ACL_EXECUTE);
      if (aclresult != ACLCHECK_OK)
            return InvalidOid;

      return conoid;
}

Generated by  Doxygen 1.6.0   Back to index