diff --git a/src/backend/catalog/Makefile b/src/backend/catalog/Makefile
index 3d1126bf01f172db1c7e6e6ced2def74e9babe49..0d021964b7a48a2dc3e8813e023e4914c4d1ee78 100644
--- a/src/backend/catalog/Makefile
+++ b/src/backend/catalog/Makefile
@@ -2,7 +2,7 @@
 #
 # Makefile for backend/catalog
 #
-# $Header: /cvsroot/pgsql/src/backend/catalog/Makefile,v 1.39 2002/03/26 19:15:22 tgl Exp $
+# $Header: /cvsroot/pgsql/src/backend/catalog/Makefile,v 1.40 2002/07/11 07:39:27 ishii Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -12,7 +12,7 @@ include $(top_builddir)/src/Makefile.global
 
 OBJS = catalog.o heap.o index.o indexing.o namespace.o aclchk.o \
        pg_aggregate.o pg_largeobject.o pg_namespace.o \
-       pg_operator.o pg_proc.o pg_type.o
+       pg_operator.o pg_proc.o pg_type.o pg_conversion.o
 
 BKIFILES = postgres.bki postgres.description
 
@@ -31,7 +31,8 @@ POSTGRES_BKI_SRCS := $(addprefix $(top_srcdir)/src/include/catalog/,\
 	pg_operator.h pg_opclass.h pg_am.h pg_amop.h pg_amproc.h \
 	pg_language.h pg_largeobject.h pg_aggregate.h pg_statistic.h \
 	pg_rewrite.h pg_trigger.h pg_listener.h pg_description.h \
-	pg_namespace.h pg_database.h pg_shadow.h pg_group.h indexing.h \
+	pg_namespace.h pg_conversion.h pg_database.h pg_shadow.h pg_group.h \
+	indexing.h \
     )
 
 pg_includes := $(sort -I$(top_srcdir)/src/include -I$(top_builddir)/src/include)
diff --git a/src/backend/catalog/indexing.c b/src/backend/catalog/indexing.c
index 4f8ee1d39799f353f013e19af1f0f018fd996b61..5611edda85343827176b48aa1353bce71607dbcd 100644
--- a/src/backend/catalog/indexing.c
+++ b/src/backend/catalog/indexing.c
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/catalog/indexing.c,v 1.94 2002/06/20 20:29:26 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/catalog/indexing.c,v 1.95 2002/07/11 07:39:27 ishii Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -45,6 +45,8 @@ char	   *Name_pg_attrdef_indices[Num_pg_attrdef_indices] =
 {AttrDefaultIndex};
 char	   *Name_pg_class_indices[Num_pg_class_indices] =
 {ClassNameNspIndex, ClassOidIndex};
+char	   *Name_pg_conversion_indices[Num_pg_conversion_indices] =
+{ConversionNameNspIndex, ConversionDefaultIndex};
 char	   *Name_pg_database_indices[Num_pg_database_indices] =
 {DatabaseNameIndex, DatabaseOidIndex};
 char	   *Name_pg_group_indices[Num_pg_group_indices] =
diff --git a/src/backend/catalog/pg_conversion.c b/src/backend/catalog/pg_conversion.c
new file mode 100644
index 0000000000000000000000000000000000000000..8cddcf064db9cb8610b0d7fc6fb7e4e5ef032ccd
--- /dev/null
+++ b/src/backend/catalog/pg_conversion.c
@@ -0,0 +1,249 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_conversion.c
+ *	  routines to support manipulation of the pg_conversion relation
+ *
+ * Portions Copyright (c) 1996-2002, 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.1 2002/07/11 07:39:27 ishii Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "access/heapam.h"
+#include "catalog/catname.h"
+#include "catalog/indexing.h"
+#include "catalog/pg_conversion.h"
+#include "catalog/namespace.h"
+#include "utils/builtins.h"
+#include "utils/syscache.h"
+#include "mb/pg_wchar.h"
+#include "utils/fmgroids.h"
+#include "utils/acl.h"
+#include "miscadmin.h"
+
+/* ----------------
+ * ConversionCreate
+ * ---------------
+ */
+Oid	ConversionCreate(const char *conname, Oid connamespace,
+							 int32 conowner,
+							 int4 conforencoding, int4 contoencoding,
+							 Oid conproc, bool def)
+{
+	int i;
+	Relation	rel;
+	TupleDesc	tupDesc;
+	HeapTuple	tup;
+	char		nulls[Natts_pg_conversion];
+	Datum		values[Natts_pg_conversion];
+	NameData	cname;
+	Oid			oid;
+
+	/* 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 (def)
+	{
+		/* make sure there is no existing default
+		   <for encoding><to encoding> 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));
+	}
+
+	/* open pg_conversion */
+	rel = heap_openr(ConversionRelationName, RowExclusiveLock);
+	tupDesc = rel->rd_att;
+
+	/* initialize nulls and values */
+	for (i = 0; i < Natts_pg_conversion; i++)
+	{
+		nulls[i] = ' ';
+		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);
+	values[Anum_pg_conversion_conowner - 1] = Int32GetDatum(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);
+	values[Anum_pg_conversion_condefault - 1] = BoolGetDatum(def);
+
+	tup = heap_formtuple(tupDesc, values, nulls);
+
+	/* insert a new tuple */
+	oid = simple_heap_insert(rel, tup);
+	Assert(OidIsValid(oid));
+
+	/* update the index if any */
+	if (RelationGetForm(rel)->relhasindex)
+	{
+		Relation	idescs[Num_pg_conversion_indices];
+
+		CatalogOpenIndices(Num_pg_conversion_indices, Name_pg_conversion_indices, idescs);
+		CatalogIndexInsert(idescs, Num_pg_conversion_indices, rel, tup);
+		CatalogCloseIndices(Num_pg_conversion_indices, idescs);
+	}
+
+	heap_close(rel, RowExclusiveLock);
+
+	return oid;
+}
+
+/* ----------------
+ * ConversionDrop
+ * ---------------
+ */
+void	ConversionDrop(const char *conname, Oid connamespace, int32 conowner)
+{
+	Relation	rel;
+	TupleDesc	tupDesc;
+	HeapTuple	tuple;
+	HeapScanDesc scan;
+	ScanKeyData scanKeyData;
+	Form_pg_conversion body;
+
+	/* 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, RowExclusiveLock);
+	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");
+
+	simple_heap_delete(rel, &tuple->t_self);
+
+	heap_endscan(scan);
+	heap_close(rel, RowExclusiveLock);
+}
+
+/* ----------------
+ * FindDefaultConversion
+ *
+ * find default conversion proc by for_encoding and to_encoding in this name space
+ * ---------------
+ */
+Oid FindDefaultConversion(Oid name_space, int4 for_encoding, int4 to_encoding)
+{
+	Relation rel;
+	HeapScanDesc scan;
+	ScanKeyData scanKeyData;
+	HeapTuple	tuple;
+	Form_pg_conversion body;
+	Oid proc = InvalidOid;
+
+	/* Check we have usage rights in target namespace */
+	if (pg_namespace_aclcheck(name_space, GetUserId(), ACL_USAGE) != ACLCHECK_OK)
+		return InvalidOid;
+
+	ScanKeyEntryInitialize(&scanKeyData,
+						   0,
+						   Anum_pg_conversion_connamespace,
+						   F_OIDEQ,
+						   ObjectIdGetDatum(name_space));
+
+	rel = heap_openr(ConversionRelationName, AccessShareLock);
+	scan = heap_beginscan(rel, SnapshotNow,
+							  1, &scanKeyData);
+
+	while (HeapTupleIsValid(tuple = heap_getnext(scan, ForwardScanDirection)))
+	{
+		body = (Form_pg_conversion)GETSTRUCT(tuple);
+		if (body->conforencoding == for_encoding &&
+			body->conforencoding == to_encoding &&
+			body->condefault == TRUE) {
+			proc = body->conproc;
+			break;
+		}
+	}
+	heap_endscan(scan);
+	heap_close(rel, AccessShareLock);
+	return proc;
+}
+
+/* ----------------
+ * FindConversionByName
+ *
+ * find conversion proc by possibly qualified conversion name.
+ * ---------------
+ */
+Oid FindConversionByName(List *name)
+{
+	HeapTuple	tuple;
+	char		*conversion_name;
+	Oid	namespaceId;
+	Oid procoid;
+	AclResult	aclresult;
+
+	/* Convert list of names to a name and namespace */
+	namespaceId = QualifiedNameGetCreationNamespace(name, &conversion_name);
+
+	/* Check we have usage rights in target namespace */
+	if (pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_USAGE) != ACLCHECK_OK)
+		return InvalidOid;
+
+	/* search pg_conversion by namespaceId and conversion name */
+	tuple = SearchSysCache(CONNAMESP,
+						   PointerGetDatum(conversion_name),
+						   ObjectIdGetDatum(namespaceId),
+						   0,0);
+
+	if (!HeapTupleIsValid(tuple))
+		return InvalidOid;
+
+	procoid = ((Form_pg_conversion)GETSTRUCT(tuple))->conproc;
+
+	ReleaseSysCache(tuple);
+
+	/* Check we have execute rights for the function */
+	aclresult = pg_proc_aclcheck(procoid, GetUserId(), ACL_EXECUTE);
+	if (aclresult != ACLCHECK_OK)
+		return InvalidOid;
+
+	return procoid;
+}
+
diff --git a/src/backend/commands/Makefile b/src/backend/commands/Makefile
index 190b0fd64f64d75290ce2767864f39c1e606f26f..58e8fe20e2d3c5386c381cb1ad48c430ed883acb 100644
--- a/src/backend/commands/Makefile
+++ b/src/backend/commands/Makefile
@@ -4,7 +4,7 @@
 #    Makefile for backend/commands
 #
 # IDENTIFICATION
-#    $Header: /cvsroot/pgsql/src/backend/commands/Makefile,v 1.28 2002/04/15 05:22:03 tgl Exp $
+#    $Header: /cvsroot/pgsql/src/backend/commands/Makefile,v 1.29 2002/07/11 07:39:27 ishii Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -12,7 +12,8 @@ subdir = src/backend/commands
 top_builddir = ../../..
 include $(top_builddir)/src/Makefile.global
 
-OBJS = aggregatecmds.o analyze.o async.o cluster.o comment.o copy.o \
+OBJS = aggregatecmds.o analyze.o async.o cluster.o comment.o  \
+	conversioncmds.o copy.o \
 	dbcommands.o define.o explain.o functioncmds.o \
 	indexcmds.o lockcmds.o operatorcmds.o portalcmds.o proclang.o \
 	schemacmds.o sequence.o tablecmds.o trigger.o typecmds.o user.o \
diff --git a/src/backend/commands/conversioncmds.c b/src/backend/commands/conversioncmds.c
new file mode 100644
index 0000000000000000000000000000000000000000..077fe9d8d874defe04b1d5d6350b5e25b9a775a2
--- /dev/null
+++ b/src/backend/commands/conversioncmds.c
@@ -0,0 +1,112 @@
+/*-------------------------------------------------------------------------
+ *
+ * conversionmacmds.c
+ *	  conversion creation command support code
+ *
+ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/conversioncmds.c,v 1.1 2002/07/11 07:39:27 ishii Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "catalog/pg_conversion.h"
+#include "catalog/catalog.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/lsyscache.h"
+
+
+/*
+ * CREATE CONVERSION
+ */
+void
+CreateConversionCommand(CreateConversionStmt *stmt)
+{
+	Oid			namespaceId;
+	char		*conversion_name;
+	AclResult	aclresult;
+	int			for_encoding;
+	int			to_encoding;
+	Oid			funcoid;
+	Oid			funcnamespace;
+	char		*dummy;
+
+	const char *for_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, 0, 0, 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, get_namespace_name(namespaceId));
+
+	/* Check the encoding names */
+	for_encoding = pg_char_to_encoding(for_encoding_name);
+	if (for_encoding < 0)
+		elog(ERROR, "Invalid for encoding name: %s", for_encoding_name);
+
+	to_encoding = pg_char_to_encoding(to_encoding_name);
+	if (to_encoding < 0)
+		elog(ERROR, "Invalid to encoding name: %s", 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);
+	if (!OidIsValid(funcoid))
+		elog(ERROR, "Function %s does not exist", NameListToString(func_name));
+
+	/* Check the rights for this function and name space */
+	funcnamespace = QualifiedNameGetCreationNamespace(func_name, &dummy);
+	aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_USAGE);
+	if (aclresult != ACLCHECK_OK)
+		aclcheck_error(aclresult, get_namespace_name(funcnamespace));
+
+	aclresult = pg_proc_aclcheck(funcoid, GetUserId(), ACL_EXECUTE);
+	if (aclresult != ACLCHECK_OK)
+		aclcheck_error(aclresult, get_namespace_name(funcnamespace));
+		
+	/* All seem ok, go ahead (possible failure would be a duplicate conversion name) */
+	ConversionCreate(conversion_name, namespaceId, GetUserId(),
+					 for_encoding, to_encoding, funcoid, stmt->def);
+}
+
+/*
+ * DROP CONVERSION
+ */
+void
+DropConversionCommand(List *name)
+{
+	Oid			namespaceId;
+	char		*conversion_name;
+	AclResult	aclresult;
+
+	/* Convert list of names to a name and namespace */
+	namespaceId = QualifiedNameGetCreationNamespace(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, get_namespace_name(namespaceId));
+
+	/* Go ahead (possible failure would be:
+	 * none existing conversion
+	 * not ower of this conversion
+	 */
+	ConversionDrop(conversion_name, namespaceId, GetUserId());
+}
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index e8e5aeabc77da8d4634eebe22a82d53c4dfeffb1..18b349c4ee2f211cc18ba29813ec7f12113fba28 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.337 2002/07/06 20:16:35 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.338 2002/07/11 07:39:25 ishii Exp $
  *
  * HISTORY
  *	  AUTHOR			DATE			MAJOR EVENT
@@ -157,7 +157,7 @@ static void doNegateFloat(Value *v);
 		SelectStmt, TransactionStmt, TruncateStmt,
 		UnlistenStmt, UpdateStmt, VacuumStmt,
 		VariableResetStmt, VariableSetStmt, VariableShowStmt,
-		ViewStmt, CheckPointStmt
+		ViewStmt, CheckPointStmt, CreateConversionStmt
 
 %type <node>	select_no_parens, select_with_parens, select_clause,
 				simple_select
@@ -246,7 +246,7 @@ static void doNegateFloat(Value *v);
 
 %type <boolean> opt_instead, opt_cursor
 %type <boolean> index_opt_unique, opt_verbose, opt_full
-%type <boolean> opt_freeze
+%type <boolean> opt_freeze, opt_default
 %type <defelt>	opt_binary, opt_oids, copy_delimiter
 
 %type <boolean> copy_from
@@ -335,7 +335,7 @@ static void doNegateFloat(Value *v);
 	CACHE, CALLED, CASCADE, CASE, CAST, CHAIN, CHAR_P,
 	CHARACTER, CHARACTERISTICS, CHECK, CHECKPOINT, CLOSE,
 	CLUSTER, COALESCE, COLLATE, COLUMN, COMMENT, COMMIT,
-	COMMITTED, CONSTRAINT, CONSTRAINTS, COPY, CREATE, CREATEDB,
+	COMMITTED, CONSTRAINT, CONSTRAINTS, CONVERSION_P, COPY, CREATE, CREATEDB,
 	CREATEUSER, CROSS, CURRENT_DATE, CURRENT_TIME,
 	CURRENT_TIMESTAMP, CURRENT_USER, CURSOR, CYCLE,
 
@@ -532,6 +532,7 @@ stmt :
 			| VariableResetStmt
 			| ConstraintsSetStmt
 			| CheckPointStmt
+			| CreateConversionStmt
 			| /*EMPTY*/
 				{ $$ = (Node *)NULL; }
 		;
@@ -2299,6 +2300,7 @@ drop_type:	TABLE									{ $$ = DROP_TABLE; }
 			| INDEX									{ $$ = DROP_INDEX; }
 			| TYPE_P								{ $$ = DROP_TYPE; }
 			| DOMAIN_P								{ $$ = DROP_DOMAIN; }
+			| CONVERSION_P								{ $$ = DROP_CONVERSION; }
 		;
 
 any_name_list:
@@ -3673,6 +3675,33 @@ opt_as:		AS										{}
 		;
 
 
+/*****************************************************************************
+ *
+ * Manipulate a conversion
+ *
+ *		CREATE [DEFAULT] CONVERSION <conversion_name>
+ *		FOR <encoding_name> TO <encoding_name> FROM <func_name>
+ *
+ *****************************************************************************/
+
+CreateConversionStmt:
+			CREATE opt_default CONVERSION_P any_name FOR Sconst
+			TO Sconst FROM any_name
+			{
+			  CreateConversionStmt *n = makeNode(CreateConversionStmt);
+			  n->conversion_name = $4;
+			  n->for_encoding_name = $6;
+			  n->to_encoding_name = $8;
+			  n->func_name = $10;
+			  n->def = $2;
+			  $$ = (Node *)n;
+			}
+		;
+
+opt_default:	DEFAULT	{ $$ = TRUE; }
+			| /*EMPTY*/	{ $$ = FALSE; }
+		;
+
 /*****************************************************************************
  *
  *		QUERY:
diff --git a/src/backend/parser/keywords.c b/src/backend/parser/keywords.c
index 92920ee4f7dfc3e6f638fcd88358643dc64ef9f6..907a26baee67ea9677fd5af63df27493605081dc 100644
--- a/src/backend/parser/keywords.c
+++ b/src/backend/parser/keywords.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.118 2002/07/04 15:24:01 thomas Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.119 2002/07/11 07:39:26 ishii Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -78,6 +78,7 @@ static const ScanKeyword ScanKeywords[] = {
 	{"committed", COMMITTED},
 	{"constraint", CONSTRAINT},
 	{"constraints", CONSTRAINTS},
+	{"conversion", CONVERSION_P},
 	{"copy", COPY},
 	{"create", CREATE},
 	{"createdb", CREATEDB},
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index a8f83e48e4da376187848e21e1c8b1a1bf568f9d..c6b8fcfafd6c0394a39d21b1e141a92c25691c50 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.268 2002/06/20 20:29:36 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.269 2002/07/11 07:39:26 ishii Exp $
  *
  * NOTES
  *	  this is the "main" module of the postgres backend and
@@ -1688,7 +1688,7 @@ PostgresMain(int argc, char *argv[], const char *username)
 	if (!IsUnderPostmaster)
 	{
 		puts("\nPOSTGRES backend interactive interface ");
-		puts("$Revision: 1.268 $ $Date: 2002/06/20 20:29:36 $\n");
+		puts("$Revision: 1.269 $ $Date: 2002/07/11 07:39:26 $\n");
 	}
 
 	/*
@@ -2211,6 +2211,9 @@ CreateCommandTag(Node *parsetree)
 				case DROP_DOMAIN:
 					tag = "DROP DOMAIN";
 					break;
+				case DROP_CONVERSION:
+					tag = "DROP CONVERSON";
+					break;
 				default:
 					tag = "???";
 			}
@@ -2426,6 +2429,10 @@ CreateCommandTag(Node *parsetree)
 			tag = "REINDEX";
 			break;
 
+		case T_CreateConversionStmt:
+			tag = "CREATE CONVERSION";
+			break;
+
 		default:
 			elog(LOG, "CreateCommandTag: unknown parse node type %d",
 				 nodeTag(parsetree));
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index f5c38d071ed74db1e815955f86abd65e5b7e2b9f..e5e57d4a6de8ce8f6685ba12e242a283f0e9af22 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.160 2002/07/01 15:27:56 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.161 2002/07/11 07:39:26 ishii Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -24,6 +24,7 @@
 #include "commands/cluster.h"
 #include "commands/comment.h"
 #include "commands/copy.h"
+#include "commands/conversioncmds.h"
 #include "commands/dbcommands.h"
 #include "commands/defrem.h"
 #include "commands/explain.h"
@@ -319,6 +320,11 @@ ProcessUtility(Node *parsetree,
 							/* RemoveDomain does its own permissions checks */
 							RemoveDomain(names, stmt->behavior);
 							break;
+
+						case DROP_CONVERSION:
+							/* RemoveDomain does its own permissions checks */
+							DropConversionCommand(names);
+							break;
 					}
 
 					/*
@@ -823,6 +829,12 @@ ProcessUtility(Node *parsetree,
 			}
 			break;
 
+		case T_CreateConversionStmt:
+			{
+				CreateConversionCommand((CreateConversionStmt *) parsetree);
+			}
+			break;
+
 		default:
 			elog(ERROR, "ProcessUtility: command #%d unsupported",
 				 nodeTag(parsetree));
diff --git a/src/backend/utils/cache/syscache.c b/src/backend/utils/cache/syscache.c
index e409ab7bc8ef3c280fae592346948637038a60dd..a724a0874eec35050497b54161ed2d5cb62cd7b1 100644
--- a/src/backend/utils/cache/syscache.c
+++ b/src/backend/utils/cache/syscache.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.80 2002/06/20 20:29:39 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.81 2002/07/11 07:39:27 ishii Exp $
  *
  * NOTES
  *	  These routines allow the parser/planner/executor to perform
@@ -28,6 +28,7 @@
 #include "catalog/pg_aggregate.h"
 #include "catalog/pg_amop.h"
 #include "catalog/pg_amproc.h"
+#include "catalog/pg_conversion.h"
 #include "catalog/pg_group.h"
 #include "catalog/pg_index.h"
 #include "catalog/pg_inherits.h"
@@ -193,6 +194,16 @@ static const struct cachedesc cacheinfo[] = {
 			0,
 			0
 	}},
+	{ConversionRelationName, /* CONNAMENSP */
+		ConversionNameNspIndex,
+		0,
+		2,
+		{
+			Anum_pg_conversion_conname,
+			Anum_pg_conversion_connamespace,
+			0,
+			0
+	}},
 	{GroupRelationName,			/* GRONAME */
 		GroupNameIndex,
 		0,
diff --git a/src/include/catalog/catname.h b/src/include/catalog/catname.h
index d679b06618c53694e79d3f71493bd03c32864dd2..6f755c9f9dc77302d845db3274cdaf10260abf1f 100644
--- a/src/include/catalog/catname.h
+++ b/src/include/catalog/catname.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: catname.h,v 1.26 2002/06/20 20:29:43 momjian Exp $
+ * $Id: catname.h,v 1.27 2002/07/11 07:39:27 ishii Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -20,6 +20,7 @@
 #define  AccessMethodOperatorRelationName "pg_amop"
 #define  AccessMethodProcedureRelationName "pg_amproc"
 #define  AttributeRelationName "pg_attribute"
+#define  ConversionRelationName "pg_conversion"
 #define  DatabaseRelationName "pg_database"
 #define  DescriptionRelationName "pg_description"
 #define  GroupRelationName "pg_group"
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index d4d04d6db96d185432b6fdb75659093181a92af9..81f52bd9b34565ea2aaf031840ff6ba1ade38733 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -37,7 +37,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: catversion.h,v 1.137 2002/07/02 05:46:14 momjian Exp $
+ * $Id: catversion.h,v 1.138 2002/07/11 07:39:27 ishii Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -53,6 +53,6 @@
  */
 
 /*							yyyymmddN */
-#define CATALOG_VERSION_NO	200207021
+#define CATALOG_VERSION_NO	200207111
 
 #endif
diff --git a/src/include/catalog/indexing.h b/src/include/catalog/indexing.h
index bbc1b5ec995b21adf19bde4ee8049ddc3acd3d32..9413e5c8586dd27a7ed006e6bd575848c7b438fd 100644
--- a/src/include/catalog/indexing.h
+++ b/src/include/catalog/indexing.h
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: indexing.h,v 1.67 2002/06/20 20:29:43 momjian Exp $
+ * $Id: indexing.h,v 1.68 2002/07/11 07:39:27 ishii Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -27,6 +27,7 @@
 #define Num_pg_attr_indices			2
 #define Num_pg_attrdef_indices		1
 #define Num_pg_class_indices		2
+#define Num_pg_conversion_indices	2
 #define Num_pg_database_indices		2
 #define Num_pg_description_indices	1
 #define Num_pg_group_indices		2
@@ -59,6 +60,8 @@
 #define AttributeRelidNumIndex		"pg_attribute_relid_attnum_index"
 #define ClassNameNspIndex			"pg_class_relname_nsp_index"
 #define ClassOidIndex				"pg_class_oid_index"
+#define ConversionDefaultIndex		"pg_conversion_default_index"
+#define ConversionNameNspIndex		"pg_conversion_name_nsp_index"
 #define DatabaseNameIndex			"pg_database_datname_index"
 #define DatabaseOidIndex			"pg_database_oid_index"
 #define DescriptionObjIndex			"pg_description_o_c_o_index"
@@ -99,6 +102,7 @@ extern char *Name_pg_amproc_indices[];
 extern char *Name_pg_attr_indices[];
 extern char *Name_pg_attrdef_indices[];
 extern char *Name_pg_class_indices[];
+extern char *Name_pg_conversion_indices[];
 extern char *Name_pg_database_indices[];
 extern char *Name_pg_description_indices[];
 extern char *Name_pg_group_indices[];
@@ -155,6 +159,9 @@ DECLARE_UNIQUE_INDEX(pg_attribute_relid_attnam_index on pg_attribute using btree
 DECLARE_UNIQUE_INDEX(pg_attribute_relid_attnum_index on pg_attribute using btree(attrelid oid_ops, attnum int2_ops));
 DECLARE_UNIQUE_INDEX(pg_class_oid_index on pg_class using btree(oid oid_ops));
 DECLARE_UNIQUE_INDEX(pg_class_relname_nsp_index on pg_class using btree(relname name_ops, relnamespace oid_ops));
+/* This following index is not used for a cache and is not unique */
+DECLARE_INDEX(pg_conversion_default_index on pg_conversion using btree(connamespace oid_ops, conforencoding int4_ops, contoencoding int4_ops));
+DECLARE_UNIQUE_INDEX(pg_conversion_name_nsp_index on pg_conversion using btree(conname name_ops, connamespace oid_ops));
 DECLARE_UNIQUE_INDEX(pg_database_datname_index on pg_database using btree(datname name_ops));
 DECLARE_UNIQUE_INDEX(pg_database_oid_index on pg_database using btree(oid oid_ops));
 DECLARE_UNIQUE_INDEX(pg_description_o_c_o_index on pg_description using btree(objoid oid_ops, classoid oid_ops, objsubid int4_ops));
diff --git a/src/include/catalog/pg_conversion.h b/src/include/catalog/pg_conversion.h
new file mode 100644
index 0000000000000000000000000000000000000000..d4c406b8ee110519de6134d59ff9bcf32784cfd0
--- /dev/null
+++ b/src/include/catalog/pg_conversion.h
@@ -0,0 +1,93 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_conversion.h
+ *	  definition of the system "conversion" relation (pg_conversion)
+ *	  along with the relation's initial contents.
+ *
+ *
+ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * $Id: pg_conversion.h,v 1.1 2002/07/11 07:39:27 ishii Exp $
+ *
+ * NOTES
+ *	  the genbki.sh script reads this file and generates .bki
+ *	  information from the DATA() statements.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_CONVERSION_H
+#define PG_CONVERSION_H
+
+/* ----------------
+ *		postgres.h contains the system type definitions and the
+ *		CATALOG(), BOOTSTRAP and DATA() sugar words so this file
+ *		can be read by both genbki.sh and the C compiler.
+ * ----------------
+ */
+
+/* ----------------------------------------------------------------
+ *		pg_conversion definition.
+ *
+ *		cpp turns this into typedef struct FormData_pg_namespace
+ *
+ *	conname				name of the conversion
+ *	connamespace		name space which the conversion belongs to
+ *	conowner			ower of the conversion
+ *	conforencoding		FOR encoding id
+ *	contoencoding		TO encoding id
+ *  conproc				OID of the conversion proc
+ *  condefault			TRUE is this is a default conversion
+ * ----------------------------------------------------------------
+ */
+CATALOG(pg_conversion)
+{
+	NameData	conname;
+	Oid			connamespace;
+	int4		conowner;
+	int4		conforencoding;
+	int4		contoencoding;
+	regproc		conproc;
+	bool		condefault;
+} FormData_pg_conversion;
+
+/* ----------------
+ *		Form_pg_conversion corresponds to a pointer to a tuple with
+ *		the format of pg_conversion relation.
+ * ----------------
+ */
+typedef FormData_pg_conversion *Form_pg_conversion;
+
+/* ----------------
+ *		compiler constants for pg_conversion
+ * ----------------
+ */
+
+#define Natts_pg_conversion				7
+#define Anum_pg_conversion_conname		1
+#define Anum_pg_conversion_connamespace	2
+#define Anum_pg_conversion_conowner		3
+#define Anum_pg_conversion_conforencoding		4
+#define Anum_pg_conversion_contoencoding		5
+#define Anum_pg_conversion_conproc		6
+#define Anum_pg_conversion_condefault	7
+
+/* ----------------
+ * initial contents of pg_conversion
+ * ---------------
+ */
+
+/*
+ * prototypes for functions in pg_conversion.c
+ */
+#include "nodes/pg_list.h"
+
+extern Oid	ConversionCreate(const char *conname, Oid connamespace,
+							 int32 conowner,
+							 int4 conforencoding, int4 contoencoding,
+							 Oid conproc, bool def);
+extern void ConversionDrop(const char *conname, Oid connamespace, int32 conowner);
+extern Oid FindDefaultConversion(Oid name_space, int4 for_encoding, int4 to_encoding);
+extern Oid FindConversionByName(List *conname);
+
+#endif   /* PG_CONVERSION_H */
diff --git a/src/include/commands/conversioncmds.h b/src/include/commands/conversioncmds.h
new file mode 100644
index 0000000000000000000000000000000000000000..fc4e5e6f51bb12d8e199e16a6bc4b986045fe6ee
--- /dev/null
+++ b/src/include/commands/conversioncmds.h
@@ -0,0 +1,23 @@
+/*-------------------------------------------------------------------------
+ *
+ * conversioncmds.h
+ *	  prototypes for conversioncmds.c.
+ *
+ *
+ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * $Id: conversioncmds.h,v 1.1 2002/07/11 07:39:27 ishii Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef CONVERSIONCMDS_H
+#define CONVERSIONCMDS_H
+
+#include "nodes/parsenodes.h"
+
+extern void CreateConversionCommand(CreateConversionStmt *parsetree);
+extern void DropConversionCommand(List *conversion_name);
+
+#endif  /* CONVERSIONCMDS_H */
diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h
index 815a9ea861f392104327bfd3fb47ad6d4cd135c6..a2980a1ff20bf0a99300009c4867f191807a9ac0 100644
--- a/src/include/nodes/nodes.h
+++ b/src/include/nodes/nodes.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: nodes.h,v 1.109 2002/06/20 20:29:51 momjian Exp $
+ * $Id: nodes.h,v 1.110 2002/07/11 07:39:27 ishii Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -198,6 +198,7 @@ typedef enum NodeTag
 	T_CreateSchemaStmt,
 	T_AlterDatabaseSetStmt,
 	T_AlterUserSetStmt,
+	T_CreateConversionStmt,
 
 	T_A_Expr = 700,
 	T_ColumnRef,
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index ce914c5cd0911edd94527e6d9bc8c033a0c0946b..19693d57b3affbd60f91e1c79d09cffd1108ea6b 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: parsenodes.h,v 1.183 2002/07/01 15:27:56 tgl Exp $
+ * $Id: parsenodes.h,v 1.184 2002/07/11 07:39:27 ishii Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1109,6 +1109,7 @@ typedef struct CreateDomainStmt
 #define DROP_INDEX	  4
 #define DROP_TYPE     5
 #define DROP_DOMAIN	  6
+#define DROP_CONVERSION	  7
 
 typedef struct DropStmt
 {
@@ -1505,4 +1506,18 @@ typedef struct ReindexStmt
 	bool		all;
 } ReindexStmt;
 
+/* ----------------------
+ *		CREATE CONVERSION Statement
+ * ----------------------
+ */
+typedef struct CreateConversionStmt
+{
+	NodeTag		type;
+	List		*conversion_name;		/* Name of the conversion */
+	char		*for_encoding_name;		/* source encoding name */
+	char		*to_encoding_name;		/* destiname encoding name */
+	List		*func_name;				/* qualified conversion function name */
+	bool		def;				/* is this a default conversion? */
+} CreateConversionStmt;
+
 #endif   /* PARSENODES_H */
diff --git a/src/include/utils/syscache.h b/src/include/utils/syscache.h
index 0cd6b7ae5f3e22513b6b6056e0feb3a7ec25285a..f40471d7948754c01e645dce11330dbe905eb172 100644
--- a/src/include/utils/syscache.h
+++ b/src/include/utils/syscache.h
@@ -9,7 +9,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: syscache.h,v 1.48 2002/06/20 20:29:53 momjian Exp $
+ * $Id: syscache.h,v 1.49 2002/07/11 07:39:28 ishii Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -38,27 +38,27 @@
 #define ATTNUM			7
 #define CLAAMNAMENSP	8
 #define CLAOID			9
-#define GRONAME			10
-#define GROSYSID		11
-#define INDEXRELID		12
-#define INHRELID		13
-#define LANGNAME		14
-#define LANGOID			15
-#define NAMESPACENAME	16
-#define NAMESPACEOID	17
-#define OPERNAMENSP		18
-#define OPEROID			19
-#define PROCNAMENSP		20
-#define PROCOID			21
-#define RELNAMENSP		22
-#define RELOID			23
-#define RULERELNAME		24
-#define SHADOWNAME		25
-#define SHADOWSYSID		26
-#define STATRELATT		27
-#define TYPENAMENSP		28
-#define TYPEOID			29
-
+#define CONNAMESP		10
+#define GRONAME			11
+#define GROSYSID		12
+#define INDEXRELID		13
+#define INHRELID		14
+#define LANGNAME		15
+#define LANGOID			16
+#define NAMESPACENAME	17
+#define NAMESPACEOID	18
+#define OPERNAMENSP		19
+#define OPEROID			20
+#define PROCNAMENSP		21
+#define PROCOID			22
+#define RELNAMENSP		23
+#define RELOID			24
+#define RULERELNAME		25
+#define SHADOWNAME		26
+#define SHADOWSYSID		27
+#define STATRELATT		28
+#define TYPENAMENSP		29
+#define TYPEOID			30
 
 extern void InitCatalogCache(void);
 extern void InitCatalogCachePhase2(void);
diff --git a/src/test/regress/expected/sanity_check.out b/src/test/regress/expected/sanity_check.out
index 7958da8433179a96290bf9625820722a6c9efdac..37544dd0ccb1f1956d212145cd8c60506f12668a 100644
--- a/src/test/regress/expected/sanity_check.out
+++ b/src/test/regress/expected/sanity_check.out
@@ -38,6 +38,7 @@ SELECT relname, relhasindex
  pg_attrdef          | t
  pg_attribute        | t
  pg_class            | t
+ pg_conversion       | t
  pg_database         | t
  pg_description      | t
  pg_group            | t
@@ -60,5 +61,5 @@ SELECT relname, relhasindex
  shighway            | t
  tenk1               | t
  tenk2               | t
-(50 rows)
+(51 rows)