Header And Logo

PostgreSQL
| The world's most advanced open source database.

pg_conversion.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * pg_conversion.c
00004  *    routines to support manipulation of the pg_conversion relation
00005  *
00006  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
00007  * Portions Copyright (c) 1994, Regents of the University of California
00008  *
00009  *
00010  * IDENTIFICATION
00011  *    src/backend/catalog/pg_conversion.c
00012  *
00013  *-------------------------------------------------------------------------
00014  */
00015 #include "postgres.h"
00016 
00017 #include "access/heapam.h"
00018 #include "access/htup_details.h"
00019 #include "access/sysattr.h"
00020 #include "catalog/dependency.h"
00021 #include "catalog/indexing.h"
00022 #include "catalog/objectaccess.h"
00023 #include "catalog/pg_conversion.h"
00024 #include "catalog/pg_conversion_fn.h"
00025 #include "catalog/pg_namespace.h"
00026 #include "catalog/pg_proc.h"
00027 #include "mb/pg_wchar.h"
00028 #include "utils/builtins.h"
00029 #include "utils/catcache.h"
00030 #include "utils/fmgroids.h"
00031 #include "utils/rel.h"
00032 #include "utils/syscache.h"
00033 #include "utils/tqual.h"
00034 
00035 /*
00036  * ConversionCreate
00037  *
00038  * Add a new tuple to pg_conversion.
00039  */
00040 Oid
00041 ConversionCreate(const char *conname, Oid connamespace,
00042                  Oid conowner,
00043                  int32 conforencoding, int32 contoencoding,
00044                  Oid conproc, bool def)
00045 {
00046     int         i;
00047     Relation    rel;
00048     TupleDesc   tupDesc;
00049     HeapTuple   tup;
00050     bool        nulls[Natts_pg_conversion];
00051     Datum       values[Natts_pg_conversion];
00052     NameData    cname;
00053     Oid         oid;
00054     ObjectAddress myself,
00055                 referenced;
00056 
00057     /* sanity checks */
00058     if (!conname)
00059         elog(ERROR, "no conversion name supplied");
00060 
00061     /* make sure there is no existing conversion of same name */
00062     if (SearchSysCacheExists2(CONNAMENSP,
00063                               PointerGetDatum(conname),
00064                               ObjectIdGetDatum(connamespace)))
00065         ereport(ERROR,
00066                 (errcode(ERRCODE_DUPLICATE_OBJECT),
00067                  errmsg("conversion \"%s\" already exists", conname)));
00068 
00069     if (def)
00070     {
00071         /*
00072          * make sure there is no existing default <for encoding><to encoding>
00073          * pair in this name space
00074          */
00075         if (FindDefaultConversion(connamespace,
00076                                   conforencoding,
00077                                   contoencoding))
00078             ereport(ERROR,
00079                     (errcode(ERRCODE_DUPLICATE_OBJECT),
00080                      errmsg("default conversion for %s to %s already exists",
00081                             pg_encoding_to_char(conforencoding),
00082                             pg_encoding_to_char(contoencoding))));
00083     }
00084 
00085     /* open pg_conversion */
00086     rel = heap_open(ConversionRelationId, RowExclusiveLock);
00087     tupDesc = rel->rd_att;
00088 
00089     /* initialize nulls and values */
00090     for (i = 0; i < Natts_pg_conversion; i++)
00091     {
00092         nulls[i] = false;
00093         values[i] = (Datum) NULL;
00094     }
00095 
00096     /* form a tuple */
00097     namestrcpy(&cname, conname);
00098     values[Anum_pg_conversion_conname - 1] = NameGetDatum(&cname);
00099     values[Anum_pg_conversion_connamespace - 1] = ObjectIdGetDatum(connamespace);
00100     values[Anum_pg_conversion_conowner - 1] = ObjectIdGetDatum(conowner);
00101     values[Anum_pg_conversion_conforencoding - 1] = Int32GetDatum(conforencoding);
00102     values[Anum_pg_conversion_contoencoding - 1] = Int32GetDatum(contoencoding);
00103     values[Anum_pg_conversion_conproc - 1] = ObjectIdGetDatum(conproc);
00104     values[Anum_pg_conversion_condefault - 1] = BoolGetDatum(def);
00105 
00106     tup = heap_form_tuple(tupDesc, values, nulls);
00107 
00108     /* insert a new tuple */
00109     oid = simple_heap_insert(rel, tup);
00110     Assert(OidIsValid(oid));
00111 
00112     /* update the index if any */
00113     CatalogUpdateIndexes(rel, tup);
00114 
00115     myself.classId = ConversionRelationId;
00116     myself.objectId = HeapTupleGetOid(tup);
00117     myself.objectSubId = 0;
00118 
00119     /* create dependency on conversion procedure */
00120     referenced.classId = ProcedureRelationId;
00121     referenced.objectId = conproc;
00122     referenced.objectSubId = 0;
00123     recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
00124 
00125     /* create dependency on namespace */
00126     referenced.classId = NamespaceRelationId;
00127     referenced.objectId = connamespace;
00128     referenced.objectSubId = 0;
00129     recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
00130 
00131     /* create dependency on owner */
00132     recordDependencyOnOwner(ConversionRelationId, HeapTupleGetOid(tup),
00133                             conowner);
00134 
00135     /* dependency on extension */
00136     recordDependencyOnCurrentExtension(&myself, false);
00137 
00138     /* Post creation hook for new conversion */
00139     InvokeObjectPostCreateHook(ConversionRelationId, HeapTupleGetOid(tup), 0);
00140 
00141     heap_freetuple(tup);
00142     heap_close(rel, RowExclusiveLock);
00143 
00144     return oid;
00145 }
00146 
00147 /*
00148  * RemoveConversionById
00149  *
00150  * Remove a tuple from pg_conversion by Oid. This function is solely
00151  * called inside catalog/dependency.c
00152  */
00153 void
00154 RemoveConversionById(Oid conversionOid)
00155 {
00156     Relation    rel;
00157     HeapTuple   tuple;
00158     HeapScanDesc scan;
00159     ScanKeyData scanKeyData;
00160 
00161     ScanKeyInit(&scanKeyData,
00162                 ObjectIdAttributeNumber,
00163                 BTEqualStrategyNumber, F_OIDEQ,
00164                 ObjectIdGetDatum(conversionOid));
00165 
00166     /* open pg_conversion */
00167     rel = heap_open(ConversionRelationId, RowExclusiveLock);
00168 
00169     scan = heap_beginscan(rel, SnapshotNow,
00170                           1, &scanKeyData);
00171 
00172     /* search for the target tuple */
00173     if (HeapTupleIsValid(tuple = heap_getnext(scan, ForwardScanDirection)))
00174         simple_heap_delete(rel, &tuple->t_self);
00175     else
00176         elog(ERROR, "could not find tuple for conversion %u", conversionOid);
00177     heap_endscan(scan);
00178     heap_close(rel, RowExclusiveLock);
00179 }
00180 
00181 /*
00182  * FindDefaultConversion
00183  *
00184  * Find "default" conversion proc by for_encoding and to_encoding in the
00185  * given namespace.
00186  *
00187  * If found, returns the procedure's oid, otherwise InvalidOid.  Note that
00188  * you get the procedure's OID not the conversion's OID!
00189  */
00190 Oid
00191 FindDefaultConversion(Oid name_space, int32 for_encoding, int32 to_encoding)
00192 {
00193     CatCList   *catlist;
00194     HeapTuple   tuple;
00195     Form_pg_conversion body;
00196     Oid         proc = InvalidOid;
00197     int         i;
00198 
00199     catlist = SearchSysCacheList3(CONDEFAULT,
00200                                   ObjectIdGetDatum(name_space),
00201                                   Int32GetDatum(for_encoding),
00202                                   Int32GetDatum(to_encoding));
00203 
00204     for (i = 0; i < catlist->n_members; i++)
00205     {
00206         tuple = &catlist->members[i]->tuple;
00207         body = (Form_pg_conversion) GETSTRUCT(tuple);
00208         if (body->condefault)
00209         {
00210             proc = body->conproc;
00211             break;
00212         }
00213     }
00214     ReleaseSysCacheList(catlist);
00215     return proc;
00216 }