2002-07-11 09:39:28 +02:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
|
|
|
* pg_conversion.c
|
|
|
|
* routines to support manipulation of the pg_conversion relation
|
|
|
|
*
|
2010-01-02 17:58:17 +01:00
|
|
|
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
|
2002-07-11 09:39:28 +02:00
|
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* IDENTIFICATION
|
2010-02-14 19:42:19 +01:00
|
|
|
* $PostgreSQL: pgsql/src/backend/catalog/pg_conversion.c,v 1.50 2010/02/14 18:42:13 rhaas Exp $
|
2002-07-11 09:39:28 +02:00
|
|
|
*
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
#include "postgres.h"
|
|
|
|
|
|
|
|
#include "access/heapam.h"
|
2008-05-12 02:00:54 +02:00
|
|
|
#include "access/sysattr.h"
|
2002-07-25 12:07:13 +02:00
|
|
|
#include "catalog/dependency.h"
|
2002-07-11 09:39:28 +02:00
|
|
|
#include "catalog/indexing.h"
|
|
|
|
#include "catalog/pg_conversion.h"
|
2008-03-27 04:57:34 +01:00
|
|
|
#include "catalog/pg_conversion_fn.h"
|
2006-05-30 15:36:30 +02:00
|
|
|
#include "catalog/pg_namespace.h"
|
2005-04-14 03:38:22 +02:00
|
|
|
#include "catalog/pg_proc.h"
|
2006-07-11 19:26:59 +02:00
|
|
|
#include "mb/pg_wchar.h"
|
2008-03-26 22:10:39 +01:00
|
|
|
#include "miscadmin.h"
|
|
|
|
#include "utils/acl.h"
|
2002-07-11 09:39:28 +02:00
|
|
|
#include "utils/builtins.h"
|
|
|
|
#include "utils/fmgroids.h"
|
2008-06-19 02:46:06 +02:00
|
|
|
#include "utils/rel.h"
|
2006-07-11 19:26:59 +02:00
|
|
|
#include "utils/syscache.h"
|
2008-03-26 22:10:39 +01:00
|
|
|
#include "utils/tqual.h"
|
2002-07-11 09:39:28 +02:00
|
|
|
|
2002-11-02 03:33:03 +01:00
|
|
|
/*
|
2002-07-11 09:39:28 +02:00
|
|
|
* ConversionCreate
|
2002-07-25 12:07:13 +02:00
|
|
|
*
|
2002-11-02 03:33:03 +01:00
|
|
|
* Add a new tuple to pg_conversion.
|
2002-07-11 09:39:28 +02:00
|
|
|
*/
|
2002-09-04 22:31:48 +02:00
|
|
|
Oid
|
|
|
|
ConversionCreate(const char *conname, Oid connamespace,
|
2005-06-28 07:09:14 +02:00
|
|
|
Oid conowner,
|
2002-11-02 03:33:03 +01:00
|
|
|
int32 conforencoding, int32 contoencoding,
|
2002-09-04 22:31:48 +02:00
|
|
|
Oid conproc, bool def)
|
2002-07-11 09:39:28 +02:00
|
|
|
{
|
2002-09-04 22:31:48 +02:00
|
|
|
int i;
|
2002-07-11 09:39:28 +02:00
|
|
|
Relation rel;
|
|
|
|
TupleDesc tupDesc;
|
|
|
|
HeapTuple tup;
|
2008-11-02 02:45:28 +01:00
|
|
|
bool nulls[Natts_pg_conversion];
|
2002-07-11 09:39:28 +02:00
|
|
|
Datum values[Natts_pg_conversion];
|
|
|
|
NameData cname;
|
|
|
|
Oid oid;
|
2002-09-04 22:31:48 +02:00
|
|
|
ObjectAddress myself,
|
|
|
|
referenced;
|
2002-07-11 09:39:28 +02:00
|
|
|
|
|
|
|
/* sanity checks */
|
|
|
|
if (!conname)
|
|
|
|
elog(ERROR, "no conversion name supplied");
|
|
|
|
|
|
|
|
/* make sure there is no existing conversion of same name */
|
2010-02-14 19:42:19 +01:00
|
|
|
if (SearchSysCacheExists2(CONNAMENSP,
|
|
|
|
PointerGetDatum(conname),
|
|
|
|
ObjectIdGetDatum(connamespace)))
|
2003-07-21 03:59:11 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_DUPLICATE_OBJECT),
|
|
|
|
errmsg("conversion \"%s\" already exists", conname)));
|
2002-07-11 09:39:28 +02:00
|
|
|
|
|
|
|
if (def)
|
|
|
|
{
|
2002-09-04 22:31:48 +02:00
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* make sure there is no existing default <for encoding><to encoding>
|
|
|
|
* pair in this name space
|
2002-09-04 22:31:48 +02:00
|
|
|
*/
|
2002-07-11 09:39:28 +02:00
|
|
|
if (FindDefaultConversion(connamespace,
|
|
|
|
conforencoding,
|
|
|
|
contoencoding))
|
2003-07-21 03:59:11 +02:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_DUPLICATE_OBJECT),
|
2005-10-15 04:49:52 +02:00
|
|
|
errmsg("default conversion for %s to %s already exists",
|
|
|
|
pg_encoding_to_char(conforencoding),
|
|
|
|
pg_encoding_to_char(contoencoding))));
|
2002-07-11 09:39:28 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* open pg_conversion */
|
2005-04-14 22:03:27 +02:00
|
|
|
rel = heap_open(ConversionRelationId, RowExclusiveLock);
|
2002-07-11 09:39:28 +02:00
|
|
|
tupDesc = rel->rd_att;
|
|
|
|
|
|
|
|
/* initialize nulls and values */
|
|
|
|
for (i = 0; i < Natts_pg_conversion; i++)
|
|
|
|
{
|
2008-11-02 02:45:28 +01:00
|
|
|
nulls[i] = false;
|
2002-07-11 09:39:28 +02:00
|
|
|
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);
|
2005-06-28 07:09:14 +02:00
|
|
|
values[Anum_pg_conversion_conowner - 1] = ObjectIdGetDatum(conowner);
|
2002-07-11 09:39:28 +02:00
|
|
|
values[Anum_pg_conversion_conforencoding - 1] = Int32GetDatum(conforencoding);
|
|
|
|
values[Anum_pg_conversion_contoencoding - 1] = Int32GetDatum(contoencoding);
|
|
|
|
values[Anum_pg_conversion_conproc - 1] = ObjectIdGetDatum(conproc);
|
2002-11-02 03:33:03 +01:00
|
|
|
values[Anum_pg_conversion_condefault - 1] = BoolGetDatum(def);
|
2002-07-11 09:39:28 +02:00
|
|
|
|
2008-11-02 02:45:28 +01:00
|
|
|
tup = heap_form_tuple(tupDesc, values, nulls);
|
2002-07-11 09:39:28 +02:00
|
|
|
|
|
|
|
/* insert a new tuple */
|
|
|
|
oid = simple_heap_insert(rel, tup);
|
|
|
|
Assert(OidIsValid(oid));
|
|
|
|
|
|
|
|
/* update the index if any */
|
2002-08-05 05:29:17 +02:00
|
|
|
CatalogUpdateIndexes(rel, tup);
|
2002-07-11 09:39:28 +02:00
|
|
|
|
2005-04-14 22:03:27 +02:00
|
|
|
myself.classId = ConversionRelationId;
|
2002-07-25 12:07:13 +02:00
|
|
|
myself.objectId = HeapTupleGetOid(tup);
|
|
|
|
myself.objectSubId = 0;
|
|
|
|
|
2002-11-02 03:33:03 +01:00
|
|
|
/* create dependency on conversion procedure */
|
2005-04-14 03:38:22 +02:00
|
|
|
referenced.classId = ProcedureRelationId;
|
2002-07-25 12:07:13 +02:00
|
|
|
referenced.objectId = conproc;
|
|
|
|
referenced.objectSubId = 0;
|
|
|
|
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
|
|
|
|
|
2006-05-30 15:36:30 +02:00
|
|
|
/* create dependency on namespace */
|
|
|
|
referenced.classId = NamespaceRelationId;
|
|
|
|
referenced.objectId = connamespace;
|
2006-08-31 19:31:33 +02:00
|
|
|
referenced.objectSubId = 0;
|
2006-05-30 15:36:30 +02:00
|
|
|
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
|
|
|
|
|
2006-08-31 19:31:33 +02:00
|
|
|
/* create dependency on owner */
|
|
|
|
recordDependencyOnOwner(ConversionRelationId, HeapTupleGetOid(tup),
|
|
|
|
conowner);
|
|
|
|
|
2002-07-25 12:07:13 +02:00
|
|
|
heap_freetuple(tup);
|
2002-07-11 09:39:28 +02:00
|
|
|
heap_close(rel, RowExclusiveLock);
|
|
|
|
|
|
|
|
return oid;
|
|
|
|
}
|
|
|
|
|
2002-11-02 03:33:03 +01:00
|
|
|
/*
|
2002-07-25 12:07:13 +02:00
|
|
|
* RemoveConversionById
|
|
|
|
*
|
2002-11-02 03:33:03 +01:00
|
|
|
* Remove a tuple from pg_conversion by Oid. This function is solely
|
2002-07-25 12:07:13 +02:00
|
|
|
* called inside catalog/dependency.c
|
2002-11-02 03:33:03 +01:00
|
|
|
*/
|
2002-07-25 12:07:13 +02:00
|
|
|
void
|
|
|
|
RemoveConversionById(Oid conversionOid)
|
|
|
|
{
|
|
|
|
Relation rel;
|
|
|
|
HeapTuple tuple;
|
|
|
|
HeapScanDesc scan;
|
|
|
|
ScanKeyData scanKeyData;
|
|
|
|
|
2003-11-12 22:15:59 +01:00
|
|
|
ScanKeyInit(&scanKeyData,
|
|
|
|
ObjectIdAttributeNumber,
|
|
|
|
BTEqualStrategyNumber, F_OIDEQ,
|
|
|
|
ObjectIdGetDatum(conversionOid));
|
2002-07-11 09:39:28 +02:00
|
|
|
|
2002-07-25 12:07:13 +02:00
|
|
|
/* open pg_conversion */
|
2005-04-14 22:03:27 +02:00
|
|
|
rel = heap_open(ConversionRelationId, RowExclusiveLock);
|
2002-07-25 12:07:13 +02:00
|
|
|
|
|
|
|
scan = heap_beginscan(rel, SnapshotNow,
|
2002-09-04 22:31:48 +02:00
|
|
|
1, &scanKeyData);
|
2002-07-25 12:07:13 +02:00
|
|
|
|
|
|
|
/* search for the target tuple */
|
|
|
|
if (HeapTupleIsValid(tuple = heap_getnext(scan, ForwardScanDirection)))
|
|
|
|
simple_heap_delete(rel, &tuple->t_self);
|
|
|
|
else
|
2003-07-21 03:59:11 +02:00
|
|
|
elog(ERROR, "could not find tuple for conversion %u", conversionOid);
|
2002-07-11 09:39:28 +02:00
|
|
|
heap_endscan(scan);
|
|
|
|
heap_close(rel, RowExclusiveLock);
|
|
|
|
}
|
|
|
|
|
2002-11-02 03:33:03 +01:00
|
|
|
/*
|
2002-07-11 09:39:28 +02:00
|
|
|
* FindDefaultConversion
|
|
|
|
*
|
2002-11-02 03:33:03 +01:00
|
|
|
* 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!
|
2002-07-11 09:39:28 +02:00
|
|
|
*/
|
2002-09-04 22:31:48 +02:00
|
|
|
Oid
|
2002-11-02 03:33:03 +01:00
|
|
|
FindDefaultConversion(Oid name_space, int32 for_encoding, int32 to_encoding)
|
2002-07-25 12:07:13 +02:00
|
|
|
{
|
2002-09-04 22:31:48 +02:00
|
|
|
CatCList *catlist;
|
2002-07-25 12:07:13 +02:00
|
|
|
HeapTuple tuple;
|
|
|
|
Form_pg_conversion body;
|
2002-09-04 22:31:48 +02:00
|
|
|
Oid proc = InvalidOid;
|
|
|
|
int i;
|
2002-07-25 12:07:13 +02:00
|
|
|
|
2010-02-14 19:42:19 +01:00
|
|
|
catlist = SearchSysCacheList3(CONDEFAULT,
|
|
|
|
ObjectIdGetDatum(name_space),
|
|
|
|
Int32GetDatum(for_encoding),
|
|
|
|
Int32GetDatum(to_encoding));
|
2002-07-25 12:07:13 +02:00
|
|
|
|
|
|
|
for (i = 0; i < catlist->n_members; i++)
|
|
|
|
{
|
|
|
|
tuple = &catlist->members[i]->tuple;
|
2002-09-04 22:31:48 +02:00
|
|
|
body = (Form_pg_conversion) GETSTRUCT(tuple);
|
2002-11-02 03:33:03 +01:00
|
|
|
if (body->condefault)
|
2002-07-25 12:07:13 +02:00
|
|
|
{
|
|
|
|
proc = body->conproc;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ReleaseSysCacheList(catlist);
|
|
|
|
return proc;
|
|
|
|
}
|