Header And Logo

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

pg_collation.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * pg_collation.c
00004  *    routines to support manipulation of the pg_collation 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_collation.c
00012  *
00013  *-------------------------------------------------------------------------
00014  */
00015 #include "postgres.h"
00016 
00017 #include "access/genam.h"
00018 #include "access/heapam.h"
00019 #include "access/htup_details.h"
00020 #include "access/sysattr.h"
00021 #include "catalog/dependency.h"
00022 #include "catalog/indexing.h"
00023 #include "catalog/objectaccess.h"
00024 #include "catalog/pg_collation.h"
00025 #include "catalog/pg_collation_fn.h"
00026 #include "catalog/pg_namespace.h"
00027 #include "mb/pg_wchar.h"
00028 #include "utils/builtins.h"
00029 #include "utils/fmgroids.h"
00030 #include "utils/rel.h"
00031 #include "utils/syscache.h"
00032 #include "utils/tqual.h"
00033 
00034 
00035 /*
00036  * CollationCreate
00037  *
00038  * Add a new tuple to pg_collation.
00039  */
00040 Oid
00041 CollationCreate(const char *collname, Oid collnamespace,
00042                 Oid collowner,
00043                 int32 collencoding,
00044                 const char *collcollate, const char *collctype)
00045 {
00046     Relation    rel;
00047     TupleDesc   tupDesc;
00048     HeapTuple   tup;
00049     Datum       values[Natts_pg_collation];
00050     bool        nulls[Natts_pg_collation];
00051     NameData    name_name,
00052                 name_collate,
00053                 name_ctype;
00054     Oid         oid;
00055     ObjectAddress myself,
00056                 referenced;
00057 
00058     AssertArg(collname);
00059     AssertArg(collnamespace);
00060     AssertArg(collowner);
00061     AssertArg(collcollate);
00062     AssertArg(collctype);
00063 
00064     /*
00065      * Make sure there is no existing collation of same name & encoding.
00066      *
00067      * This would be caught by the unique index anyway; we're just giving a
00068      * friendlier error message.  The unique index provides a backstop against
00069      * race conditions.
00070      */
00071     if (SearchSysCacheExists3(COLLNAMEENCNSP,
00072                               PointerGetDatum(collname),
00073                               Int32GetDatum(collencoding),
00074                               ObjectIdGetDatum(collnamespace)))
00075         ereport(ERROR,
00076                 (errcode(ERRCODE_DUPLICATE_OBJECT),
00077                  errmsg("collation \"%s\" for encoding \"%s\" already exists",
00078                         collname, pg_encoding_to_char(collencoding))));
00079 
00080     /*
00081      * Also forbid matching an any-encoding entry.  This test of course is not
00082      * backed up by the unique index, but it's not a problem since we don't
00083      * support adding any-encoding entries after initdb.
00084      */
00085     if (SearchSysCacheExists3(COLLNAMEENCNSP,
00086                               PointerGetDatum(collname),
00087                               Int32GetDatum(-1),
00088                               ObjectIdGetDatum(collnamespace)))
00089         ereport(ERROR,
00090                 (errcode(ERRCODE_DUPLICATE_OBJECT),
00091                  errmsg("collation \"%s\" already exists",
00092                         collname)));
00093 
00094     /* open pg_collation */
00095     rel = heap_open(CollationRelationId, RowExclusiveLock);
00096     tupDesc = RelationGetDescr(rel);
00097 
00098     /* form a tuple */
00099     memset(nulls, 0, sizeof(nulls));
00100 
00101     namestrcpy(&name_name, collname);
00102     values[Anum_pg_collation_collname - 1] = NameGetDatum(&name_name);
00103     values[Anum_pg_collation_collnamespace - 1] = ObjectIdGetDatum(collnamespace);
00104     values[Anum_pg_collation_collowner - 1] = ObjectIdGetDatum(collowner);
00105     values[Anum_pg_collation_collencoding - 1] = Int32GetDatum(collencoding);
00106     namestrcpy(&name_collate, collcollate);
00107     values[Anum_pg_collation_collcollate - 1] = NameGetDatum(&name_collate);
00108     namestrcpy(&name_ctype, collctype);
00109     values[Anum_pg_collation_collctype - 1] = NameGetDatum(&name_ctype);
00110 
00111     tup = heap_form_tuple(tupDesc, values, nulls);
00112 
00113     /* insert a new tuple */
00114     oid = simple_heap_insert(rel, tup);
00115     Assert(OidIsValid(oid));
00116 
00117     /* update the index if any */
00118     CatalogUpdateIndexes(rel, tup);
00119 
00120     /* set up dependencies for the new collation */
00121     myself.classId = CollationRelationId;
00122     myself.objectId = oid;
00123     myself.objectSubId = 0;
00124 
00125     /* create dependency on namespace */
00126     referenced.classId = NamespaceRelationId;
00127     referenced.objectId = collnamespace;
00128     referenced.objectSubId = 0;
00129     recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
00130 
00131     /* create dependency on owner */
00132     recordDependencyOnOwner(CollationRelationId, HeapTupleGetOid(tup),
00133                             collowner);
00134 
00135     /* dependency on extension */
00136     recordDependencyOnCurrentExtension(&myself, false);
00137 
00138     /* Post creation hook for new collation */
00139     InvokeObjectPostCreateHook(CollationRelationId, oid, 0);
00140 
00141     heap_freetuple(tup);
00142     heap_close(rel, RowExclusiveLock);
00143 
00144     return oid;
00145 }
00146 
00147 /*
00148  * RemoveCollationById
00149  *
00150  * Remove a tuple from pg_collation by Oid. This function is solely
00151  * called inside catalog/dependency.c
00152  */
00153 void
00154 RemoveCollationById(Oid collationOid)
00155 {
00156     Relation    rel;
00157     ScanKeyData scanKeyData;
00158     SysScanDesc scandesc;
00159     HeapTuple   tuple;
00160 
00161     rel = heap_open(CollationRelationId, RowExclusiveLock);
00162 
00163     ScanKeyInit(&scanKeyData,
00164                 ObjectIdAttributeNumber,
00165                 BTEqualStrategyNumber, F_OIDEQ,
00166                 ObjectIdGetDatum(collationOid));
00167 
00168     scandesc = systable_beginscan(rel, CollationOidIndexId, true,
00169                                   SnapshotNow, 1, &scanKeyData);
00170 
00171     tuple = systable_getnext(scandesc);
00172 
00173     if (HeapTupleIsValid(tuple))
00174         simple_heap_delete(rel, &tuple->t_self);
00175     else
00176         elog(ERROR, "could not find tuple for collation %u", collationOid);
00177 
00178     systable_endscan(scandesc);
00179 
00180     heap_close(rel, RowExclusiveLock);
00181 }