diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c
index bce39f1166e53a6b9913b31d714d0416d7cee8bc..3d9ec2eb23af4ba0bfa7ba7a11d4643f4ce2426f 100644
--- a/src/backend/optimizer/path/indxpath.c
+++ b/src/backend/optimizer/path/indxpath.c
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.120 2002/07/13 19:20:34 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.121 2002/09/02 06:22:18 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -97,7 +97,7 @@ static bool function_index_operand(Expr *funcOpnd, RelOptInfo *rel,
 static bool match_special_index_operator(Expr *clause, Oid opclass,
 							 bool indexkey_on_left);
 static List *prefix_quals(Var *leftop, Oid expr_op,
-			 char *prefix, Pattern_Prefix_Status pstatus);
+			 Const *prefix, Pattern_Prefix_Status pstatus);
 static List *network_prefix_quals(Var *leftop, Oid expr_op, Datum rightop);
 static Oid	find_operator(const char *opname, Oid datatype);
 static Datum string_to_datum(const char *str, Oid datatype);
@@ -1675,10 +1675,9 @@ match_special_index_operator(Expr *clause, Oid opclass,
 	Var		   *leftop,
 			   *rightop;
 	Oid			expr_op;
-	Datum		constvalue;
-	char	   *patt;
-	char	   *prefix;
-	char	   *rest;
+	Const	   *patt = NULL;
+	Const	   *prefix = NULL;
+	Const	   *rest = NULL;
 
 	/*
 	 * Currently, all known special operators require the indexkey on the
@@ -1697,7 +1696,7 @@ match_special_index_operator(Expr *clause, Oid opclass,
 	if (!IsA(rightop, Const) ||
 		((Const *) rightop)->constisnull)
 		return false;
-	constvalue = ((Const *) rightop)->constvalue;
+	patt = (Const *) rightop;
 
 	switch (expr_op)
 	{
@@ -1705,68 +1704,45 @@ match_special_index_operator(Expr *clause, Oid opclass,
 		case OID_BPCHAR_LIKE_OP:
 		case OID_VARCHAR_LIKE_OP:
 		case OID_NAME_LIKE_OP:
+			/* the right-hand const is type text for all of these */
 			if (locale_is_like_safe())
-			{
-				/* the right-hand const is type text for all of these */
-				patt = DatumGetCString(DirectFunctionCall1(textout,
-														   constvalue));
 				isIndexable = pattern_fixed_prefix(patt, Pattern_Type_Like,
 								  &prefix, &rest) != Pattern_Prefix_None;
-				if (prefix)
-					pfree(prefix);
-				pfree(patt);
-			}
+			break;
+
+		case OID_BYTEA_LIKE_OP:
+			isIndexable = pattern_fixed_prefix(patt, Pattern_Type_Like,
+							  &prefix, &rest) != Pattern_Prefix_None;
 			break;
 
 		case OID_TEXT_ICLIKE_OP:
 		case OID_BPCHAR_ICLIKE_OP:
 		case OID_VARCHAR_ICLIKE_OP:
 		case OID_NAME_ICLIKE_OP:
+			/* the right-hand const is type text for all of these */
 			if (locale_is_like_safe())
-			{
-				/* the right-hand const is type text for all of these */
-				patt = DatumGetCString(DirectFunctionCall1(textout,
-														   constvalue));
 				isIndexable = pattern_fixed_prefix(patt, Pattern_Type_Like_IC,
 								  &prefix, &rest) != Pattern_Prefix_None;
-				if (prefix)
-					pfree(prefix);
-				pfree(patt);
-			}
 			break;
 
 		case OID_TEXT_REGEXEQ_OP:
 		case OID_BPCHAR_REGEXEQ_OP:
 		case OID_VARCHAR_REGEXEQ_OP:
 		case OID_NAME_REGEXEQ_OP:
+			/* the right-hand const is type text for all of these */
 			if (locale_is_like_safe())
-			{
-				/* the right-hand const is type text for all of these */
-				patt = DatumGetCString(DirectFunctionCall1(textout,
-														   constvalue));
 				isIndexable = pattern_fixed_prefix(patt, Pattern_Type_Regex,
 								  &prefix, &rest) != Pattern_Prefix_None;
-				if (prefix)
-					pfree(prefix);
-				pfree(patt);
-			}
 			break;
 
 		case OID_TEXT_ICREGEXEQ_OP:
 		case OID_BPCHAR_ICREGEXEQ_OP:
 		case OID_VARCHAR_ICREGEXEQ_OP:
 		case OID_NAME_ICREGEXEQ_OP:
+			/* the right-hand const is type text for all of these */
 			if (locale_is_like_safe())
-			{
-				/* the right-hand const is type text for all of these */
-				patt = DatumGetCString(DirectFunctionCall1(textout,
-														   constvalue));
 				isIndexable = pattern_fixed_prefix(patt, Pattern_Type_Regex_IC,
 								  &prefix, &rest) != Pattern_Prefix_None;
-				if (prefix)
-					pfree(prefix);
-				pfree(patt);
-			}
 			break;
 
 		case OID_INET_SUB_OP:
@@ -1777,6 +1753,12 @@ match_special_index_operator(Expr *clause, Oid opclass,
 			break;
 	}
 
+	if (prefix)
+	{
+		pfree(DatumGetPointer(prefix->constvalue));
+		pfree(prefix);
+	}
+
 	/* done if the expression doesn't look indexable */
 	if (!isIndexable)
 		return false;
@@ -1798,6 +1780,12 @@ match_special_index_operator(Expr *clause, Oid opclass,
 				isIndexable = false;
 			break;
 
+		case OID_BYTEA_LIKE_OP:
+			if (!op_in_opclass(find_operator(">=", BYTEAOID), opclass) ||
+				!op_in_opclass(find_operator("<", BYTEAOID), opclass))
+				isIndexable = false;
+			break;
+
 		case OID_BPCHAR_LIKE_OP:
 		case OID_BPCHAR_ICLIKE_OP:
 		case OID_BPCHAR_REGEXEQ_OP:
@@ -1867,10 +1855,9 @@ expand_indexqual_conditions(List *indexquals)
 		Var		   *leftop = get_leftop(clause);
 		Var		   *rightop = get_rightop(clause);
 		Oid			expr_op = ((Oper *) clause->oper)->opno;
-		Datum		constvalue;
-		char	   *patt;
-		char	   *prefix;
-		char	   *rest;
+		Const	   *patt = (Const *) rightop;
+		Const	   *prefix = NULL;
+		Const	   *rest = NULL;
 		Pattern_Prefix_Status pstatus;
 
 		switch (expr_op)
@@ -1885,18 +1872,12 @@ expand_indexqual_conditions(List *indexquals)
 			case OID_BPCHAR_LIKE_OP:
 			case OID_VARCHAR_LIKE_OP:
 			case OID_NAME_LIKE_OP:
-				/* the right-hand const is type text for all of these */
-				constvalue = ((Const *) rightop)->constvalue;
-				patt = DatumGetCString(DirectFunctionCall1(textout,
-														   constvalue));
+			case OID_BYTEA_LIKE_OP:
 				pstatus = pattern_fixed_prefix(patt, Pattern_Type_Like,
 											   &prefix, &rest);
 				resultquals = nconc(resultquals,
 									prefix_quals(leftop, expr_op,
 												 prefix, pstatus));
-				if (prefix)
-					pfree(prefix);
-				pfree(patt);
 				break;
 
 			case OID_TEXT_ICLIKE_OP:
@@ -1904,17 +1885,11 @@ expand_indexqual_conditions(List *indexquals)
 			case OID_VARCHAR_ICLIKE_OP:
 			case OID_NAME_ICLIKE_OP:
 				/* the right-hand const is type text for all of these */
-				constvalue = ((Const *) rightop)->constvalue;
-				patt = DatumGetCString(DirectFunctionCall1(textout,
-														   constvalue));
 				pstatus = pattern_fixed_prefix(patt, Pattern_Type_Like_IC,
 											   &prefix, &rest);
 				resultquals = nconc(resultquals,
 									prefix_quals(leftop, expr_op,
 												 prefix, pstatus));
-				if (prefix)
-					pfree(prefix);
-				pfree(patt);
 				break;
 
 			case OID_TEXT_REGEXEQ_OP:
@@ -1922,17 +1897,11 @@ expand_indexqual_conditions(List *indexquals)
 			case OID_VARCHAR_REGEXEQ_OP:
 			case OID_NAME_REGEXEQ_OP:
 				/* the right-hand const is type text for all of these */
-				constvalue = ((Const *) rightop)->constvalue;
-				patt = DatumGetCString(DirectFunctionCall1(textout,
-														   constvalue));
 				pstatus = pattern_fixed_prefix(patt, Pattern_Type_Regex,
 											   &prefix, &rest);
 				resultquals = nconc(resultquals,
 									prefix_quals(leftop, expr_op,
 												 prefix, pstatus));
-				if (prefix)
-					pfree(prefix);
-				pfree(patt);
 				break;
 
 			case OID_TEXT_ICREGEXEQ_OP:
@@ -1940,27 +1909,20 @@ expand_indexqual_conditions(List *indexquals)
 			case OID_VARCHAR_ICREGEXEQ_OP:
 			case OID_NAME_ICREGEXEQ_OP:
 				/* the right-hand const is type text for all of these */
-				constvalue = ((Const *) rightop)->constvalue;
-				patt = DatumGetCString(DirectFunctionCall1(textout,
-														   constvalue));
 				pstatus = pattern_fixed_prefix(patt, Pattern_Type_Regex_IC,
 											   &prefix, &rest);
 				resultquals = nconc(resultquals,
 									prefix_quals(leftop, expr_op,
 												 prefix, pstatus));
-				if (prefix)
-					pfree(prefix);
-				pfree(patt);
 				break;
 
 			case OID_INET_SUB_OP:
 			case OID_INET_SUBEQ_OP:
 			case OID_CIDR_SUB_OP:
 			case OID_CIDR_SUBEQ_OP:
-				constvalue = ((Const *) rightop)->constvalue;
 				resultquals = nconc(resultquals,
 									network_prefix_quals(leftop, expr_op,
-														 constvalue));
+														 patt->constvalue));
 				break;
 
 			default:
@@ -1980,15 +1942,16 @@ expand_indexqual_conditions(List *indexquals)
  */
 static List *
 prefix_quals(Var *leftop, Oid expr_op,
-			 char *prefix, Pattern_Prefix_Status pstatus)
+			 Const *prefix_const, Pattern_Prefix_Status pstatus)
 {
 	List	   *result;
 	Oid			datatype;
 	Oid			oproid;
+	char	   *prefix;
 	Const	   *con;
 	Oper	   *op;
 	Expr	   *expr;
-	char	   *greaterstr;
+	Const	   *greaterstr = NULL;
 
 	Assert(pstatus != Pattern_Prefix_None);
 
@@ -2001,6 +1964,10 @@ prefix_quals(Var *leftop, Oid expr_op,
 			datatype = TEXTOID;
 			break;
 
+		case OID_BYTEA_LIKE_OP:
+			datatype = BYTEAOID;
+			break;
+
 		case OID_BPCHAR_LIKE_OP:
 		case OID_BPCHAR_ICLIKE_OP:
 		case OID_BPCHAR_REGEXEQ_OP:
@@ -2027,6 +1994,11 @@ prefix_quals(Var *leftop, Oid expr_op,
 			return NIL;
 	}
 
+	if (prefix_const->consttype != BYTEAOID)
+		prefix = DatumGetCString(DirectFunctionCall1(textout, prefix_const->constvalue));
+	else
+		prefix = DatumGetCString(DirectFunctionCall1(byteaout, prefix_const->constvalue));
+
 	/*
 	 * If we found an exact-match pattern, generate an "=" indexqual.
 	 */
@@ -2060,17 +2032,15 @@ prefix_quals(Var *leftop, Oid expr_op,
 	 * "x < greaterstr".
 	 *-------
 	 */
-	greaterstr = make_greater_string(prefix, datatype);
+	greaterstr = make_greater_string(con);
 	if (greaterstr)
 	{
 		oproid = find_operator("<", datatype);
 		if (oproid == InvalidOid)
 			elog(ERROR, "prefix_quals: no < operator for type %u", datatype);
-		con = string_to_const(greaterstr, datatype);
 		op = makeOper(oproid, InvalidOid, BOOLOID, false);
-		expr = make_opclause(op, leftop, (Var *) con);
+		expr = make_opclause(op, leftop, (Var *) greaterstr);
 		result = lappend(result, expr);
-		pfree(greaterstr);
 	}
 
 	return result;
@@ -2186,6 +2156,8 @@ string_to_datum(const char *str, Oid datatype)
 	 */
 	if (datatype == NAMEOID)
 		return DirectFunctionCall1(namein, CStringGetDatum(str));
+	else if (datatype == BYTEAOID)
+		return DirectFunctionCall1(byteain, CStringGetDatum(str));
 	else
 		return DirectFunctionCall1(textin, CStringGetDatum(str));
 }
diff --git a/src/backend/utils/adt/like.c b/src/backend/utils/adt/like.c
index 3e67e947a9d7ef900442c20929eb13d8c0a2c928..fab47e37fa25900829dd258707a5fb4717c0d79a 100644
--- a/src/backend/utils/adt/like.c
+++ b/src/backend/utils/adt/like.c
@@ -11,7 +11,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	$Header: /cvsroot/pgsql/src/backend/utils/adt/like.c,v 1.51 2002/08/29 07:22:26 ishii Exp $
+ *	$Header: /cvsroot/pgsql/src/backend/utils/adt/like.c,v 1.52 2002/09/02 06:22:19 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -242,7 +242,7 @@ Datum
 bytealike(PG_FUNCTION_ARGS)
 {
 	bytea	   *str = PG_GETARG_BYTEA_P(0);
-	text	   *pat = PG_GETARG_TEXT_P(1);
+	bytea	   *pat = PG_GETARG_BYTEA_P(1);
 	bool		result;
 	unsigned char *s,
 			   *p;
@@ -263,7 +263,7 @@ Datum
 byteanlike(PG_FUNCTION_ARGS)
 {
 	bytea	   *str = PG_GETARG_BYTEA_P(0);
-	text	   *pat = PG_GETARG_TEXT_P(1);
+	bytea	   *pat = PG_GETARG_BYTEA_P(1);
 	bool		result;
 	unsigned char *s,
 			   *p;
diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c
index 4835b0c3a5e339a7aecfe2d9dcb44113711b6a2e..dc0b520b925a02205acaff9929840e063dd2bf30 100644
--- a/src/backend/utils/adt/selfuncs.c
+++ b/src/backend/utils/adt/selfuncs.c
@@ -15,7 +15,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v 1.114 2002/08/29 07:22:27 ishii Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v 1.115 2002/09/02 06:22:19 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -73,6 +73,7 @@
 #include <locale.h>
 
 #include "access/heapam.h"
+#include "access/tuptoaster.h"
 #include "catalog/catname.h"
 #include "catalog/pg_namespace.h"
 #include "catalog/pg_operator.h"
@@ -168,8 +169,8 @@ static bool get_restriction_var(List *args, int varRelid,
 					Var **var, Node **other,
 					bool *varonleft);
 static void get_join_vars(List *args, Var **var1, Var **var2);
-static Selectivity prefix_selectivity(Query *root, Var *var, char *prefix);
-static Selectivity pattern_selectivity(char *patt, Pattern_Type ptype);
+static Selectivity prefix_selectivity(Query *root, Var *var, Const *prefix);
+static Selectivity pattern_selectivity(Const *patt, Pattern_Type ptype);
 static bool string_lessthan(const char *str1, const char *str2,
 				Oid datatype);
 static Oid	find_operator(const char *opname, Oid datatype);
@@ -826,10 +827,10 @@ patternsel(PG_FUNCTION_ARGS, Pattern_Type ptype)
 	bool		varonleft;
 	Oid			relid;
 	Datum		constval;
-	char	   *patt;
 	Pattern_Prefix_Status pstatus;
-	char	   *prefix;
-	char	   *rest;
+	Const	   *patt = NULL;
+	Const	   *prefix = NULL;
+	Const	   *rest = NULL;
 	double		result;
 
 	/*
@@ -853,11 +854,13 @@ patternsel(PG_FUNCTION_ARGS, Pattern_Type ptype)
 	if (((Const *) other)->constisnull)
 		return 0.0;
 	constval = ((Const *) other)->constvalue;
-	/* the right-hand const is type text for all supported operators */
-	Assert(((Const *) other)->consttype == TEXTOID);
-	patt = DatumGetCString(DirectFunctionCall1(textout, constval));
+
+	/* the right-hand const is type text or bytea for all supported operators */
+	Assert(((Const *) other)->consttype == TEXTOID ||
+				((Const *) other)->consttype == BYTEAOID);
 
 	/* divide pattern into fixed prefix and remainder */
+	patt = (Const *) other;
 	pstatus = pattern_fixed_prefix(patt, ptype, &prefix, &rest);
 
 	if (pstatus == Pattern_Prefix_Exact)
@@ -866,14 +869,12 @@ patternsel(PG_FUNCTION_ARGS, Pattern_Type ptype)
 		 * Pattern specifies an exact match, so pretend operator is '='
 		 */
 		Oid			eqopr = find_operator("=", var->vartype);
-		Const	   *eqcon;
 		List	   *eqargs;
 
 		if (eqopr == InvalidOid)
 			elog(ERROR, "patternsel: no = operator for type %u",
 				 var->vartype);
-		eqcon = string_to_const(prefix, var->vartype);
-		eqargs = makeList2(var, eqcon);
+		eqargs = makeList2(var, prefix);
 		result = DatumGetFloat8(DirectFunctionCall4(eqsel,
 													PointerGetDatum(root),
 												 ObjectIdGetDatum(eqopr),
@@ -903,8 +904,10 @@ patternsel(PG_FUNCTION_ARGS, Pattern_Type ptype)
 	}
 
 	if (prefix)
+	{
+		pfree(DatumGetPointer(prefix->constvalue));
 		pfree(prefix);
-	pfree(patt);
+	}
 
 	return result;
 }
@@ -2693,17 +2696,39 @@ get_join_vars(List *args, Var **var1, Var **var2)
  */
 
 static Pattern_Prefix_Status
-like_fixed_prefix(char *patt, bool case_insensitive,
-				  char **prefix, char **rest)
+like_fixed_prefix(Const *patt_const, bool case_insensitive,
+				  Const **prefix_const, Const **rest_const)
 {
 	char	   *match;
+	char	   *patt;
+	int			pattlen;
+	char	   *prefix;
+	char	   *rest;
+	Oid			typeid = patt_const->consttype;
 	int			pos,
 				match_pos;
 
-	*prefix = match = palloc(strlen(patt) + 1);
+	/* the right-hand const is type text or bytea */
+	Assert(typeid == BYTEAOID || typeid == TEXTOID);
+
+	if (typeid == BYTEAOID && case_insensitive)
+		elog(ERROR, "Cannot perform case insensitive matching on type BYTEA");
+
+	if (typeid != BYTEAOID)
+	{
+		patt = DatumGetCString(DirectFunctionCall1(textout, patt_const->constvalue));
+		pattlen = strlen(patt);
+	}
+	else
+	{
+		patt = DatumGetCString(DirectFunctionCall1(byteaout, patt_const->constvalue));
+		pattlen = toast_raw_datum_size(patt_const->constvalue) - VARHDRSZ;
+	}
+	
+	prefix = match = palloc(pattlen + 1);
 	match_pos = 0;
 
-	for (pos = 0; patt[pos]; pos++)
+	for (pos = 0; pos < pattlen; pos++)
 	{
 		/* % and _ are wildcard characters in LIKE */
 		if (patt[pos] == '%' ||
@@ -2713,7 +2738,7 @@ like_fixed_prefix(char *patt, bool case_insensitive,
 		if (patt[pos] == '\\')
 		{
 			pos++;
-			if (patt[pos] == '\0')
+			if (patt[pos] == '\0' && typeid != BYTEAOID)
 				break;
 		}
 
@@ -2733,35 +2758,58 @@ like_fixed_prefix(char *patt, bool case_insensitive,
 	}
 
 	match[match_pos] = '\0';
-	*rest = &patt[pos];
+	rest = &patt[pos];
+
+   *prefix_const = string_to_const(prefix, typeid);
+   *rest_const = string_to_const(rest, typeid);
+
+	pfree(patt);
+	pfree(match);
+	prefix = NULL;
 
 	/* in LIKE, an empty pattern is an exact match! */
-	if (patt[pos] == '\0')
+	if (pos == pattlen)
 		return Pattern_Prefix_Exact;	/* reached end of pattern, so
 										 * exact */
 
 	if (match_pos > 0)
 		return Pattern_Prefix_Partial;
 
-	pfree(match);
-	*prefix = NULL;
 	return Pattern_Prefix_None;
 }
 
 static Pattern_Prefix_Status
-regex_fixed_prefix(char *patt, bool case_insensitive,
-				   char **prefix, char **rest)
+regex_fixed_prefix(Const *patt_const, bool case_insensitive,
+				   Const **prefix_const, Const **rest_const)
 {
 	char	   *match;
 	int			pos,
 				match_pos,
 				paren_depth;
+	char	   *patt;
+	char	   *prefix;
+	char	   *rest;
+	Oid			typeid = patt_const->consttype;
+
+	/*
+	 * Should be unnecessary, there are no bytea regex operators defined.
+	 * As such, it should be noted that the rest of this function has *not*
+	 * been made safe for binary (possibly NULL containing) strings.
+	 */
+	if (typeid == BYTEAOID)
+		elog(ERROR, "Regex matching not supported on type BYTEA");
+
+	/* the right-hand const is type text for all of these */
+	patt = DatumGetCString(DirectFunctionCall1(textout, patt_const->constvalue));
 
 	/* Pattern must be anchored left */
 	if (patt[0] != '^')
 	{
-		*prefix = NULL;
-		*rest = patt;
+		rest = patt;
+
+	   *prefix_const = NULL;
+	   *rest_const = string_to_const(rest, typeid);
+
 		return Pattern_Prefix_None;
 	}
 
@@ -2774,8 +2822,11 @@ regex_fixed_prefix(char *patt, bool case_insensitive,
 	{
 		if (patt[pos] == '|' && paren_depth == 0)
 		{
-			*prefix = NULL;
-			*rest = patt;
+			rest = patt;
+
+		   *prefix_const = NULL;
+		   *rest_const = string_to_const(rest, typeid);
+
 			return Pattern_Prefix_None;
 		}
 		else if (patt[pos] == '(')
@@ -2792,7 +2843,7 @@ regex_fixed_prefix(char *patt, bool case_insensitive,
 	}
 
 	/* OK, allocate space for pattern */
-	*prefix = match = palloc(strlen(patt) + 1);
+	prefix = match = palloc(strlen(patt) + 1);
 	match_pos = 0;
 
 	/* note start at pos 1 to skip leading ^ */
@@ -2841,25 +2892,34 @@ regex_fixed_prefix(char *patt, bool case_insensitive,
 	}
 
 	match[match_pos] = '\0';
-	*rest = &patt[pos];
+	rest = &patt[pos];
 
 	if (patt[pos] == '$' && patt[pos + 1] == '\0')
 	{
-		*rest = &patt[pos + 1];
+		rest = &patt[pos + 1];
+
+	   *prefix_const = string_to_const(prefix, typeid);
+	   *rest_const = string_to_const(rest, typeid);
+
 		return Pattern_Prefix_Exact;	/* pattern specifies exact match */
 	}
 
+   *prefix_const = string_to_const(prefix, typeid);
+   *rest_const = string_to_const(rest, typeid);
+
+	pfree(patt);
+	pfree(match);
+	prefix = NULL;
+
 	if (match_pos > 0)
 		return Pattern_Prefix_Partial;
 
-	pfree(match);
-	*prefix = NULL;
 	return Pattern_Prefix_None;
 }
 
 Pattern_Prefix_Status
-pattern_fixed_prefix(char *patt, Pattern_Type ptype,
-					 char **prefix, char **rest)
+pattern_fixed_prefix(Const *patt, Pattern_Type ptype,
+					 Const **prefix, Const **rest)
 {
 	Pattern_Prefix_Status result;
 
@@ -2897,19 +2957,23 @@ pattern_fixed_prefix(char *patt, Pattern_Type ptype,
  * more useful to use the upper-bound code than not.
  */
 static Selectivity
-prefix_selectivity(Query *root, Var *var, char *prefix)
+prefix_selectivity(Query *root, Var *var, Const *prefixcon)
 {
 	Selectivity prefixsel;
 	Oid			cmpopr;
-	Const	   *prefixcon;
+	char	   *prefix;
 	List	   *cmpargs;
-	char	   *greaterstr;
+	Const	   *greaterstrcon;
 
 	cmpopr = find_operator(">=", var->vartype);
 	if (cmpopr == InvalidOid)
 		elog(ERROR, "prefix_selectivity: no >= operator for type %u",
 			 var->vartype);
-	prefixcon = string_to_const(prefix, var->vartype);
+	if (prefixcon->consttype != BYTEAOID)
+		prefix = DatumGetCString(DirectFunctionCall1(textout, prefixcon->constvalue));
+	else
+		prefix = DatumGetCString(DirectFunctionCall1(byteaout, prefixcon->constvalue));
+
 	cmpargs = makeList2(var, prefixcon);
 	/* Assume scalargtsel is appropriate for all supported types */
 	prefixsel = DatumGetFloat8(DirectFunctionCall4(scalargtsel,
@@ -2923,8 +2987,8 @@ prefix_selectivity(Query *root, Var *var, char *prefix)
 	 *	"x < greaterstr".
 	 *-------
 	 */
-	greaterstr = make_greater_string(prefix, var->vartype);
-	if (greaterstr)
+	greaterstrcon = make_greater_string(prefixcon);
+	if (greaterstrcon)
 	{
 		Selectivity topsel;
 
@@ -2932,8 +2996,7 @@ prefix_selectivity(Query *root, Var *var, char *prefix)
 		if (cmpopr == InvalidOid)
 			elog(ERROR, "prefix_selectivity: no < operator for type %u",
 				 var->vartype);
-		prefixcon = string_to_const(greaterstr, var->vartype);
-		cmpargs = makeList2(var, prefixcon);
+		cmpargs = makeList2(var, greaterstrcon);
 		/* Assume scalarltsel is appropriate for all supported types */
 		topsel = DatumGetFloat8(DirectFunctionCall4(scalarltsel,
 													PointerGetDatum(root),
@@ -2997,14 +3060,35 @@ prefix_selectivity(Query *root, Var *var, char *prefix)
 #define PARTIAL_WILDCARD_SEL 2.0
 
 static Selectivity
-like_selectivity(char *patt, bool case_insensitive)
+like_selectivity(Const *patt_const, bool case_insensitive)
 {
 	Selectivity sel = 1.0;
 	int			pos;
+	int			start;
+	Oid			typeid = patt_const->consttype;
+	char	   *patt;
+	int			pattlen;
+
+	/* the right-hand const is type text or bytea */
+	Assert(typeid == BYTEAOID || typeid == TEXTOID);
+
+	if (typeid == BYTEAOID && case_insensitive)
+		elog(ERROR, "Cannot perform case insensitive matching on type BYTEA");
+
+	if (typeid != BYTEAOID)
+	{
+		patt = DatumGetCString(DirectFunctionCall1(textout, patt_const->constvalue));
+		pattlen = strlen(patt);
+	}
+	else
+	{
+		patt = DatumGetCString(DirectFunctionCall1(byteaout, patt_const->constvalue));
+		pattlen = toast_raw_datum_size(patt_const->constvalue) - VARHDRSZ;
+	}
 
 	/* Skip any leading %; it's already factored into initial sel */
-	pos = (*patt == '%') ? 1 : 0;
-	for (; patt[pos]; pos++)
+	start = (*patt == '%') ? 1 : 0;
+	for (pos = start; pos < pattlen; pos++)
 	{
 		/* % and _ are wildcard characters in LIKE */
 		if (patt[pos] == '%')
@@ -3015,7 +3099,7 @@ like_selectivity(char *patt, bool case_insensitive)
 		{
 			/* Backslash quotes the next character */
 			pos++;
-			if (patt[pos] == '\0')
+			if (patt[pos] == '\0' && typeid != BYTEAOID)
 				break;
 			sel *= FIXED_CHAR_SEL;
 		}
@@ -3122,10 +3206,24 @@ regex_selectivity_sub(char *patt, int pattlen, bool case_insensitive)
 }
 
 static Selectivity
-regex_selectivity(char *patt, bool case_insensitive)
+regex_selectivity(Const *patt_const, bool case_insensitive)
 {
 	Selectivity sel;
-	int			pattlen = strlen(patt);
+	char	   *patt;
+	int			pattlen;
+	Oid			typeid = patt_const->consttype;
+
+	/*
+	 * Should be unnecessary, there are no bytea regex operators defined.
+	 * As such, it should be noted that the rest of this function has *not*
+	 * been made safe for binary (possibly NULL containing) strings.
+	 */
+	if (typeid == BYTEAOID)
+		elog(ERROR, "Regex matching not supported on type BYTEA");
+
+	/* the right-hand const is type text for all of these */
+	patt = DatumGetCString(DirectFunctionCall1(textout, patt_const->constvalue));
+	pattlen = strlen(patt);
 
 	/* If patt doesn't end with $, consider it to have a trailing wildcard */
 	if (pattlen > 0 && patt[pattlen - 1] == '$' &&
@@ -3146,7 +3244,7 @@ regex_selectivity(char *patt, bool case_insensitive)
 }
 
 static Selectivity
-pattern_selectivity(char *patt, Pattern_Type ptype)
+pattern_selectivity(Const *patt, Pattern_Type ptype)
 {
 	Selectivity result;
 
@@ -3220,19 +3318,33 @@ locale_is_like_safe(void)
  * sort passes, etc.  For now, we just shut down the whole thing in locales
  * that do such things :-(
  */
-char *
-make_greater_string(const char *str, Oid datatype)
+Const *
+make_greater_string(const Const *str_const)
 {
+	Oid			datatype = str_const->consttype;
+	char	   *str;
 	char	   *workstr;
 	int			len;
 
-	/*
-	 * Make a modifiable copy, which will be our return value if
-	 * successful
-	 */
-	workstr = pstrdup((char *) str);
+	/* Get the string and a modifiable copy */
+	if (datatype == NAMEOID)
+	{
+		str = DatumGetCString(DirectFunctionCall1(nameout, str_const->constvalue));
+		len = strlen(str);
+	}
+	else if (datatype == BYTEAOID)
+	{
+		str = DatumGetCString(DirectFunctionCall1(byteaout, str_const->constvalue));
+		len = toast_raw_datum_size(str_const->constvalue) - VARHDRSZ;
+	}
+	else
+	{
+		str = DatumGetCString(DirectFunctionCall1(textout, str_const->constvalue));
+		len = strlen(str);
+	}
+	workstr = pstrdup(str);
 
-	while ((len = strlen(workstr)) > 0)
+	while (len > 0)
 	{
 		unsigned char *lastchar = (unsigned char *) (workstr + len - 1);
 
@@ -3243,20 +3355,34 @@ make_greater_string(const char *str, Oid datatype)
 		{
 			(*lastchar)++;
 			if (string_lessthan(str, workstr, datatype))
-				return workstr; /* Success! */
+			{
+				 /* Success! */
+				Const *workstr_const = string_to_const(workstr, datatype);
+
+				pfree(str);
+				pfree(workstr);
+				return workstr_const;
+			}
 		}
 
 		/*
 		 * Truncate off the last character, which might be more than 1
 		 * byte in MULTIBYTE case.
 		 */
-		len = pg_mbcliplen((const unsigned char *) workstr, len, len - 1);
-		workstr[len] = '\0';
+		if (datatype != BYTEAOID && pg_database_encoding_max_length() > 1)
+			len = pg_mbcliplen((const unsigned char *) workstr, len, len - 1);
+		else
+			len -= - 1;
+
+		if (datatype != BYTEAOID)
+			workstr[len] = '\0';
 	}
 
 	/* Failed... */
+	pfree(str);
 	pfree(workstr);
-	return NULL;
+
+	return (Const *) NULL;
 }
 
 /*
@@ -3330,12 +3456,16 @@ find_operator(const char *opname, Oid datatype)
 static Datum
 string_to_datum(const char *str, Oid datatype)
 {
+	Assert(str != NULL);
+
 	/*
 	 * We cheat a little by assuming that textin() will do for bpchar and
 	 * varchar constants too...
 	 */
 	if (datatype == NAMEOID)
 		return DirectFunctionCall1(namein, CStringGetDatum(str));
+	else if (datatype == BYTEAOID)
+		return DirectFunctionCall1(byteain, CStringGetDatum(str));
 	else
 		return DirectFunctionCall1(textin, CStringGetDatum(str));
 }
diff --git a/src/include/catalog/pg_operator.h b/src/include/catalog/pg_operator.h
index ed71bae3bbed0b59b15eb862653e620de113e36f..ccf32bb2eadc58c3aa6cc457d638e16d6a73d9be 100644
--- a/src/include/catalog/pg_operator.h
+++ b/src/include/catalog/pg_operator.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: pg_operator.h,v 1.107 2002/08/22 04:45:11 momjian Exp $
+ * $Id: pg_operator.h,v 1.108 2002/09/02 06:22:19 momjian Exp $
  *
  * NOTES
  *	  the genbki.sh script reads this file and generates .bki
@@ -827,9 +827,9 @@ DATA(insert OID = 1957 ( "<"	   PGNSP PGUID b f 17 17	16 1959 1960 0	  0   0   0
 DATA(insert OID = 1958 ( "<="	   PGNSP PGUID b f 17 17	16 1960 1959 0	  0   0   0 byteale scalarltsel scalarltjoinsel ));
 DATA(insert OID = 1959 ( ">"	   PGNSP PGUID b f 17 17	16 1957 1958 0	  0   0   0 byteagt scalargtsel scalargtjoinsel ));
 DATA(insert OID = 1960 ( ">="	   PGNSP PGUID b f 17 17	16 1958 1957 0	  0   0   0 byteage scalargtsel scalargtjoinsel ));
-DATA(insert OID = 2016 (  "~~"	   PGNSP PGUID b f 17 25	16 0	2017 0	  0   0   0 bytealike likesel likejoinsel ));
+DATA(insert OID = 2016 (  "~~"	   PGNSP PGUID b f 17 17	16 0	2017 0	  0   0   0 bytealike likesel likejoinsel ));
 #define OID_BYTEA_LIKE_OP		2016
-DATA(insert OID = 2017 (  "!~~"    PGNSP PGUID b f 17 25	16 0	2016 0	  0   0   0 byteanlike nlikesel nlikejoinsel ));
+DATA(insert OID = 2017 (  "!~~"    PGNSP PGUID b f 17 17	16 0	2016 0	  0   0   0 byteanlike nlikesel nlikejoinsel ));
 DATA(insert OID = 2018 (  "||"	   PGNSP PGUID b f 17 17	17 0	0	 0	  0   0   0 byteacat - - ));
 
 /* timestamp operators */
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index e0b7c2beeea9e1b1619c996624873b4ca27bdd98..0106132f59fe420ee32619684b7388292cfb37d8 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.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: pg_proc.h,v 1.267 2002/09/01 00:58:06 tgl Exp $
+ * $Id: pg_proc.h,v 1.268 2002/09/02 06:22:19 momjian Exp $
  *
  * NOTES
  *	  The script catalog/genbki.sh reads this file and generates .bki
@@ -2770,13 +2770,13 @@ DESCR("adjust time precision");
 DATA(insert OID = 1969 (  timetz		   PGNSP PGUID 12 f f t f i 2 1266 "1266 23"	timetz_scale - _null_ ));
 DESCR("adjust time with time zone precision");
 
-DATA(insert OID = 2005 (  bytealike		   PGNSP PGUID 12 f f t f i 2 16 "17 25" bytealike - _null_ ));
+DATA(insert OID = 2005 (  bytealike		   PGNSP PGUID 12 f f t f i 2 16 "17 17" bytealike - _null_ ));
 DESCR("matches LIKE expression");
-DATA(insert OID = 2006 (  byteanlike	   PGNSP PGUID 12 f f t f i 2 16 "17 25" byteanlike - _null_ ));
+DATA(insert OID = 2006 (  byteanlike	   PGNSP PGUID 12 f f t f i 2 16 "17 17" byteanlike - _null_ ));
 DESCR("does not match LIKE expression");
-DATA(insert OID = 2007 (  like			   PGNSP PGUID 12 f f t f i 2 16 "17 25"	bytealike - _null_ ));
+DATA(insert OID = 2007 (  like			   PGNSP PGUID 12 f f t f i 2 16 "17 17"	bytealike - _null_ ));
 DESCR("matches LIKE expression");
-DATA(insert OID = 2008 (  notlike		   PGNSP PGUID 12 f f t f i 2 16 "17 25"	byteanlike - _null_ ));
+DATA(insert OID = 2008 (  notlike		   PGNSP PGUID 12 f f t f i 2 16 "17 17"	byteanlike - _null_ ));
 DESCR("does not match LIKE expression");
 DATA(insert OID = 2009 (  like_escape	   PGNSP PGUID 12 f f t f i 2 17 "17 17" like_escape_bytea - _null_ ));
 DESCR("convert match pattern to use backslash escapes");
diff --git a/src/include/utils/selfuncs.h b/src/include/utils/selfuncs.h
index 18047f5dbf9a2ca7b35108754c9b38c86e2a3556..b85500dfde7ac33823f743ced77b4b132ce68cb8 100644
--- a/src/include/utils/selfuncs.h
+++ b/src/include/utils/selfuncs.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: selfuncs.h,v 1.6 2002/06/20 20:29:53 momjian Exp $
+ * $Id: selfuncs.h,v 1.7 2002/09/02 06:22:20 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -33,12 +33,12 @@ typedef enum
 
 /* selfuncs.c */
 
-extern Pattern_Prefix_Status pattern_fixed_prefix(char *patt,
+extern Pattern_Prefix_Status pattern_fixed_prefix(Const *patt,
 					 Pattern_Type ptype,
-					 char **prefix,
-					 char **rest);
+					 Const **prefix,
+					 Const **rest);
 extern bool locale_is_like_safe(void);
-extern char *make_greater_string(const char *str, Oid datatype);
+extern Const *make_greater_string(const Const *str_const);
 
 extern Datum eqsel(PG_FUNCTION_ARGS);
 extern Datum neqsel(PG_FUNCTION_ARGS);