postgresql/src/backend/commands/conversioncmds.c
PostgreSQL Daemon 2ff501590b Tag appropriate files for rc3
Also performed an initial run through of upgrading our Copyright date to
extend to 2005 ... first run here was very simple ... change everything
where: grep 1996-2004 && the word 'Copyright' ... scanned through the
generated list with 'less' first, and after, to make sure that I only
picked up the right entries ...
2004-12-31 22:04:05 +00:00

229 lines
6.3 KiB
C

/*-------------------------------------------------------------------------
*
* conversioncmds.c
* conversion creation command support code
*
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/conversioncmds.c,v 1.16 2004/12/31 21:59:41 pgsql Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include "catalog/pg_conversion.h"
#include "access/heapam.h"
#include "catalog/catalog.h"
#include "catalog/catname.h"
#include "catalog/indexing.h"
#include "catalog/namespace.h"
#include "catalog/pg_type.h"
#include "mb/pg_wchar.h"
#include "commands/conversioncmds.h"
#include "miscadmin.h"
#include "parser/parse_func.h"
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
#include "utils/syscache.h"
/*
* CREATE CONVERSION
*/
void
CreateConversionCommand(CreateConversionStmt *stmt)
{
Oid namespaceId;
char *conversion_name;
AclResult aclresult;
int from_encoding;
int to_encoding;
Oid funcoid;
const char *from_encoding_name = stmt->for_encoding_name;
const char *to_encoding_name = stmt->to_encoding_name;
List *func_name = stmt->func_name;
static Oid funcargs[] = {INT4OID, INT4OID, CSTRINGOID, CSTRINGOID, INT4OID};
/* Convert list of names to a name and namespace */
namespaceId = QualifiedNameGetCreationNamespace(stmt->conversion_name,
&conversion_name);
/* Check we have creation rights in target namespace */
aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_CREATE);
if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
get_namespace_name(namespaceId));
/* Check the encoding names */
from_encoding = pg_char_to_encoding(from_encoding_name);
if (from_encoding < 0)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("source encoding \"%s\" does not exist",
from_encoding_name)));
to_encoding = pg_char_to_encoding(to_encoding_name);
if (to_encoding < 0)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("destination encoding \"%s\" does not exist",
to_encoding_name)));
/*
* Check the existence of the conversion function. Function name could
* be a qualified name.
*/
funcoid = LookupFuncName(func_name, sizeof(funcargs) / sizeof(Oid),
funcargs, false);
/* Check we have EXECUTE rights for the function */
aclresult = pg_proc_aclcheck(funcoid, GetUserId(), ACL_EXECUTE);
if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, ACL_KIND_PROC,
NameListToString(func_name));
/*
* All seem ok, go ahead (possible failure would be a duplicate
* conversion name)
*/
ConversionCreate(conversion_name, namespaceId, GetUserId(),
from_encoding, to_encoding, funcoid, stmt->def);
}
/*
* DROP CONVERSION
*/
void
DropConversionCommand(List *name, DropBehavior behavior)
{
Oid conversionOid;
conversionOid = FindConversionByName(name);
if (!OidIsValid(conversionOid))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("conversion \"%s\" does not exist",
NameListToString(name))));
ConversionDrop(conversionOid, behavior);
}
/*
* Rename conversion
*/
void
RenameConversion(List *name, const char *newname)
{
Oid conversionOid;
Oid namespaceOid;
HeapTuple tup;
Relation rel;
AclResult aclresult;
rel = heap_openr(ConversionRelationName, RowExclusiveLock);
conversionOid = FindConversionByName(name);
if (!OidIsValid(conversionOid))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("conversion \"%s\" does not exist",
NameListToString(name))));
tup = SearchSysCacheCopy(CONOID,
ObjectIdGetDatum(conversionOid),
0, 0, 0);
if (!HeapTupleIsValid(tup)) /* should not happen */
elog(ERROR, "cache lookup failed for conversion %u", conversionOid);
namespaceOid = ((Form_pg_conversion) GETSTRUCT(tup))->connamespace;
/* make sure the new name doesn't exist */
if (SearchSysCacheExists(CONNAMENSP,
CStringGetDatum(newname),
ObjectIdGetDatum(namespaceOid),
0, 0))
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_OBJECT),
errmsg("conversion \"%s\" already exists in schema \"%s\"",
newname, get_namespace_name(namespaceOid))));
/* must be owner */
if (!superuser() &&
((Form_pg_conversion) GETSTRUCT(tup))->conowner != GetUserId())
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CONVERSION,
NameListToString(name));
/* must have CREATE privilege on namespace */
aclresult = pg_namespace_aclcheck(namespaceOid, GetUserId(), ACL_CREATE);
if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
get_namespace_name(namespaceOid));
/* rename */
namestrcpy(&(((Form_pg_conversion) GETSTRUCT(tup))->conname), newname);
simple_heap_update(rel, &tup->t_self, tup);
CatalogUpdateIndexes(rel, tup);
heap_close(rel, NoLock);
heap_freetuple(tup);
}
/*
* Change conversion owner
*/
void
AlterConversionOwner(List *name, AclId newOwnerSysId)
{
Oid conversionOid;
HeapTuple tup;
Relation rel;
Form_pg_conversion convForm;
rel = heap_openr(ConversionRelationName, RowExclusiveLock);
conversionOid = FindConversionByName(name);
if (!OidIsValid(conversionOid))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("conversion \"%s\" does not exist",
NameListToString(name))));
tup = SearchSysCacheCopy(CONOID,
ObjectIdGetDatum(conversionOid),
0, 0, 0);
if (!HeapTupleIsValid(tup)) /* should not happen */
elog(ERROR, "cache lookup failed for conversion %u", conversionOid);
convForm = (Form_pg_conversion) GETSTRUCT(tup);
/*
* If the new owner is the same as the existing owner, consider the
* command to have succeeded. This is for dump restoration purposes.
*/
if (convForm->conowner != newOwnerSysId)
{
/* Otherwise, must be superuser to change object ownership */
if (!superuser())
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser to change owner")));
/*
* Modify the owner --- okay to scribble on tup because it's a
* copy
*/
convForm->conowner = newOwnerSysId;
simple_heap_update(rel, &tup->t_self, tup);
CatalogUpdateIndexes(rel, tup);
}
heap_close(rel, NoLock);
heap_freetuple(tup);
}