X-Git-Url: https://granicus.if.org/sourcecode?a=blobdiff_plain;f=src%2Fbackend%2Fcatalog%2Fpg_conversion.c;h=753acb133df114b50b8e9b933c060eee487f2e84;hb=0cefb50f3ce964d6097aad64dabd9b544c3d2e68;hp=7dfd0679a22112318789cbf522baf89af2f276ed;hpb=6206a880cf233e5bf70a0ced6be810c399c7e006;p=postgresql diff --git a/src/backend/catalog/pg_conversion.c b/src/backend/catalog/pg_conversion.c index 7dfd0679a2..753acb133d 100644 --- a/src/backend/catalog/pg_conversion.c +++ b/src/backend/catalog/pg_conversion.c @@ -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 - pair in this name space */ + /* + * make sure there is no existing default + * 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 - * USING - * - * 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); -}