diff --git a/doc/src/sgml/ref/create_operator.sgml b/doc/src/sgml/ref/create_operator.sgml
index 82ea44921d986cd33ac92b5d8ff4a2410e6c37b3..2a4955113f3fc8f467d23f0a714d5d74f00c8d9b 100644
--- a/doc/src/sgml/ref/create_operator.sgml
+++ b/doc/src/sgml/ref/create_operator.sgml
@@ -1,5 +1,5 @@
 <!--
-$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_operator.sgml,v 1.29 2002/05/18 15:44:47 petere Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_operator.sgml,v 1.30 2002/08/10 19:01:53 tgl Exp $
 PostgreSQL documentation
 -->
 
@@ -437,6 +437,15 @@ MYBOXES.description === box '((0,0), (1,1))'
     Refer to <command>DROP OPERATOR</command> to delete
     user-defined operators from a database.
    </para>
+
+   <para>
+    To give a schema-qualified operator name in <replaceable
+    class="parameter">com_op</replaceable> or the other optional
+    arguments, use the <literal>OPERATOR()</> syntax, for example
+<programlisting>
+   COMMUTATOR = OPERATOR(myschema.===) ,
+</programlisting>  
+   </para>
   </refsect2>
  </refsect1>
   
diff --git a/doc/src/sgml/syntax.sgml b/doc/src/sgml/syntax.sgml
index 90f33bfd0ff7dceec512dc36dc6876191693699b..fbbe78db9a8f7e2f2c6562eb874f6d86d6f3939c 100644
--- a/doc/src/sgml/syntax.sgml
+++ b/doc/src/sgml/syntax.sgml
@@ -1,5 +1,5 @@
 <!--
-$Header: /cvsroot/pgsql/doc/src/sgml/syntax.sgml,v 1.64 2002/08/05 19:43:31 petere Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/syntax.sgml,v 1.65 2002/08/10 19:01:53 tgl Exp $
 -->
 
 <chapter id="sql-syntax">
@@ -755,7 +755,7 @@ SELECT (5 !) - 6;
       </row>
 
       <row>
-       <entry><token>LIKE</token> <token>ILIKE</token></entry>
+       <entry><token>LIKE</token> <token>ILIKE</token> <token>SIMILAR</token></entry>
        <entry></entry>
        <entry>string pattern matching</entry>
       </row>
@@ -801,6 +801,17 @@ SELECT (5 !) - 6;
     the same precedence as the built-in <quote>+</quote> operator, no
     matter what yours does.
    </para>
+
+   <para>
+    When a schema-qualified operator name is used in the
+    <literal>OPERATOR</> syntax, as for example in
+<programlisting>
+SELECT 3 OPERATOR(pg_catalog.+) 4;
+</programlisting>
+    the <literal>OPERATOR</> construct is taken to have the default precedence
+    shown above for <quote>any other</> operator.  This is true no matter
+    which specific operator name appears inside <literal>OPERATOR()</>.
+   </para>
   </sect2>
  </sect1>
 
diff --git a/src/backend/commands/define.c b/src/backend/commands/define.c
index a1b47d1274dcd00f0922f84b581591b226ffb3bf..02b730944b417cf722ed4526f631c4cfd2114802 100644
--- a/src/backend/commands/define.c
+++ b/src/backend/commands/define.c
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.78 2002/06/20 20:29:27 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.79 2002/08/10 19:01:53 tgl Exp $
  *
  * DESCRIPTION
  *	  The "DefineFoo" routines take the parse tree and pick out the
@@ -35,6 +35,7 @@
 #include <ctype.h>
 #include <math.h>
 
+#include "catalog/namespace.h"
 #include "commands/defrem.h"
 #include "parser/parse_type.h"
 #include "utils/int8.h"
@@ -86,6 +87,8 @@ defGetString(DefElem *def)
 			return strVal(def->arg);
 		case T_TypeName:
 			return TypeNameToString((TypeName *) def->arg);
+		case T_List:
+			return NameListToString((List *) def->arg);
 		default:
 			elog(ERROR, "Define: cannot interpret argument of \"%s\"",
 				 def->defname);
@@ -156,6 +159,8 @@ defGetQualifiedName(DefElem *def)
 	{
 		case T_TypeName:
 			return ((TypeName *) def->arg)->names;
+		case T_List:
+			return (List *) def->arg;
 		case T_String:
 			/* Allow quoted name for backwards compatibility */
 			return makeList1(def->arg);
@@ -168,6 +173,9 @@ defGetQualifiedName(DefElem *def)
 
 /*
  * Extract a TypeName from a DefElem.
+ *
+ * Note: we do not accept a List arg here, because the parser will only
+ * return a bare List when the name looks like an operator name.
  */
 TypeName *
 defGetTypeName(DefElem *def)
@@ -223,11 +231,14 @@ defGetTypeLength(DefElem *def)
 						   "variable") == 0)
 				return -1;		/* variable length */
 			break;
+		case T_List:
+			/* must be an operator name */
+			break;
 		default:
 			elog(ERROR, "Define: cannot interpret argument of \"%s\"",
 				 def->defname);
 	}
-	elog(ERROR, "Define: invalid argument for \"%s\"",
-		 def->defname);
+	elog(ERROR, "Define: invalid argument for \"%s\": \"%s\"",
+		 def->defname, defGetString(def));
 	return 0;					/* keep compiler quiet */
 }
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index f57f461124dc435b614087ff44b548cc87b960b2..98acc050d56ab71d02bad375db2687fa0382087c 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.357 2002/08/06 05:40:45 ishii Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.358 2002/08/10 19:01:53 tgl Exp $
  *
  * HISTORY
  *	  AUTHOR			DATE			MAJOR EVENT
@@ -1307,27 +1307,19 @@ copy_opt_list:
 copy_opt_item:
 			BINARY
 				{
-					$$ = makeNode(DefElem);
-					$$->defname = "binary";
-					$$->arg = (Node *)makeInteger(TRUE);
+					$$ = makeDefElem("binary", (Node *)makeInteger(TRUE));
 				}
 			| OIDS
 				{
-					$$ = makeNode(DefElem);
-					$$->defname = "oids";
-					$$->arg = (Node *)makeInteger(TRUE);
+					$$ = makeDefElem("oids", (Node *)makeInteger(TRUE));
 				}
 			| DELIMITER opt_as Sconst
 				{
-					$$ = makeNode(DefElem);
-					$$->defname = "delimiter";
-					$$->arg = (Node *)makeString($3);
+					$$ = makeDefElem("delimiter", (Node *)makeString($3));
 				}
 			| NULL_P opt_as Sconst
 				{
-					$$ = makeNode(DefElem);
-					$$->defname = "null";
-					$$->arg = (Node *)makeString($3);
+					$$ = makeDefElem("null", (Node *)makeString($3));
 				}
 		;
 
@@ -1336,9 +1328,7 @@ copy_opt_item:
 opt_binary:
 			BINARY
 				{
-					$$ = makeNode(DefElem);
-					$$->defname = "binary";
-					$$->arg = (Node *)makeInteger(TRUE);
+					$$ = makeDefElem("binary", (Node *)makeInteger(TRUE));
 				}
 			| /*EMPTY*/								{ $$ = NULL; }
 		;
@@ -1346,9 +1336,7 @@ opt_binary:
 opt_oids:
 			WITH OIDS
 				{
-					$$ = makeNode(DefElem);
-					$$->defname = "oids";
-					$$->arg = (Node *)makeInteger(TRUE);
+					$$ = makeDefElem("oids", (Node *)makeInteger(TRUE));
 				}
 			| /*EMPTY*/								{ $$ = NULL; }
 		;
@@ -1357,9 +1345,7 @@ copy_delimiter:
 			/* USING DELIMITERS kept for backward compatibility. 2002-06-15 */
 			opt_using DELIMITERS Sconst
 				{
-					$$ = makeNode(DefElem);
-					$$->defname = "delimiter";
-					$$->arg = (Node *)makeString($3);
+					$$ = makeDefElem("delimiter", (Node *)makeString($3));
 				}
 			| /*EMPTY*/								{ $$ = NULL; }
 		;
@@ -2276,7 +2262,7 @@ def_elem:  ColLabel '=' def_arg
 
 /* Note: any simple identifier will be returned as a type name! */
 def_arg:	func_return						{ $$ = (Node *)$1; }
-			| all_Op						{ $$ = (Node *)makeString($1); }
+			| qual_all_Op					{ $$ = (Node *)$1; }
 			| NumericOnly					{ $$ = (Node *)$1; }
 			| Sconst						{ $$ = (Node *)makeString($1); }
 		;
@@ -3568,27 +3554,19 @@ createdb_opt_list:
 createdb_opt_item:
 			LOCATION opt_equal Sconst
 				{
-					$$ = makeNode(DefElem);
-					$$->defname = "location";
-					$$->arg = (Node *)makeString($3);
+					$$ = makeDefElem("location", (Node *)makeString($3));
 				}
 			| LOCATION opt_equal DEFAULT
 				{
-					$$ = makeNode(DefElem);
-					$$->defname = "location";
-					$$->arg = NULL;
+					$$ = makeDefElem("location", NULL);
 				}
 			| TEMPLATE opt_equal name
 				{
-					$$ = makeNode(DefElem);
-					$$->defname = "template";
-					$$->arg = (Node *)makeString($3);
+					$$ = makeDefElem("template", (Node *)makeString($3));
 				}
 			| TEMPLATE opt_equal DEFAULT
 				{
-					$$ = makeNode(DefElem);
-					$$->defname = "template";
-					$$->arg = NULL;
+					$$ = makeDefElem("template", NULL);
 				}
 			| ENCODING opt_equal Sconst
 				{
@@ -3598,9 +3576,7 @@ createdb_opt_item:
 						elog(ERROR, "%s is not a valid encoding name", $3);
 					encoding = pg_char_to_encoding($3);
 
-					$$ = makeNode(DefElem);
-					$$->defname = "encoding";
-					$$->arg = (Node *)makeInteger(encoding);
+					$$ = makeDefElem("encoding", (Node *)makeInteger(encoding));
 				}
 			| ENCODING opt_equal Iconst
 				{
@@ -3610,27 +3586,19 @@ createdb_opt_item:
 					if (!strcmp(encoding_name,"") ||
 					    pg_valid_server_encoding(encoding_name) < 0)
 						elog(ERROR, "%d is not a valid encoding code", $3);
-					$$ = makeNode(DefElem);
-					$$->defname = "encoding";
-					$$->arg = (Node *)makeInteger($3);
+					$$ = makeDefElem("encoding", (Node *)makeInteger($3));
 				}
 			| ENCODING opt_equal DEFAULT
 				{
-					$$ = makeNode(DefElem);
-					$$->defname = "encoding";
-					$$->arg = (Node *)makeInteger(-1);
+					$$ = makeDefElem("encoding", (Node *)makeInteger(-1));
 				}
 			| OWNER opt_equal name
 				{
-					$$ = makeNode(DefElem);
-					$$->defname = "owner";
-					$$->arg = (Node *)makeString($3);
+					$$ = makeDefElem("owner", (Node *)makeString($3));
 				}
 			| OWNER opt_equal DEFAULT
 				{
-					$$ = makeNode(DefElem);
-					$$->defname = "owner";
-					$$->arg = NULL;
+					$$ = makeDefElem("owner", NULL);
 				}
 		;