From 77ccd9c8d455a365b2ad6eb779ed76da0d431e3f Mon Sep 17 00:00:00 2001
From: Kyotaro Horiguchi <horiguchi.kyotaro@lab.ntt.co.jp>
Date: Thu, 16 Jul 2015 13:56:58 +0900
Subject: [PATCH 2/2] PoC: Planner part refactoring of mv stats facility

---
 src/backend/catalog/pg_operator.c      |    6 +
 src/backend/nodes/nodeFuncs.c          |    2 +-
 src/backend/optimizer/path/clausesel.c | 4107 +++++++-------------------------
 src/backend/utils/cache/lsyscache.c    |   40 +
 src/include/catalog/pg_operator.h      | 1550 ++++++------
 src/include/nodes/nodes.h              |    1 +
 src/include/nodes/relation.h           |   22 +-
 src/include/optimizer/cost.h           |    6 +-
 src/include/utils/lsyscache.h          |    1 +
 src/include/utils/mvstats.h            |    3 +
 10 files changed, 1668 insertions(+), 4070 deletions(-)

diff --git a/src/backend/catalog/pg_operator.c b/src/backend/catalog/pg_operator.c
index 072f530..dea39d3 100644
--- a/src/backend/catalog/pg_operator.c
+++ b/src/backend/catalog/pg_operator.c
@@ -251,6 +251,9 @@ OperatorShellMake(const char *operatorName,
 	values[Anum_pg_operator_oprrest - 1] = ObjectIdGetDatum(InvalidOid);
 	values[Anum_pg_operator_oprjoin - 1] = ObjectIdGetDatum(InvalidOid);
 
+	/* XXXX: How this should be implemented? */
+	values[Anum_pg_operator_oprmvstat - 1] = CStringGetTextDatum("---");
+
 	/*
 	 * open pg_operator
 	 */
@@ -508,6 +511,9 @@ OperatorCreate(const char *operatorName,
 	values[Anum_pg_operator_oprrest - 1] = ObjectIdGetDatum(restrictionId);
 	values[Anum_pg_operator_oprjoin - 1] = ObjectIdGetDatum(joinId);
 
+	/* XXXX: How this should be implemented? */
+	values[Anum_pg_operator_oprmvstat - 1] = CStringGetTextDatum("---");
+
 	pg_operator_desc = heap_open(OperatorRelationId, RowExclusiveLock);
 
 	/*
diff --git a/src/backend/nodes/nodeFuncs.c b/src/backend/nodes/nodeFuncs.c
index 115ff98..00ef04b 100644
--- a/src/backend/nodes/nodeFuncs.c
+++ b/src/backend/nodes/nodeFuncs.c
@@ -1996,7 +1996,7 @@ expression_tree_walker(Node *node,
 		case T_RangeTblFunction:
 			return walker(((RangeTblFunction *) node)->funcexpr, context);
 		case T_RestrictInfo:
-			elog(LOG, "HOGEEEEE: RestrictInfo");
+//			elog(LOG, "HOGEEEEE: RestrictInfo");
 			return walker(((RestrictInfo *) node)->clause, context);
 		default:
 			elog(ERROR, "unrecognized node type: %d",
diff --git a/src/backend/optimizer/path/clausesel.c b/src/backend/optimizer/path/clausesel.c
index fce77ec..61f3cd8 100644
--- a/src/backend/optimizer/path/clausesel.c
+++ b/src/backend/optimizer/path/clausesel.c
@@ -46,13 +46,6 @@ typedef struct RangeQueryClause
 	Selectivity hibound;		/* Selectivity of a var < something clause */
 } RangeQueryClause;
 
-static Selectivity clauselist_selectivity_or(PlannerInfo *root,
-											 List *clauses,
-											 int varRelid,
-											 JoinType jointype,
-											 SpecialJoinInfo *sjinfo,
-											 List *conditions);
-
 static void addRangeClause(RangeQueryClause **rqlist, Node *clause,
 			   bool varonleft, bool isLTsel, Selectivity s2);
 
@@ -60,38 +53,6 @@ static void addRangeClause(RangeQueryClause **rqlist, Node *clause,
 #define		MV_CLAUSE_TYPE_MCV		0x02
 #define		MV_CLAUSE_TYPE_HIST		0x04
 
-static bool clause_is_mv_compatible(PlannerInfo *root, Node *clause, Oid varRelid,
-							 Index *relid, Bitmapset **attnums, SpecialJoinInfo *sjinfo,
-							 int type);
-
-static Bitmapset  *collect_mv_attnums(PlannerInfo *root, List *clauses,
-									  Oid varRelid, Index *relid, SpecialJoinInfo *sjinfo,
-									  int type);
-
-static Bitmapset *clause_mv_get_attnums(PlannerInfo *root, Node *clause);
-
-static List *clauselist_apply_dependencies(PlannerInfo *root, List *clauses,
-								Oid varRelid, List *stats,
-								SpecialJoinInfo *sjinfo);
-
-static List *clauselist_mv_split(PlannerInfo *root, SpecialJoinInfo *sjinfo,
-								 List *clauses, Oid varRelid,
-								 List **mvclauses, MVStatisticInfo *mvstats, int types);
-
-static Selectivity clauselist_mv_selectivity(PlannerInfo *root,
-						MVStatisticInfo *mvstats, List *clauses,
-						List *conditions, bool is_or);
-
-static Selectivity clauselist_mv_selectivity_mcvlist(PlannerInfo *root,
-									MVStatisticInfo *mvstats,
-									List *clauses, List *conditions,
-									bool is_or, bool *fullmatch,
-									Selectivity *lowsel);
-static Selectivity clauselist_mv_selectivity_histogram(PlannerInfo *root,
-									MVStatisticInfo *mvstats,
-									List *clauses, List *conditions,
-									bool is_or);
-
 static int update_match_bitmap_mcvlist(PlannerInfo *root, List *clauses,
 									int2vector *stakeys, MCVList mcvlist,
 									int nmatches, char * matches,
@@ -104,79 +65,11 @@ static int update_match_bitmap_histogram(PlannerInfo *root, List *clauses,
 									int nmatches, char * matches,
 									bool is_or);
 
-/*
- * Describes a combination of multiple statistics to cover attributes
- * referenced by the clauses. The array 'stats' (with nstats elements)
- * lists attributes (in the order as they are applied), and number of
- * clause attributes covered by this solution.
- *
- * choose_mv_statistics_exhaustive() uses this to track both the current
- * and the best solutions, while walking through the state of possible
- * combination.
- */
-typedef struct mv_solution_t {
-	int		nclauses;		/* number of clauses covered */
-	int		nconditions;	/* number of conditions covered */
-	int		nstats;			/* number of stats applied */
-	int	   *stats;			/* stats (in the apply order) */
-} mv_solution_t;
-
-static List *choose_mv_statistics(PlannerInfo *root,
-								List *mvstats,
-								List *clauses, List *conditions,
-								Oid varRelid,
-								SpecialJoinInfo *sjinfo);
-
-static List *filter_clauses(PlannerInfo *root, Oid varRelid,
-							SpecialJoinInfo *sjinfo, int type,
-							List *stats, List *clauses,
-							Bitmapset **attnums);
-
-static List *filter_stats(List *stats, Bitmapset *new_attnums,
-						  Bitmapset *all_attnums);
-
-static Bitmapset **make_stats_attnums(MVStatisticInfo *mvstats,
-									  int nmvstats);
-
-static MVStatisticInfo *make_stats_array(List *stats, int *nmvstats);
-
-static List* filter_redundant_stats(List *stats,
-									List *clauses, List *conditions);
-
-static Node** make_clauses_array(List *clauses, int *nclauses);
-
-static Bitmapset ** make_clauses_attnums(PlannerInfo *root, Oid varRelid,
-										 SpecialJoinInfo *sjinfo, int type,
-										 Node **clauses, int nclauses);
-
-static bool* make_cover_map(Bitmapset **stats_attnums, int nmvstats,
-							Bitmapset **clauses_attnums, int nclauses);
-
-static bool has_stats(List *stats, int type);
-
-static List * find_stats(PlannerInfo *root, List *clauses,
-						 Oid varRelid, Index *relid);
-
-static Bitmapset* fdeps_collect_attnums(List *stats);
-
-static int	*make_idx_to_attnum_mapping(Bitmapset *attnums);
-static int	*make_attnum_to_idx_mapping(Bitmapset *attnums);
-
-static bool	*build_adjacency_matrix(List *stats, Bitmapset *attnums,
-								int *idx_to_attnum, int *attnum_to_idx);
-
-static void	multiply_adjacency_matrix(bool *matrix, int natts);
-
 static List* fdeps_reduce_clauses(List *clauses,
 								  Bitmapset *attnums, bool *matrix,
 								  int *idx_to_attnum, int *attnum_to_idx,
 								  Index relid);
 
-static Bitmapset *fdeps_filter_clauses(PlannerInfo *root,
-					 List *clauses, Bitmapset *deps_attnums,
-					 List **reduced_clauses, List **deps_clauses,
-					 Oid varRelid, Index *relid, SpecialJoinInfo *sjinfo);
-
 static Bitmapset * get_varattnos(Node * node, Index relid);
 
 int mvstat_search_type = MVSTAT_SEARCH_GREEDY;
@@ -188,397 +81,41 @@ int mvstat_search_type = MVSTAT_SEARCH_GREEDY;
 #define UPDATE_RESULT(m,r,isor)	\
 	(m) = (isor) ? (MAX(m,r)) : (MIN(m,r))
 
+typedef enum mv_selec_status
+{
+	NORMAL,
+	FULL_MATCH,
+	FAILURE
+} mv_selec_status;
+
 /****************************************************************************
  *		ROUTINES TO COMPUTE SELECTIVITIES
  ****************************************************************************/
+/***************/
+RestrictStatData *
+transformRestrictInfoForEstimate(PlannerInfo *root, List *clauses, int varRelid, SpecialJoinInfo *sjinfo);
 
 /*
- * clauselist_selectivity -
- *	  Compute the selectivity of an implicitly-ANDed list of boolean
- *	  expression clauses.  The list can be empty, in which case 1.0
- *	  must be returned.  List elements may be either RestrictInfos
- *	  or bare expression clauses --- the former is preferred since
- *	  it allows caching of results.
- *
- * See clause_selectivity() for the meaning of the additional parameters.
- *
- * Our basic approach is to take the product of the selectivities of the
- * subclauses.  However, that's only right if the subclauses have independent
- * probabilities, and in reality they are often NOT independent.  So,
- * we want to be smarter where we can.
- *
- * Currently, the only extra smarts we have is to recognize "range queries",
- * such as "x > 34 AND x < 42".  Clauses are recognized as possible range
- * query components if they are restriction opclauses whose operators have
- * scalarltsel() or scalargtsel() as their restriction selectivity estimator.
- * We pair up clauses of this form that refer to the same variable.  An
- * unpairable clause of this kind is simply multiplied into the selectivity
- * product in the normal way.  But when we find a pair, we know that the
- * selectivities represent the relative positions of the low and high bounds
- * within the column's range, so instead of figuring the selectivity as
- * hisel * losel, we can figure it as hisel + losel - 1.  (To visualize this,
- * see that hisel is the fraction of the range below the high bound, while
- * losel is the fraction above the low bound; so hisel can be interpreted
- * directly as a 0..1 value but we need to convert losel to 1-losel before
- * interpreting it as a value.  Then the available range is 1-losel to hisel.
- * However, this calculation double-excludes nulls, so really we need
- * hisel + losel + null_frac - 1.)
- *
- * If either selectivity is exactly DEFAULT_INEQ_SEL, we forget this equation
- * and instead use DEFAULT_RANGE_INEQ_SEL.  The same applies if the equation
- * yields an impossible (negative) result.
- *
- * A free side-effect is that we can recognize redundant inequalities such
- * as "x < 4 AND x < 5"; only the tighter constraint will be counted.
- *
- * Of course this is all very dependent on the behavior of
- * scalarltsel/scalargtsel; perhaps some day we can generalize the approach.
- *
- *
- * Multivariate statististics
- * --------------------------
- * This also uses multivariate stats to estimate combinations of
- * conditions, in a way (a) maximizing the estimate accuracy by using
- * as many stats as possible, and (b) minimizing the overhead,
- * especially when there are no suitable multivariate stats (so if you
- * are not using multivariate stats, there's no additional overhead).
- *
- * The following checks are performed (in this order), and the optimizer
- * falls back to regular stats on the first 'false'.
- *
- * NOTE: This explains how this works with all the patches applied, not
- *       just the functional dependencies.
- *
- * (0) check if there are multivariate stats on the relation
- *
- *     If no, just skip all the following steps (directly to the
- *     original code).
- *
- * (1) check how many attributes are there in conditions compatible
- *     with functional dependencies
- *
- *     Only simple equality clauses are considered compatible with
- *     functional dependencies (and that's unlikely to change, because
- *     that's the only case when functional dependencies are useful).
- *
- *     If there are no conditions that might be handled by multivariate
- *     stats, or if the conditions reference just a single column, it
- *     makes no sense to use functional dependencies, so skip to (4).
- *
- * (2) reduce the clauses using functional dependencies
- *
- *     This simply attempts to 'reduce' the clauses by applying functional
- *     dependencies. For example if there are two clauses:
- *
- *         WHERE (a = 1) AND (b = 2)
- *
- *     and we know that 'a' determines the value of 'b', we may remove
- *     the second condition (b = 2) when computing the selectivity.
- *     This is of course tricky - see mvstats/dependencies.c for details.
- *
- *     After the reduction, step (1) is to be repeated.
- *
- * (3) check how many attributes are there in conditions compatible
- *     with MCV lists and histograms
- *
- *     What conditions are compatible with multivariate stats is decided
- *     by clause_is_mv_compatible(). At this moment, only conditions
- *     of the form "column operator constant" (for simple comparison
- *     operators), IS [NOT] NULL and some AND/OR clauses are considered
- *     compatible with multivariate statistics.
- *
- *     Again, see clause_is_mv_compatible() for details.
- *
- * (4) check how many attributes are there in conditions compatible
- *     with MCV lists and histograms
- *
- *     If there are no conditions that might be handled by MCV lists
- *     or histograms, or if the conditions reference just a single
- *     column, it makes no sense to continue, so just skip to (7).
- *
- * (5) choose the stats matching the most columns
- *
- *     If there are multiple instances of multivariate statistics (e.g.
- *     built on different sets of columns), we choose the stats covering
- *     the most columns from step (1). It may happen that all available
- *     stats match just a single column - for example with conditions
- *
- *         WHERE a = 1 AND b = 2
- *
- *     and statistics built on (a,c) and (b,c). In such case just fall
- *     back to the regular stats because it makes no sense to use the
- *     multivariate statistics.
- *
- *     For more details about how exactly we choose the stats, see
- *     choose_mv_statistics().
- *
- * (6) use the multivariate stats to estimate matching clauses
- *
- * (7) estimate the remaining clauses using the regular statistics
+ * boolop_selectivity -
  */
-Selectivity
-clauselist_selectivity(PlannerInfo *root,
+static Selectivity
+and_clause_selectivity(PlannerInfo *root,
 					   List *clauses,
 					   int varRelid,
 					   JoinType jointype,
-					   SpecialJoinInfo *sjinfo,
-					   List *conditions)
+					   SpecialJoinInfo *sjinfo)
 {
 	Selectivity s1 = 1.0;
 	RangeQueryClause *rqlist = NULL;
 	ListCell   *l;
 
-	/* processing mv stats */
-	Index		relid = InvalidOid;
-
-	/* attributes in mv-compatible clauses */
-	Bitmapset  *mvattnums = NULL;
-	List	   *stats = NIL;
-
-	/* use clauses (not conditions), because those are always non-empty */
-	stats = find_stats(root, clauses, varRelid, &relid);
-
-	/*
-	 * If there's exactly one clause, then no use in trying to match up
-	 * pairs, or matching multivariate statistics, so just go directly
-	 * to clause_selectivity().
-	 */
-	if (list_length(clauses) == 1)
-		return clause_selectivity(root, (Node *) linitial(clauses),
-								  varRelid, jointype, sjinfo, conditions);
-
-	/*
-	 * Check that there are some stats with functional dependencies
-	 * built (by walking the stats list). We're going to find that
-	 * anyway when trying to apply the functional dependencies, but
-	 * this is probably a tad faster.
-	 */
-	if (has_stats(stats, MV_CLAUSE_TYPE_FDEP))
-	{
-		/*
-		 * Collect attributes referenced by mv-compatible clauses (looking
-		 * for clauses compatible with functional dependencies for now).
-		 */
-		mvattnums = collect_mv_attnums(root, clauses, varRelid, &relid, sjinfo,
-									   MV_CLAUSE_TYPE_FDEP);
-
-		/*
-		 * If there are mv-compatible clauses, referencing at least two
-		 * different columns (otherwise it makes no sense to use mv stats),
-		 * try to reduce the clauses using functional dependencies, and
-		 * recollect the attributes from the reduced list.
-		 *
-		 * We don't need to select a single statistics for this - we can
-		 * apply all the functional dependencies we have.
-		 */
-		if (bms_num_members(mvattnums) >= 2)
-			clauses = clauselist_apply_dependencies(root, clauses, varRelid,
-													stats, sjinfo);
-	}
-
-	/*
-	 * Check that there are statistics with MCV list or histogram.
-	 * If not, we don't need to waste time with the optimization.
-	 */
-	if (has_stats(stats, MV_CLAUSE_TYPE_MCV | MV_CLAUSE_TYPE_HIST))
-	{
-		/*
-		 * Recollect attributes from mv-compatible clauses (maybe we've
-		 * removed so many clauses we have a single mv-compatible attnum).
-		 * From now on we're only interested in MCV-compatible clauses.
-		 */
-		mvattnums = collect_mv_attnums(root, clauses, varRelid, &relid, sjinfo,
-									   (MV_CLAUSE_TYPE_MCV | MV_CLAUSE_TYPE_HIST));
-
-		/*
-		 * If there still are at least two columns, we'll try to select
-		 * a suitable combination of multivariate stats. If there are
-		 * multiple combinations, we'll try to choose the best one.
-		 * See choose_mv_statistics for more details.
-		 */
-		if (bms_num_members(mvattnums) >= 2)
-		{
-			int k;
-			ListCell *s;
-
-			/*
-			 * Copy the list of conditions, so that we can build a list
-			 * of local conditions (and keep the original intact, for
-			 * the other clauses at the same level).
-			 */
-			List *conditions_local = list_copy(conditions);
-
-			/* find the best combination of statistics */
-			List *solution = choose_mv_statistics(root, stats,
-												  clauses, conditions,
-												  varRelid, sjinfo);
-
-			/* we have a good solution (list of stats) */
-			foreach (s, solution)
-			{
-				MVStatisticInfo *mvstat = (MVStatisticInfo *)lfirst(s);
-
-				/* clauses compatible with multi-variate stats */
-				List	*mvclauses = NIL;
-				List	*mvclauses_new = NIL;
-				List	*mvclauses_conditions = NIL;
-				Bitmapset	*stat_attnums = NULL;
-
-				/* build attnum bitmapset for this statistics */
-				for (k = 0; k < mvstat->stakeys->dim1; k++)
-					stat_attnums = bms_add_member(stat_attnums,
-												  mvstat->stakeys->values[k]);
-
-				/*
-				 * Append the compatible conditions (passed from above)
-				 * to mvclauses_conditions.
-				 */
-				foreach (l, conditions)
-				{
-					Node *c = (Node*)lfirst(l);
-					Bitmapset *tmp = clause_mv_get_attnums(root, c);
-
-					if (bms_is_subset(tmp, stat_attnums))
-						mvclauses_conditions
-							= lappend(mvclauses_conditions, c);
-
-					bms_free(tmp);
-				}
-
-				/* split the clauselist into regular and mv-clauses
-				 *
-				 * We keep the list of clauses (we don't remove the
-				 * clauses yet, because we want to use the clauses
-				 * as conditions of other clauses).
-				 *
-				 * FIXME Do this only once, i.e. filter the clauses
-				 *       once (selecting clauses covered by at least
-				 *       one statistics) and then convert them into
-				 *       smaller per-statistics lists of conditions
-				 *       and estimated clauses.
-				 */
-				clauselist_mv_split(root, sjinfo, clauses,
-										varRelid, &mvclauses, mvstat,
-										(MV_CLAUSE_TYPE_MCV | MV_CLAUSE_TYPE_HIST));
-
-				/*
-				 * We've chosen the statistics to match the clauses, so
-				 * each statistics from the solution should have at least
-				 * one new clause (not covered by the previous stats).
-				 */
-				Assert(mvclauses != NIL);
-
-				/*
-				 * Mvclauses now contains only clauses compatible
-				 * with the currently selected stats, but we have to
-				 * split that into conditions (already matched by
-				 * the previous stats), and the new clauses we need
-				 * to estimate using this stats.
-				 */
-				foreach (l, mvclauses)
-				{
-					ListCell *p;
-					bool covered = false;
-					Node  *clause = (Node *) lfirst(l);
-					Bitmapset *clause_attnums = clause_mv_get_attnums(root, clause);
-
-					/*
-					 * If already covered by previous stats, add it to
-					 * conditions.
-					 *
-					 * TODO Maybe this could be relaxed a bit? Because
-					 *      with complex and/or clauses, this might
-					 *      mean no statistics actually covers such
-					 *      complex clause.
-					 */
-					foreach (p, solution)
-					{
-						int k;
-						Bitmapset  *stat_attnums = NULL;
-
-						MVStatisticInfo *prev_stat
-							= (MVStatisticInfo *)lfirst(p);
-
-						/* break if we've ran into current statistic */
-						if (prev_stat == mvstat)
-							break;
-
-						for (k = 0; k < prev_stat->stakeys->dim1; k++)
-							stat_attnums = bms_add_member(stat_attnums,
-														  prev_stat->stakeys->values[k]);
-
-						covered = bms_is_subset(clause_attnums, stat_attnums);
-
-						bms_free(stat_attnums);
-
-						if (covered)
-							break;
-					}
-
-					if (covered)
-						mvclauses_conditions
-							= lappend(mvclauses_conditions, clause);
-					else
-						mvclauses_new
-							= lappend(mvclauses_new, clause);
-				}
-
-				/*
-				 * We need at least one new clause (not just conditions).
-				 */
-				Assert(mvclauses_new != NIL);
-
-				/* compute the multivariate stats */
-				s1 *= clauselist_mv_selectivity(root, mvstat,
-												mvclauses_new,
-												mvclauses_conditions,
-												false); /* AND */
-			}
-
-			/*
-			 * And now finally remove all the mv-compatible clauses.
-			 *
-			 * This only repeats the same split as above, but this
-			 * time we actually use the result list (and feed it to
-			 * the next call).
-			 */
-			foreach (s, solution)
-			{
-				/* clauses compatible with multi-variate stats */
-				List	*mvclauses = NIL;
-
-				MVStatisticInfo *mvstat = (MVStatisticInfo *)lfirst(s);
-
-				/* split the list into regular and mv-clauses */
-				clauses = clauselist_mv_split(root, sjinfo, clauses,
-										varRelid, &mvclauses, mvstat,
-										(MV_CLAUSE_TYPE_MCV | MV_CLAUSE_TYPE_HIST));
-
-				/*
-				 * Add the clauses to the conditions (to be passed
-				 * to regular clauses), irrespectedly whether it
-				 * will be used as a condition or a clause here.
-				 *
-				 * We only keep the remaining conditions in the
-				 * clauses (we keep what clauselist_mv_split returns)
-				 * so we add each MV condition exactly once.
-				 */
-				conditions_local = list_concat(conditions_local, mvclauses);
-			}
-
-			/* from now on, work with the 'local' list of conditions */
-			conditions = conditions_local;
-		}
-	}
-
 	/*
 	 * If there's exactly one clause, then no use in trying to match up
 	 * pairs, so just go directly to clause_selectivity().
 	 */
 	if (list_length(clauses) == 1)
 		return clause_selectivity(root, (Node *) linitial(clauses),
-								  varRelid, jointype, sjinfo, conditions);
-
+								  varRelid, jointype, sjinfo);
 	/*
 	 * Initial scan over clauses.  Anything that doesn't look like a potential
 	 * rangequery clause gets multiplied into s1 and forgotten. Anything that
@@ -591,8 +128,7 @@ clauselist_selectivity(PlannerInfo *root,
 		Selectivity s2;
 
 		/* Always compute the selectivity using clause_selectivity */
-		s2 = clause_selectivity(root, clause, varRelid, jointype, sjinfo,
-								conditions);
+		s2 = clause_selectivity(root, clause, varRelid, jointype, sjinfo);
 
 		/*
 		 * Check for being passed a RestrictInfo.
@@ -750,250 +286,334 @@ clauselist_selectivity(PlannerInfo *root,
 	return s1;
 }
 
-/*
- * Similar to clauselist_selectivity(), but for clauses connected by OR.
- *
- * That means a few differences:
- *
- *   - functional dependencies don't apply to OR-clauses
- *
- *   - we can't add the previous clauses to conditions
- *
- *   - combined selectivities are combined using (s1+s2 - s1*s2)
- *     and not as a multiplication (s1*s2)
- *
- * Another way to evaluate this might be turning
- *
- *     (a OR b OR c)
- *
- * into
- *
- *     NOT ((NOT a) AND (NOT b) AND (NOT c))
- *
- * and computing selectivity of that using clauselist_selectivity().
- * That would allow (a) using the clauselist_selectivity directly and
- * (b) using the previous clauses as conditions. Not sure if it's
- * worth the additional complexity, though.
- */
 static Selectivity
-clauselist_selectivity_or(PlannerInfo *root,
-					   List *clauses,
-					   int varRelid,
-					   JoinType jointype,
-					   SpecialJoinInfo *sjinfo,
-					   List *conditions)
+clause_mcv_selectivity(PlannerInfo *root, MVStatisticInfo *stats,
+					   Node *clause, int *status)
 {
-	Selectivity s1 = 0.0;
-	ListCell   *l;
-
-	/* processing mv stats */
-	Index		relid = InvalidOid;
-
-	/* attributes in mv-compatible clauses */
-	Bitmapset  *mvattnums = NULL;
-	List	   *stats = NIL;
-
-	/* use clauses (not conditions), because those are always non-empty */
-	stats = find_stats(root, clauses, varRelid, &relid);
+	MCVList mcvlist = NULL;
+	int		nmatches = 0;
+	int		nconditions = 0;
+	char   *matches = NULL;
+	char   *condition_matches = NULL;
+	Selectivity s = 0.0;
+	Selectivity t = 0.0;
+	Selectivity u = 0.0;
+	BoolExpr *expr = (BoolExpr*) clause;
+	bool	is_or = or_clause(clause);
+	int i;
+	bool fullmatch;
+	Selectivity lowsel;
 
-	/* OR-clauses do not work with functional dependencies */
-	if (has_stats(stats, MV_CLAUSE_TYPE_MCV | MV_CLAUSE_TYPE_HIST))
+	Assert(IsA(expr, BoolExpr));
+	
+	if (!expr || not_clause(clause)) /* For now!! */
 	{
-		/*
-		 * Recollect attributes from mv-compatible clauses (maybe we've
-		 * removed so many clauses we have a single mv-compatible attnum).
-		 * From now on we're only interested in MCV-compatible clauses.
-		 */
-		mvattnums = collect_mv_attnums(root, clauses, varRelid, &relid, sjinfo,
-									   (MV_CLAUSE_TYPE_MCV | MV_CLAUSE_TYPE_HIST));
-
-		/*
-		 * If there still are at least two columns, we'll try to select
-		 * a suitable multivariate stats.
-		 */
-		if (bms_num_members(mvattnums) >= 2)
-		{
-			int k;
-			ListCell *s;
+		*status = FAILURE;
+		return 0.0;
+	}
+	if (!stats->mcv_built)
+	{
+		*status = FAILURE;
+		return 0.0;
+	}
+	
+	mcvlist = load_mv_mcvlist(stats->mvoid);
+	Assert (mcvlist != NULL);
+	Assert (mcvlist->nitems > 0);
 
-			List *solution
-				= choose_mv_statistics(root, stats,
-									   clauses, conditions,
-									   varRelid, sjinfo);
+	nmatches = mcvlist->nitems;
+	nconditions = mcvlist->nitems;
 
-			/* we have a good solution stats */
-			foreach (s, solution)
-			{
-				Selectivity s2;
-				MVStatisticInfo *mvstat = (MVStatisticInfo *)lfirst(s);
+	matches = palloc0(sizeof(char) * nmatches);
 
-				/* clauses compatible with multi-variate stats */
-				List	*mvclauses = NIL;
-				List	*mvclauses_new = NIL;
-				List	*mvclauses_conditions = NIL;
-				Bitmapset	*stat_attnums = NULL;
+	if (!is_or) /* AND-clause */
+		memset(matches, MVSTATS_MATCH_FULL, sizeof(char)*nmatches);
 
-				/* build attnum bitmapset for this statistics */
-				for (k = 0; k < mvstat->stakeys->dim1; k++)
-					stat_attnums = bms_add_member(stat_attnums,
-												  mvstat->stakeys->values[k]);
+	/* Conditions are treated as AND clause, so match by default. */
+	condition_matches = palloc0(sizeof(char)*nconditions);
+	memset(condition_matches, MVSTATS_MATCH_FULL, sizeof(char)*nconditions);
 
-				/*
-				 * Append the compatible conditions (passed from above)
-				 * to mvclauses_conditions.
-				 */
-				foreach (l, conditions)
-				{
-					Node *c = (Node*)lfirst(l);
-					Bitmapset *tmp = clause_mv_get_attnums(root, c);
+	nmatches = update_match_bitmap_mcvlist(root, expr->args,
+										   stats->stakeys, mcvlist,
+										   (is_or ? 0 : nmatches), matches,
+										   &lowsel, &fullmatch, is_or);
 
-					if (bms_is_subset(tmp, stat_attnums))
-						mvclauses_conditions
-							= lappend(mvclauses_conditions, c);
-
-					bms_free(tmp);
-				}
+	for (i = 0; i < mcvlist->nitems; i++)
+	{
+		u += mcvlist->items[i]->frequency;
+		
+		if (condition_matches[i] == MVSTATS_MATCH_NONE)
+			continue;
 
-				/* split the clauselist into regular and mv-clauses
-				 *
-				 * We keep the list of clauses (we don't remove the
-				 * clauses yet, because we want to use the clauses
-				 * as conditions of other clauses).
-				 *
-				 * FIXME Do this only once, i.e. filter the clauses
-				 *       once (selecting clauses covered by at least
-				 *       one statistics) and then convert them into
-				 *       smaller per-statistics lists of conditions
-				 *       and estimated clauses.
-				 */
-				clauselist_mv_split(root, sjinfo, clauses,
-										varRelid, &mvclauses, mvstat,
-										(MV_CLAUSE_TYPE_MCV | MV_CLAUSE_TYPE_HIST));
+		if (matches[i] != MVSTATS_MATCH_NONE)
+			s += mcvlist->items[i]->frequency;
 
-				/*
-				 * We've chosen the statistics to match the clauses, so
-				 * each statistics from the solution should have at least
-				 * one new clause (not covered by the previous stats).
-				 */
-				Assert(mvclauses != NIL);
+		t += mcvlist->items[i]->frequency;
+	}
 
-				/*
-				 * Mvclauses now contains only clauses compatible
-				 * with the currently selected stats, but we have to
-				 * split that into conditions (already matched by
-				 * the previous stats), and the new clauses we need
-				 * to estimate using this stats.
-				 *
-				 * XXX We'll only use the new clauses, but maybe we
-				 *     should use the conditions too, somehow. We can't
-				 *     use that directly in conditional probability, but
-				 *     maybe we might use them in a different way?
-				 *
-				 *     If we have a clause (a OR b OR c), then knowing
-				 *     that 'a' is TRUE means (b OR c) can't make the
-				 *     whole clause FALSE.
-				 *
-				 *     This is pretty much what
-				 *
-				 *         (a OR b) == NOT ((NOT a) AND (NOT b))
-				 *
-				 *     implies.
-				 */
-				foreach (l, mvclauses)
-				{
-					ListCell *p;
-					bool covered = false;
-					Node  *clause = (Node *) lfirst(l);
-					Bitmapset *clause_attnums = clause_mv_get_attnums(root, clause);
+	pfree(matches);
+	pfree(condition_matches);
+	pfree(mcvlist);
 
-					/*
-					 * If already covered by previous stats, add it to
-					 * conditions.
-					 *
-					 * TODO Maybe this could be relaxed a bit? Because
-					 *      with complex and/or clauses, this might
-					 *      mean no statistics actually covers such
-					 *      complex clause.
-					 */
-					foreach (p, solution)
-					{
-						int k;
-						Bitmapset  *stat_attnums = NULL;
+	if (fullmatch)
+		*status = FULL_MATCH;
 
-						MVStatisticInfo *prev_stat
-							= (MVStatisticInfo *)lfirst(p);
+	/* mcv_low is omitted for now */
 
-						/* break if we've ran into current statistic */
-						if (prev_stat == mvstat)
-							break;
+	/* no condition matches */
+	if (t == 0.0)
+		return (Selectivity)0.0;
 
-						for (k = 0; k < prev_stat->stakeys->dim1; k++)
-							stat_attnums = bms_add_member(stat_attnums,
-														  prev_stat->stakeys->values[k]);
+	return (s / t) * u;
+}
 
-						covered = bms_is_subset(clause_attnums, stat_attnums);
+static Selectivity
+clause_hist_selectivity(PlannerInfo *root, MVStatisticInfo *stats,
+						Node *clause, int *status)
+{
+	MVSerializedHistogram mvhist = NULL;
+	int		nmatches = 0;
+	int		nconditions = 0;
+	char   *matches = NULL;
+	char   *condition_matches = NULL;
+	Selectivity s = 0.0;
+	Selectivity t = 0.0;
+	Selectivity u = 0.0;
+	BoolExpr *expr = (BoolExpr*) clause;
+	bool	is_or = or_clause(clause);
+	int i;
 
-						bms_free(stat_attnums);
+	Assert(IsA(expr, BoolExpr));
 
-						if (covered)
-							break;
-					}
+	if (!expr || not_clause(clause))  /* for now */
+	{
+		*status = 0;
+		return 0.0;
+	}
+	if (!stats->hist_built)
+	{
+		*status = 1;
+		return 0.0;
+	}
+	mvhist = load_mv_histogram(stats->mvoid);
+	Assert (mvhist != NULL);
+	Assert (clause != NULL);
 
-					if (! covered)
-						mvclauses_new = lappend(mvclauses_new, clause);
-				}
+	nmatches = mvhist->nbuckets;
+	nconditions = mvhist->nbuckets;
+	matches = palloc0(sizeof(char) * nmatches);
+	if (!is_or) /* AND-clause */
+		memset(matches, MVSTATS_MATCH_FULL, sizeof(char)*nmatches);
 
-				/*
-				 * We need at least one new clause (not just conditions).
-				 */
-				Assert(mvclauses_new != NIL);
+	/* Conditions are treated as AND clause, so match by default. */
+	condition_matches = palloc0(sizeof(char)*nconditions);
+	memset(condition_matches, MVSTATS_MATCH_FULL, sizeof(char)*nconditions);
 
-				/* compute the multivariate stats */
-				s2 = clauselist_mv_selectivity(root, mvstat,
-												mvclauses_new,
-												mvclauses_conditions,
-												true); /* OR */
+	update_match_bitmap_histogram(root, expr->args, stats->stakeys, mvhist,
+								  (is_or ? 0 : nmatches), matches, is_or);
 
-				s1 = s1 + s2 - s1 * s2;
-			}
+	for (i = 0; i < mvhist->nbuckets; i++)
+	{
+		float coeff = 1.0;
+		u += mvhist->buckets[i]->ntuples;
 
-			/*
-			 * And now finally remove all the mv-compatible clauses.
-			 *
-			 * This only repeats the same split as above, but this
-			 * time we actually use the result list (and feed it to
-			 * the next call).
-			 */
-			foreach (s, solution)
-			{
-				/* clauses compatible with multi-variate stats */
-				List	*mvclauses = NIL;
+		if (condition_matches[i] == MVSTATS_MATCH_NONE)
+			continue;
+		else if (condition_matches[i] == MVSTATS_MATCH_PARTIAL)
+			coeff = 0.5;
 
-				MVStatisticInfo *mvstat = (MVStatisticInfo *)lfirst(s);
+		t += coeff * mvhist->buckets[i]->ntuples;
 
-				/* split the list into regular and mv-clauses */
-				clauses = clauselist_mv_split(root, sjinfo, clauses,
-										varRelid, &mvclauses, mvstat,
-										(MV_CLAUSE_TYPE_MCV | MV_CLAUSE_TYPE_HIST));
-			}
-		}
+		if (matches[i] == MVSTATS_MATCH_FULL)
+			s += coeff * mvhist->buckets[i]->ntuples;
+		else if (matches[i] == MVSTATS_MATCH_PARTIAL)
+			s += coeff * 0.5 * mvhist->buckets[i]->ntuples;
 	}
 
-	/*
-	 * Handle the remaining clauses (either using regular statistics,
-	 * or by multivariate stats at the next level).
-	 */
-	foreach(l, clauses)
+	pfree(matches);
+	pfree(condition_matches);
+	pfree(mvhist);
+
+	/* no condition matches */
+	if (t == 0.0)
+		return (Selectivity)0.0;
+
+	return (s / t) * u;
+}
+
+static Selectivity
+apply_mvstats(PlannerInfo *root, Node *clause, bm_mvstat *statent)
+{
+	Selectivity s1 = 0.0;
+	int status;
+
+	if (statent->mvkind & MVSTATISTIC_MCV)
 	{
-		Selectivity s2 = clause_selectivity(root,
-											(Node *) lfirst(l),
-											varRelid,
-											jointype,
-											sjinfo,
-											conditions);
+		s1 = clause_mcv_selectivity(root, statent->stats, clause, &status);
+		if (status == FULL_MATCH && s1 > 0.0)
+			return s1;
+	}
+	
+	if (statent->mvkind & MVSTATISTIC_HIST)
+		s1 = s1 + clause_hist_selectivity(root, statent->stats,
+										  clause, &status);
+
+	return s1;
+}
+
+static inline Selectivity
+merge_selectivity(Selectivity s1, Selectivity s2, BoolExprType op)
+{
+	if (op == AND_EXPR)
+		s1 = s1 * s2;
+	else
 		s1 = s1 + s2 - s1 * s2;
+
+	return s1;
+}
+/*
+ * mvclause_selectivity -
+ */
+static Selectivity
+mvclause_selectivity(PlannerInfo *root,
+					 RestrictStatData *rstat,
+					 int varRelid,
+					 JoinType jointype,
+					 SpecialJoinInfo *sjinfo)
+{
+	Selectivity s1;
+	ListCell *lc;
+
+	if (!rstat->mvclause && !rstat->nonmvclause && !rstat->children)
+		return clause_selectivity(root, rstat->clause, varRelid, jointype,
+								  sjinfo);
+
+	if (rstat->boolop == NOT_EXPR)
+	{
+		RestrictStatData *clause =
+			(RestrictStatData *)linitial(rstat->children);
+
+		s1 = 1.0 - mvclause_selectivity(root, clause, varRelid,
+										jointype, sjinfo);
+		return s1;
+	}
+
+	s1 = (rstat->boolop == AND_EXPR ? 1.0 : 0.0);
+
+	if (rstat->nonmvclause)
+		s1 = merge_selectivity(s1,
+				   clause_selectivity(root, rstat->nonmvclause,
+									  varRelid, jointype, sjinfo),
+							   rstat->boolop);
+
+	if (rstat->mvclause)
+	{
+		bm_mvstat *mvs = (bm_mvstat*)linitial(rstat->mvstats);
+		Selectivity s2 = apply_mvstats(root, rstat->mvclause, mvs);
+
+		/* Fall back to ordinary calculation */
+		if (s2 < 0)
+			s2 = clause_selectivity(root, rstat->mvclause, varRelid,
+									jointype, sjinfo);
+		s1 = merge_selectivity(s1, s2, rstat->boolop);
+	}
+
+	foreach(lc, rstat->children)
+	{
+		RestrictStatData *rsd = (RestrictStatData *) lfirst(lc);
+		Assert(IsA(rsd, RestrictStatData));
+
+		s1 = merge_selectivity(s1,
+							   mvclause_selectivity(root, rsd, varRelid,
+													jointype, sjinfo),
+							   rstat->boolop);
+	}
+
+	return s1;
+}
+
+
+/*
+ * clauselist_selectivity -
+ *	  Compute the selectivity of an implicitly-ANDed list of boolean
+ *	  expression clauses.  The list can be empty, in which case 1.0
+ *	  must be returned.  List elements may be either RestrictInfos
+ *	  or bare expression clauses --- the former is preferred since
+ *	  it allows caching of results.
+ *
+ * See clause_selectivity() for the meaning of the additional parameters.
+ *
+ * Our basic approach is to take the product of the selectivities of the
+ * subclauses.  However, that's only right if the subclauses have independent
+ * probabilities, and in reality they are often NOT independent.  So,
+ * we want to be smarter where we can.
+ *
+ * Currently, the only extra smarts we have is to recognize "range queries",
+ * such as "x > 34 AND x < 42".  Clauses are recognized as possible range
+ * query components if they are restriction opclauses whose operators have
+ * scalarltsel() or scalargtsel() as their restriction selectivity estimator.
+ * We pair up clauses of this form that refer to the same variable.  An
+ * unpairable clause of this kind is simply multiplied into the selectivity
+ * product in the normal way.  But when we find a pair, we know that the
+ * selectivities represent the relative positions of the low and high bounds
+ * within the column's range, so instead of figuring the selectivity as
+ * hisel * losel, we can figure it as hisel + losel - 1.  (To visualize this,
+ * see that hisel is the fraction of the range below the high bound, while
+ * losel is the fraction above the low bound; so hisel can be interpreted
+ * directly as a 0..1 value but we need to convert losel to 1-losel before
+ * interpreting it as a value.  Then the available range is 1-losel to hisel.
+ * However, this calculation double-excludes nulls, so really we need
+ * hisel + losel + null_frac - 1.)
+ *
+ * If either selectivity is exactly DEFAULT_INEQ_SEL, we forget this equation
+ * and instead use DEFAULT_RANGE_INEQ_SEL.  The same applies if the equation
+ * yields an impossible (negative) result.
+ *
+ * A free side-effect is that we can recognize redundant inequalities such
+ * as "x < 4 AND x < 5"; only the tighter constraint will be counted.
+ *
+ * Of course this is all very dependent on the behavior of
+ * scalarltsel/scalargtsel; perhaps some day we can generalize the approach.
+ *
+ *
+ * Multivariate statististics
+ * --------------------------
+ * This also uses multivariate stats to estimate combinations of
+ * conditions, in a way (a) maximizing the estimate accuracy by using
+ * as many stats as possible, and (b) minimizing the overhead,
+ * especially when there are no suitable multivariate stats (so if you
+ * are not using multivariate stats, there's no additional overhead).
+ *
+ * The following checks are performed (in this order), and the optimizer
+ * falls back to regular stats on the first 'false'.
+ *
+ * NOTE: This explains how this works with all the patches applied, not
+ *       just the functional dependencies.
+ *
+ */
+Selectivity
+clauselist_selectivity(PlannerInfo *root,
+					   List *clauses,
+					   int varRelid,
+					   JoinType jointype,
+					   SpecialJoinInfo *sjinfo)
+{
+	Selectivity s1 = 1.0;
+	RestrictStatData *rstat;
+	List *rinfos = clauses;
+
+	/* Reconstruct clauses so that multivariate statistics can be applied */
+	rstat = transformRestrictInfoForEstimate(root, clauses, varRelid, sjinfo);
+
+	if (rstat)
+	{
+		rinfos = rstat->unusedrinfos;
+
+		s1 = mvclause_selectivity(root, rstat, varRelid, jointype, sjinfo);
 	}
 
+	s1 = s1 * and_clause_selectivity(root, rinfos, varRelid, jointype, sjinfo);
+
 	return s1;
 }
 
@@ -1204,8 +824,7 @@ clause_selectivity(PlannerInfo *root,
 				   Node *clause,
 				   int varRelid,
 				   JoinType jointype,
-				   SpecialJoinInfo *sjinfo,
-				   List *conditions)
+				   SpecialJoinInfo *sjinfo)
 {
 	Selectivity s1 = 0.5;		/* default for any unhandled clause type */
 	RestrictInfo *rinfo = NULL;
@@ -1335,28 +954,37 @@ clause_selectivity(PlannerInfo *root,
 								  (Node *) get_notclausearg((Expr *) clause),
 									  varRelid,
 									  jointype,
-									  sjinfo,
-									  conditions);
+									  sjinfo);
 	}
 	else if (and_clause(clause))
 	{
-		/* share code with clauselist_selectivity() */
-		s1 = clauselist_selectivity(root,
+		s1 = and_clause_selectivity(root,
 									((BoolExpr *) clause)->args,
 									varRelid,
 									jointype,
-									sjinfo,
-									conditions);
+									sjinfo);
 	}
 	else if (or_clause(clause))
 	{
-		/* just call to clauselist_selectivity_or() */
-		s1 = clauselist_selectivity_or(root,
-									((BoolExpr *) clause)->args,
-									varRelid,
-									jointype,
-									sjinfo,
-									conditions);
+		/*
+		 * Selectivities for an OR clause are computed as s1+s2 - s1*s2 to
+		 * account for the probable overlap of selected tuple sets.
+		 *
+		 * XXX is this too conservative?
+		 */
+		ListCell   *arg;
+
+		s1 = 0.0;
+		foreach(arg, ((BoolExpr *) clause)->args)
+		{
+			Selectivity s2 = clause_selectivity(root,
+												(Node *) lfirst(arg),
+												varRelid,
+												jointype,
+												sjinfo);
+
+			s1 = s1 + s2 - s1 * s2;
+		}
 	}
 	else if (is_opclause(clause) || IsA(clause, DistinctExpr))
 	{
@@ -1445,1899 +1073,55 @@ clause_selectivity(PlannerInfo *root,
 		s1 = booltestsel(root,
 						 ((BooleanTest *) clause)->booltesttype,
 						 (Node *) ((BooleanTest *) clause)->arg,
-						 varRelid,
-						 jointype,
-						 sjinfo);
-	}
-	else if (IsA(clause, CurrentOfExpr))
-	{
-		/* CURRENT OF selects at most one row of its table */
-		CurrentOfExpr *cexpr = (CurrentOfExpr *) clause;
-		RelOptInfo *crel = find_base_rel(root, cexpr->cvarno);
-
-		if (crel->tuples > 0)
-			s1 = 1.0 / crel->tuples;
-	}
-	else if (IsA(clause, RelabelType))
-	{
-		/* Not sure this case is needed, but it can't hurt */
-		s1 = clause_selectivity(root,
-								(Node *) ((RelabelType *) clause)->arg,
-								varRelid,
-								jointype,
-								sjinfo,
-								conditions);
-	}
-	else if (IsA(clause, CoerceToDomain))
-	{
-		/* Not sure this case is needed, but it can't hurt */
-		s1 = clause_selectivity(root,
-								(Node *) ((CoerceToDomain *) clause)->arg,
-								varRelid,
-								jointype,
-								sjinfo,
-								conditions);
-	}
-
-	/* Cache the result if possible */
-	if (cacheable)
-	{
-		if (jointype == JOIN_INNER)
-			rinfo->norm_selec = s1;
-		else
-			rinfo->outer_selec = s1;
-	}
-
-#ifdef SELECTIVITY_DEBUG
-	elog(DEBUG4, "clause_selectivity: s1 %f", s1);
-#endif   /* SELECTIVITY_DEBUG */
-
-	return s1;
-}
-
-
-/*
- * Estimate selectivity for the list of MV-compatible clauses, using
- * using a MV statistics (combining a histogram and MCV list).
- *
- * This simply passes the estimation to the MCV list and then to the
- * histogram, if available.
- *
- * TODO Clamp the selectivity by min of the per-clause selectivities
- *      (i.e. the selectivity of the most restrictive clause), because
- *      that's the maximum we can ever get from ANDed list of clauses.
- *      This may probably prevent issues with hitting too many buckets
- *      and low precision histograms.
- *
- * TODO We may support some additional conditions, most importantly
- *      those matching multiple columns (e.g. "a = b" or "a < b").
- *      Ultimately we could track multi-table histograms for join
- *      cardinality estimation.
- *
- * TODO Further thoughts on processing equality clauses: Maybe it'd be
- *      better to look for stats (with MCV) covered by the equality
- *      clauses, because then we have a chance to find an exact match
- *      in the MCV list, which is pretty much the best we can do. We may
- *      also look at the least frequent MCV item, and use it as a upper
- *      boundary for the selectivity (had there been a more frequent
- *      item, it'd be in the MCV list).
- *
- * TODO There are several options for 'sanity clamping' the estimates.
- *
- *      First, if we have selectivities for each condition, then
- *
- *          P(A,B) <= MIN(P(A), P(B))
- *
- *      Because additional conditions (connected by AND) can only lower
- *      the probability.
- *
- *      So we can do some basic sanity checks using the single-variate
- *      stats (the ones we have right now).
- *
- *      Second, when we have multivariate stats with a MCV list, then
- *
- *      (a) if we have a full equality condition (one equality condition
- *          on each column) and we found a match in the MCV list, this is
- *          the selectivity (and it's supposed to be exact)
- *
- *      (b) if we have a full equality condition and we haven't found a
- *          match in the MCV list, then the selectivity is below the
- *          lowest selectivity in the MCV list
- *
- *      (c) if we have a equality condition (not full), we can still
- *          search the MCV for matches and use the sum of probabilities
- *          as a lower boundary for the histogram (if there are no
- *          matches in the MCV list, then we have no boundary)
- *
- *      Third, if there are multiple (combinations of) multivariate
- *      stats for a set of clauses, we may compute all of them and then
- *      somehow aggregate them - e.g. by choosing the minimum, median or
- *      average. The stats are susceptible to overestimation (because
- *      we take 50% of the bucket for partial matches). Some stats may
- *      give better estimates than others, but it's very difficult to
- *      say that in advance which one is the best (it depends on the
- *      number of buckets, number of additional columns not referenced
- *      in the clauses, type of condition etc.).
- *
- *      So we may compute them all and then choose a sane aggregation
- *      (minimum seems like a good approach). Of course, this may result
- *      in longer / more expensive estimation (CPU-wise), but it may be
- *      worth it.
- *
- *      It's possible to add a GUC choosing whether to do a 'simple'
- *      (using a single stats expected to give the best estimate) and
- *      'complex' (combining the multiple estimates).
- *
- *          multivariate_estimates = (simple|full)
- *
- *      Also, this might be enabled at a table level, by something like
- *
- *          ALTER TABLE ... SET STATISTICS (simple|full)
- *
- *      Which would make it possible to use this only for the tables
- *      where the simple approach does not work.
- *
- *      Also, there are ways to optimize this algorithmically. E.g. we
- *      may try to get an estimate from a matching MCV list first, and
- *      if we happen to get a "full equality match" we may stop computing
- *      the estimates from other stats (for this condition) because
- *      that's probably the best estimate we can really get.
- *
- * TODO When applying the clauses to the histogram/MCV list, we can do
- *      that from the most selective clauses first, because that'll
- *      eliminate the buckets/items sooner (so we'll be able to skip
- *      them without inspection, which is more expensive). But this
- *      requires really knowing the per-clause selectivities in advance,
- *      and that's not what we do now.
- *
- * TODO All this is based on the assumption that the statistics represent
- *      the necessary dependencies, i.e. that if two colunms are not in
- *      the same statistics, there's no dependency. If that's not the
- *      case, we may get misestimates, just like before. For example
- *      assume we have a table with three columns [a,b,c] with exactly
- *      the same values, and statistics on [a,b] and [b,c]. So somthing
- *      like this:
- *
- *          CREATE TABLE test AS SELECT i, i, i
-                                  FROM generate_series(1,1000);
- *
- *          ALTER TABLE test ADD STATISTICS (mcv) ON (a,b);
- *          ALTER TABLE test ADD STATISTICS (mcv) ON (b,c);
- *
- *          ANALYZE test;
- *
- *          EXPLAIN ANALYZE SELECT * FROM test
- *                    WHERE (a < 10) AND (b < 20) AND (c < 10);
- *
- *      The problem here is that the only shared column between the two
- *      statistics is 'b' so the probability will be computed like this
- *
- *          P[(a < 10) & (b < 20) & (c < 10)]
- *             = P[(a < 10) & (b < 20)] * P[(c < 10) | (a < 10) & (b < 20)]
- *             = P[(a < 10) & (b < 20)] * P[(c < 10) | (b < 20)]
- *
- *      or like this
- *
- *          P[(a < 10) & (b < 20) & (c < 10)]
- *             = P[(b < 20) & (c < 10)] * P[(a < 10) | (b < 20) & (c < 10)]
- *             = P[(b < 20) & (c < 10)] * P[(a < 10) | (b < 20)]
- *
- *      In both cases the conditional probabilities will be evaluated as
- *      0.5, because they lack the other column (which would make it 1.0).
- *
- *      Theoretically it might be possible to transfer the dependency,
- *      e.g. by building bitmap for [a,b] and then combine it with [b,c]
- *      by doing something like this:
- *
- *          1) build bitmap on [a,b] using [(a<10) & (b < 20)]
- *          2) for each element in [b,c] check the bitmap
- *
- *      But that's certainly nontrivial - for example the statistics may
- *      be different (MCV list vs. histogram) and/or the items may not
- *      match (e.g. MCV items or histogram buckets will be built
- *      differently). Also, for one value of 'b' there might be multiple
- *      MCV items (because of the other column values) with different
- *      bitmap values (some will match, some won't) - so it's not exactly
- *      bitmap but a partial match.
- *
- *      Maybe a hash table with number of matches and mismatches (or
- *      maybe sums of frequencies) would work? The step (2) would then
- *      lookup the values and use that to weight the item somehow.
- * 
- *      Currently the only solution is to build statistics on all three
- *      columns.
- */
-static Selectivity
-clauselist_mv_selectivity(PlannerInfo *root, MVStatisticInfo *mvstats,
-						  List *clauses, List *conditions, bool is_or)
-{
-	bool fullmatch = false;
-	Selectivity s1 = 0.0, s2 = 0.0;
-
-	/*
-	 * Lowest frequency in the MCV list (may be used as an upper bound
-	 * for full equality conditions that did not match any MCV item).
-	 */
-	Selectivity mcv_low = 0.0;
-
-	/* TODO Evaluate simple 1D selectivities, use the smallest one as
-	 *      an upper bound, product as lower bound, and sort the
-	 *      clauses in ascending order by selectivity (to optimize the
-	 *      MCV/histogram evaluation).
-	 */
-
-	/* Evaluate the MCV first. */
-	s1 = clauselist_mv_selectivity_mcvlist(root, mvstats,
-										   clauses, conditions, is_or,
-										   &fullmatch, &mcv_low);
-
-	/*
-	 * If we got a full equality match on the MCV list, we're done (and
-	 * the estimate is pretty good).
-	 */
-	if (fullmatch && (s1 > 0.0))
-		return s1;
-
-	/* FIXME if (fullmatch) without matching MCV item, use the mcv_low
-	 *       selectivity as upper bound */
-
-	s2 = clauselist_mv_selectivity_histogram(root, mvstats,
-											 clauses, conditions, is_or);
-
-	/* TODO clamp to <= 1.0 (or more strictly, when possible) */
-	return s1 + s2;
-}
-
-/*
- * Collect attributes from mv-compatible clauses.
- */
-static Bitmapset *
-collect_mv_attnums(PlannerInfo *root, List *clauses, Oid varRelid,
-				   Index *relid, SpecialJoinInfo *sjinfo, int types)
-{
-	Bitmapset  *attnums = NULL;
-	ListCell   *l;
-
-	/*
-	 * Walk through the clauses and identify the ones we can estimate
-	 * using multivariate stats, and remember the relid/columns. We'll
-	 * then cross-check if we have suitable stats, and only if needed
-	 * we'll split the clauses into multivariate and regular lists.
-	 *
-	 * For now we're only interested in RestrictInfo nodes with nested
-	 * OpExpr, using either a range or equality.
-	 */
-	foreach (l, clauses)
-	{
-		Node	   *clause = (Node *) lfirst(l);
-
-		/* ignore the result here - we only need the attnums */
-		clause_is_mv_compatible(root, clause, varRelid, relid, &attnums,
-								sjinfo, types);
-	}
-
-	/*
-	 * If there are not at least two attributes referenced by the clause(s),
-	 * we can throw everything out (as we'll revert to simple stats).
-	 */
-	if (bms_num_members(attnums) <= 1)
-	{
-		bms_free(attnums);
-		attnums = NULL;
-		*relid = InvalidOid;
-	}
-
-	return attnums;
-}
-
-/*
- * Selects the best combination of multivariate statistics, in an
- * exhaustive way, where 'best' means:
- *
- * (a) covering the most attributes (referenced by clauses)
- * (b) using the least number of multivariate stats
- * (c) using the most conditions to exploit dependency
- *
- * There may be other optimality criteria, not considered in the initial
- * implementation (more on that 'weaknesses' section).
- *
- * This pretty much splits the probability of clauses (aka selectivity)
- * into a sequence of conditional probabilities, like this
- *
- *    P(A,B,C,D) = P(A,B) * P(C|A,B) * P(D|A,B,C)
- *
- * and removing the attributes not referenced by the existing stats,
- * under the assumption that there's no dependency (otherwise the DBA
- * would create the stats).
- *
- * The last criteria means that when we have the choice to compute like
- * this
- *
- *      P(A,B,C,D) = P(A,B,C) * P(D|B,C)
- *
- * or like this
- *
- *      P(A,B,C,D) = P(A,B,C) * P(D|C)
- *
- * we should use the first option, as that exploits more dependencies.
- *
- * The order of statistics in the solution implicitly determines the
- * order of estimation of clauses, because as we apply a statistics,
- * we always use it to estimate all the clauses covered by it (and
- * then we use those clauses as conditions for the next statistics).
- *
- * Don't call this directly but through choose_mv_statistics().
- *
- *
- * Algorithm
- * ---------
- * The algorithm is a recursive implementation of backtracking, with
- * maximum 'depth' equal to the number of multi-variate statistics
- * available on the table.
- *
- * It explores all the possible permutations of the stats.
- * 
- * Whenever it considers adding the next statistics, the clauses it
- * matches are divided into 'conditions' (clauses already matched by at
- * least one previous statistics) and clauses that are estimated.
- *
- * Then several checks are performed:
- *
- *  (a) The statistics covers at least 2 columns, referenced in the
- *      estimated clauses (otherwise multi-variate stats are useless).
- *
- *  (b) The statistics covers at least 1 new column, i.e. column not
- *      refefenced by the already used stats (and the new column has
- *      to be referenced by the clauses, of couse). Otherwise the
- *      statistics would not add any new information.
- *
- * There are some other sanity checks (e.g. that the stats must not be
- * used twice etc.).
- *
- * Finally the new solution is compared to the currently best one, and
- * if it's considered better, it's used instead.
- *
- *
- * Weaknesses
- * ----------
- * The current implemetation uses a somewhat simple optimality criteria,
- * suffering by the following weaknesses.
- *
- * (a) There may be multiple solutions with the same number of covered
- *     attributes and number of statistics (e.g. the same solution but
- *     with statistics in a different order). It's unclear which solution
- *     is the best one - in a sense all of them are equal.
- *
- * TODO It might be possible to compute estimate for each of those
- *      solutions, and then combine them to get the final estimate
- *      (e.g. by using average or median).
- *
- * (b) Does not consider that some types of stats are a better match for
- *     some types of clauses (e.g. MCV list is a good match for equality
- *     than a histogram).
- *
- *     XXX Maybe MCV is almost always better / more accurate?
- *
- *     But maybe this is pointless - generally, each column is either
- *     a label (it's not important whether because of the data type or
- *     how it's used), or a value with ordering that makes sense. So
- *     either a MCV list is more appropriate (labels) or a histogram
- *     (values with orderings).
- *
- *     Now sure what to do with statistics on columns mixing columns of
- *     both types - maybe it'd be beeter to invent a new type of stats
- *     combining MCV list and histogram (keeping a small histogram for
- *     each MCV item, and a separate histogram for values not on the
- *     MCV list). But that's not implemented at this moment.
- *
- * TODO The algorithm should probably count number of Vars (not just
- *      attnums) when computing the 'score' of each solution. Computing
- *      the ratio of (num of all vars) / (num of condition vars) as a
- *      measure of how well the solution uses conditions might be
- *      useful.
- */
-static void
-choose_mv_statistics_exhaustive(PlannerInfo *root, int step,
-					int nmvstats, MVStatisticInfo *mvstats, Bitmapset ** stats_attnums,
-					int nclauses, Node ** clauses, Bitmapset ** clauses_attnums,
-					int nconditions, Node ** conditions, Bitmapset ** conditions_attnums,
-					bool *cover_map, bool *condition_map, int *ruled_out,
-					mv_solution_t *current, mv_solution_t **best)
-{
-	int i, j;
-
-	Assert(best != NULL);
-	Assert((step == 0 && current == NULL) || (step > 0 && current != NULL));
-
-	CHECK_FOR_INTERRUPTS();
-
-	if (current == NULL)
-	{
-		current = (mv_solution_t*)palloc0(sizeof(mv_solution_t));
-		current->stats = (int*)palloc0(sizeof(int)*nmvstats);
-		current->nstats = 0;
-		current->nclauses = 0;
-		current->nconditions = 0;
-	}
-
-	/*
-	 * Now try to apply each statistics, matching at least two attributes,
-	 * unless it's already used in one of the previous steps.
-	 */
-	for (i = 0; i < nmvstats; i++)
-	{
-		int c;
-
-		int ncovered_clauses = 0;		/* number of covered clauses */
-		int ncovered_conditions = 0;	/* number of covered conditions */
-		int nattnums = 0;		/* number of covered attributes */
-
-		Bitmapset  *all_attnums = NULL;
-		Bitmapset  *new_attnums = NULL;
-
-		/* skip statistics that were already used or eliminated */
-		if (ruled_out[i] != -1)
-			continue;
-
-		/*
-		 * See if we have clauses covered by this statistics, but not
-		 * yet covered by any of the preceding onces.
-		 */
-		for (c = 0; c < nclauses; c++)
-		{
-			bool covered = false;
-			Bitmapset *clause_attnums = clauses_attnums[c];
-			Bitmapset *tmp = NULL;
-
-			/*
-			 * If this clause is not covered by this stats, we can't
-			 * use the stats to estimate that at all.
-			 */
-			if (! cover_map[i * nclauses + c])
-				continue;
-
-			/*
-			 * Now we know we'll use this clause - either as a condition
-			 * or as a new clause (the estimated one). So let's add the
-			 * attributes to the attnums from all the clauses usable with
-			 * this statistics.
-			 */
-			tmp = bms_union(all_attnums, clause_attnums);
-
-			/* free the old bitmap */
-			bms_free(all_attnums);
-			all_attnums = tmp;
-
-			/* let's see if it's covered by any of the previous stats */
-			for (j = 0; j < step; j++)
-			{
-				/* already covered by the previous stats */
-				if (cover_map[current->stats[j] * nclauses + c])
-					covered = true;
-
-				if (covered)
-					break;
-			}
-
-			/* if already covered, continue with the next clause */
-			if (covered)
-			{
-				ncovered_conditions += 1;
-				continue;
-			}
-
-			/*
-			 * OK, this clause is covered by this statistics (and not by
-			 * any of the previous ones)
-			 */
-			ncovered_clauses += 1;
-
-			/* add the attnums into attnums from 'new clauses' */
-			// new_attnums = bms_union(new_attnums, clause_attnums);
-		}
-
-		/* can't have more new clauses than original clauses */
-		Assert(nclauses >= ncovered_clauses);
-		Assert(ncovered_clauses >= 0);	/* mostly paranoia */
-
-		nattnums = bms_num_members(all_attnums);
-
-		/* free all the bitmapsets - we don't need them anymore */
-		bms_free(all_attnums);
-		bms_free(new_attnums);
-
-		all_attnums = NULL;
-		new_attnums = NULL;
-
-		/*
-		 * See if we have clauses covered by this statistics, but not
-		 * yet covered by any of the preceding onces.
-		 */
-		for (c = 0; c < nconditions; c++)
-		{
-			Bitmapset *clause_attnums = conditions_attnums[c];
-			Bitmapset *tmp = NULL;
-
-			/*
-			 * If this clause is not covered by this stats, we can't
-			 * use the stats to estimate that at all.
-			 */
-			if (! condition_map[i * nconditions + c])
-				continue;
-
-			/* count this as a condition */
-			ncovered_conditions += 1;
-
-			/*
-			 * Now we know we'll use this clause - either as a condition
-			 * or as a new clause (the estimated one). So let's add the
-			 * attributes to the attnums from all the clauses usable with
-			 * this statistics.
-			 */
-			tmp = bms_union(all_attnums, clause_attnums);
-
-			/* free the old bitmap */
-			bms_free(all_attnums);
-			all_attnums = tmp;
-		}
-
-		/*
-		 * Let's mark the statistics as 'ruled out' - either we'll use
-		 * it (and proceed to the next step), or it's incompatible.
-		 */
-		ruled_out[i] = step;
-
-		/*
-		 * There are no clauses usable with this statistics (not already
-		 * covered by aome of the previous stats).
-		 *
-		 * Similarly, if the clauses only use a single attribute, we
-		 * can't really use that.
-		 */
-		if ((ncovered_clauses == 0) || (nattnums < 2))
-			continue;
-
-		/*
-		 * TODO Not sure if it's possible to add a clause referencing
-		 *      only attributes already covered by previous stats?
-		 *      Introducing only some new dependency, not a new
-		 *      attribute. Couldn't come up with an example, though.
-		 *      Might be worth adding some assert.
-		 */
-
-		/*
-		 * got a suitable statistics - let's update the current solution,
-		 * maybe use it as the best solution
-		 */
-		current->nclauses += ncovered_clauses;
-		current->nconditions += ncovered_conditions;
-		current->nstats += 1;
-		current->stats[step] = i;
-
-		/*
-		 * We can never cover more clauses, or use more stats that we
-		 * actually have at the beginning.
-		 */
-		Assert(nclauses >= current->nclauses);
-		Assert(nmvstats >= current->nstats);
-		Assert(step < nmvstats);
-
-		/* we can't get more conditions that clauses and conditions combined
-		 *
-		 * FIXME This assert does not work because we count the conditions
-		 *       repeatedly (once for each statistics covering it).
-		 */
-		/* Assert((nconditions + nclauses) >= current->nconditions); */
-
-		if (*best == NULL)
-		{
-			*best = (mv_solution_t*)palloc0(sizeof(mv_solution_t));
-			(*best)->stats = (int*)palloc0(sizeof(int)*nmvstats);
-			(*best)->nstats = 0;
-			(*best)->nclauses = 0;
-			(*best)->nconditions = 0;
-		}
-
-		/* see if it's better than the current 'best' solution */
-		if ((current->nclauses > (*best)->nclauses) ||
-			((current->nclauses == (*best)->nclauses) &&
-			((current->nstats > (*best)->nstats))))
-		{
-			(*best)->nstats = current->nstats;
-			(*best)->nclauses = current->nclauses;
-			(*best)->nconditions = current->nconditions;
-			memcpy((*best)->stats, current->stats, nmvstats * sizeof(int));
-		}
-
-		/*
-		 * The recursion only makes sense if we haven't covered all the
-		 * attributes (then adding stats is not really possible).
-		 */
-		if ((step + 1) < nmvstats)
-			choose_mv_statistics_exhaustive(root, step+1,
-									nmvstats, mvstats, stats_attnums,
-									nclauses, clauses, clauses_attnums,
-									nconditions, conditions, conditions_attnums,
-									cover_map, condition_map, ruled_out,
-									current, best);
-
-		/* reset the last step */
-		current->nclauses -= ncovered_clauses;
-		current->nconditions -= ncovered_conditions;
-		current->nstats -= 1;
-		current->stats[step] = 0;
-
-		/* mark the statistics as usable again */
-		ruled_out[i] = -1;
-
-		Assert(current->nclauses >= 0);
-		Assert(current->nstats >= 0);
-	}
-
-	/* reset all statistics as 'incompatible' in this step */
-	for (i = 0; i < nmvstats; i++)
-		if (ruled_out[i] == step)
-			ruled_out[i] = -1;
-
-}
-
-/*
- * Greedy search for a multivariate solution - a sequence of statistics
- * covering the clauses. This chooses the "best" statistics at each step,
- * so the resulting solution may not be the best solution globally, but
- * this produces the solution in only N steps (where N is the number of
- * statistics), while the exhaustive approach may have to walk through
- * ~N! combinations (although some of those are terminated early).
- *
- * See the comments at choose_mv_statistics_exhaustive() as this does
- * the same thing (but in a different way).
- *
- * Don't call this directly, but through choose_mv_statistics().
- *
- * TODO There are probably other metrics we might use - e.g. using
- *      number of columns (num_cond_columns / num_cov_columns), which
- *      might work better with a mix of simple and complex clauses.
- *
- * TODO Also the choice at the very first step should be handled
- *      in a special way, because there will be 0 conditions at that
- *      moment, so there needs to be some other criteria - e.g. using
- *      the simplest (or most complex?) clause might be a good idea.
- *
- * TODO We might also select multiple stats using different criteria,
- *      and branch the search. This is however tricky, because if we
- *      choose k statistics at each step, we get k^N branches to
- *      walk through (with N steps). That's not really good with
- *      large number of stats (yet better than exhaustive search).
- */
-static void
-choose_mv_statistics_greedy(PlannerInfo *root, int step,
-					int nmvstats, MVStatisticInfo *mvstats, Bitmapset ** stats_attnums,
-					int nclauses, Node ** clauses, Bitmapset ** clauses_attnums,
-					int nconditions, Node ** conditions, Bitmapset ** conditions_attnums,
-					bool *cover_map, bool *condition_map, int *ruled_out,
-					mv_solution_t *current, mv_solution_t **best)
-{
-	int i, j;
-	int best_stat = -1;
-	double gain, max_gain = -1.0;
-
-	/*
-	 * Bitmap tracking which clauses are already covered (by the previous
-	 * statistics) and may thus serve only as a condition in this step.
-	 */
-	bool *covered_clauses = (bool*)palloc0(nclauses);
-
-	/*
-	 * Number of clauses and columns covered by each statistics - this
-	 * includes both conditions and clauses covered by the statistics for
-	 * the first time. The number of columns may count some columns
-	 * repeatedly - if a column is shared by multiple clauses, it will
-	 * be counted once for each clause (covered by the statistics).
-	 * So with two clauses [(a=1 OR b=2),(a<2 OR c>1)] the column "a"
-	 * will be counted twice (if both clauses are covered).
-	 *
-	 * The values for reduded statistics (that can't be applied) are
-	 * not computed, because that'd be pointless.
-	 */
-	int	*num_cov_clauses	= (int*)palloc0(sizeof(int) * nmvstats);
-	int	*num_cov_columns	= (int*)palloc0(sizeof(int) * nmvstats);
-
-	/*
-	 * Same as above, but this only includes clauses that are already
-	 * covered by the previous stats (and the current one).
-	 */
-	int	*num_cond_clauses	= (int*)palloc0(sizeof(int) * nmvstats);
-	int	*num_cond_columns	= (int*)palloc0(sizeof(int) * nmvstats);
-
-	/*
-	 * Number of attributes for each clause.
-	 *
-	 * TODO Might be computed in choose_mv_statistics() and then passed
-	 *      here, but then the function would not have the same signature
-	 *      as _exhaustive().
-	 */
-	int *attnum_counts = (int*)palloc0(sizeof(int) * nclauses);
-	int *attnum_cond_counts = (int*)palloc0(sizeof(int) * nconditions);
-
-	CHECK_FOR_INTERRUPTS();
-
-	Assert(best != NULL);
-	Assert((step == 0 && current == NULL) || (step > 0 && current != NULL));
-
-	/* compute attributes (columns) for each clause */
-	for (i = 0; i < nclauses; i++)
-		attnum_counts[i] = bms_num_members(clauses_attnums[i]);
-
-	/* compute attributes (columns) for each condition */
-	for (i = 0; i < nconditions; i++)
-		attnum_cond_counts[i] = bms_num_members(conditions_attnums[i]);
-
-	/* see which clauses are already covered at this point (by previous stats) */
-	for (i = 0; i < step; i++)
-		for (j = 0; j < nclauses; j++)
-			covered_clauses[j] |= (cover_map[current->stats[i] * nclauses + j]);
-
-	/* which remaining statistics covers most clauses / uses most conditions? */
-	for (i = 0; i < nmvstats; i++)
-	{
-		Bitmapset *attnums_covered = NULL;
-		Bitmapset *attnums_conditions = NULL;
-
-		/* skip stats that are already ruled out (either used or inapplicable) */
-		if (ruled_out[i] != -1)
-			continue;
-
-		/* count covered clauses and conditions (for the statistics) */
-		for (j = 0; j < nclauses; j++)
-		{
-			if (cover_map[i * nclauses + j])
-			{
-				Bitmapset *attnums_new
-					= bms_union(attnums_covered, clauses_attnums[j]);
-
-				/* get rid of the old bitmap and keep the unified result */
-				bms_free(attnums_covered);
-				attnums_covered = attnums_new;
-
-				num_cov_clauses[i] += 1;
-				num_cov_columns[i] += attnum_counts[j];
-
-				/* is the clause already covered (i.e. a condition)? */
-				if (covered_clauses[j])
-				{
-					num_cond_clauses[i] += 1;
-					num_cond_columns[i] += attnum_counts[j];
-					attnums_new = bms_union(attnums_conditions,
-											clauses_attnums[j]);
-
-					bms_free(attnums_conditions);
-					attnums_conditions = attnums_new;
-				}
-			}
-		}
-
-		/* if all covered clauses are covered by prev stats (thus conditions) */
-		if (num_cov_clauses[i] == num_cond_clauses[i])
-			ruled_out[i] = step;
-
-		/* same if there are no new attributes */
-		else if (bms_num_members(attnums_conditions) == bms_num_members(attnums_covered))
-			ruled_out[i] = step;
-
-		bms_free(attnums_covered);
-		bms_free(attnums_conditions);
-
-		/* if the statistics is inapplicable, try the next one */
-		if (ruled_out[i] != -1)
-			continue;
-
-		/* now let's walk through conditions and count the covered */
-		for (j = 0; j < nconditions; j++)
-		{
-			if (condition_map[i * nconditions + j])
-			{
-				num_cond_clauses[i] += 1;
-				num_cond_columns[i] += attnum_cond_counts[j];
-			}
-		}
-
-		/* otherwise see if this improves the interesting metrics */
-		gain = num_cond_columns[i] / (double)num_cov_columns[i];
-
-		if (gain > max_gain)
-		{
-			max_gain = gain;
-			best_stat = i;
-		}
-	}
-
-	/*
-	 * Have we found a suitable statistics? Add it to the solution and
-	 * try next step.
-	 */
-	if (best_stat != -1)
-	{
-		/* mark the statistics, so that we skip it in next steps */
-		ruled_out[best_stat] = step;
-
-		/* allocate current solution if necessary */
-		if (current == NULL)
-		{
-			current = (mv_solution_t*)palloc0(sizeof(mv_solution_t));
-			current->stats = (int*)palloc0(sizeof(int)*nmvstats);
-			current->nstats = 0;
-			current->nclauses = 0;
-			current->nconditions = 0;
-		}
-
-		current->nclauses += num_cov_clauses[best_stat];
-		current->nconditions += num_cond_clauses[best_stat];
-		current->stats[step] = best_stat;
-		current->nstats++;
-
-		if (*best == NULL)
-		{
-			(*best) = (mv_solution_t*)palloc0(sizeof(mv_solution_t));
-			(*best)->nstats = current->nstats;
-			(*best)->nclauses = current->nclauses;
-			(*best)->nconditions = current->nconditions;
-
-			(*best)->stats = (int*)palloc0(sizeof(int)*nmvstats);
-			memcpy((*best)->stats, current->stats, nmvstats * sizeof(int));
-		}
-		else
-		{
-			/* see if this is a better solution */
-			double current_gain = (double)current->nconditions / current->nclauses;
-			double best_gain    = (double)(*best)->nconditions / (*best)->nclauses;
-
-			if ((current_gain > best_gain) ||
-				((current_gain == best_gain) && (current->nstats < (*best)->nstats)))
-			{
-				(*best)->nstats = current->nstats;
-				(*best)->nclauses = current->nclauses;
-				(*best)->nconditions = current->nconditions;
-				memcpy((*best)->stats, current->stats, nmvstats * sizeof(int));
-			}
-		}
-
-		/*
-		 * The recursion only makes sense if we haven't covered all the
-		 * attributes (then adding stats is not really possible).
-		*/
-		if ((step + 1) < nmvstats)
-			choose_mv_statistics_greedy(root, step+1,
-									nmvstats, mvstats, stats_attnums,
-									nclauses, clauses, clauses_attnums,
-									nconditions, conditions, conditions_attnums,
-									cover_map, condition_map, ruled_out,
-									current, best);
-
-		/* reset the last step */
-		current->nclauses -= num_cov_clauses[best_stat];
-		current->nconditions -= num_cond_clauses[best_stat];
-		current->nstats -= 1;
-		current->stats[step] = 0;
-
-		/* mark the statistics as usable again */
-		ruled_out[best_stat] = -1;
-	}
-
-	/* reset all statistics eliminated in this step */
-	for (i = 0; i < nmvstats; i++)
-		if (ruled_out[i] == step)
-			ruled_out[i] = -1;
-
-	/* free everything allocated in this step */
-	pfree(covered_clauses);
-	pfree(attnum_counts);
-	pfree(num_cov_clauses);
-	pfree(num_cov_columns);
-	pfree(num_cond_clauses);
-	pfree(num_cond_columns);
-}
-
-/*
- * Chooses the combination of statistics, optimal for estimation of
- * a particular clause list.
- *
- * This only handles a 'preparation' shared by the exhaustive and greedy
- * implementations (see the previous methods), mostly trying to reduce
- * the size of the problem (eliminate clauses/statistics that can't be
- * really used in the solution).
- *
- * It also precomputes bitmaps for attributes covered by clauses and
- * statistics, so that we don't need to do that over and over in the
- * actual optimizations (as it's both CPU and memory intensive).
- *
- * TODO This will probably have to consider compatibility of clauses,
- *      because 'dependencies' will probably work only with equality
- *      clauses.
- *
- * TODO Another way to make the optimization problems smaller might
- *      be splitting the statistics into several disjoint subsets, i.e.
- *      if we can split the graph of statistics (after the elimination)
- *      into multiple components (so that stats in different components
- *      share no attributes), we can do the optimization for each
- *      component separately.
- *
- * TODO If we could compute what is a "perfect solution" maybe we could
- *      terminate the search after reaching ~90% of it? Say, if we knew
- *      that we can cover 10 clauses and reuse 8 dependencies, maybe
- *      covering 9 clauses and 7 dependencies would be OK?
- */
-static List*
-choose_mv_statistics(PlannerInfo *root, List *stats,
-					 List *clauses, List *conditions,
-					 Oid varRelid, SpecialJoinInfo *sjinfo)
-{
-	int i;
-	mv_solution_t *best = NULL;
-	List *result = NIL;
-
-	int nmvstats;
-	MVStatisticInfo *mvstats;
-
-	/* we only work with MCV lists and histograms here */
-	int type = (MV_CLAUSE_TYPE_MCV | MV_CLAUSE_TYPE_HIST);
-
-	bool   *clause_cover_map = NULL,
-		   *condition_cover_map = NULL;
-	int	   *ruled_out = NULL;
-
-	/* build bitmapsets for all stats and clauses */
-	Bitmapset **stats_attnums;
-	Bitmapset **clauses_attnums;
-	Bitmapset **conditions_attnums;
-
-	int nclauses, nconditions;
-	Node ** clauses_array;
-	Node ** conditions_array;
-
-	/* copy lists, so that we can free them during elimination easily */
-	clauses = list_copy(clauses);
-	conditions = list_copy(conditions);
-	stats = list_copy(stats);
-
-	/*
-	 * Reduce the optimization problem size as much as possible.
-	 *
-	 * Eliminate clauses and conditions not covered by any statistics,
-	 * or statistics not matching at least two attributes (one of them
-	 * has to be in a regular clause).
-	 *
-	 * It's possible that removing a statistics in one iteration
-	 * eliminates clause in the next one, so we'll repeat this until we
-	 * eliminate no clauses/stats in that iteration.
-	 *
-	 * This can only happen after eliminating a statistics - clauses are
-	 * eliminated first, so statistics always reflect that.
-	 */
-	while (true)
-	{
-		List	   *tmp;
-
-		Bitmapset *compatible_attnums = NULL;
-		Bitmapset *condition_attnums  = NULL;
-		Bitmapset *all_attnums = NULL;
-
-		/*
-		 * Clauses
-		 *
-		 * Walk through clauses and keep only those covered by at least
-		 * one of the statistics we still have. We'll also keep info
-		 * about attnums in clauses (without conditions) so that we can
-		 * ignore stats covering just conditions (which is pointless).
-		 */
-		tmp = filter_clauses(root, varRelid, sjinfo, type,
-							 stats, clauses, &compatible_attnums);
-
-		/* discard the original list */
-		list_free(clauses);
-		clauses = tmp;
-
-		/*
-		 * Conditions
-		 *
-		 * Walk through clauses and keep only those covered by at least
-		 * one of the statistics we still have. Also, collect bitmap of
-		 * attributes so that we can make sure we add at least one new
-		 * attribute (by comparing with clauses).
-		 */
-		if (conditions != NIL)
-		{
-			tmp = filter_clauses(root, varRelid, sjinfo, type,
-								 stats, conditions, &condition_attnums);
-
-			/* discard the original list */
-			list_free(conditions);
-			conditions = tmp;
-		}
-
-		/* get a union of attnums (from conditions and new clauses) */
-		all_attnums = bms_union(compatible_attnums, condition_attnums);
-
-		/*
-		 * Statisitics
-		 *
-		 * Walk through statistics and only keep those covering at least
-		 * one new attribute (excluding conditions) and at two attributes
-		 * in both clauses and conditions.
-		 */
-		tmp = filter_stats(stats, compatible_attnums, all_attnums);
-
-		/* if we've not eliminated anything, terminate */
-		if (list_length(stats) == list_length(tmp))
-			break;
-
-		/* work only with filtered statistics from now */
-		list_free(stats);
-		stats = tmp;
-	}
-
-	/* only do the optimization if we have clauses/statistics */
-	if ((list_length(stats) == 0) || (list_length(clauses) == 0))
-		return NULL;
-
-	/* remove redundant stats (stats covered by another stats) */
-	stats = filter_redundant_stats(stats, clauses, conditions);
-
-	/*
-	 * TODO We should sort the stats to make the order deterministic,
-	 *      otherwise we may get different estimates on different
-	 *      executions - if there are multiple "equally good" solutions,
-	 *      we'll keep the first solution we see.
-	 *
-	 *      Sorting by OID probably is not the right solution though,
-	 *      because we'd like it to be somehow reproducible,
-	 *      irrespectedly of the order of ADD STATISTICS commands.
-	 *      So maybe statkeys?
-	 */
-	mvstats = make_stats_array(stats, &nmvstats);
-	stats_attnums = make_stats_attnums(mvstats, nmvstats);
-
-	/* collect clauses an bitmap of attnums */
-	clauses_array = make_clauses_array(clauses, &nclauses);
-	clauses_attnums = make_clauses_attnums(root, varRelid, sjinfo, type,
-										   clauses_array, nclauses);
-
-	/* collect conditions and bitmap of attnums */
-	conditions_array = make_clauses_array(conditions, &nconditions);
-	conditions_attnums = make_clauses_attnums(root, varRelid, sjinfo, type,
-										   conditions_array, nconditions);
-
-	/*
-	 * Build bitmaps with info about which clauses/conditions are
-	 * covered by each statistics (so that we don't need to call the
-	 * bms_is_subset over and over again).
-	 */
-	clause_cover_map = make_cover_map(stats_attnums, nmvstats,
-									  clauses_attnums, nclauses);
-
-	condition_cover_map	= make_cover_map(stats_attnums, nmvstats,
-										 conditions_attnums, nconditions);
-
-	ruled_out =  (int*)palloc0(nmvstats * sizeof(int));
-
-	/* no stats are ruled out by default */
-	for (i = 0; i < nmvstats; i++)
-		ruled_out[i] = -1;
-
-	/* do the optimization itself */
-	if (mvstat_search_type == MVSTAT_SEARCH_EXHAUSTIVE)
-		choose_mv_statistics_exhaustive(root, 0,
-									   nmvstats, mvstats, stats_attnums,
-									   nclauses, clauses_array, clauses_attnums,
-									   nconditions, conditions_array, conditions_attnums,
-									   clause_cover_map, condition_cover_map,
-									   ruled_out, NULL, &best);
-	else
-		choose_mv_statistics_greedy(root, 0,
-									   nmvstats, mvstats, stats_attnums,
-									   nclauses, clauses_array, clauses_attnums,
-									   nconditions, conditions_array, conditions_attnums,
-									   clause_cover_map, condition_cover_map,
-									   ruled_out, NULL, &best);
-
-	/* create a list of statistics from the array */
-	if (best != NULL)
-	{
-		for (i = 0; i < best->nstats; i++)
-		{
-			MVStatisticInfo *info = makeNode(MVStatisticInfo);
-			memcpy(info, &mvstats[best->stats[i]], sizeof(MVStatisticInfo));
-			result = lappend(result, info);
-		}
-		pfree(best);
-	}
-
-	/* cleanup (maybe leave it up to the memory context?) */
-	for (i = 0; i < nmvstats; i++)
-		bms_free(stats_attnums[i]);
-
-	for (i = 0; i < nclauses; i++)
-		bms_free(clauses_attnums[i]);
-
-	for (i = 0; i < nconditions; i++)
-		bms_free(conditions_attnums[i]);
-
-	pfree(stats_attnums);
-	pfree(clauses_attnums);
-	pfree(conditions_attnums);
-
-	pfree(clauses_array);
-	pfree(conditions_array);
-	pfree(clause_cover_map);
-	pfree(condition_cover_map);
-	pfree(ruled_out);
-	pfree(mvstats);
-
-	list_free(clauses);
-	list_free(conditions);
-	list_free(stats);
-
-	return result;
-}
-
-
-/*
- * This splits the clauses list into two parts - one containing clauses
- * that will be evaluated using the chosen statistics, and the remaining
- * clauses (either non-mvcompatible, or not related to the histogram).
- */
-static List *
-clauselist_mv_split(PlannerInfo *root, SpecialJoinInfo *sjinfo,
-					List *clauses, Oid varRelid, List **mvclauses,
-					MVStatisticInfo *mvstats, int types)
-{
-	int i;
-	ListCell *l;
-	List	 *non_mvclauses = NIL;
-
-	/* FIXME is there a better way to get info on int2vector? */
-	int2vector * attrs = mvstats->stakeys;
-	int	numattrs = mvstats->stakeys->dim1;
-
-	Bitmapset *mvattnums = NULL;
-
-	/* build bitmap of attributes covered by the stats, so we can
-	 * do bms_is_subset later */
-	for (i = 0; i < numattrs; i++)
-		mvattnums = bms_add_member(mvattnums, attrs->values[i]);
-
-	/* erase the list of mv-compatible clauses */
-	*mvclauses = NIL;
-
-	foreach (l, clauses)
-	{
-		bool		match = false;	/* by default not mv-compatible */
-		Bitmapset	*attnums = NULL;
-		Node	   *clause = (Node *) lfirst(l);
-
-		if (clause_is_mv_compatible(root, clause, varRelid, NULL,
-									&attnums, sjinfo, types))
-		{
-			/* are all the attributes part of the selected stats? */
-			if (bms_is_subset(attnums, mvattnums))
-				match = true;
-		}
-
-		/*
-		 * The clause matches the selected stats, so put it to the list
-		 * of mv-compatible clauses. Otherwise, keep it in the list of
-		 * 'regular' clauses (that may be selected later).
-		 */
-		if (match)
-			*mvclauses = lappend(*mvclauses, clause);
-		else
-			non_mvclauses = lappend(non_mvclauses, clause);
-	}
-
-	/*
-	 * Perform regular estimation using the clauses incompatible
-	 * with the chosen histogram (or MV stats in general).
-	 */
-	return non_mvclauses;
-
-}
-
-/*
- * Determines whether the clause is compatible with multivariate stats,
- * and if it is, returns some additional information - varno (index
- * into simple_rte_array) and a bitmap of attributes. This is then
- * used to fetch related multivariate statistics.
- *
- * At this moment we only support basic conditions of the form
- *
- *     variable OP constant
- *
- * where OP is one of [=,<,<=,>=,>] (which is however determined by
- * looking at the associated function for estimating selectivity, just
- * like with the single-dimensional case).
- *
- * TODO Support 'OR clauses' - shouldn't be all that difficult to
- *      evaluate them using multivariate stats.
- */
-static bool
-clause_is_mv_compatible(PlannerInfo *root, Node *clause, Oid varRelid,
-						Index *relid, Bitmapset **attnums, SpecialJoinInfo *sjinfo,
-						int types)
-{
-	Relids clause_relids;
-	Relids left_relids;
-	Relids right_relids;
-
-	if (IsA(clause, RestrictInfo))
-	{
-		RestrictInfo *rinfo = (RestrictInfo *) clause;
-
-		/* Pseudoconstants are not really interesting here. */
-		if (rinfo->pseudoconstant)
-			return false;
-
-		/* get the actual clause from the RestrictInfo (it's not an OR clause) */
-		clause = (Node*)rinfo->clause;
-
-		/* we don't support join conditions at this moment */
-		if (treat_as_join_clause(clause, rinfo, varRelid, sjinfo))
-			return false;
-
-		clause_relids = rinfo->clause_relids;
-		left_relids = rinfo->left_relids;
-		right_relids = rinfo->right_relids;
-	}
-	else if (is_opclause(clause) && list_length(((OpExpr *) clause)->args) == 2)
-	{
-		left_relids = pull_varnos(get_leftop((Expr*)clause));
-		right_relids = pull_varnos(get_rightop((Expr*)clause));
-
-		clause_relids = bms_union(left_relids,
-								  right_relids);
-	}
-	else
-	{
-		/* Not a binary opclause, so mark left/right relid sets as empty */
-		left_relids = NULL;
-		right_relids = NULL;
-		/* and get the total relid set the hard way */
-		clause_relids = pull_varnos((Node *) clause);
-	}
-
-	/*
-	 * Only simple opclauses and IS NULL tests are compatible with
-	 * multivariate stats at this point.
-	 */
-	if ((is_opclause(clause))
-		&& (list_length(((OpExpr *) clause)->args) == 2))
-	{
-		OpExpr	   *expr = (OpExpr *) clause;
-		bool		varonleft = true;
-		bool		ok;
-
-		/* is it 'variable op constant' ? */
-		ok = (bms_membership(clause_relids) == BMS_SINGLETON) &&
-			(is_pseudo_constant_clause_relids(lsecond(expr->args),
-											  right_relids) ||
-			(varonleft = false,
-			is_pseudo_constant_clause_relids(linitial(expr->args),
-											 left_relids)));
-
-		if (ok)
-		{
-			Var * var = (varonleft) ? linitial(expr->args) : lsecond(expr->args);
-
-			/*
-			 * Simple variables only - otherwise the planner_rt_fetch seems to fail
-			 * (return NULL).
-			 *
-			 * TODO Maybe use examine_variable() would fix that?
-			 */
-			if (! (IsA(var, Var) && (varRelid == 0 || varRelid == var->varno)))
-				return false;
-
-			/*
-			 * Only consider this variable if (varRelid == 0) or when the varno
-			 * matches varRelid (see explanation at clause_selectivity).
-			 *
-			 * FIXME I suspect this may not be really necessary. The (varRelid == 0)
-			 *       part seems to be enforced by treat_as_join_clause().
-			 */
-			if (! ((varRelid == 0) || (varRelid == var->varno)))
-				return false;
-
-			/* Also skip special varno values, and system attributes ... */
-			if ((IS_SPECIAL_VARNO(var->varno)) || (! AttrNumberIsForUserDefinedAttr(var->varattno)))
-				return false;
-
-			/* Lookup info about the base relation (we need to pass the OID out) */
-			if (relid != NULL)
-				*relid = var->varno;
-
-			/*
-			 * If it's not a "<" or ">" or "=" operator, just ignore the
-			 * clause. Otherwise note the relid and attnum for the variable.
-			 * This uses the function for estimating selectivity, ont the
-			 * operator directly (a bit awkward, but well ...).
-			 */
-			switch (get_oprrest(expr->opno))
-				{
-					case F_SCALARLTSEL:
-					case F_SCALARGTSEL:
-						/* not compatible with functional dependencies */
-						if (types & (MV_CLAUSE_TYPE_MCV | MV_CLAUSE_TYPE_HIST))
-						{
-							*attnums = bms_add_member(*attnums, var->varattno);
-							return (types & (MV_CLAUSE_TYPE_MCV | MV_CLAUSE_TYPE_HIST));
-						}
-						return false;
-
-					case F_EQSEL:
-						*attnums = bms_add_member(*attnums, var->varattno);
-						return true;
-				}
-		}
-	}
-	else if (IsA(clause, NullTest)
-			 && IsA(((NullTest*)clause)->arg, Var))
-	{
-		Var * var = (Var*)((NullTest*)clause)->arg;
-
-		/*
-		 * Simple variables only - otherwise the planner_rt_fetch seems to fail
-		 * (return NULL).
-		 *
-		 * TODO Maybe use examine_variable() would fix that?
-		 */
-		if (! (IsA(var, Var) && (varRelid == 0 || varRelid == var->varno)))
-			return false;
-
-		/*
-		 * Only consider this variable if (varRelid == 0) or when the varno
-		 * matches varRelid (see explanation at clause_selectivity).
-		 *
-		 * FIXME I suspect this may not be really necessary. The (varRelid == 0)
-		 *       part seems to be enforced by treat_as_join_clause().
-		 */
-		if (! ((varRelid == 0) || (varRelid == var->varno)))
-			return false;
-
-		/* Also skip special varno values, and system attributes ... */
-		if ((IS_SPECIAL_VARNO(var->varno)) || (! AttrNumberIsForUserDefinedAttr(var->varattno)))
-			return false;
-
-		/* Lookup info about the base relation (we need to pass the OID out) */
-		if (relid != NULL)
-				*relid = var->varno;
-
-		*attnums = bms_add_member(*attnums, var->varattno);
-
-		return true;
-	}
-	else if (or_clause(clause) || and_clause(clause))
-	{
-		/*
-		 * AND/OR-clauses are supported if all sub-clauses are supported
-		 *
-		 * TODO We might support mixed case, where some of the clauses
-		 *      are supported and some are not, and treat all supported
-		 *      subclauses as a single clause, compute it's selectivity
-		 *      using mv stats, and compute the total selectivity using
-		 *      the current algorithm.
-		 *
-		 * TODO For RestrictInfo above an OR-clause, we might use the
-		 *      orclause with nested RestrictInfo - we won't have to
-		 *      call pull_varnos() for each clause, saving time. 
-		 */
-		Bitmapset *tmp = NULL;
-		ListCell *l;
-		foreach (l, ((BoolExpr*)clause)->args)
-		{
-			if (! clause_is_mv_compatible(root, (Node*)lfirst(l),
-						varRelid, relid, &tmp, sjinfo, types))
-				return false;
-		}
-
-		/* add the attnums from the OR-clause to the set of attnums */
-		*attnums = bms_join(*attnums, tmp);
-
-		return true;
-	}
-
-	return false;
-}
-
-
-static Bitmapset *
-clause_mv_get_attnums(PlannerInfo *root, Node *clause)
-{
-	Bitmapset * attnums = NULL;
-
-	/* Extract clause from restrict info, if needed. */
-	if (IsA(clause, RestrictInfo))
-		clause = (Node*)((RestrictInfo*)clause)->clause;
-
-	/*
-	 * Only simple opclauses and IS NULL tests are compatible with
-	 * multivariate stats at this point.
-	 */
-	if ((is_opclause(clause))
-		&& (list_length(((OpExpr *) clause)->args) == 2))
-	{
-		OpExpr	   *expr = (OpExpr *) clause;
-
-		if (IsA(linitial(expr->args), Var))
-			attnums = bms_add_member(attnums,
-							((Var*)linitial(expr->args))->varattno);
-		else
-			attnums = bms_add_member(attnums,
-							((Var*)lsecond(expr->args))->varattno);
-	}
-	else if (IsA(clause, NullTest)
-			 && IsA(((NullTest*)clause)->arg, Var))
-	{
-		attnums = bms_add_member(attnums,
-							((Var*)((NullTest*)clause)->arg)->varattno);
-	}
-	else if (or_clause(clause) || and_clause(clause))
-	{
-		ListCell *l;
-		foreach (l, ((BoolExpr*)clause)->args)
-		{
-			attnums = bms_join(attnums,
-						clause_mv_get_attnums(root, (Node*)lfirst(l)));
-		}
-	}
-
-	return attnums;
-}
-
-/*
- * Performs reduction of clauses using functional dependencies, i.e.
- * removes clauses that are considered redundant. It simply walks
- * through dependencies, and checks whether the dependency 'matches'
- * the clauses, i.e. if there's a clause matching the condition. If yes,
- * all clauses matching the implied part of the dependency are removed
- * from the list.
- *
- * This simply looks at attnums references by the clauses, not at the
- * type of the operator (equality, inequality, ...). This may not be the
- * right way to do - it certainly works best for equalities, which is
- * naturally consistent with functional dependencies (implications).
- * It's not clear that other operators are handled sensibly - for
- * example for inequalities, like
- *
- *     WHERE (A >= 10) AND (B <= 20)
- *
- * and a trivial case where [A == B], resulting in symmetric pair of
- * rules [A => B], [B => A], it's rather clear we can't remove either of
- * those clauses.
- *
- * That only highlights that functional dependencies are most suitable
- * for label-like data, where using non-equality operators is very rare.
- * Using the common city/zipcode example, clauses like
- *
- *     (zipcode <= 12345)
- *
- * or
- *
- *     (cityname >= 'Washington')
- *
- * are rare. So restricting the reduction to equality should not harm
- * the usefulness / applicability.
- *
- * The other assumption is that this assumes 'compatible' clauses. For
- * example by using mismatching zip code and city name, this is unable
- * to identify the discrepancy and eliminates one of the clauses. The
- * usual approach (multiplying both selectivities) thus produces a more
- * accurate estimate, although mostly by luck - the multiplication
- * comes from assumption of statistical independence of the two
- * conditions (which is not not valid in this case), but moves the
- * estimate in the right direction (towards 0%).
- *
- * This might be somewhat improved by cross-checking the selectivities
- * against MCV and/or histogram.
- *
- * The implementation needs to be careful about cyclic rules, i.e. rules
- * like [A => B] and [B => A] at the same time. This must not reduce
- * clauses on both attributes at the same time.
- *
- * Technically we might consider selectivities here too, somehow. E.g.
- * when (A => B) and (B => A), we might use the clauses with minimum
- * selectivity.
- *
- * TODO Consider restricting the reduction to equality clauses. Or maybe
- *      use equality classes somehow?
- *
- * TODO Merge this docs to dependencies.c, as it's saying mostly the
- *      same things as the comments there.
- *
- * TODO Currently this is applied only to the top-level clauses, but
- *      maybe we could apply it to lists at subtrees too, e.g. to the
- *      two AND-clauses in
- *
- *          (x=1 AND y=2) OR (z=3 AND q=10)
- *
- */
-static List *
-clauselist_apply_dependencies(PlannerInfo *root, List *clauses,
-							  Oid varRelid, List *stats,
-							  SpecialJoinInfo *sjinfo)
-{
-	List	   *reduced_clauses = NIL;
-	Index		relid;
-
-	/*
-	 * matrix of (natts x natts), 1 means x=>y
-	 *
-	 * This serves two purposes - first, it merges dependencies from all
-	 * the statistics, second it makes generating all the transitive
-	 * dependencies easier.
-	 *
-	 * We need to build this only for attributes from the dependencies,
-	 * not for all attributes in the table.
-	 *
-	 * We can't do that only for attributes from the clauses, because we
-	 * want to build transitive dependencies (including those going
-	 * through attributes not listed in the stats).
-	 *
-	 * This only works for A=>B dependencies, not sure how to do that
-	 * for complex dependencies.
-	 */
-	bool       *deps_matrix;
-	int			deps_natts;	/* size of the matric */
-
-	/* mapping attnum <=> matrix index */
-	int		   *deps_idx_to_attnum;
-	int		   *deps_attnum_to_idx;
-
-	/* attnums in dependencies and clauses (and intersection) */
-	List	   *deps_clauses   = NIL;
-	Bitmapset  *deps_attnums   = NULL;
-	Bitmapset  *clause_attnums = NULL;
-	Bitmapset  *intersect_attnums = NULL;
-
-	/*
-	 * Is there at least one statistics with functional dependencies?
-	 * If not, return the original clauses right away.
-	 *
-	 * XXX Isn't this pointless, thanks to exactly the same check in
-	 *     clauselist_selectivity()? Can we trigger the condition here?
-	 */
-	if (! has_stats(stats, MV_CLAUSE_TYPE_FDEP))
-		return clauses;
-
-	/*
-	 * Build the dependency matrix, i.e. attribute adjacency matrix,
-	 * where 1 means (a=>b). Once we have the adjacency matrix, we'll
-	 * multiply it by itself, to get transitive dependencies.
-	 *
-	 * Note: This is pretty much transitive closure from graph theory.
-	 *
-	 * First, let's see what attributes are covered by functional
-	 * dependencies (sides of the adjacency matrix), and also a maximum
-	 * attribute (size of mapping to simple integer indexes);
-	 */
-	deps_attnums = fdeps_collect_attnums(stats);
-
-	/*
-	 * Walk through the clauses - clauses that are (one of)
-	 *
-	 * (a) not mv-compatible
-	 * (b) are using more than a single attnum
-	 * (c) using attnum not covered by functional depencencies
-	 *
-	 * may be copied directly to the result. The interesting clauses are
-	 * kept in 'deps_clauses' and will be processed later.
-	 */
-	clause_attnums = fdeps_filter_clauses(root, clauses, deps_attnums,
-										  &reduced_clauses, &deps_clauses,
-										  varRelid, &relid, sjinfo);
-
-	/*
-	 * we need at least two clauses referencing two different attributes
-	 * referencing to do the reduction
-	 */
-	if ((list_length(deps_clauses) < 2) || (bms_num_members(clause_attnums) < 2))
-	{
-		bms_free(clause_attnums);
-		list_free(reduced_clauses);
-		list_free(deps_clauses);
-
-		return clauses;
-	}
-
-
-	/*
-	 * We need at least two matching attributes in the clauses and
-	 * dependencies, otherwise we can't really reduce anything.
-	 */
-	intersect_attnums = bms_intersect(clause_attnums, deps_attnums);
-	if (bms_num_members(intersect_attnums) < 2)
-	{
-		bms_free(clause_attnums);
-		bms_free(deps_attnums);
-		bms_free(intersect_attnums);
-
-		list_free(deps_clauses);
-		list_free(reduced_clauses);
-
-		return clauses;
-	}
-
-	/*
-	 * Build mapping between matrix indexes and attnums, and then the
-	 * adjacency matrix itself.
-	 */
-	deps_idx_to_attnum = make_idx_to_attnum_mapping(deps_attnums);
-	deps_attnum_to_idx = make_attnum_to_idx_mapping(deps_attnums);
-
-	/* build the adjacency matrix */
-	deps_matrix = build_adjacency_matrix(stats, deps_attnums,
-										 deps_idx_to_attnum,
-										 deps_attnum_to_idx);
-
-	deps_natts = bms_num_members(deps_attnums);
-
-	/*
-	 * Multiply the matrix N-times (N = size of the matrix), so that we
-	 * get all the transitive dependencies. That makes the next step
-	 * much easier and faster.
-	 *
-	 * This is essentially an adjacency matrix from graph theory, and
-	 * by multiplying it we get transitive edges. We don't really care
-	 * about the exact number (number of paths between vertices) though,
-	 * so we can do the multiplication in-place (we don't care whether
-	 * we found the dependency in this round or in the previous one).
-	 *
-	 * Track how many new dependencies were added, and stop when 0, but
-	 * we can't multiply more than N-times (longest path in the graph).
-	 */
-	multiply_adjacency_matrix(deps_matrix, deps_natts);
-
-	/*
-	 * Walk through the clauses, and see which other clauses we may
-	 * reduce. The matrix contains all transitive dependencies, which
-	 * makes this very fast.
-	 *
-	 * We have to be careful not to reduce the clause using itself, or
-	 * reducing all clauses forming a cycle (so we have to skip already
-	 * eliminated clauses).
-	 *
-	 * I'm not sure whether this guarantees finding the best solution,
-	 * i.e. reducing the most clauses, but it probably does (thanks to
-	 * having all the transitive dependencies).
-	 */
-	deps_clauses = fdeps_reduce_clauses(deps_clauses,
-										deps_attnums, deps_matrix,
-										deps_idx_to_attnum,
-										deps_attnum_to_idx, relid);
-
-	/* join the two lists of clauses */
-	reduced_clauses = list_union(reduced_clauses, deps_clauses);
-
-	pfree(deps_matrix);
-	pfree(deps_idx_to_attnum);
-	pfree(deps_attnum_to_idx);
-
-	bms_free(deps_attnums);
-	bms_free(clause_attnums);
-	bms_free(intersect_attnums);
-
-	return reduced_clauses;
-}
-
-static bool
-has_stats(List *stats, int type)
-{
-	ListCell   *s;
-
-	foreach (s, stats)
-	{
-		MVStatisticInfo	*stat = (MVStatisticInfo *)lfirst(s);
-
-		if ((type & MV_CLAUSE_TYPE_FDEP) && stat->deps_built)
-			return true;
-
-		if ((type & MV_CLAUSE_TYPE_MCV) && stat->mcv_built)
-			return true;
-
-		if ((type & MV_CLAUSE_TYPE_HIST) && stat->hist_built)
-			return true;
-	}
-
-	return false;
-}
-
-/*
- * Determing relid (either from varRelid or from clauses) and then
- * lookup stats using the relid.
- */
-static List *
-find_stats(PlannerInfo *root, List *clauses, Oid varRelid, Index *relid)
-{
-	/* unknown relid by default */
-	*relid = InvalidOid;
-
-	/*
-	 * First we need to find the relid (index info simple_rel_array).
-	 * If varRelid is not 0, we already have it, otherwise we have to
-	 * look it up from the clauses.
-	 */
-	if (varRelid != 0)
-		*relid = varRelid;
-	else
-	{
-		Relids	relids = pull_varnos((Node*)clauses);
-
-		/*
-		 * We only expect 0 or 1 members in the bitmapset. If there are
-		 * no vars, we'll get empty bitmapset, otherwise we'll get the
-		 * relid as the single member.
-		 *
-		 * FIXME For some reason we can get 2 relids here (e.g. \d in
-		 *       psql does that).
-		 */
-		if (bms_num_members(relids) == 1)
-			*relid = bms_singleton_member(relids);
-
-		bms_free(relids);
-	}
-
-	/*
-	 * if we found the relid, we can get the stats from simple_rel_array
-	 *
-	 * This only gets stats that are already built, because that's how
-	 * we load it into RelOptInfo (see get_relation_info), but we don't
-	 * detoast the whole stats yet. That'll be done later, after we
-	 * decide which stats to use.
-	 */
-	if (*relid != InvalidOid)
-		return root->simple_rel_array[*relid]->mvstatlist;
-
-	return NIL;
-}
-
-static Bitmapset*
-fdeps_collect_attnums(List *stats)
-{
-	ListCell *lc;
-	Bitmapset *attnums = NULL;
-
-	foreach (lc, stats)
-	{
-		int j;
-		MVStatisticInfo *info = (MVStatisticInfo *)lfirst(lc);
-
-		int2vector *stakeys = info->stakeys;
-
-		/* skip stats without functional dependencies built */
-		if (! info->deps_built)
-			continue;
-
-		for (j = 0; j < stakeys->dim1; j++)
-			attnums = bms_add_member(attnums, stakeys->values[j]);
-	}
-
-	return attnums;
-}
-
-
-static int*
-make_idx_to_attnum_mapping(Bitmapset *attnums)
-{
-	int		attidx = 0;
-	int		attnum = -1;
-
-	int	   *mapping = (int*)palloc0(bms_num_members(attnums) * sizeof(int));
-
-	while ((attnum = bms_next_member(attnums, attnum)) >= 0)
-		mapping[attidx++] = attnum;
-
-	Assert(attidx == bms_num_members(attnums));
-
-	return mapping;
-}
-
-static int*
-make_attnum_to_idx_mapping(Bitmapset *attnums)
-{
-	int		attidx = 0;
-	int		attnum = -1;
-	int		maxattnum = -1;
-	int	   *mapping;
-
-	while ((attnum = bms_next_member(attnums, attnum)) >= 0)
-		maxattnum = attnum;
-
-	mapping = (int*)palloc0((maxattnum+1) * sizeof(int));
-
-	attnum = -1;
-	while ((attnum = bms_next_member(attnums, attnum)) >= 0)
-		mapping[attnum] = attidx++;
-
-	Assert(attidx == bms_num_members(attnums));
-
-	return mapping;
-}
-
-static bool*
-build_adjacency_matrix(List *stats, Bitmapset *attnums,
-					   int *idx_to_attnum, int *attnum_to_idx)
-{
-	ListCell *lc;
-	int		natts  = bms_num_members(attnums);
-	bool   *matrix = (bool*)palloc0(natts * natts * sizeof(bool));
-
-	foreach (lc, stats)
-	{
-		int j;
-		MVStatisticInfo *stat = (MVStatisticInfo *)lfirst(lc);
-		MVDependencies dependencies = NULL;
-
-		/* skip stats without functional dependencies built */
-		if (! stat->deps_built)
-			continue;
-
-		/* fetch and deserialize dependencies */
-		dependencies = load_mv_dependencies(stat->mvoid);
-		if (dependencies == NULL)
-		{
-			elog(WARNING, "failed to deserialize func deps %d", stat->mvoid);
-			continue;
-		}
-
-		/* set matrix[a,b] to 'true' if 'a=>b' */
-		for (j = 0; j < dependencies->ndeps; j++)
-		{
-			int aidx = attnum_to_idx[dependencies->deps[j]->a];
-			int bidx = attnum_to_idx[dependencies->deps[j]->b];
-
-			/* a=> b */
-			matrix[aidx * natts + bidx] = true;
-		}
+						 varRelid,
+						 jointype,
+						 sjinfo);
 	}
+	else if (IsA(clause, CurrentOfExpr))
+	{
+		/* CURRENT OF selects at most one row of its table */
+		CurrentOfExpr *cexpr = (CurrentOfExpr *) clause;
+		RelOptInfo *crel = find_base_rel(root, cexpr->cvarno);
 
-	return matrix;
-}
-
-static void
-multiply_adjacency_matrix(bool *matrix, int natts)
-{
-	int i;
-
-	for (i = 0; i < natts; i++)
+		if (crel->tuples > 0)
+			s1 = 1.0 / crel->tuples;
+	}
+	else if (IsA(clause, RelabelType))
+	{
+		/* Not sure this case is needed, but it can't hurt */
+		s1 = clause_selectivity(root,
+								(Node *) ((RelabelType *) clause)->arg,
+								varRelid,
+								jointype,
+								sjinfo);
+	}
+	else if (IsA(clause, CoerceToDomain))
 	{
-		int k, l, m;
-		int nchanges = 0;
+		/* Not sure this case is needed, but it can't hurt */
+		s1 = clause_selectivity(root,
+								(Node *) ((CoerceToDomain *) clause)->arg,
+								varRelid,
+								jointype,
+								sjinfo);
+	}
 
-		/* k => l */
-		for (k = 0; k < natts; k++)
-		{
-			for (l = 0; l < natts; l++)
-			{
-				/* we already have this dependency */
-				if (matrix[k * natts + l])
-					continue;
+	/* Cache the result if possible */
+	if (cacheable)
+	{
+		if (jointype == JOIN_INNER)
+			rinfo->norm_selec = s1;
+		else
+			rinfo->outer_selec = s1;
+	}
 
-				/* we don't really care about the exact value, just 0/1 */
-				for (m = 0; m < natts; m++)
-				{
-					if (matrix[k * natts + m] * matrix[m * natts + l])
-					{
-						matrix[k * natts + l] = true;
-						nchanges += 1;
-						break;
-					}
-				}
-			}
-		}
+#ifdef SELECTIVITY_DEBUG
+	elog(DEBUG4, "clause_selectivity: s1 %f", s1);
+#endif   /* SELECTIVITY_DEBUG */
 
-		/* no transitive dependency added here, so terminate */
-		if (nchanges == 0)
-			break;
-	}
+	return s1;
 }
 
+
 static List*
 fdeps_reduce_clauses(List *clauses, Bitmapset *attnums, bool *matrix,
 					int *idx_to_attnum, int *attnum_to_idx, Index relid)
@@ -3427,55 +1211,6 @@ fdeps_reduce_clauses(List *clauses, Bitmapset *attnums, bool *matrix,
 }
 
 
-static Bitmapset *
-fdeps_filter_clauses(PlannerInfo *root,
-					 List *clauses, Bitmapset *deps_attnums,
-					 List **reduced_clauses, List **deps_clauses,
-					 Oid varRelid, Index *relid, SpecialJoinInfo *sjinfo)
-{
-	ListCell *lc;
-	Bitmapset *clause_attnums = NULL;
-
-	foreach (lc, clauses)
-	{
-		Bitmapset *attnums = NULL;
-		Node	   *clause = (Node *) lfirst(lc);
-
-		if (! clause_is_mv_compatible(root, clause, varRelid, relid, &attnums,
-									  sjinfo, MV_CLAUSE_TYPE_FDEP))
-
-			/* clause incompatible with functional dependencies */
-			*reduced_clauses = lappend(*reduced_clauses, clause);
-
-		else if (bms_num_members(attnums) > 1)
-
-			/*
-			 * clause referencing multiple attributes (strange, should
-			 * this be handled by clause_is_mv_compatible directly)
-			 */
-			*reduced_clauses = lappend(*reduced_clauses, clause);
-
-		else if (! bms_is_member(bms_singleton_member(attnums), deps_attnums))
-
-			/* clause not covered by the dependencies */
-			*reduced_clauses = lappend(*reduced_clauses, clause);
-
-		else
-		{
-			/* ok, clause compatible with existing dependencies */
-			Assert(bms_num_members(attnums) == 1);
-
-			*deps_clauses   = lappend(*deps_clauses, clause);
-			clause_attnums = bms_add_member(clause_attnums,
-										bms_singleton_member(attnums));
-		}
-
-		bms_free(attnums);
-	}
-
-	return clause_attnums;
-}
-
 /*
  * Pull varattnos from the clauses, similarly to pull_varattnos() but:
  *
@@ -3509,162 +1244,6 @@ get_varattnos(Node * node, Index relid)
 	return result;
 }
 
-/*
- * Estimate selectivity of clauses using a MCV list.
- *
- * If there's no MCV list for the stats, the function returns 0.0.
- *
- * While computing the estimate, the function checks whether all the
- * columns were matched with an equality condition. If that's the case,
- * we can skip processing the histogram, as there can be no rows in
- * it with the same values - all the rows matching the condition are
- * represented by the MCV item. This can only happen with equality
- * on all the attributes.
- *
- * The algorithm works like this:
- *
- *   1) mark all items as 'match'
- *   2) walk through all the clauses
- *   3) for a particular clause, walk through all the items
- *   4) skip items that are already 'no match'
- *   5) check clause for items that still match
- *   6) sum frequencies for items to get selectivity
- *
- * The function also returns the frequency of the least frequent item
- * on the MCV list, which may be useful for clamping estimate from the
- * histogram (all items not present in the MCV list are less frequent).
- * This however seems useful only for cases with conditions on all
- * attributes.
- *
- * TODO This only handles AND-ed clauses, but it might work for OR-ed
- *      lists too - it just needs to reverse the logic a bit. I.e. start
- *      with 'no match' for all items, and mark the items as a match
- *      as the clauses are processed (and skip items that are 'match').
- */
-static Selectivity
-clauselist_mv_selectivity_mcvlist(PlannerInfo *root, MVStatisticInfo *mvstats,
-								  List *clauses, List *conditions, bool is_or,
-								  bool *fullmatch, Selectivity *lowsel)
-{
-	int i;
-	Selectivity s = 0.0;
-	Selectivity t = 0.0;
-	Selectivity u = 0.0;
-
-	MCVList mcvlist = NULL;
-
-	int	nmatches = 0;
-	int	nconditions = 0;
-
-	/* match/mismatch bitmap for each MCV item */
-	char * matches = NULL;
-	char * condition_matches = NULL;
-
-	Assert(clauses != NIL);
-	Assert(list_length(clauses) >= 1);
-
-	/* there's no MCV list built yet */
-	if (! mvstats->mcv_built)
-		return 0.0;
-
-	mcvlist = load_mv_mcvlist(mvstats->mvoid);
-
-	Assert(mcvlist != NULL);
-	Assert(mcvlist->nitems > 0);
-
-	/* number of matching MCV items */
-	nmatches = mcvlist->nitems;
-	nconditions = mcvlist->nitems;
-
-	/*
-	 * Bitmap of bucket matches (mismatch, partial, full).
-	 *
-	 * For AND clauses all buckets match (and we'll eliminate them).
-	 * For OR  clauses no  buckets match (and we'll add them).
-	 *
-	 * We only need to do the memset for AND clauses (for OR clauses
-	 * it's already set correctly by the palloc0).
-	 */
-	matches = palloc0(sizeof(char) * nmatches);
-
-	if (! is_or) /* AND-clause */
-		memset(matches, MVSTATS_MATCH_FULL, sizeof(char)*nmatches);
-
-	/* Conditions are treated as AND clause, so match by default. */
-	condition_matches = palloc0(sizeof(char) * nconditions);
-	memset(condition_matches, MVSTATS_MATCH_FULL, sizeof(char)*nconditions);
-
-	/*
-	 * build the match bitmap for the conditions (conditions are always
-	 * connected by AND)
-	 */
-	if (conditions != NIL)
-		nconditions = update_match_bitmap_mcvlist(root, conditions,
-									   mvstats->stakeys, mcvlist,
-									   nconditions, condition_matches,
-									   lowsel, fullmatch, false);
-
-	/*
-	 * build the match bitmap for the estimated clauses
-	 *
-	 * TODO This evaluates the clauses for all MCV items, even those
-	 *      ruled out by the conditions. The final result should be the
-	 *      same, but it might be faster.
-	 */
-	nmatches = update_match_bitmap_mcvlist(root, clauses,
-										   mvstats->stakeys, mcvlist,
-										   ((is_or) ? 0 : nmatches), matches,
-										   lowsel, fullmatch, is_or);
-
-	/* sum frequencies for all the matching MCV items */
-	for (i = 0; i < mcvlist->nitems; i++)
-	{
-		/*
-		 * Find out what part of the data is covered by the MCV list,
-		 * so that we can 'scale' the selectivity properly (e.g. when
-		 * only 50% of the sample items got into the MCV, and the rest
-		 * is either in a histogram, or not covered by stats).
-		 *
-		 * TODO This might be handled by keeping a global "frequency"
-		 *      for the whole list, which might save us a bit of time
-		 *      spent on accessing the not-matching part of the MCV list.
-		 *      Although it's likely in a cache, so it's very fast.
-		 */
-		u += mcvlist->items[i]->frequency;
-
-		/* skit MCV items not matching the conditions */
-		if (condition_matches[i] == MVSTATS_MATCH_NONE)
-			continue;
-
-		if (matches[i] != MVSTATS_MATCH_NONE)
-			s += mcvlist->items[i]->frequency;
-
-		t += mcvlist->items[i]->frequency;
-	}
-
-	pfree(matches);
-	pfree(condition_matches);
-	pfree(mcvlist);
-
-	/* no condition matches */
-	if (t == 0.0)
-		return (Selectivity)0.0;
-
-	return (s / t) * u;
-}
-
-/*
- * Evaluate clauses using the MCV list, and update the match bitmap.
- *
- * The bitmap may be already partially set, so this is really a way to
- * combine results of several clause lists - either when computing
- * conditional probability P(A|B) or a combination of AND/OR clauses.
- *
- * TODO This works with 'bitmap' where each bit is represented as a char,
- *      which is slightly wasteful. Instead, we could use a regular
- *      bitmap, reducing the size to ~1/8. Another thing is merging the
- *      bitmaps using & and |, which might be faster than min/max.
- */
 static int
 update_match_bitmap_mcvlist(PlannerInfo *root, List *clauses,
 						   int2vector *stakeys, MCVList mcvlist,
@@ -3952,213 +1531,58 @@ update_match_bitmap_mcvlist(PlannerInfo *root, List *clauses,
 
 			/* match/mismatch bitmap for each MCV item */
 			int	tmp_nmatches = 0;
-			char * tmp_matches = NULL;
-
-			Assert(tmp_clauses != NIL);
-			Assert(list_length(tmp_clauses) >= 2);
-
-			/* number of matching MCV items */
-			tmp_nmatches = (or_clause(clause)) ? 0 : mcvlist->nitems;
-
-			/* by default none of the MCV items matches the clauses */
-			tmp_matches = palloc0(sizeof(char) * mcvlist->nitems);
-
-			/* AND clauses assume everything matches, initially */
-			if (! or_clause(clause))
-				memset(tmp_matches, MVSTATS_MATCH_FULL, sizeof(char)*mcvlist->nitems);
-
-			/* build the match bitmap for the OR-clauses */
-			tmp_nmatches = update_match_bitmap_mcvlist(root, tmp_clauses,
-									   stakeys, mcvlist,
-									   tmp_nmatches, tmp_matches,
-									   lowsel, fullmatch, or_clause(clause));
-
-			/* merge the bitmap into the existing one*/
-			for (i = 0; i < mcvlist->nitems; i++)
-			{
-				/*
-				 * To AND-merge the bitmaps, a MIN() semantics is used.
-				 * For OR-merge, use MAX().
-				 *
-				 * FIXME this does not decrease the number of matches
-				 */
-				UPDATE_RESULT(matches[i], tmp_matches[i], is_or);
-			}
-
-			pfree(tmp_matches);
-
-		}
-		else
-			elog(ERROR, "unknown clause type: %d", clause->type);
-	}
-
-	/*
-	 * If all the columns were matched by equality, it's a full match.
-	 * In this case there can be just a single MCV item, matching the
-	 * clause (if there were two, both would match the other one).
-	 */
-	*fullmatch = (bms_num_members(eqmatches) == mcvlist->ndimensions);
-
-	/* free the allocated pieces */
-	if (eqmatches)
-		pfree(eqmatches);
-
-	return nmatches;
-}
-
-/*
- * Estimate selectivity of clauses using a histogram.
- *
- * If there's no histogram for the stats, the function returns 0.0.
- *
- * The general idea of this method is similar to how MCV lists are
- * processed, except that this introduces the concept of a partial
- * match (MCV only works with full match / mismatch).
- *
- * The algorithm works like this:
- *
- *   1) mark all buckets as 'full match'
- *   2) walk through all the clauses
- *   3) for a particular clause, walk through all the buckets
- *   4) skip buckets that are already 'no match'
- *   5) check clause for buckets that still match (at least partially)
- *   6) sum frequencies for buckets to get selectivity
- *
- * Unlike MCV lists, histograms have a concept of a partial match. In
- * that case we use 1/2 the bucket, to minimize the average error. The
- * MV histograms are usually less detailed than the per-column ones,
- * meaning the sum is often quite high (thanks to combining a lot of
- * "partially hit" buckets).
- *
- * Maybe we could use per-bucket information with number of distinct
- * values it contains (for each dimension), and then use that to correct
- * the estimate (so with 10 distinct values, we'd use 1/10 of the bucket
- * frequency). We might also scale the value depending on the actual
- * ndistinct estimate (not just the values observed in the sample).
- *
- * Another option would be to multiply the selectivities, i.e. if we get
- * 'partial match' for a bucket for multiple conditions, we might use
- * 0.5^k (where k is the number of conditions), instead of 0.5. This
- * probably does not minimize the average error, though.
- *
- * TODO This might use a similar shortcut to MCV lists - count buckets
- *      marked as partial/full match, and terminate once this drop to 0.
- *      Not sure if it's really worth it - for MCV lists a situation like
- *      this is not uncommon, but for histograms it's not that clear.
- */
-static Selectivity
-clauselist_mv_selectivity_histogram(PlannerInfo *root, MVStatisticInfo *mvstats,
-									List *clauses, List *conditions, bool is_or)
-{
-	int i;
-	Selectivity s = 0.0;
-	Selectivity t = 0.0;
-	Selectivity u = 0.0;
-
-	int		nmatches = 0;
-	int		nconditions = 0;
-	char   *matches = NULL;
-	char   *condition_matches = NULL;
-
-	MVSerializedHistogram mvhist = NULL;
-
-	/* there's no histogram */
-	if (! mvstats->hist_built)
-		return 0.0;
-
-	/* There may be no histogram in the stats (check hist_built flag) */
-	mvhist = load_mv_histogram(mvstats->mvoid);
-
-	Assert (mvhist != NULL);
-	Assert (clauses != NIL);
-	Assert (list_length(clauses) >= 1);
-
-	nmatches = mvhist->nbuckets;
-	nconditions = mvhist->nbuckets;
-
-	/*
-	 * Bitmap of bucket matches (mismatch, partial, full).
-	 *
-	 * For AND clauses all buckets match (and we'll eliminate them).
-	 * For OR  clauses no  buckets match (and we'll add them).
-	 *
-	 * We only need to do the memset for AND clauses (for OR clauses
-	 * it's already set correctly by the palloc0).
-	 */
-	matches = palloc0(sizeof(char) * nmatches);
-
-	if (! is_or) /* AND-clause */
-		memset(matches, MVSTATS_MATCH_FULL, sizeof(char)*nmatches);
+			char * tmp_matches = NULL;
 
-	/* Conditions are treated as AND clause, so match by default. */
-	condition_matches = palloc0(sizeof(char)*nconditions);
-	memset(condition_matches, MVSTATS_MATCH_FULL, sizeof(char)*nconditions);
+			Assert(tmp_clauses != NIL);
+			Assert(list_length(tmp_clauses) >= 2);
 
-	/* build the match bitmap for the conditions */
-	if (conditions != NIL)
-		update_match_bitmap_histogram(root, conditions,
-								  mvstats->stakeys, mvhist,
-								  nconditions, condition_matches, is_or);
+			/* number of matching MCV items */
+			tmp_nmatches = (or_clause(clause)) ? 0 : mcvlist->nitems;
 
-	/*
-	 * build the match bitmap for the estimated clauses
-	 *
-	 * TODO This evaluates the clauses for all buckets, even those
-	 *      ruled out by the conditions. The final result should be
-	 *      the same, but it might be faster.
-	 */
-	update_match_bitmap_histogram(root, clauses,
-								  mvstats->stakeys, mvhist,
-								  ((is_or) ? 0 : nmatches), matches,
-								  is_or);
+			/* by default none of the MCV items matches the clauses */
+			tmp_matches = palloc0(sizeof(char) * mcvlist->nitems);
 
-	/* now, walk through the buckets and sum the selectivities */
-	for (i = 0; i < mvhist->nbuckets; i++)
-	{
-		float coeff = 1.0;
+			/* AND clauses assume everything matches, initially */
+			if (! or_clause(clause))
+				memset(tmp_matches, MVSTATS_MATCH_FULL, sizeof(char)*mcvlist->nitems);
 
-		/*
-		 * Find out what part of the data is covered by the histogram,
-		 * so that we can 'scale' the selectivity properly (e.g. when
-		 * only 50% of the sample got into the histogram, and the rest
-		 * is in a MCV list).
-		 *
-		 * TODO This might be handled by keeping a global "frequency"
-		 *      for the whole histogram, which might save us some time
-		 *      spent accessing the not-matching part of the histogram.
-		 *      Although it's likely in a cache, so it's very fast.
-		 */
-		u += mvhist->buckets[i]->ntuples;
+			/* build the match bitmap for the OR-clauses */
+			tmp_nmatches = update_match_bitmap_mcvlist(root, tmp_clauses,
+									   stakeys, mcvlist,
+									   tmp_nmatches, tmp_matches,
+									   lowsel, fullmatch, or_clause(clause));
 
-		/* skip buckets not matching the conditions */
-		if (condition_matches[i] == MVSTATS_MATCH_NONE)
-			continue;
-		else if (condition_matches[i] == MVSTATS_MATCH_PARTIAL)
-			coeff = 0.5;
+			/* merge the bitmap into the existing one*/
+			for (i = 0; i < mcvlist->nitems; i++)
+			{
+				/*
+				 * To AND-merge the bitmaps, a MIN() semantics is used.
+				 * For OR-merge, use MAX().
+				 *
+				 * FIXME this does not decrease the number of matches
+				 */
+				UPDATE_RESULT(matches[i], tmp_matches[i], is_or);
+			}
 
-		t += coeff * mvhist->buckets[i]->ntuples;
+			pfree(tmp_matches);
 
-		if (matches[i] == MVSTATS_MATCH_FULL)
-			s += coeff * mvhist->buckets[i]->ntuples;
-		else if (matches[i] == MVSTATS_MATCH_PARTIAL)
-			/*
-			 * TODO If both conditions and clauses match partially, this
-			 *      will use 0.25 match - not sure if that's the right
-			 *      thing solution, but seems about right.
-			 */
-			s += coeff * 0.5 * mvhist->buckets[i]->ntuples;
+		}
+		else
+			elog(ERROR, "unknown clause type: %d", clause->type);
 	}
 
-	/* release the allocated bitmap and deserialized histogram */
-	pfree(matches);
-	pfree(condition_matches);
-	pfree(mvhist);
+	/*
+	 * If all the columns were matched by equality, it's a full match.
+	 * In this case there can be just a single MCV item, matching the
+	 * clause (if there were two, both would match the other one).
+	 */
+	*fullmatch = (bms_num_members(eqmatches) == mcvlist->ndimensions);
 
-	/* no condition matches */
-	if (t == 0.0)
-		return (Selectivity)0.0;
+	/* free the allocated pieces */
+	if (eqmatches)
+		pfree(eqmatches);
 
-	return (s / t) * u;
+	return nmatches;
 }
 
 /*
@@ -4715,362 +2139,463 @@ update_match_bitmap_histogram(PlannerInfo *root, List *clauses,
 	return nmatches;
 }
 
-/*
- * Walk through clauses and keep only those covered by at least
- * one of the statistics.
- */
-static List *
-filter_clauses(PlannerInfo *root, Oid varRelid, SpecialJoinInfo *sjinfo,
-			   int type, List *stats, List *clauses, Bitmapset **attnums)
+static Node *
+stripRestrictStatData(List *clauses, BoolExprType boolop, Bitmapset **attrs)
 {
-	ListCell   *c;
-	ListCell   *s;
-
-	/* results (list of compatible clauses, attnums) */
-	List	   *rclauses = NIL;
+	Expr *newexpr;
+	ListCell *lc;
 
-	foreach (c, clauses)
+	if (attrs) *attrs = NULL;
+	
+	if (list_length(clauses) == 0)
+		newexpr = NULL;
+	else if (list_length(clauses) == 1)
 	{
-		Node *clause = (Node*)lfirst(c);
-		Bitmapset *clause_attnums = NULL;
-		Index relid;
+		RestrictStatData *rsd = (RestrictStatData *) linitial(clauses);
+		Assert(IsA(rsd, RestrictStatData));
 
-		/*
-		 * The clause has to be mv-compatible (suitable operators etc.).
-		 */
-		if (! clause_is_mv_compatible(root, clause, varRelid,
-							 &relid, &clause_attnums, sjinfo, type))
-				elog(ERROR, "should not get non-mv-compatible cluase");
+		newexpr = (Expr*)(rsd->clause);
+		if (attrs) *attrs = rsd->mvattrs;
+	}
+	else
+	{
+		BoolExpr *newboolexpr;
+		newboolexpr = makeNode(BoolExpr);
+		newboolexpr->boolop = boolop;
 
-		/* is there a statistics covering this clause? */
-		foreach (s, stats)
+		foreach (lc, clauses)
 		{
-			int k, matches = 0;
-			MVStatisticInfo	*stat = (MVStatisticInfo *)lfirst(s);
-
-			for (k = 0; k < stat->stakeys->dim1; k++)
-			{
-				if (bms_is_member(stat->stakeys->values[k],
-								  clause_attnums))
-					matches += 1;
-			}
-
-			/*
-			 * The clause is compatible if all attributes it references
-			 * are covered by the statistics.
-			 */
-			if (bms_num_members(clause_attnums) == matches)
-			{
-				*attnums = bms_union(*attnums, clause_attnums);
-				rclauses = lappend(rclauses, clause);
-				break;
-			}
+			RestrictStatData *rsd = (RestrictStatData *) lfirst(lc);
+			Assert(IsA(rsd, RestrictStatData));
+			newboolexpr->args = 
+				lappend(newboolexpr->args, rsd->clause);
+			if (attrs)
+				*attrs = bms_add_members(*attrs, rsd->mvattrs);
 		}
-
-		bms_free(clause_attnums);
+		newexpr = (Expr*) newboolexpr;
 	}
 
-	/* we can't have more compatible conditions than source conditions */
-	Assert(list_length(clauses) >= list_length(rclauses));
-
-	return rclauses;
+	return (Node*)newexpr;
 }
 
-
-/*
- * Walk through statistics and only keep those covering at least
- * one new attribute (excluding conditions) and at two attributes
- * in both clauses and conditions.
- *
- * This check might be made more strict by checking against individual
- * clauses, because by using the bitmapsets of all attnums we may
- * actually use attnums from clauses that are not covered by the
- * statistics. For example, we may have a condition
- *
- *    (a=1 AND b=2)
- *
- * and a new clause
- *
- *    (c=1 AND d=1)
- *
- * With only bitmapsets, statistics on [b,c] will pass through this
- * (assuming there are some statistics covering both clases).
- *
- * TODO Do the more strict check.
- */
-static List *
-filter_stats(List *stats, Bitmapset *new_attnums, Bitmapset *all_attnums)
+RestrictStatData *
+transformRestrictInfoForEstimate(PlannerInfo *root, List *clauses,
+								 int relid, SpecialJoinInfo *sjinfo)
 {
-	ListCell   *s;
-	List	   *stats_filtered = NIL;
+	static int level = 0;
+	int i = -1;
+	char head[100];
+	RestrictStatData *rdata = makeNode(RestrictStatData);
+	Node *clause;
 
-	foreach (s, stats)
+	memset(head, '.', 100);
+	head[level] = 0;
+	
+	if (list_length(clauses) == 1 &&
+		!IsA((Node*)linitial(clauses), RestrictInfo))
 	{
-		int k;
-		int matches_new = 0,
-			matches_all = 0;
-
-		MVStatisticInfo	*stat = (MVStatisticInfo *)lfirst(s);
-
-		/* see how many attributes the statistics covers */
-		for (k = 0; k < stat->stakeys->dim1; k++)
-		{
-			/* attributes from new clauses */
-			if (bms_is_member(stat->stakeys->values[k], new_attnums))
-				matches_new += 1;
-
-			/* attributes from onditions */
-			if (bms_is_member(stat->stakeys->values[k], all_attnums))
-				matches_all += 1;
-		}
-
-		/* check we have enough attributes for this statistics */
-		if ((matches_new >= 1) && (matches_all >= 2))
-			stats_filtered = lappend(stats_filtered, stat);
+		Assert(relid > 0);
+		clause = (Node*)linitial(clauses);
 	}
+	else
+	{
+		/* This is top level clauselist. Convert it to and expression */
+		ListCell *lc;
+		Index clauserelid = 0;
+		Relids relids = pull_varnos((Node*)clauses);
 
-	/* we can't have more useful stats than we had originally */
-	Assert(list_length(stats) >= list_length(stats_filtered));
-
-	return stats_filtered;
-}
+		if (bms_num_members(relids) != 1)
+			return NULL;
 
-static MVStatisticInfo *
-make_stats_array(List *stats, int *nmvstats)
-{
-	int i;
-	ListCell   *l;
+		clauserelid = bms_singleton_member(relids);
+		if (relid != 0 && relid != clauserelid)
+			return NULL;
 
-	MVStatisticInfo *mvstats = NULL;
-	*nmvstats = list_length(stats);
+		relid = clauserelid;
 
-	mvstats
-		= (MVStatisticInfo*)palloc0((*nmvstats) * sizeof(MVStatisticInfo));
+		if (list_length(clauses) == 1)
+		{
+			RestrictInfo *rinfo = (RestrictInfo *) linitial(clauses);
+			Assert(IsA(rinfo, RestrictInfo));
+			
+			clause = (Node*) rinfo->clause;
+		}
+		else
+		{
+			BoolExpr *andexpr = makeNode(BoolExpr);
+			andexpr->boolop = AND_EXPR;
+			foreach (lc, clauses)
+			{
+				RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
+				
+				Assert(IsA(rinfo, RestrictInfo));
+				if (rinfo->pseudoconstant ||
+					treat_as_join_clause((Node*)rinfo->clause,
+										 rinfo, 0, sjinfo))
+					rdata->unusedrinfos = lappend(rdata->unusedrinfos,
+												  rinfo);
+				else
+					andexpr->args = lappend(andexpr->args, rinfo->clause);
+			}
+			clause = (Node*)andexpr;
+		}
 
-	i = 0;
-	foreach (l, stats)
-	{
-		MVStatisticInfo	*stat = (MVStatisticInfo *)lfirst(l);
-		memcpy(&mvstats[i++], stat, sizeof(MVStatisticInfo));
 	}
 
-	return mvstats;
-}
-
-static Bitmapset **
-make_stats_attnums(MVStatisticInfo *mvstats, int nmvstats)
-{
-	int			i, j;
-	Bitmapset **stats_attnums = NULL;
-
-	Assert(nmvstats > 0);
+	Assert(!IsA(clause, RestrictInfo));
 
-	/* build bitmaps of attnums for the stats (easier to compare) */
-	stats_attnums = (Bitmapset **)palloc0(nmvstats * sizeof(Bitmapset*));
+	rdata->clause = clause;
+	rdata->boolop = AND_EXPR;
 
-	for (i = 0; i < nmvstats; i++)
-		for (j = 0; j < mvstats[i].stakeys->dim1; j++)
-			stats_attnums[i]
-				= bms_add_member(stats_attnums[i],
-								 mvstats[i].stakeys->values[j]);
+	if (and_clause(clause) || or_clause(clause))
+	{
+		BoolExpr *boolexpr = (BoolExpr *)clause;
+		ListCell *lc;
+		List *mvclauses = NIL;
+		List *nonmvclauses = NIL;
+		List *partialclauses = NIL;
+		Bitmapset *resultattrs = NULL;
+		List *resultstats = NIL;
 
-	return stats_attnums;
-}
+		rdata->boolop = boolexpr->boolop;
+		ereport(DEBUG1,
+				(errmsg ("%s%s[%d][%d](%d)",
+						 head,
+						 and_clause(clause)?"AND":
+						 (or_clause(clause)?"OR":"NOT"),
+						 level, i, list_length(boolexpr->args)),
+				 errhidestmt(level)));
 
+		/* Recursively process the subexpressions */
+		level++;
+		foreach (lc, (boolexpr->args))
+		{
+			Node *nd = (Node*) lfirst(lc);
+			RestrictStatData *tmpsd;
 
-/*
- * Now let's remove redundant statistics, covering the same columns
- * as some other stats, when restricted to the attributes from
- * remaining clauses.
- *
- * If statistics S1 covers S2 (covers S2 attributes and possibly
- * some more), we can probably remove S2. What actually matters are
- * attributes from covered clauses (not all the attributes). This
- * might however prefer larger, and thus less accurate, statistics.
- *
- * When a redundancy is detected, we simply keep the smaller
- * statistics (less number of columns), on the assumption that it's
- * more accurate and faster to process. That might be incorrect for
- * two reasons - first, the accuracy really depends on number of
- * buckets/MCV items, not the number of columns. Second, we might
- * prefer MCV lists over histograms or something like that.
- */
-static List*
-filter_redundant_stats(List *stats, List *clauses, List *conditions)
-{
-	int i, j, nmvstats;
+			tmpsd = transformRestrictInfoForEstimate(root,
+													 list_make1(nd),
+													 relid, sjinfo);
+			/*
+			 * mvclauses is to hold the child RestrictStatData that
+			 * potentially can be pulled-up to this node's mvclause, which is
+			 * to be estimated using multivariate statistics.
+			 *
+			 * partialclauses is to hold the child RestrictStatData that
+			 * cannot be pulled-up.
+			 * 
+			 * nonmvclauses is to hold the child RestrictStatData to be
+			 * pulled-up into the clause to be estimated in the normal way.
+			 */
+			if (tmpsd->mvattrs)
+				mvclauses = lappend(mvclauses, tmpsd);
+			else if (tmpsd->mvclause)
+				partialclauses = lappend(partialclauses, tmpsd);
+			else
+				nonmvclauses = lappend(nonmvclauses, tmpsd);
+		}
+		level--;
 
-	MVStatisticInfo	   *mvstats;
-	bool			   *redundant;
-	Bitmapset		  **stats_attnums;
-	Bitmapset		   *varattnos;
-	Index				relid;
 
-	Assert(list_length(stats) > 0);
-	Assert(list_length(clauses) > 0);
+		if (list_length(mvclauses) == 1)
+		{
+			/*
+			 * If this boolean clause has only one mv clause, pull it up for
+			 * now.
+			 */
+			RestrictStatData *rsd = (RestrictStatData *) linitial(mvclauses);
+			resultattrs = rsd->mvattrs;
+			resultstats = rsd->mvstats;
+		}
+		if (list_length(mvclauses) > 1)
+		{
+			/*
+			 * Pick up the smallest mv-stats that covers as large part as
+			 * possible of the attrutes appeard in the subclauses, then remove
+			 * clauses that is not covered by the selected mv-stats.
+			 */
+			int nmvstats = 0;
+			ListCell *lc;
+			bm_mvstat *mvstatslist[16];
+			int maxnattrs = 0;
+			int candidatestats;
+			int i;
+
+			/* Check functional dependency first, maybe.. */
+//			if (list_length(mvclauses) == 2)
+//			{
+//				RestrictStatData *rsd1 =
+//					(RestrictStatData *) linitial(mvclauses);
+//				RestrictStatData *rsd2 =
+//					(RestrictStatData *) lsecond(mvclauses);
+//				/* To do more...*/
+//			}
 
-	/*
-	 * We'll convert the list of statistics into an array now, because
-	 * the reduction of redundant statistics is easier to do that way
-	 * (we can mark previous stats as redundant, etc.).
-	 */
-	mvstats = make_stats_array(stats, &nmvstats);
-	stats_attnums = make_stats_attnums(mvstats, nmvstats);
+			/*
+			 * Collect all mvstats from all subclauses. Attribute set should
+			 * be unique so use it as key. There should be not so many stats.
+			 */
+			foreach (lc, mvclauses)
+			{
+				RestrictStatData *rsd = (RestrictStatData *) lfirst(lc);
+				Bitmapset *mvattrs = rsd->mvattrs;
+				ListCell *lcs;
 
-	/* by default, none of the stats is redundant (so palloc0) */
-	redundant = palloc0(nmvstats * sizeof(bool));
+				/* make a covering attribute set of all cluases */
+				resultattrs = bms_add_members(resultattrs, mvattrs);
 
-	/*
-	 * We only expect a single relid here, and also we should get the
-	 * same relid from clauses and conditions (but we get it from
-	 * clauses, because those are certainly non-empty).
-	 */
-	relid = bms_singleton_member(pull_varnos((Node*)clauses));
+				/* pick up new mv stats */
+				foreach (lcs, rsd->mvstats)
+				{
+					bm_mvstat *mvs = (bm_mvstat*) lfirst(lcs);
+					bool found = false;
 
-	/*
-	 * Get the varattnos from both conditions and clauses.
-	 *
-	 * This skips system attributes, although that should be impossible
-	 * thanks to previous filtering out of incompatible clauses.
-	 *
-	 * XXX Is that really true?
-	 */
-	varattnos = bms_union(get_varattnos((Node*)clauses, relid),
-						  get_varattnos((Node*)conditions, relid));
+					for (i = 0 ; !found && i < nmvstats ; i++)
+					{
+						if(bms_equal(mvstatslist[i]->attrs, mvs->attrs))
+							found = true;
+					}
+					if (!found)
+					{
+						mvstatslist[nmvstats] = mvs;
+						nmvstats++;
+					}
 
-	for (i = 1; i < nmvstats; i++)
-	{
-		/* intersect with current statistics */
-		Bitmapset *curr = bms_intersect(stats_attnums[i], varattnos);
+					/* ignore more than 15(!) stats for a clause */
+					if (nmvstats > 15)
+						break;
+				}
+			}
 
-		/* walk through 'previous' stats and check redundancy */
-		for (j = 0; j < i; j++)
-		{
-			/* intersect with current statistics */
-			Bitmapset *prev;
+			/* we try functional dependency first? */
+			//if (clauseboolop == AND_EXPR && ...
+				
+			/*
+			 * find a mv stats covers the largest number of attribute used in
+			 * the cluases and having the smallest attrubute set.
+			 */
+			maxnattrs = 0;
+			candidatestats = -1;
+			for (i = 0 ; i < nmvstats ; i++)
+			{
+				Bitmapset *matchattr =
+					bms_intersect(resultattrs, mvstatslist[i]->attrs);
+				int nmatchattrs = bms_num_members(matchattr);
 
-			/* skip stats already identified as redundant */
-			if (redundant[j])
-				continue;
+				if (maxnattrs < nmatchattrs)
+				{
+					candidatestats = i;
+					maxnattrs = nmatchattrs;
+				}
+				else if (maxnattrs > 0 && maxnattrs == nmatchattrs)
+				{
+					if (bms_num_members(mvstatslist[i]->attrs) <
+						bms_num_members(mvstatslist[candidatestats]->attrs))
+						candidatestats = i;
+				}
+			}
 
-			prev = bms_intersect(stats_attnums[j], varattnos);
+			Assert(candidatestats >= 0);
 
-			switch (bms_subset_compare(curr, prev))
+			if (maxnattrs == 1)
 			{
-				case BMS_EQUAL:
+				/*
+				 * No two of mvclauses share a mv statistics. Make this node
+				 * non-mv.
+				 */
+				mvclauses = NIL;
+				nonmvclauses = NIL;
+				resultattrs = NULL;
+				resultstats = NIL;
+			}
+			else
+			{
+				if (!bms_is_subset(resultattrs,
+								   mvstatslist[candidatestats]->attrs))
+				{
 					/*
-					 * Use the smaller one (hopefully more accurate).
-					 * If both have the same size, use the first one.
+					 * move out the clauses that is not covered by the
+					 * candidate stats
 					 */
-					if (mvstats[i].stakeys->dim1 >= mvstats[j].stakeys->dim1)
-						redundant[i] = TRUE;
-					else
-						redundant[j] = TRUE;
-
-					break;
-
-				case BMS_SUBSET1: /* curr is subset of prev */
-					redundant[i] = TRUE;
-					break;
+					List *old_mvclauses = mvclauses;
+					ListCell *lc;
+					Bitmapset *statsattrs =
+						mvstatslist[candidatestats]->attrs;
+					mvclauses = NIL;
 
-				case BMS_SUBSET2: /* prev is subset of curr */
-					redundant[j] = TRUE;
-					break;
+					foreach(lc, old_mvclauses)
+					{
+						RestrictStatData *rsd =	(RestrictStatData *) lfirst(lc);
+						Assert(IsA(rsd, RestrictStatData));
 
-				case BMS_DIFFERENT:
-					/* do nothing - keep both stats */
-					break;
+						if (bms_is_subset(rsd->mvattrs, statsattrs))
+							mvclauses = lappend(mvclauses, rsd);
+						else
+							nonmvclauses = lappend(nonmvclauses, rsd);
+					}
+					resultattrs = bms_intersect(resultattrs, 
+										mvstatslist[candidatestats]->attrs);
+				}
+				resultstats = list_make1(mvstatslist[candidatestats]);
 			}
-
-			bms_free(prev);
 		}
 
-		bms_free(curr);
-	}
-
-	/* can't reduce all statistics (at least one has to remain) */
-	Assert(nmvstats > 0);
+		if (bms_num_members(resultattrs) < 2)
+		{
+			/*
+			 * make this non-mv if mvclause covers only one mv-attribute.
+			 */
+			nonmvclauses = list_concat(nonmvclauses, mvclauses);
+			mvclauses = NULL;
+			resultattrs = NULL;
+			resultstats = NIL;
+		}
 
-	/* now, let's remove the reduced statistics from the arrays */
-	list_free(stats);
-	stats = NIL;
+		/*
+		 * All mvclauses are covered by the candidate stats	here.
+		 */
+		rdata->mvclause =
+			stripRestrictStatData(mvclauses, rdata->boolop, NULL);
+		rdata->children = partialclauses;
+		rdata->mvattrs = resultattrs;
+		rdata->nonmvclause =
+			stripRestrictStatData(nonmvclauses, rdata->boolop, NULL);
+		rdata->mvstats = resultstats;
 
-	for (i = 0; i < nmvstats; i++)
+	}
+	else if (not_clause(clause))
 	{
-		MVStatisticInfo *info;
-
-		pfree(stats_attnums[i]);
+		Node *nd = (Node *) linitial(((BoolExpr*)clause)->args);
+		RestrictStatData *tmpsd;
 
-		if (redundant[i])
-			continue;
-
-		info = makeNode(MVStatisticInfo);
-		memcpy(info, &mvstats[i], sizeof(MVStatisticInfo));
-
-		stats = lappend(stats, info);
+		tmpsd = transformRestrictInfoForEstimate(root, list_make1(nd),
+												 relid, sjinfo);
+		rdata->children = list_make1(tmpsd);
 	}
-
-	pfree(mvstats);
-	pfree(stats_attnums);
-	pfree(redundant);
-
-	return stats;
-}
-
-static Node**
-make_clauses_array(List *clauses, int *nclauses)
-{
-	int i;
-	ListCell *l;
-
-	Node** clauses_array;
-
-	*nclauses = list_length(clauses);
-	clauses_array = (Node **)palloc0((*nclauses) * sizeof(Node *));
-
-	i = 0;
-	foreach (l, clauses)
-		clauses_array[i++] = (Node *)lfirst(l);
-
-	*nclauses = i;
-
-	return clauses_array;
-}
-
-static Bitmapset **
-make_clauses_attnums(PlannerInfo *root, Oid varRelid, SpecialJoinInfo *sjinfo,
-					 int type, Node **clauses, int nclauses)
-{
-	int			i;
-	Index		relid;
-	Bitmapset **clauses_attnums
-		= (Bitmapset **)palloc0(nclauses * sizeof(Bitmapset *));
-
-	for (i = 0; i < nclauses; i++)
+	else if (is_opclause(clause) &&
+			 list_length(((OpExpr *) clause)->args) == 2)
 	{
-		Bitmapset * attnums = NULL;
+		Node *varnode = get_leftop((Expr*)clause);
+		Node *nonvarnode = get_rightop((Expr*)clause);
 
-		if (! clause_is_mv_compatible(root, clauses[i], varRelid,
-									  &relid, &attnums, sjinfo, type))
-			elog(ERROR, "should not get non-mv-compatible cluase");
+		/* Place var on vernode if any */
+		if (!IsA(varnode, Var))
+		{
+			Node *tmp = nonvarnode;
+			nonvarnode = varnode;
+			varnode = tmp;
+		}
+		
+		if (IsA(varnode, Var) && is_pseudo_constant_clause(nonvarnode))
+		{
+			Var *var = (Var *)varnode;
+			List *statslist = root->simple_rel_array[relid]->mvstatlist;
+			Oid opno = ((OpExpr*)clause)->opno;
+			int varmvbitmap = get_oprmvstat(opno);
+
+			if (varmvbitmap &&
+				!IS_SPECIAL_VARNO(var->varno) &&
+				AttrNumberIsForUserDefinedAttr(var->varattno))
+			{
+				List *mvstats = NIL;
+				ListCell *lc;
+				Bitmapset *varattrs = bms_make_singleton(var->varattno);
 
-		clauses_attnums[i] = attnums;
+				/*
+				 * Add mv statistics if it is applicable on this expression
+				 */
+				foreach (lc, statslist)
+				{
+					int k;
+					MVStatisticInfo *stats = (MVStatisticInfo *) lfirst(lc);
+					Bitmapset *statsattrs = NULL;
+					int statsmvbitmap =
+						(stats->mcv_built ? MVSTATISTIC_MCV : 0) |
+						(stats->hist_built ? MVSTATISTIC_HIST : 0) |
+						(stats->deps_built ? MVSTATISTIC_FDEP : 0);
+
+					for (k = 0 ; k < stats->stakeys->dim1 ; k++)
+						statsattrs = bms_add_member(statsattrs,
+													stats->stakeys->values[k]);
+					/* XXX: Does this work as expected? */
+					if (bms_is_subset(varattrs, statsattrs) &&
+						(statsmvbitmap & varmvbitmap))
+					{
+						bm_mvstat *mvstatsent = palloc0(sizeof(bm_mvstat));
+						mvstatsent->attrs = statsattrs;
+						mvstatsent->stats = stats;
+						mvstatsent->mvkind = statsmvbitmap;
+						mvstats = lappend(mvstats, mvstatsent);
+					}
+				}
+				if (mvstats)
+				{
+					/* MV stats is potentially applicable on this expression */
+					ereport(DEBUG1,
+							(errmsg ("%sMATCH[%d][%d](varno = %d, attno = %d)",
+									 head, level, i,
+									 var->varno, var->varattno),
+							 errhidestmt(level)));
+
+					rdata->mvstats = mvstats;
+					rdata->mvattrs = varattrs;
+				}
+			}
+		}
+		else
+		{
+			ereport(DEBUG1,
+					(errmsg ("%sno match BinOp[%d][%d]: r=%d, l=%d",
+							 head, level, i,
+							 varnode->type, nonvarnode->type),
+					 errhidestmt(level)));
+		}
 	}
+	else if (IsA(clause, NullTest))
+	{
+		NullTest *expr = (NullTest*)clause;
+		Var *var = (Var *)(expr->arg);
 
-	return clauses_attnums;
-}
-
-static bool*
-make_cover_map(Bitmapset **stats_attnums, int nmvstats,
-			   Bitmapset **clauses_attnums, int nclauses)
-{
-	int		i, j;
-	bool   *cover_map	= (bool*)palloc0(nclauses * nmvstats);
+		if (IsA(var, Var) &&
+			!IS_SPECIAL_VARNO(var->varno) &&
+			AttrNumberIsForUserDefinedAttr(var->varattno))
+		{
+			Bitmapset *varattrs = bms_make_singleton(var->varattno);
+			List *mvstats = NIL;
+			ListCell *lc;
 
-	for (i = 0; i < nmvstats; i++)
-		for (j = 0; j < nclauses; j++)
-			cover_map[i * nclauses + j]
-				= bms_is_subset(clauses_attnums[j], stats_attnums[i]);
+			foreach(lc, root->simple_rel_array[relid]->mvstatlist)
+			{
+				MVStatisticInfo *stats = (MVStatisticInfo *) lfirst(lc);
+				Bitmapset *statsattrs = NULL;			
+				int k;
+
+				for (k = 0 ; k < stats->stakeys->dim1 ; k++)
+					statsattrs = bms_add_member(statsattrs,
+											stats->stakeys->values[k]);
+				if (bms_is_subset(varattrs, statsattrs))
+				{
+					bm_mvstat *mvstatsent = palloc0(sizeof(bm_mvstat));
+					mvstatsent->stats = stats;
+					mvstatsent->attrs = statsattrs;
+					mvstatsent->mvkind = (MVSTATISTIC_MCV |MVSTATISTIC_HIST);
+					mvstats = lappend(mvstats, mvstatsent);
+				}
+			}
+			if (mvstats)
+			{
+				rdata->mvstats = mvstats;
+				rdata->mvattrs = varattrs;
+			}		
+		}
+	}
+	else
+	{
+		ereport(DEBUG1,
+				(errmsg ("%sno match node(%d)[%d][%d]",
+						 head, clause->type, level, i),
+				 errhidestmt(level)));
+	}
 
-	return cover_map;
+	return rdata;
 }
diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c
index 7b32247..61e578f 100644
--- a/src/backend/utils/cache/lsyscache.c
+++ b/src/backend/utils/cache/lsyscache.c
@@ -45,6 +45,7 @@
 #include "utils/rel.h"
 #include "utils/syscache.h"
 #include "utils/typcache.h"
+#include "utils/mvstats.h"
 
 /* Hook for plugins to get control in get_attavgwidth() */
 get_attavgwidth_hook_type get_attavgwidth_hook = NULL;
@@ -1345,6 +1346,45 @@ get_oprjoin(Oid opno)
 		return (RegProcedure) InvalidOid;
 }
 
+/*
+ * get_oprmvstat
+ *
+ *		Returns mv stats compatibility for computing selectivity
+ *      Return valueis bitwise or of MVSTATISTIC_* symbols
+ */
+int
+get_oprmvstat(Oid opno)
+{
+	HeapTuple	tp;
+
+	tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno));
+	if (HeapTupleIsValid(tp))
+	{
+		Datum tmp;
+		bool  isnull;
+		char *str;
+		int result = 0;
+
+		tmp = SysCacheGetAttr(OPEROID, tp,
+							  Anum_pg_operator_oprmvstat, &isnull);
+		if (!isnull)
+		{
+			str = TextDatumGetCString(tmp);
+			if (strlen(str) == 3)
+			{
+				if (str[0] != '-') result |= MVSTATISTIC_MCV;
+				if (str[1] != '-') result |= MVSTATISTIC_HIST;
+				if (str[2] != '-') result |= MVSTATISTIC_FDEP;
+			}
+		}
+		ReleaseSysCache(tp);
+		return result;
+	}
+	else
+		return 0;
+}
+
+
 /*				---------- FUNCTION CACHE ----------					 */
 
 /*
diff --git a/src/include/catalog/pg_operator.h b/src/include/catalog/pg_operator.h
index 26c9d4e..c75ac72 100644
--- a/src/include/catalog/pg_operator.h
+++ b/src/include/catalog/pg_operator.h
@@ -49,6 +49,9 @@ CATALOG(pg_operator,2617)
 	regproc		oprcode;		/* OID of underlying function */
 	regproc		oprrest;		/* OID of restriction estimator, or 0 */
 	regproc		oprjoin;		/* OID of join estimator, or 0 */
+#ifdef CATALOG_VARLEN			/* variable-length fields start here */
+	text		oprmvstat;		/* MV stat compatibility in '[m-][h-][f-]' */
+#endif
 } FormData_pg_operator;
 
 /* ----------------
@@ -63,7 +66,7 @@ typedef FormData_pg_operator *Form_pg_operator;
  * ----------------
  */
 
-#define Natts_pg_operator				14
+#define Natts_pg_operator				15
 #define Anum_pg_operator_oprname		1
 #define Anum_pg_operator_oprnamespace	2
 #define Anum_pg_operator_oprowner		3
@@ -78,6 +81,7 @@ typedef FormData_pg_operator *Form_pg_operator;
 #define Anum_pg_operator_oprcode		12
 #define Anum_pg_operator_oprrest		13
 #define Anum_pg_operator_oprjoin		14
+#define Anum_pg_operator_oprmvstat		15
 
 /* ----------------
  *		initial contents of pg_operator
@@ -91,1735 +95,1735 @@ typedef FormData_pg_operator *Form_pg_operator;
  * for the underlying function.
  */
 
-DATA(insert OID =  15 ( "="		   PGNSP PGUID b t t	23	20	16 416	36 int48eq eqsel eqjoinsel ));
+DATA(insert OID =  15 ( "="		   PGNSP PGUID b t t	23	20	16 416	36 int48eq eqsel eqjoinsel "mhf"));
 DESCR("equal");
-DATA(insert OID =  36 ( "<>"	   PGNSP PGUID b f f	23	20	16 417	15 int48ne neqsel neqjoinsel ));
+DATA(insert OID =  36 ( "<>"	   PGNSP PGUID b f f	23	20	16 417	15 int48ne neqsel neqjoinsel "mhf"));
 DESCR("not equal");
-DATA(insert OID =  37 ( "<"		   PGNSP PGUID b f f	23	20	16 419	82 int48lt scalarltsel scalarltjoinsel ));
+DATA(insert OID =  37 ( "<"		   PGNSP PGUID b f f	23	20	16 419	82 int48lt scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than");
-DATA(insert OID =  76 ( ">"		   PGNSP PGUID b f f	23	20	16 418	80 int48gt scalargtsel scalargtjoinsel ));
+DATA(insert OID =  76 ( ">"		   PGNSP PGUID b f f	23	20	16 418	80 int48gt scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than");
-DATA(insert OID =  80 ( "<="	   PGNSP PGUID b f f	23	20	16 430	76 int48le scalarltsel scalarltjoinsel ));
+DATA(insert OID =  80 ( "<="	   PGNSP PGUID b f f	23	20	16 430	76 int48le scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than or equal");
-DATA(insert OID =  82 ( ">="	   PGNSP PGUID b f f	23	20	16 420	37 int48ge scalargtsel scalargtjoinsel ));
+DATA(insert OID =  82 ( ">="	   PGNSP PGUID b f f	23	20	16 420	37 int48ge scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than or equal");
 
-DATA(insert OID =  58 ( "<"		   PGNSP PGUID b f f	16	16	16	59	1695 boollt scalarltsel scalarltjoinsel ));
+DATA(insert OID =  58 ( "<"		   PGNSP PGUID b f f	16	16	16	59	1695 boollt scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than");
-DATA(insert OID =  59 ( ">"		   PGNSP PGUID b f f	16	16	16	58	1694 boolgt scalargtsel scalargtjoinsel ));
+DATA(insert OID =  59 ( ">"		   PGNSP PGUID b f f	16	16	16	58	1694 boolgt scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than");
-DATA(insert OID =  85 ( "<>"	   PGNSP PGUID b f f	16	16	16	85	91 boolne neqsel neqjoinsel ));
+DATA(insert OID =  85 ( "<>"	   PGNSP PGUID b f f	16	16	16	85	91 boolne neqsel neqjoinsel "mhf"));
 DESCR("not equal");
 #define BooleanNotEqualOperator   85
-DATA(insert OID =  91 ( "="		   PGNSP PGUID b t t	16	16	16	91	85 booleq eqsel eqjoinsel ));
+DATA(insert OID =  91 ( "="		   PGNSP PGUID b t t	16	16	16	91	85 booleq eqsel eqjoinsel "mhf"));
 DESCR("equal");
 #define BooleanEqualOperator   91
-DATA(insert OID = 1694 (  "<="	   PGNSP PGUID b f f	16	16	16 1695 59 boolle scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1694 (  "<="	   PGNSP PGUID b f f	16	16	16 1695 59 boolle scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than or equal");
-DATA(insert OID = 1695 (  ">="	   PGNSP PGUID b f f	16	16	16 1694 58 boolge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 1695 (  ">="	   PGNSP PGUID b f f	16	16	16 1694 58 boolge scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than or equal");
 
-DATA(insert OID =  92 ( "="		   PGNSP PGUID b t t	18	18	16	92 630 chareq eqsel eqjoinsel ));
+DATA(insert OID =  92 ( "="		   PGNSP PGUID b t t	18	18	16	92 630 chareq eqsel eqjoinsel "mhf"));
 DESCR("equal");
-DATA(insert OID =  93 ( "="		   PGNSP PGUID b t t	19	19	16	93 643 nameeq eqsel eqjoinsel ));
+DATA(insert OID =  93 ( "="		   PGNSP PGUID b t t	19	19	16	93 643 nameeq eqsel eqjoinsel "mhf"));
 DESCR("equal");
-DATA(insert OID =  94 ( "="		   PGNSP PGUID b t t	21	21	16	94 519 int2eq eqsel eqjoinsel ));
+DATA(insert OID =  94 ( "="		   PGNSP PGUID b t t	21	21	16	94 519 int2eq eqsel eqjoinsel "mhf"));
 DESCR("equal");
-DATA(insert OID =  95 ( "<"		   PGNSP PGUID b f f	21	21	16 520 524 int2lt scalarltsel scalarltjoinsel ));
+DATA(insert OID =  95 ( "<"		   PGNSP PGUID b f f	21	21	16 520 524 int2lt scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than");
-DATA(insert OID =  96 ( "="		   PGNSP PGUID b t t	23	23	16	96 518 int4eq eqsel eqjoinsel ));
+DATA(insert OID =  96 ( "="		   PGNSP PGUID b t t	23	23	16	96 518 int4eq eqsel eqjoinsel "mhf"));
 DESCR("equal");
 #define Int4EqualOperator	96
-DATA(insert OID =  97 ( "<"		   PGNSP PGUID b f f	23	23	16 521 525 int4lt scalarltsel scalarltjoinsel ));
+DATA(insert OID =  97 ( "<"		   PGNSP PGUID b f f	23	23	16 521 525 int4lt scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than");
 #define Int4LessOperator	97
-DATA(insert OID =  98 ( "="		   PGNSP PGUID b t t	25	25	16	98 531 texteq eqsel eqjoinsel ));
+DATA(insert OID =  98 ( "="		   PGNSP PGUID b t t	25	25	16	98 531 texteq eqsel eqjoinsel "mhf"));
 DESCR("equal");
 #define TextEqualOperator	98
 
-DATA(insert OID = 349 (  "||"	   PGNSP PGUID b f f 2277 2283 2277 0 0 array_append   -	   -	 ));
+DATA(insert OID = 349 (  "||"	   PGNSP PGUID b f f 2277 2283 2277 0 0 array_append   -	   -	 "---"));
 DESCR("append element onto end of array");
-DATA(insert OID = 374 (  "||"	   PGNSP PGUID b f f 2283 2277 2277 0 0 array_prepend  -	   -	 ));
+DATA(insert OID = 374 (  "||"	   PGNSP PGUID b f f 2283 2277 2277 0 0 array_prepend  -	   -	 "---"));
 DESCR("prepend element onto front of array");
-DATA(insert OID = 375 (  "||"	   PGNSP PGUID b f f 2277 2277 2277 0 0 array_cat	   -	   -	 ));
+DATA(insert OID = 375 (  "||"	   PGNSP PGUID b f f 2277 2277 2277 0 0 array_cat	   -	   -	 "---"));
 DESCR("concatenate");
 
-DATA(insert OID = 352 (  "="	   PGNSP PGUID b f t	28	28	16 352	 0 xideq eqsel eqjoinsel ));
+DATA(insert OID = 352 (  "="	   PGNSP PGUID b f t	28	28	16 352	 0 xideq eqsel eqjoinsel "mhf"));
 DESCR("equal");
-DATA(insert OID = 353 (  "="	   PGNSP PGUID b f f	28	23	16	 0	 0 xideqint4 eqsel eqjoinsel ));
+DATA(insert OID = 353 (  "="	   PGNSP PGUID b f f	28	23	16	 0	 0 xideqint4 eqsel eqjoinsel "mhf"));
 DESCR("equal");
-DATA(insert OID = 388 (  "!"	   PGNSP PGUID r f f	20	 0	1700  0  0 numeric_fac - - ));
+DATA(insert OID = 388 (  "!"	   PGNSP PGUID r f f	20	 0	1700  0  0 numeric_fac - - "---"));
 DESCR("factorial");
-DATA(insert OID = 389 (  "!!"	   PGNSP PGUID l f f	 0	20	1700  0  0 numeric_fac - - ));
+DATA(insert OID = 389 (  "!!"	   PGNSP PGUID l f f	 0	20	1700  0  0 numeric_fac - - "---"));
 DESCR("deprecated, use ! instead");
-DATA(insert OID = 385 (  "="	   PGNSP PGUID b f t	29	29	16 385	 0 cideq eqsel eqjoinsel ));
+DATA(insert OID = 385 (  "="	   PGNSP PGUID b f t	29	29	16 385	 0 cideq eqsel eqjoinsel "mhf"));
 DESCR("equal");
-DATA(insert OID = 386 (  "="	   PGNSP PGUID b f t	22	22	16 386	 0 int2vectoreq eqsel eqjoinsel ));
+DATA(insert OID = 386 (  "="	   PGNSP PGUID b f t	22	22	16 386	 0 int2vectoreq eqsel eqjoinsel "mhf"));
 DESCR("equal");
 
-DATA(insert OID = 387 (  "="	   PGNSP PGUID b t f	27	27	16 387 402 tideq eqsel eqjoinsel ));
+DATA(insert OID = 387 (  "="	   PGNSP PGUID b t f	27	27	16 387 402 tideq eqsel eqjoinsel "mhf"));
 DESCR("equal");
 #define TIDEqualOperator   387
-DATA(insert OID = 402 (  "<>"	   PGNSP PGUID b f f	27	27	16 402 387 tidne neqsel neqjoinsel ));
+DATA(insert OID = 402 (  "<>"	   PGNSP PGUID b f f	27	27	16 402 387 tidne neqsel neqjoinsel "mhf"));
 DESCR("not equal");
-DATA(insert OID = 2799 (  "<"	   PGNSP PGUID b f f	27	27	16 2800 2802 tidlt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 2799 (  "<"	   PGNSP PGUID b f f	27	27	16 2800 2802 tidlt scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than");
 #define TIDLessOperator    2799
-DATA(insert OID = 2800 (  ">"	   PGNSP PGUID b f f	27	27	16 2799 2801 tidgt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 2800 (  ">"	   PGNSP PGUID b f f	27	27	16 2799 2801 tidgt scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than");
-DATA(insert OID = 2801 (  "<="	   PGNSP PGUID b f f	27	27	16 2802 2800 tidle scalarltsel scalarltjoinsel ));
+DATA(insert OID = 2801 (  "<="	   PGNSP PGUID b f f	27	27	16 2802 2800 tidle scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than or equal");
-DATA(insert OID = 2802 (  ">="	   PGNSP PGUID b f f	27	27	16 2801 2799 tidge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 2802 (  ">="	   PGNSP PGUID b f f	27	27	16 2801 2799 tidge scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than or equal");
 
-DATA(insert OID = 410 ( "="		   PGNSP PGUID b t t	20	20	16 410 411 int8eq eqsel eqjoinsel ));
+DATA(insert OID = 410 ( "="		   PGNSP PGUID b t t	20	20	16 410 411 int8eq eqsel eqjoinsel "mhf"));
 DESCR("equal");
-DATA(insert OID = 411 ( "<>"	   PGNSP PGUID b f f	20	20	16 411 410 int8ne neqsel neqjoinsel ));
+DATA(insert OID = 411 ( "<>"	   PGNSP PGUID b f f	20	20	16 411 410 int8ne neqsel neqjoinsel "mhf"));
 DESCR("not equal");
-DATA(insert OID = 412 ( "<"		   PGNSP PGUID b f f	20	20	16 413 415 int8lt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 412 ( "<"		   PGNSP PGUID b f f	20	20	16 413 415 int8lt scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than");
 #define Int8LessOperator	412
-DATA(insert OID = 413 ( ">"		   PGNSP PGUID b f f	20	20	16 412 414 int8gt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 413 ( ">"		   PGNSP PGUID b f f	20	20	16 412 414 int8gt scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than");
-DATA(insert OID = 414 ( "<="	   PGNSP PGUID b f f	20	20	16 415 413 int8le scalarltsel scalarltjoinsel ));
+DATA(insert OID = 414 ( "<="	   PGNSP PGUID b f f	20	20	16 415 413 int8le scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than or equal");
-DATA(insert OID = 415 ( ">="	   PGNSP PGUID b f f	20	20	16 414 412 int8ge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 415 ( ">="	   PGNSP PGUID b f f	20	20	16 414 412 int8ge scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than or equal");
 
-DATA(insert OID = 416 ( "="		   PGNSP PGUID b t t	20	23	16	15 417 int84eq eqsel eqjoinsel ));
+DATA(insert OID = 416 ( "="		   PGNSP PGUID b t t	20	23	16	15 417 int84eq eqsel eqjoinsel "mhf"));
 DESCR("equal");
-DATA(insert OID = 417 ( "<>"	   PGNSP PGUID b f f	20	23	16	36 416 int84ne neqsel neqjoinsel ));
+DATA(insert OID = 417 ( "<>"	   PGNSP PGUID b f f	20	23	16	36 416 int84ne neqsel neqjoinsel "mhf"));
 DESCR("not equal");
-DATA(insert OID = 418 ( "<"		   PGNSP PGUID b f f	20	23	16	76 430 int84lt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 418 ( "<"		   PGNSP PGUID b f f	20	23	16	76 430 int84lt scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than");
-DATA(insert OID = 419 ( ">"		   PGNSP PGUID b f f	20	23	16	37 420 int84gt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 419 ( ">"		   PGNSP PGUID b f f	20	23	16	37 420 int84gt scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than");
-DATA(insert OID = 420 ( "<="	   PGNSP PGUID b f f	20	23	16	82 419 int84le scalarltsel scalarltjoinsel ));
+DATA(insert OID = 420 ( "<="	   PGNSP PGUID b f f	20	23	16	82 419 int84le scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than or equal");
-DATA(insert OID = 430 ( ">="	   PGNSP PGUID b f f	20	23	16	80 418 int84ge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 430 ( ">="	   PGNSP PGUID b f f	20	23	16	80 418 int84ge scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than or equal");
-DATA(insert OID = 439 (  "%"	   PGNSP PGUID b f f	20	20	20	 0	 0 int8mod - - ));
+DATA(insert OID = 439 (  "%"	   PGNSP PGUID b f f	20	20	20	 0	 0 int8mod - - "---"));
 DESCR("modulus");
-DATA(insert OID = 473 (  "@"	   PGNSP PGUID l f f	 0	20	20	 0	 0 int8abs - - ));
+DATA(insert OID = 473 (  "@"	   PGNSP PGUID l f f	 0	20	20	 0	 0 int8abs - - "---"));
 DESCR("absolute value");
 
-DATA(insert OID = 484 (  "-"	   PGNSP PGUID l f f	 0	20	20	 0	 0 int8um - - ));
+DATA(insert OID = 484 (  "-"	   PGNSP PGUID l f f	 0	20	20	 0	 0 int8um - - "---"));
 DESCR("negate");
-DATA(insert OID = 485 (  "<<"	   PGNSP PGUID b f f 604 604	16	 0	 0 poly_left positionsel positionjoinsel ));
+DATA(insert OID = 485 (  "<<"	   PGNSP PGUID b f f 604 604	16	 0	 0 poly_left positionsel positionjoinsel "---"));
 DESCR("is left of");
-DATA(insert OID = 486 (  "&<"	   PGNSP PGUID b f f 604 604	16	 0	 0 poly_overleft positionsel positionjoinsel ));
+DATA(insert OID = 486 (  "&<"	   PGNSP PGUID b f f 604 604	16	 0	 0 poly_overleft positionsel positionjoinsel "---"));
 DESCR("overlaps or is left of");
-DATA(insert OID = 487 (  "&>"	   PGNSP PGUID b f f 604 604	16	 0	 0 poly_overright positionsel positionjoinsel ));
+DATA(insert OID = 487 (  "&>"	   PGNSP PGUID b f f 604 604	16	 0	 0 poly_overright positionsel positionjoinsel "---"));
 DESCR("overlaps or is right of");
-DATA(insert OID = 488 (  ">>"	   PGNSP PGUID b f f 604 604	16	 0	 0 poly_right positionsel positionjoinsel ));
+DATA(insert OID = 488 (  ">>"	   PGNSP PGUID b f f 604 604	16	 0	 0 poly_right positionsel positionjoinsel "---"));
 DESCR("is right of");
-DATA(insert OID = 489 (  "<@"	   PGNSP PGUID b f f 604 604	16 490	 0 poly_contained contsel contjoinsel ));
+DATA(insert OID = 489 (  "<@"	   PGNSP PGUID b f f 604 604	16 490	 0 poly_contained contsel contjoinsel "---"));
 DESCR("is contained by");
-DATA(insert OID = 490 (  "@>"	   PGNSP PGUID b f f 604 604	16 489	 0 poly_contain contsel contjoinsel ));
+DATA(insert OID = 490 (  "@>"	   PGNSP PGUID b f f 604 604	16 489	 0 poly_contain contsel contjoinsel "---"));
 DESCR("contains");
-DATA(insert OID = 491 (  "~="	   PGNSP PGUID b f f 604 604	16 491	 0 poly_same eqsel eqjoinsel ));
+DATA(insert OID = 491 (  "~="	   PGNSP PGUID b f f 604 604	16 491	 0 poly_same eqsel eqjoinsel "mhf"));
 DESCR("same as");
-DATA(insert OID = 492 (  "&&"	   PGNSP PGUID b f f 604 604	16 492	 0 poly_overlap areasel areajoinsel ));
+DATA(insert OID = 492 (  "&&"	   PGNSP PGUID b f f 604 604	16 492	 0 poly_overlap areasel areajoinsel "---"));
 DESCR("overlaps");
-DATA(insert OID = 493 (  "<<"	   PGNSP PGUID b f f 603 603	16	 0	 0 box_left positionsel positionjoinsel ));
+DATA(insert OID = 493 (  "<<"	   PGNSP PGUID b f f 603 603	16	 0	 0 box_left positionsel positionjoinsel "---"));
 DESCR("is left of");
-DATA(insert OID = 494 (  "&<"	   PGNSP PGUID b f f 603 603	16	 0	 0 box_overleft positionsel positionjoinsel ));
+DATA(insert OID = 494 (  "&<"	   PGNSP PGUID b f f 603 603	16	 0	 0 box_overleft positionsel positionjoinsel "---"));
 DESCR("overlaps or is left of");
-DATA(insert OID = 495 (  "&>"	   PGNSP PGUID b f f 603 603	16	 0	 0 box_overright positionsel positionjoinsel ));
+DATA(insert OID = 495 (  "&>"	   PGNSP PGUID b f f 603 603	16	 0	 0 box_overright positionsel positionjoinsel "---"));
 DESCR("overlaps or is right of");
-DATA(insert OID = 496 (  ">>"	   PGNSP PGUID b f f 603 603	16	 0	 0 box_right positionsel positionjoinsel ));
+DATA(insert OID = 496 (  ">>"	   PGNSP PGUID b f f 603 603	16	 0	 0 box_right positionsel positionjoinsel "---"));
 DESCR("is right of");
-DATA(insert OID = 497 (  "<@"	   PGNSP PGUID b f f 603 603	16 498	 0 box_contained contsel contjoinsel ));
+DATA(insert OID = 497 (  "<@"	   PGNSP PGUID b f f 603 603	16 498	 0 box_contained contsel contjoinsel "---"));
 DESCR("is contained by");
-DATA(insert OID = 498 (  "@>"	   PGNSP PGUID b f f 603 603	16 497	 0 box_contain contsel contjoinsel ));
+DATA(insert OID = 498 (  "@>"	   PGNSP PGUID b f f 603 603	16 497	 0 box_contain contsel contjoinsel "---"));
 DESCR("contains");
-DATA(insert OID = 499 (  "~="	   PGNSP PGUID b f f 603 603	16 499	 0 box_same eqsel eqjoinsel ));
+DATA(insert OID = 499 (  "~="	   PGNSP PGUID b f f 603 603	16 499	 0 box_same eqsel eqjoinsel "mhf"));
 DESCR("same as");
-DATA(insert OID = 500 (  "&&"	   PGNSP PGUID b f f 603 603	16 500	 0 box_overlap areasel areajoinsel ));
+DATA(insert OID = 500 (  "&&"	   PGNSP PGUID b f f 603 603	16 500	 0 box_overlap areasel areajoinsel "---"));
 DESCR("overlaps");
-DATA(insert OID = 501 (  ">="	   PGNSP PGUID b f f 603 603	16 505 504 box_ge areasel areajoinsel ));
+DATA(insert OID = 501 (  ">="	   PGNSP PGUID b f f 603 603	16 505 504 box_ge areasel areajoinsel "---"));
 DESCR("greater than or equal by area");
-DATA(insert OID = 502 (  ">"	   PGNSP PGUID b f f 603 603	16 504 505 box_gt areasel areajoinsel ));
+DATA(insert OID = 502 (  ">"	   PGNSP PGUID b f f 603 603	16 504 505 box_gt areasel areajoinsel "---"));
 DESCR("greater than by area");
-DATA(insert OID = 503 (  "="	   PGNSP PGUID b f f 603 603	16 503	 0 box_eq eqsel eqjoinsel ));
+DATA(insert OID = 503 (  "="	   PGNSP PGUID b f f 603 603	16 503	 0 box_eq eqsel eqjoinsel "mhf"));
 DESCR("equal by area");
-DATA(insert OID = 504 (  "<"	   PGNSP PGUID b f f 603 603	16 502 501 box_lt areasel areajoinsel ));
+DATA(insert OID = 504 (  "<"	   PGNSP PGUID b f f 603 603	16 502 501 box_lt areasel areajoinsel "---"));
 DESCR("less than by area");
-DATA(insert OID = 505 (  "<="	   PGNSP PGUID b f f 603 603	16 501 502 box_le areasel areajoinsel ));
+DATA(insert OID = 505 (  "<="	   PGNSP PGUID b f f 603 603	16 501 502 box_le areasel areajoinsel "---"));
 DESCR("less than or equal by area");
-DATA(insert OID = 506 (  ">^"	   PGNSP PGUID b f f 600 600	16	 0	 0 point_above positionsel positionjoinsel ));
+DATA(insert OID = 506 (  ">^"	   PGNSP PGUID b f f 600 600	16	 0	 0 point_above positionsel positionjoinsel "---"));
 DESCR("is above");
-DATA(insert OID = 507 (  "<<"	   PGNSP PGUID b f f 600 600	16	 0	 0 point_left positionsel positionjoinsel ));
+DATA(insert OID = 507 (  "<<"	   PGNSP PGUID b f f 600 600	16	 0	 0 point_left positionsel positionjoinsel "---"));
 DESCR("is left of");
-DATA(insert OID = 508 (  ">>"	   PGNSP PGUID b f f 600 600	16	 0	 0 point_right positionsel positionjoinsel ));
+DATA(insert OID = 508 (  ">>"	   PGNSP PGUID b f f 600 600	16	 0	 0 point_right positionsel positionjoinsel "---"));
 DESCR("is right of");
-DATA(insert OID = 509 (  "<^"	   PGNSP PGUID b f f 600 600	16	 0	 0 point_below positionsel positionjoinsel ));
+DATA(insert OID = 509 (  "<^"	   PGNSP PGUID b f f 600 600	16	 0	 0 point_below positionsel positionjoinsel "---"));
 DESCR("is below");
-DATA(insert OID = 510 (  "~="	   PGNSP PGUID b f f 600 600	16 510 713 point_eq eqsel eqjoinsel ));
+DATA(insert OID = 510 (  "~="	   PGNSP PGUID b f f 600 600	16 510 713 point_eq eqsel eqjoinsel "mhf"));
 DESCR("same as");
-DATA(insert OID = 511 (  "<@"	   PGNSP PGUID b f f 600 603	16 433	 0 on_pb contsel contjoinsel ));
+DATA(insert OID = 511 (  "<@"	   PGNSP PGUID b f f 600 603	16 433	 0 on_pb contsel contjoinsel "---"));
 DESCR("point inside box");
-DATA(insert OID = 433 (  "@>"	   PGNSP PGUID b f f 603 600	16 511	 0 box_contain_pt contsel contjoinsel ));
+DATA(insert OID = 433 (  "@>"	   PGNSP PGUID b f f 603 600	16 511	 0 box_contain_pt contsel contjoinsel "---"));
 DESCR("contains");
-DATA(insert OID = 512 (  "<@"	   PGNSP PGUID b f f 600 602	16 755	 0 on_ppath - - ));
+DATA(insert OID = 512 (  "<@"	   PGNSP PGUID b f f 600 602	16 755	 0 on_ppath - - "---"));
 DESCR("point within closed path, or point on open path");
-DATA(insert OID = 513 (  "@@"	   PGNSP PGUID l f f	 0 603 600	 0	 0 box_center - - ));
+DATA(insert OID = 513 (  "@@"	   PGNSP PGUID l f f	 0 603 600	 0	 0 box_center - - "---"));
 DESCR("center of");
-DATA(insert OID = 514 (  "*"	   PGNSP PGUID b f f	23	23	23 514	 0 int4mul - - ));
+DATA(insert OID = 514 (  "*"	   PGNSP PGUID b f f	23	23	23 514	 0 int4mul - - "---"));
 DESCR("multiply");
-DATA(insert OID = 517 (  "<->"	   PGNSP PGUID b f f 600 600 701 517	 0 point_distance - - ));
+DATA(insert OID = 517 (  "<->"	   PGNSP PGUID b f f 600 600 701 517	 0 point_distance - - "---"));
 DESCR("distance between");
-DATA(insert OID = 518 (  "<>"	   PGNSP PGUID b f f	23	23	16 518	96 int4ne neqsel neqjoinsel ));
+DATA(insert OID = 518 (  "<>"	   PGNSP PGUID b f f	23	23	16 518	96 int4ne neqsel neqjoinsel "mhf"));
 DESCR("not equal");
-DATA(insert OID = 519 (  "<>"	   PGNSP PGUID b f f	21	21	16 519	94 int2ne neqsel neqjoinsel ));
+DATA(insert OID = 519 (  "<>"	   PGNSP PGUID b f f	21	21	16 519	94 int2ne neqsel neqjoinsel "mhf"));
 DESCR("not equal");
-DATA(insert OID = 520 (  ">"	   PGNSP PGUID b f f	21	21	16	95 522 int2gt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 520 (  ">"	   PGNSP PGUID b f f	21	21	16	95 522 int2gt scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than");
-DATA(insert OID = 521 (  ">"	   PGNSP PGUID b f f	23	23	16	97 523 int4gt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 521 (  ">"	   PGNSP PGUID b f f	23	23	16	97 523 int4gt scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than");
-DATA(insert OID = 522 (  "<="	   PGNSP PGUID b f f	21	21	16 524 520 int2le scalarltsel scalarltjoinsel ));
+DATA(insert OID = 522 (  "<="	   PGNSP PGUID b f f	21	21	16 524 520 int2le scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than or equal");
-DATA(insert OID = 523 (  "<="	   PGNSP PGUID b f f	23	23	16 525 521 int4le scalarltsel scalarltjoinsel ));
+DATA(insert OID = 523 (  "<="	   PGNSP PGUID b f f	23	23	16 525 521 int4le scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than or equal");
-DATA(insert OID = 524 (  ">="	   PGNSP PGUID b f f	21	21	16 522	95 int2ge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 524 (  ">="	   PGNSP PGUID b f f	21	21	16 522	95 int2ge scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than or equal");
-DATA(insert OID = 525 (  ">="	   PGNSP PGUID b f f	23	23	16 523	97 int4ge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 525 (  ">="	   PGNSP PGUID b f f	23	23	16 523	97 int4ge scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than or equal");
-DATA(insert OID = 526 (  "*"	   PGNSP PGUID b f f	21	21	21 526	 0 int2mul - - ));
+DATA(insert OID = 526 (  "*"	   PGNSP PGUID b f f	21	21	21 526	 0 int2mul - - "---"));
 DESCR("multiply");
-DATA(insert OID = 527 (  "/"	   PGNSP PGUID b f f	21	21	21	 0	 0 int2div - - ));
+DATA(insert OID = 527 (  "/"	   PGNSP PGUID b f f	21	21	21	 0	 0 int2div - - "---"));
 DESCR("divide");
-DATA(insert OID = 528 (  "/"	   PGNSP PGUID b f f	23	23	23	 0	 0 int4div - - ));
+DATA(insert OID = 528 (  "/"	   PGNSP PGUID b f f	23	23	23	 0	 0 int4div - - "---"));
 DESCR("divide");
-DATA(insert OID = 529 (  "%"	   PGNSP PGUID b f f	21	21	21	 0	 0 int2mod - - ));
+DATA(insert OID = 529 (  "%"	   PGNSP PGUID b f f	21	21	21	 0	 0 int2mod - - "---"));
 DESCR("modulus");
-DATA(insert OID = 530 (  "%"	   PGNSP PGUID b f f	23	23	23	 0	 0 int4mod - - ));
+DATA(insert OID = 530 (  "%"	   PGNSP PGUID b f f	23	23	23	 0	 0 int4mod - - "---"));
 DESCR("modulus");
-DATA(insert OID = 531 (  "<>"	   PGNSP PGUID b f f	25	25	16 531	98 textne neqsel neqjoinsel ));
+DATA(insert OID = 531 (  "<>"	   PGNSP PGUID b f f	25	25	16 531	98 textne neqsel neqjoinsel "mhf"));
 DESCR("not equal");
-DATA(insert OID = 532 (  "="	   PGNSP PGUID b t t	21	23	16 533 538 int24eq eqsel eqjoinsel ));
+DATA(insert OID = 532 (  "="	   PGNSP PGUID b t t	21	23	16 533 538 int24eq eqsel eqjoinsel "mhf"));
 DESCR("equal");
-DATA(insert OID = 533 (  "="	   PGNSP PGUID b t t	23	21	16 532 539 int42eq eqsel eqjoinsel ));
+DATA(insert OID = 533 (  "="	   PGNSP PGUID b t t	23	21	16 532 539 int42eq eqsel eqjoinsel "mhf"));
 DESCR("equal");
-DATA(insert OID = 534 (  "<"	   PGNSP PGUID b f f	21	23	16 537 542 int24lt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 534 (  "<"	   PGNSP PGUID b f f	21	23	16 537 542 int24lt scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than");
-DATA(insert OID = 535 (  "<"	   PGNSP PGUID b f f	23	21	16 536 543 int42lt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 535 (  "<"	   PGNSP PGUID b f f	23	21	16 536 543 int42lt scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than");
-DATA(insert OID = 536 (  ">"	   PGNSP PGUID b f f	21	23	16 535 540 int24gt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 536 (  ">"	   PGNSP PGUID b f f	21	23	16 535 540 int24gt scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than");
-DATA(insert OID = 537 (  ">"	   PGNSP PGUID b f f	23	21	16 534 541 int42gt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 537 (  ">"	   PGNSP PGUID b f f	23	21	16 534 541 int42gt scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than");
-DATA(insert OID = 538 (  "<>"	   PGNSP PGUID b f f	21	23	16 539 532 int24ne neqsel neqjoinsel ));
+DATA(insert OID = 538 (  "<>"	   PGNSP PGUID b f f	21	23	16 539 532 int24ne neqsel neqjoinsel "mhf"));
 DESCR("not equal");
-DATA(insert OID = 539 (  "<>"	   PGNSP PGUID b f f	23	21	16 538 533 int42ne neqsel neqjoinsel ));
+DATA(insert OID = 539 (  "<>"	   PGNSP PGUID b f f	23	21	16 538 533 int42ne neqsel neqjoinsel "mhf"));
 DESCR("not equal");
-DATA(insert OID = 540 (  "<="	   PGNSP PGUID b f f	21	23	16 543 536 int24le scalarltsel scalarltjoinsel ));
+DATA(insert OID = 540 (  "<="	   PGNSP PGUID b f f	21	23	16 543 536 int24le scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than or equal");
-DATA(insert OID = 541 (  "<="	   PGNSP PGUID b f f	23	21	16 542 537 int42le scalarltsel scalarltjoinsel ));
+DATA(insert OID = 541 (  "<="	   PGNSP PGUID b f f	23	21	16 542 537 int42le scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than or equal");
-DATA(insert OID = 542 (  ">="	   PGNSP PGUID b f f	21	23	16 541 534 int24ge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 542 (  ">="	   PGNSP PGUID b f f	21	23	16 541 534 int24ge scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than or equal");
-DATA(insert OID = 543 (  ">="	   PGNSP PGUID b f f	23	21	16 540 535 int42ge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 543 (  ">="	   PGNSP PGUID b f f	23	21	16 540 535 int42ge scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than or equal");
-DATA(insert OID = 544 (  "*"	   PGNSP PGUID b f f	21	23	23 545	 0 int24mul - - ));
+DATA(insert OID = 544 (  "*"	   PGNSP PGUID b f f	21	23	23 545	 0 int24mul - - "---"));
 DESCR("multiply");
-DATA(insert OID = 545 (  "*"	   PGNSP PGUID b f f	23	21	23 544	 0 int42mul - - ));
+DATA(insert OID = 545 (  "*"	   PGNSP PGUID b f f	23	21	23 544	 0 int42mul - - "---"));
 DESCR("multiply");
-DATA(insert OID = 546 (  "/"	   PGNSP PGUID b f f	21	23	23	 0	 0 int24div - - ));
+DATA(insert OID = 546 (  "/"	   PGNSP PGUID b f f	21	23	23	 0	 0 int24div - - "---"));
 DESCR("divide");
-DATA(insert OID = 547 (  "/"	   PGNSP PGUID b f f	23	21	23	 0	 0 int42div - - ));
+DATA(insert OID = 547 (  "/"	   PGNSP PGUID b f f	23	21	23	 0	 0 int42div - - "---"));
 DESCR("divide");
-DATA(insert OID = 550 (  "+"	   PGNSP PGUID b f f	21	21	21 550	 0 int2pl - - ));
+DATA(insert OID = 550 (  "+"	   PGNSP PGUID b f f	21	21	21 550	 0 int2pl - - "---"));
 DESCR("add");
-DATA(insert OID = 551 (  "+"	   PGNSP PGUID b f f	23	23	23 551	 0 int4pl - - ));
+DATA(insert OID = 551 (  "+"	   PGNSP PGUID b f f	23	23	23 551	 0 int4pl - - "---"));
 DESCR("add");
-DATA(insert OID = 552 (  "+"	   PGNSP PGUID b f f	21	23	23 553	 0 int24pl - - ));
+DATA(insert OID = 552 (  "+"	   PGNSP PGUID b f f	21	23	23 553	 0 int24pl - - "---"));
 DESCR("add");
-DATA(insert OID = 553 (  "+"	   PGNSP PGUID b f f	23	21	23 552	 0 int42pl - - ));
+DATA(insert OID = 553 (  "+"	   PGNSP PGUID b f f	23	21	23 552	 0 int42pl - - "---"));
 DESCR("add");
-DATA(insert OID = 554 (  "-"	   PGNSP PGUID b f f	21	21	21	 0	 0 int2mi - - ));
+DATA(insert OID = 554 (  "-"	   PGNSP PGUID b f f	21	21	21	 0	 0 int2mi - - "---"));
 DESCR("subtract");
-DATA(insert OID = 555 (  "-"	   PGNSP PGUID b f f	23	23	23	 0	 0 int4mi - - ));
+DATA(insert OID = 555 (  "-"	   PGNSP PGUID b f f	23	23	23	 0	 0 int4mi - - "---"));
 DESCR("subtract");
-DATA(insert OID = 556 (  "-"	   PGNSP PGUID b f f	21	23	23	 0	 0 int24mi - - ));
+DATA(insert OID = 556 (  "-"	   PGNSP PGUID b f f	21	23	23	 0	 0 int24mi - - "---"));
 DESCR("subtract");
-DATA(insert OID = 557 (  "-"	   PGNSP PGUID b f f	23	21	23	 0	 0 int42mi - - ));
+DATA(insert OID = 557 (  "-"	   PGNSP PGUID b f f	23	21	23	 0	 0 int42mi - - "---"));
 DESCR("subtract");
-DATA(insert OID = 558 (  "-"	   PGNSP PGUID l f f	 0	23	23	 0	 0 int4um - - ));
+DATA(insert OID = 558 (  "-"	   PGNSP PGUID l f f	 0	23	23	 0	 0 int4um - - "---"));
 DESCR("negate");
-DATA(insert OID = 559 (  "-"	   PGNSP PGUID l f f	 0	21	21	 0	 0 int2um - - ));
+DATA(insert OID = 559 (  "-"	   PGNSP PGUID l f f	 0	21	21	 0	 0 int2um - - "---"));
 DESCR("negate");
-DATA(insert OID = 560 (  "="	   PGNSP PGUID b t t 702 702	16 560 561 abstimeeq eqsel eqjoinsel ));
+DATA(insert OID = 560 (  "="	   PGNSP PGUID b t t 702 702	16 560 561 abstimeeq eqsel eqjoinsel "mhf"));
 DESCR("equal");
-DATA(insert OID = 561 (  "<>"	   PGNSP PGUID b f f 702 702	16 561 560 abstimene neqsel neqjoinsel ));
+DATA(insert OID = 561 (  "<>"	   PGNSP PGUID b f f 702 702	16 561 560 abstimene neqsel neqjoinsel "mhf"));
 DESCR("not equal");
-DATA(insert OID = 562 (  "<"	   PGNSP PGUID b f f 702 702	16 563 565 abstimelt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 562 (  "<"	   PGNSP PGUID b f f 702 702	16 563 565 abstimelt scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than");
-DATA(insert OID = 563 (  ">"	   PGNSP PGUID b f f 702 702	16 562 564 abstimegt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 563 (  ">"	   PGNSP PGUID b f f 702 702	16 562 564 abstimegt scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than");
-DATA(insert OID = 564 (  "<="	   PGNSP PGUID b f f 702 702	16 565 563 abstimele scalarltsel scalarltjoinsel ));
+DATA(insert OID = 564 (  "<="	   PGNSP PGUID b f f 702 702	16 565 563 abstimele scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than or equal");
-DATA(insert OID = 565 (  ">="	   PGNSP PGUID b f f 702 702	16 564 562 abstimege scalargtsel scalargtjoinsel ));
+DATA(insert OID = 565 (  ">="	   PGNSP PGUID b f f 702 702	16 564 562 abstimege scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than or equal");
-DATA(insert OID = 566 (  "="	   PGNSP PGUID b t t 703 703	16 566 567 reltimeeq eqsel eqjoinsel ));
+DATA(insert OID = 566 (  "="	   PGNSP PGUID b t t 703 703	16 566 567 reltimeeq eqsel eqjoinsel "mhf"));
 DESCR("equal");
-DATA(insert OID = 567 (  "<>"	   PGNSP PGUID b f f 703 703	16 567 566 reltimene neqsel neqjoinsel ));
+DATA(insert OID = 567 (  "<>"	   PGNSP PGUID b f f 703 703	16 567 566 reltimene neqsel neqjoinsel "mhf"));
 DESCR("not equal");
-DATA(insert OID = 568 (  "<"	   PGNSP PGUID b f f 703 703	16 569 571 reltimelt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 568 (  "<"	   PGNSP PGUID b f f 703 703	16 569 571 reltimelt scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than");
-DATA(insert OID = 569 (  ">"	   PGNSP PGUID b f f 703 703	16 568 570 reltimegt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 569 (  ">"	   PGNSP PGUID b f f 703 703	16 568 570 reltimegt scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than");
-DATA(insert OID = 570 (  "<="	   PGNSP PGUID b f f 703 703	16 571 569 reltimele scalarltsel scalarltjoinsel ));
+DATA(insert OID = 570 (  "<="	   PGNSP PGUID b f f 703 703	16 571 569 reltimele scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than or equal");
-DATA(insert OID = 571 (  ">="	   PGNSP PGUID b f f 703 703	16 570 568 reltimege scalargtsel scalargtjoinsel ));
+DATA(insert OID = 571 (  ">="	   PGNSP PGUID b f f 703 703	16 570 568 reltimege scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than or equal");
-DATA(insert OID = 572 (  "~="	   PGNSP PGUID b f f 704 704	16 572	 0 tintervalsame eqsel eqjoinsel ));
+DATA(insert OID = 572 (  "~="	   PGNSP PGUID b f f 704 704	16 572	 0 tintervalsame eqsel eqjoinsel "mhf"));
 DESCR("same as");
-DATA(insert OID = 573 (  "<<"	   PGNSP PGUID b f f 704 704	16	 0	 0 tintervalct - - ));
+DATA(insert OID = 573 (  "<<"	   PGNSP PGUID b f f 704 704	16	 0	 0 tintervalct - - "---"));
 DESCR("contains");
-DATA(insert OID = 574 (  "&&"	   PGNSP PGUID b f f 704 704	16 574	 0 tintervalov - - ));
+DATA(insert OID = 574 (  "&&"	   PGNSP PGUID b f f 704 704	16 574	 0 tintervalov - - "---"));
 DESCR("overlaps");
-DATA(insert OID = 575 (  "#="	   PGNSP PGUID b f f 704 703	16	 0 576 tintervalleneq - - ));
+DATA(insert OID = 575 (  "#="	   PGNSP PGUID b f f 704 703	16	 0 576 tintervalleneq - - "---"));
 DESCR("equal by length");
-DATA(insert OID = 576 (  "#<>"	   PGNSP PGUID b f f 704 703	16	 0 575 tintervallenne - - ));
+DATA(insert OID = 576 (  "#<>"	   PGNSP PGUID b f f 704 703	16	 0 575 tintervallenne - - "---"));
 DESCR("not equal by length");
-DATA(insert OID = 577 (  "#<"	   PGNSP PGUID b f f 704 703	16	 0 580 tintervallenlt - - ));
+DATA(insert OID = 577 (  "#<"	   PGNSP PGUID b f f 704 703	16	 0 580 tintervallenlt - - "---"));
 DESCR("less than by length");
-DATA(insert OID = 578 (  "#>"	   PGNSP PGUID b f f 704 703	16	 0 579 tintervallengt - - ));
+DATA(insert OID = 578 (  "#>"	   PGNSP PGUID b f f 704 703	16	 0 579 tintervallengt - - "---"));
 DESCR("greater than by length");
-DATA(insert OID = 579 (  "#<="	   PGNSP PGUID b f f 704 703	16	 0 578 tintervallenle - - ));
+DATA(insert OID = 579 (  "#<="	   PGNSP PGUID b f f 704 703	16	 0 578 tintervallenle - - "---"));
 DESCR("less than or equal by length");
-DATA(insert OID = 580 (  "#>="	   PGNSP PGUID b f f 704 703	16	 0 577 tintervallenge - - ));
+DATA(insert OID = 580 (  "#>="	   PGNSP PGUID b f f 704 703	16	 0 577 tintervallenge - - "---"));
 DESCR("greater than or equal by length");
-DATA(insert OID = 581 (  "+"	   PGNSP PGUID b f f 702 703 702	 0	 0 timepl - - ));
+DATA(insert OID = 581 (  "+"	   PGNSP PGUID b f f 702 703 702	 0	 0 timepl - - "---"));
 DESCR("add");
-DATA(insert OID = 582 (  "-"	   PGNSP PGUID b f f 702 703 702	 0	 0 timemi - - ));
+DATA(insert OID = 582 (  "-"	   PGNSP PGUID b f f 702 703 702	 0	 0 timemi - - "---"));
 DESCR("subtract");
-DATA(insert OID = 583 (  "<?>"	   PGNSP PGUID b f f 702 704	16	 0	 0 intinterval - - ));
+DATA(insert OID = 583 (  "<?>"	   PGNSP PGUID b f f 702 704	16	 0	 0 intinterval - - "---"));
 DESCR("is contained by");
-DATA(insert OID = 584 (  "-"	   PGNSP PGUID l f f	 0 700 700	 0	 0 float4um - - ));
+DATA(insert OID = 584 (  "-"	   PGNSP PGUID l f f	 0 700 700	 0	 0 float4um - - "---"));
 DESCR("negate");
-DATA(insert OID = 585 (  "-"	   PGNSP PGUID l f f	 0 701 701	 0	 0 float8um - - ));
+DATA(insert OID = 585 (  "-"	   PGNSP PGUID l f f	 0 701 701	 0	 0 float8um - - "---"));
 DESCR("negate");
-DATA(insert OID = 586 (  "+"	   PGNSP PGUID b f f 700 700 700 586	 0 float4pl - - ));
+DATA(insert OID = 586 (  "+"	   PGNSP PGUID b f f 700 700 700 586	 0 float4pl - - "---"));
 DESCR("add");
-DATA(insert OID = 587 (  "-"	   PGNSP PGUID b f f 700 700 700	 0	 0 float4mi - - ));
+DATA(insert OID = 587 (  "-"	   PGNSP PGUID b f f 700 700 700	 0	 0 float4mi - - "---"));
 DESCR("subtract");
-DATA(insert OID = 588 (  "/"	   PGNSP PGUID b f f 700 700 700	 0	 0 float4div - - ));
+DATA(insert OID = 588 (  "/"	   PGNSP PGUID b f f 700 700 700	 0	 0 float4div - - "---"));
 DESCR("divide");
-DATA(insert OID = 589 (  "*"	   PGNSP PGUID b f f 700 700 700 589	 0 float4mul - - ));
+DATA(insert OID = 589 (  "*"	   PGNSP PGUID b f f 700 700 700 589	 0 float4mul - - "---"));
 DESCR("multiply");
-DATA(insert OID = 590 (  "@"	   PGNSP PGUID l f f	 0 700 700	 0	 0 float4abs - - ));
+DATA(insert OID = 590 (  "@"	   PGNSP PGUID l f f	 0 700 700	 0	 0 float4abs - - "---"));
 DESCR("absolute value");
-DATA(insert OID = 591 (  "+"	   PGNSP PGUID b f f 701 701 701 591	 0 float8pl - - ));
+DATA(insert OID = 591 (  "+"	   PGNSP PGUID b f f 701 701 701 591	 0 float8pl - - "---"));
 DESCR("add");
-DATA(insert OID = 592 (  "-"	   PGNSP PGUID b f f 701 701 701	 0	 0 float8mi - - ));
+DATA(insert OID = 592 (  "-"	   PGNSP PGUID b f f 701 701 701	 0	 0 float8mi - - "---"));
 DESCR("subtract");
-DATA(insert OID = 593 (  "/"	   PGNSP PGUID b f f 701 701 701	 0	 0 float8div - - ));
+DATA(insert OID = 593 (  "/"	   PGNSP PGUID b f f 701 701 701	 0	 0 float8div - - "---"));
 DESCR("divide");
-DATA(insert OID = 594 (  "*"	   PGNSP PGUID b f f 701 701 701 594	 0 float8mul - - ));
+DATA(insert OID = 594 (  "*"	   PGNSP PGUID b f f 701 701 701 594	 0 float8mul - - "---"));
 DESCR("multiply");
-DATA(insert OID = 595 (  "@"	   PGNSP PGUID l f f	 0 701 701	 0	 0 float8abs - - ));
+DATA(insert OID = 595 (  "@"	   PGNSP PGUID l f f	 0 701 701	 0	 0 float8abs - - "---"));
 DESCR("absolute value");
-DATA(insert OID = 596 (  "|/"	   PGNSP PGUID l f f	 0 701 701	 0	 0 dsqrt - - ));
+DATA(insert OID = 596 (  "|/"	   PGNSP PGUID l f f	 0 701 701	 0	 0 dsqrt - - "---"));
 DESCR("square root");
-DATA(insert OID = 597 (  "||/"	   PGNSP PGUID l f f	 0 701 701	 0	 0 dcbrt - - ));
+DATA(insert OID = 597 (  "||/"	   PGNSP PGUID l f f	 0 701 701	 0	 0 dcbrt - - "---"));
 DESCR("cube root");
-DATA(insert OID = 1284 (  "|"	   PGNSP PGUID l f f	 0 704 702	 0	 0 tintervalstart - - ));
+DATA(insert OID = 1284 (  "|"	   PGNSP PGUID l f f	 0 704 702	 0	 0 tintervalstart - - "---"));
 DESCR("start of interval");
-DATA(insert OID = 606 (  "<#>"	   PGNSP PGUID b f f 702 702 704	 0	 0 mktinterval - - ));
+DATA(insert OID = 606 (  "<#>"	   PGNSP PGUID b f f 702 702 704	 0	 0 mktinterval - - "---"));
 DESCR("convert to tinterval");
 
-DATA(insert OID = 607 (  "="	   PGNSP PGUID b t t	26	26	16 607 608 oideq eqsel eqjoinsel ));
+DATA(insert OID = 607 (  "="	   PGNSP PGUID b t t	26	26	16 607 608 oideq eqsel eqjoinsel "mhf"));
 DESCR("equal");
-DATA(insert OID = 608 (  "<>"	   PGNSP PGUID b f f	26	26	16 608 607 oidne neqsel neqjoinsel ));
+DATA(insert OID = 608 (  "<>"	   PGNSP PGUID b f f	26	26	16 608 607 oidne neqsel neqjoinsel "mhf"));
 DESCR("not equal");
-DATA(insert OID = 609 (  "<"	   PGNSP PGUID b f f	26	26	16 610 612 oidlt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 609 (  "<"	   PGNSP PGUID b f f	26	26	16 610 612 oidlt scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than");
-DATA(insert OID = 610 (  ">"	   PGNSP PGUID b f f	26	26	16 609 611 oidgt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 610 (  ">"	   PGNSP PGUID b f f	26	26	16 609 611 oidgt scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than");
-DATA(insert OID = 611 (  "<="	   PGNSP PGUID b f f	26	26	16 612 610 oidle scalarltsel scalarltjoinsel ));
+DATA(insert OID = 611 (  "<="	   PGNSP PGUID b f f	26	26	16 612 610 oidle scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than or equal");
-DATA(insert OID = 612 (  ">="	   PGNSP PGUID b f f	26	26	16 611 609 oidge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 612 (  ">="	   PGNSP PGUID b f f	26	26	16 611 609 oidge scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than or equal");
 
-DATA(insert OID = 644 (  "<>"	   PGNSP PGUID b f f	30	30	16 644 649 oidvectorne neqsel neqjoinsel ));
+DATA(insert OID = 644 (  "<>"	   PGNSP PGUID b f f	30	30	16 644 649 oidvectorne neqsel neqjoinsel "mhf"));
 DESCR("not equal");
-DATA(insert OID = 645 (  "<"	   PGNSP PGUID b f f	30	30	16 646 648 oidvectorlt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 645 (  "<"	   PGNSP PGUID b f f	30	30	16 646 648 oidvectorlt scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than");
-DATA(insert OID = 646 (  ">"	   PGNSP PGUID b f f	30	30	16 645 647 oidvectorgt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 646 (  ">"	   PGNSP PGUID b f f	30	30	16 645 647 oidvectorgt scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than");
-DATA(insert OID = 647 (  "<="	   PGNSP PGUID b f f	30	30	16 648 646 oidvectorle scalarltsel scalarltjoinsel ));
+DATA(insert OID = 647 (  "<="	   PGNSP PGUID b f f	30	30	16 648 646 oidvectorle scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than or equal");
-DATA(insert OID = 648 (  ">="	   PGNSP PGUID b f f	30	30	16 647 645 oidvectorge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 648 (  ">="	   PGNSP PGUID b f f	30	30	16 647 645 oidvectorge scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than or equal");
-DATA(insert OID = 649 (  "="	   PGNSP PGUID b t t	30	30	16 649 644 oidvectoreq eqsel eqjoinsel ));
+DATA(insert OID = 649 (  "="	   PGNSP PGUID b t t	30	30	16 649 644 oidvectoreq eqsel eqjoinsel "mhf"));
 DESCR("equal");
 
-DATA(insert OID = 613 (  "<->"	   PGNSP PGUID b f f 600 628 701	 0	 0 dist_pl - - ));
+DATA(insert OID = 613 (  "<->"	   PGNSP PGUID b f f 600 628 701	 0	 0 dist_pl - - "---"));
 DESCR("distance between");
-DATA(insert OID = 614 (  "<->"	   PGNSP PGUID b f f 600 601 701	 0	 0 dist_ps - - ));
+DATA(insert OID = 614 (  "<->"	   PGNSP PGUID b f f 600 601 701	 0	 0 dist_ps - - "---"));
 DESCR("distance between");
-DATA(insert OID = 615 (  "<->"	   PGNSP PGUID b f f 600 603 701	 0	 0 dist_pb - - ));
+DATA(insert OID = 615 (  "<->"	   PGNSP PGUID b f f 600 603 701	 0	 0 dist_pb - - "---"));
 DESCR("distance between");
-DATA(insert OID = 616 (  "<->"	   PGNSP PGUID b f f 601 628 701	 0	 0 dist_sl - - ));
+DATA(insert OID = 616 (  "<->"	   PGNSP PGUID b f f 601 628 701	 0	 0 dist_sl - - "---"));
 DESCR("distance between");
-DATA(insert OID = 617 (  "<->"	   PGNSP PGUID b f f 601 603 701	 0	 0 dist_sb - - ));
+DATA(insert OID = 617 (  "<->"	   PGNSP PGUID b f f 601 603 701	 0	 0 dist_sb - - "---"));
 DESCR("distance between");
-DATA(insert OID = 618 (  "<->"	   PGNSP PGUID b f f 600 602 701	 0	 0 dist_ppath - - ));
+DATA(insert OID = 618 (  "<->"	   PGNSP PGUID b f f 600 602 701	 0	 0 dist_ppath - - "---"));
 DESCR("distance between");
 
-DATA(insert OID = 620 (  "="	   PGNSP PGUID b t t	700  700	16 620 621 float4eq eqsel eqjoinsel ));
+DATA(insert OID = 620 (  "="	   PGNSP PGUID b t t	700  700	16 620 621 float4eq eqsel eqjoinsel "mhf"));
 DESCR("equal");
-DATA(insert OID = 621 (  "<>"	   PGNSP PGUID b f f	700  700	16 621 620 float4ne neqsel neqjoinsel ));
+DATA(insert OID = 621 (  "<>"	   PGNSP PGUID b f f	700  700	16 621 620 float4ne neqsel neqjoinsel "mhf"));
 DESCR("not equal");
-DATA(insert OID = 622 (  "<"	   PGNSP PGUID b f f	700  700	16 623 625 float4lt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 622 (  "<"	   PGNSP PGUID b f f	700  700	16 623 625 float4lt scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than");
-DATA(insert OID = 623 (  ">"	   PGNSP PGUID b f f	700  700	16 622 624 float4gt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 623 (  ">"	   PGNSP PGUID b f f	700  700	16 622 624 float4gt scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than");
-DATA(insert OID = 624 (  "<="	   PGNSP PGUID b f f	700  700	16 625 623 float4le scalarltsel scalarltjoinsel ));
+DATA(insert OID = 624 (  "<="	   PGNSP PGUID b f f	700  700	16 625 623 float4le scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than or equal");
-DATA(insert OID = 625 (  ">="	   PGNSP PGUID b f f	700  700	16 624 622 float4ge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 625 (  ">="	   PGNSP PGUID b f f	700  700	16 624 622 float4ge scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than or equal");
-DATA(insert OID = 630 (  "<>"	   PGNSP PGUID b f f	18	18		16 630	92	charne neqsel neqjoinsel ));
+DATA(insert OID = 630 (  "<>"	   PGNSP PGUID b f f	18	18		16 630	92	charne neqsel neqjoinsel "mhf"));
 DESCR("not equal");
 
-DATA(insert OID = 631 (  "<"	   PGNSP PGUID b f f	18	18	16 633 634 charlt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 631 (  "<"	   PGNSP PGUID b f f	18	18	16 633 634 charlt scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than");
-DATA(insert OID = 632 (  "<="	   PGNSP PGUID b f f	18	18	16 634 633 charle scalarltsel scalarltjoinsel ));
+DATA(insert OID = 632 (  "<="	   PGNSP PGUID b f f	18	18	16 634 633 charle scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than or equal");
-DATA(insert OID = 633 (  ">"	   PGNSP PGUID b f f	18	18	16 631 632 chargt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 633 (  ">"	   PGNSP PGUID b f f	18	18	16 631 632 chargt scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than");
-DATA(insert OID = 634 (  ">="	   PGNSP PGUID b f f	18	18	16 632 631 charge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 634 (  ">="	   PGNSP PGUID b f f	18	18	16 632 631 charge scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than or equal");
 
-DATA(insert OID = 639 (  "~"	   PGNSP PGUID b f f	19	25	16 0 640 nameregexeq regexeqsel regexeqjoinsel ));
+DATA(insert OID = 639 (  "~"	   PGNSP PGUID b f f	19	25	16 0 640 nameregexeq regexeqsel regexeqjoinsel "mhf"));
 DESCR("matches regular expression, case-sensitive");
 #define OID_NAME_REGEXEQ_OP		639
-DATA(insert OID = 640 (  "!~"	   PGNSP PGUID b f f	19	25	16 0 639 nameregexne regexnesel regexnejoinsel ));
+DATA(insert OID = 640 (  "!~"	   PGNSP PGUID b f f	19	25	16 0 639 nameregexne regexnesel regexnejoinsel "---"));
 DESCR("does not match regular expression, case-sensitive");
-DATA(insert OID = 641 (  "~"	   PGNSP PGUID b f f	25	25	16 0 642 textregexeq regexeqsel regexeqjoinsel ));
+DATA(insert OID = 641 (  "~"	   PGNSP PGUID b f f	25	25	16 0 642 textregexeq regexeqsel regexeqjoinsel "mhf"));
 DESCR("matches regular expression, case-sensitive");
 #define OID_TEXT_REGEXEQ_OP		641
-DATA(insert OID = 642 (  "!~"	   PGNSP PGUID b f f	25	25	16 0 641 textregexne regexnesel regexnejoinsel ));
+DATA(insert OID = 642 (  "!~"	   PGNSP PGUID b f f	25	25	16 0 641 textregexne regexnesel regexnejoinsel "---"));
 DESCR("does not match regular expression, case-sensitive");
-DATA(insert OID = 643 (  "<>"	   PGNSP PGUID b f f	19	19	16 643 93 namene neqsel neqjoinsel ));
+DATA(insert OID = 643 (  "<>"	   PGNSP PGUID b f f	19	19	16 643 93 namene neqsel neqjoinsel "mhf"));
 DESCR("not equal");
-DATA(insert OID = 654 (  "||"	   PGNSP PGUID b f f	25	25	25	 0 0 textcat - - ));
+DATA(insert OID = 654 (  "||"	   PGNSP PGUID b f f	25	25	25	 0 0 textcat - - "---"));
 DESCR("concatenate");
 
-DATA(insert OID = 660 (  "<"	   PGNSP PGUID b f f	19	19	16 662 663 namelt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 660 (  "<"	   PGNSP PGUID b f f	19	19	16 662 663 namelt scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than");
-DATA(insert OID = 661 (  "<="	   PGNSP PGUID b f f	19	19	16 663 662 namele scalarltsel scalarltjoinsel ));
+DATA(insert OID = 661 (  "<="	   PGNSP PGUID b f f	19	19	16 663 662 namele scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than or equal");
-DATA(insert OID = 662 (  ">"	   PGNSP PGUID b f f	19	19	16 660 661 namegt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 662 (  ">"	   PGNSP PGUID b f f	19	19	16 660 661 namegt scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than");
-DATA(insert OID = 663 (  ">="	   PGNSP PGUID b f f	19	19	16 661 660 namege scalargtsel scalargtjoinsel ));
+DATA(insert OID = 663 (  ">="	   PGNSP PGUID b f f	19	19	16 661 660 namege scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than or equal");
-DATA(insert OID = 664 (  "<"	   PGNSP PGUID b f f	25	25	16 666 667 text_lt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 664 (  "<"	   PGNSP PGUID b f f	25	25	16 666 667 text_lt scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than");
-DATA(insert OID = 665 (  "<="	   PGNSP PGUID b f f	25	25	16 667 666 text_le scalarltsel scalarltjoinsel ));
+DATA(insert OID = 665 (  "<="	   PGNSP PGUID b f f	25	25	16 667 666 text_le scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than or equal");
-DATA(insert OID = 666 (  ">"	   PGNSP PGUID b f f	25	25	16 664 665 text_gt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 666 (  ">"	   PGNSP PGUID b f f	25	25	16 664 665 text_gt scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than");
-DATA(insert OID = 667 (  ">="	   PGNSP PGUID b f f	25	25	16 665 664 text_ge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 667 (  ">="	   PGNSP PGUID b f f	25	25	16 665 664 text_ge scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than or equal");
 
-DATA(insert OID = 670 (  "="	   PGNSP PGUID b t t	701  701	16 670 671 float8eq eqsel eqjoinsel ));
+DATA(insert OID = 670 (  "="	   PGNSP PGUID b t t	701  701	16 670 671 float8eq eqsel eqjoinsel "mhf"));
 DESCR("equal");
-DATA(insert OID = 671 (  "<>"	   PGNSP PGUID b f f	701  701	16 671 670 float8ne neqsel neqjoinsel ));
+DATA(insert OID = 671 (  "<>"	   PGNSP PGUID b f f	701  701	16 671 670 float8ne neqsel neqjoinsel "mhf"));
 DESCR("not equal");
-DATA(insert OID = 672 (  "<"	   PGNSP PGUID b f f	701  701	16 674 675 float8lt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 672 (  "<"	   PGNSP PGUID b f f	701  701	16 674 675 float8lt scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than");
 #define Float8LessOperator	672
-DATA(insert OID = 673 (  "<="	   PGNSP PGUID b f f	701  701	16 675 674 float8le scalarltsel scalarltjoinsel ));
+DATA(insert OID = 673 (  "<="	   PGNSP PGUID b f f	701  701	16 675 674 float8le scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than or equal");
-DATA(insert OID = 674 (  ">"	   PGNSP PGUID b f f	701  701	16 672 673 float8gt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 674 (  ">"	   PGNSP PGUID b f f	701  701	16 672 673 float8gt scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than");
-DATA(insert OID = 675 (  ">="	   PGNSP PGUID b f f	701  701	16 673 672 float8ge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 675 (  ">="	   PGNSP PGUID b f f	701  701	16 673 672 float8ge scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than or equal");
 
-DATA(insert OID = 682 (  "@"	   PGNSP PGUID l f f	 0	21	21	 0	 0 int2abs - - ));
+DATA(insert OID = 682 (  "@"	   PGNSP PGUID l f f	 0	21	21	 0	 0 int2abs - - "---"));
 DESCR("absolute value");
-DATA(insert OID = 684 (  "+"	   PGNSP PGUID b f f	20	20	20 684	 0 int8pl - - ));
+DATA(insert OID = 684 (  "+"	   PGNSP PGUID b f f	20	20	20 684	 0 int8pl - - "---"));
 DESCR("add");
-DATA(insert OID = 685 (  "-"	   PGNSP PGUID b f f	20	20	20	 0	 0 int8mi - - ));
+DATA(insert OID = 685 (  "-"	   PGNSP PGUID b f f	20	20	20	 0	 0 int8mi - - "---"));
 DESCR("subtract");
-DATA(insert OID = 686 (  "*"	   PGNSP PGUID b f f	20	20	20 686	 0 int8mul - - ));
+DATA(insert OID = 686 (  "*"	   PGNSP PGUID b f f	20	20	20 686	 0 int8mul - - "---"));
 DESCR("multiply");
-DATA(insert OID = 687 (  "/"	   PGNSP PGUID b f f	20	20	20	 0	 0 int8div - - ));
+DATA(insert OID = 687 (  "/"	   PGNSP PGUID b f f	20	20	20	 0	 0 int8div - - "---"));
 DESCR("divide");
 
-DATA(insert OID = 688 (  "+"	   PGNSP PGUID b f f	20	23	20 692	 0 int84pl - - ));
+DATA(insert OID = 688 (  "+"	   PGNSP PGUID b f f	20	23	20 692	 0 int84pl - - "---"));
 DESCR("add");
-DATA(insert OID = 689 (  "-"	   PGNSP PGUID b f f	20	23	20	 0	 0 int84mi - - ));
+DATA(insert OID = 689 (  "-"	   PGNSP PGUID b f f	20	23	20	 0	 0 int84mi - - "---"));
 DESCR("subtract");
-DATA(insert OID = 690 (  "*"	   PGNSP PGUID b f f	20	23	20 694	 0 int84mul - - ));
+DATA(insert OID = 690 (  "*"	   PGNSP PGUID b f f	20	23	20 694	 0 int84mul - - "---"));
 DESCR("multiply");
-DATA(insert OID = 691 (  "/"	   PGNSP PGUID b f f	20	23	20	 0	 0 int84div - - ));
+DATA(insert OID = 691 (  "/"	   PGNSP PGUID b f f	20	23	20	 0	 0 int84div - - "---"));
 DESCR("divide");
-DATA(insert OID = 692 (  "+"	   PGNSP PGUID b f f	23	20	20 688	 0 int48pl - - ));
+DATA(insert OID = 692 (  "+"	   PGNSP PGUID b f f	23	20	20 688	 0 int48pl - - "---"));
 DESCR("add");
-DATA(insert OID = 693 (  "-"	   PGNSP PGUID b f f	23	20	20	 0	 0 int48mi - - ));
+DATA(insert OID = 693 (  "-"	   PGNSP PGUID b f f	23	20	20	 0	 0 int48mi - - "---"));
 DESCR("subtract");
-DATA(insert OID = 694 (  "*"	   PGNSP PGUID b f f	23	20	20 690	 0 int48mul - - ));
+DATA(insert OID = 694 (  "*"	   PGNSP PGUID b f f	23	20	20 690	 0 int48mul - - "---"));
 DESCR("multiply");
-DATA(insert OID = 695 (  "/"	   PGNSP PGUID b f f	23	20	20	 0	 0 int48div - - ));
+DATA(insert OID = 695 (  "/"	   PGNSP PGUID b f f	23	20	20	 0	 0 int48div - - "---"));
 DESCR("divide");
 
-DATA(insert OID = 818 (  "+"	   PGNSP PGUID b f f	20	21	20 822	 0 int82pl - - ));
+DATA(insert OID = 818 (  "+"	   PGNSP PGUID b f f	20	21	20 822	 0 int82pl - - "---"));
 DESCR("add");
-DATA(insert OID = 819 (  "-"	   PGNSP PGUID b f f	20	21	20	 0	 0 int82mi - - ));
+DATA(insert OID = 819 (  "-"	   PGNSP PGUID b f f	20	21	20	 0	 0 int82mi - - "---"));
 DESCR("subtract");
-DATA(insert OID = 820 (  "*"	   PGNSP PGUID b f f	20	21	20 824	 0 int82mul - - ));
+DATA(insert OID = 820 (  "*"	   PGNSP PGUID b f f	20	21	20 824	 0 int82mul - - "---"));
 DESCR("multiply");
-DATA(insert OID = 821 (  "/"	   PGNSP PGUID b f f	20	21	20	 0	 0 int82div - - ));
+DATA(insert OID = 821 (  "/"	   PGNSP PGUID b f f	20	21	20	 0	 0 int82div - - "---"));
 DESCR("divide");
-DATA(insert OID = 822 (  "+"	   PGNSP PGUID b f f	21	20	20 818	 0 int28pl - - ));
+DATA(insert OID = 822 (  "+"	   PGNSP PGUID b f f	21	20	20 818	 0 int28pl - - "---"));
 DESCR("add");
-DATA(insert OID = 823 (  "-"	   PGNSP PGUID b f f	21	20	20	 0	 0 int28mi - - ));
+DATA(insert OID = 823 (  "-"	   PGNSP PGUID b f f	21	20	20	 0	 0 int28mi - - "---"));
 DESCR("subtract");
-DATA(insert OID = 824 (  "*"	   PGNSP PGUID b f f	21	20	20 820	 0 int28mul - - ));
+DATA(insert OID = 824 (  "*"	   PGNSP PGUID b f f	21	20	20 820	 0 int28mul - - "---"));
 DESCR("multiply");
-DATA(insert OID = 825 (  "/"	   PGNSP PGUID b f f	21	20	20	 0	 0 int28div - - ));
+DATA(insert OID = 825 (  "/"	   PGNSP PGUID b f f	21	20	20	 0	 0 int28div - - "---"));
 DESCR("divide");
 
-DATA(insert OID = 706 (  "<->"	   PGNSP PGUID b f f 603 603 701 706	 0 box_distance - - ));
+DATA(insert OID = 706 (  "<->"	   PGNSP PGUID b f f 603 603 701 706	 0 box_distance - - "---"));
 DESCR("distance between");
-DATA(insert OID = 707 (  "<->"	   PGNSP PGUID b f f 602 602 701 707	 0 path_distance - - ));
+DATA(insert OID = 707 (  "<->"	   PGNSP PGUID b f f 602 602 701 707	 0 path_distance - - "---"));
 DESCR("distance between");
-DATA(insert OID = 708 (  "<->"	   PGNSP PGUID b f f 628 628 701 708	 0 line_distance - - ));
+DATA(insert OID = 708 (  "<->"	   PGNSP PGUID b f f 628 628 701 708	 0 line_distance - - "---"));
 DESCR("distance between");
-DATA(insert OID = 709 (  "<->"	   PGNSP PGUID b f f 601 601 701 709	 0 lseg_distance - - ));
+DATA(insert OID = 709 (  "<->"	   PGNSP PGUID b f f 601 601 701 709	 0 lseg_distance - - "---"));
 DESCR("distance between");
-DATA(insert OID = 712 (  "<->"	   PGNSP PGUID b f f 604 604 701 712	 0 poly_distance - - ));
+DATA(insert OID = 712 (  "<->"	   PGNSP PGUID b f f 604 604 701 712	 0 poly_distance - - "---"));
 DESCR("distance between");
 
-DATA(insert OID = 713 (  "<>"	   PGNSP PGUID b f f 600 600	16 713 510 point_ne neqsel neqjoinsel ));
+DATA(insert OID = 713 (  "<>"	   PGNSP PGUID b f f 600 600	16 713 510 point_ne neqsel neqjoinsel "mhf"));
 DESCR("not equal");
 
 /* add translation/rotation/scaling operators for geometric types. - thomas 97/05/10 */
-DATA(insert OID = 731 (  "+"	   PGNSP PGUID b f f	600  600	600  731  0 point_add - - ));
+DATA(insert OID = 731 (  "+"	   PGNSP PGUID b f f	600  600	600  731  0 point_add - - "---"));
 DESCR("add points (translate)");
-DATA(insert OID = 732 (  "-"	   PGNSP PGUID b f f	600  600	600    0  0 point_sub - - ));
+DATA(insert OID = 732 (  "-"	   PGNSP PGUID b f f	600  600	600    0  0 point_sub - - "---"));
 DESCR("subtract points (translate)");
-DATA(insert OID = 733 (  "*"	   PGNSP PGUID b f f	600  600	600  733  0 point_mul - - ));
+DATA(insert OID = 733 (  "*"	   PGNSP PGUID b f f	600  600	600  733  0 point_mul - - "---"));
 DESCR("multiply points (scale/rotate)");
-DATA(insert OID = 734 (  "/"	   PGNSP PGUID b f f	600  600	600    0  0 point_div - - ));
+DATA(insert OID = 734 (  "/"	   PGNSP PGUID b f f	600  600	600    0  0 point_div - - "---"));
 DESCR("divide points (scale/rotate)");
-DATA(insert OID = 735 (  "+"	   PGNSP PGUID b f f	602  602	602  735  0 path_add - - ));
+DATA(insert OID = 735 (  "+"	   PGNSP PGUID b f f	602  602	602  735  0 path_add - - "---"));
 DESCR("concatenate");
-DATA(insert OID = 736 (  "+"	   PGNSP PGUID b f f	602  600	602    0  0 path_add_pt - - ));
+DATA(insert OID = 736 (  "+"	   PGNSP PGUID b f f	602  600	602    0  0 path_add_pt - - "---"));
 DESCR("add (translate path)");
-DATA(insert OID = 737 (  "-"	   PGNSP PGUID b f f	602  600	602    0  0 path_sub_pt - - ));
+DATA(insert OID = 737 (  "-"	   PGNSP PGUID b f f	602  600	602    0  0 path_sub_pt - - "---"));
 DESCR("subtract (translate path)");
-DATA(insert OID = 738 (  "*"	   PGNSP PGUID b f f	602  600	602    0  0 path_mul_pt - - ));
+DATA(insert OID = 738 (  "*"	   PGNSP PGUID b f f	602  600	602    0  0 path_mul_pt - - "---"));
 DESCR("multiply (rotate/scale path)");
-DATA(insert OID = 739 (  "/"	   PGNSP PGUID b f f	602  600	602    0  0 path_div_pt - - ));
+DATA(insert OID = 739 (  "/"	   PGNSP PGUID b f f	602  600	602    0  0 path_div_pt - - "---"));
 DESCR("divide (rotate/scale path)");
-DATA(insert OID = 755 (  "@>"	   PGNSP PGUID b f f	602  600	 16  512  0 path_contain_pt - - ));
+DATA(insert OID = 755 (  "@>"	   PGNSP PGUID b f f	602  600	 16  512  0 path_contain_pt - - "---"));
 DESCR("contains");
-DATA(insert OID = 756 (  "<@"	   PGNSP PGUID b f f	600  604	 16  757  0 pt_contained_poly contsel contjoinsel ));
+DATA(insert OID = 756 (  "<@"	   PGNSP PGUID b f f	600  604	 16  757  0 pt_contained_poly contsel contjoinsel "---"));
 DESCR("is contained by");
-DATA(insert OID = 757 (  "@>"	   PGNSP PGUID b f f	604  600	 16  756  0 poly_contain_pt contsel contjoinsel ));
+DATA(insert OID = 757 (  "@>"	   PGNSP PGUID b f f	604  600	 16  756  0 poly_contain_pt contsel contjoinsel "---"));
 DESCR("contains");
-DATA(insert OID = 758 (  "<@"	   PGNSP PGUID b f f	600  718	 16  759  0 pt_contained_circle contsel contjoinsel ));
+DATA(insert OID = 758 (  "<@"	   PGNSP PGUID b f f	600  718	 16  759  0 pt_contained_circle contsel contjoinsel "---"));
 DESCR("is contained by");
-DATA(insert OID = 759 (  "@>"	   PGNSP PGUID b f f	718  600	 16  758  0 circle_contain_pt contsel contjoinsel ));
+DATA(insert OID = 759 (  "@>"	   PGNSP PGUID b f f	718  600	 16  758  0 circle_contain_pt contsel contjoinsel "---"));
 DESCR("contains");
 
-DATA(insert OID = 773 (  "@"	   PGNSP PGUID l f f	 0	23	23	 0	 0 int4abs - - ));
+DATA(insert OID = 773 (  "@"	   PGNSP PGUID l f f	 0	23	23	 0	 0 int4abs - - "---"));
 DESCR("absolute value");
 
 /* additional operators for geometric types - thomas 1997-07-09 */
-DATA(insert OID =  792 (  "="	   PGNSP PGUID b f f	602  602	 16  792  0 path_n_eq eqsel eqjoinsel ));
+DATA(insert OID =  792 (  "="	   PGNSP PGUID b f f	602  602	 16  792  0 path_n_eq eqsel eqjoinsel "mhf"));
 DESCR("equal");
-DATA(insert OID =  793 (  "<"	   PGNSP PGUID b f f	602  602	 16  794  0 path_n_lt - - ));
+DATA(insert OID =  793 (  "<"	   PGNSP PGUID b f f	602  602	 16  794  0 path_n_lt - - "---"));
 DESCR("less than");
-DATA(insert OID =  794 (  ">"	   PGNSP PGUID b f f	602  602	 16  793  0 path_n_gt - - ));
+DATA(insert OID =  794 (  ">"	   PGNSP PGUID b f f	602  602	 16  793  0 path_n_gt - - "---"));
 DESCR("greater than");
-DATA(insert OID =  795 (  "<="	   PGNSP PGUID b f f	602  602	 16  796  0 path_n_le - - ));
+DATA(insert OID =  795 (  "<="	   PGNSP PGUID b f f	602  602	 16  796  0 path_n_le - - "---"));
 DESCR("less than or equal");
-DATA(insert OID =  796 (  ">="	   PGNSP PGUID b f f	602  602	 16  795  0 path_n_ge - - ));
+DATA(insert OID =  796 (  ">="	   PGNSP PGUID b f f	602  602	 16  795  0 path_n_ge - - "---"));
 DESCR("greater than or equal");
-DATA(insert OID =  797 (  "#"	   PGNSP PGUID l f f	0	 602	 23    0  0 path_npoints - - ));
+DATA(insert OID =  797 (  "#"	   PGNSP PGUID l f f	0	 602	 23    0  0 path_npoints - - "---"));
 DESCR("number of points");
-DATA(insert OID =  798 (  "?#"	   PGNSP PGUID b f f	602  602	 16    0  0 path_inter - - ));
+DATA(insert OID =  798 (  "?#"	   PGNSP PGUID b f f	602  602	 16    0  0 path_inter - - "---"));
 DESCR("intersect");
-DATA(insert OID =  799 (  "@-@"    PGNSP PGUID l f f	0	 602	701    0  0 path_length - - ));
+DATA(insert OID =  799 (  "@-@"    PGNSP PGUID l f f	0	 602	701    0  0 path_length - - "---"));
 DESCR("sum of path segment lengths");
-DATA(insert OID =  800 (  ">^"	   PGNSP PGUID b f f	603  603	 16    0  0 box_above_eq positionsel positionjoinsel ));
+DATA(insert OID =  800 (  ">^"	   PGNSP PGUID b f f	603  603	 16    0  0 box_above_eq positionsel positionjoinsel "---"));
 DESCR("is above (allows touching)");
-DATA(insert OID =  801 (  "<^"	   PGNSP PGUID b f f	603  603	 16    0  0 box_below_eq positionsel positionjoinsel ));
+DATA(insert OID =  801 (  "<^"	   PGNSP PGUID b f f	603  603	 16    0  0 box_below_eq positionsel positionjoinsel "---"));
 DESCR("is below (allows touching)");
-DATA(insert OID =  802 (  "?#"	   PGNSP PGUID b f f	603  603	 16    0  0 box_overlap areasel areajoinsel ));
+DATA(insert OID =  802 (  "?#"	   PGNSP PGUID b f f	603  603	 16    0  0 box_overlap areasel areajoinsel "---"));
 DESCR("deprecated, use && instead");
-DATA(insert OID =  803 (  "#"	   PGNSP PGUID b f f	603  603	603    0  0 box_intersect - - ));
+DATA(insert OID =  803 (  "#"	   PGNSP PGUID b f f	603  603	603    0  0 box_intersect - - "---"));
 DESCR("box intersection");
-DATA(insert OID =  804 (  "+"	   PGNSP PGUID b f f	603  600	603    0  0 box_add - - ));
+DATA(insert OID =  804 (  "+"	   PGNSP PGUID b f f	603  600	603    0  0 box_add - - "---"));
 DESCR("add point to box (translate)");
-DATA(insert OID =  805 (  "-"	   PGNSP PGUID b f f	603  600	603    0  0 box_sub - - ));
+DATA(insert OID =  805 (  "-"	   PGNSP PGUID b f f	603  600	603    0  0 box_sub - - "---"));
 DESCR("subtract point from box (translate)");
-DATA(insert OID =  806 (  "*"	   PGNSP PGUID b f f	603  600	603    0  0 box_mul - - ));
+DATA(insert OID =  806 (  "*"	   PGNSP PGUID b f f	603  600	603    0  0 box_mul - - "---"));
 DESCR("multiply box by point (scale)");
-DATA(insert OID =  807 (  "/"	   PGNSP PGUID b f f	603  600	603    0  0 box_div - - ));
+DATA(insert OID =  807 (  "/"	   PGNSP PGUID b f f	603  600	603    0  0 box_div - - "---"));
 DESCR("divide box by point (scale)");
-DATA(insert OID =  808 (  "?-"	   PGNSP PGUID b f f	600  600	 16  808  0 point_horiz - - ));
+DATA(insert OID =  808 (  "?-"	   PGNSP PGUID b f f	600  600	 16  808  0 point_horiz - - "---"));
 DESCR("horizontally aligned");
-DATA(insert OID =  809 (  "?|"	   PGNSP PGUID b f f	600  600	 16  809  0 point_vert - - ));
+DATA(insert OID =  809 (  "?|"	   PGNSP PGUID b f f	600  600	 16  809  0 point_vert - - "---"));
 DESCR("vertically aligned");
 
-DATA(insert OID = 811 (  "="	   PGNSP PGUID b t f 704 704	16 811 812 tintervaleq eqsel eqjoinsel ));
+DATA(insert OID = 811 (  "="	   PGNSP PGUID b t f 704 704	16 811 812 tintervaleq eqsel eqjoinsel "mhf"));
 DESCR("equal");
-DATA(insert OID = 812 (  "<>"	   PGNSP PGUID b f f 704 704	16 812 811 tintervalne neqsel neqjoinsel ));
+DATA(insert OID = 812 (  "<>"	   PGNSP PGUID b f f 704 704	16 812 811 tintervalne neqsel neqjoinsel "mhf"));
 DESCR("not equal");
-DATA(insert OID = 813 (  "<"	   PGNSP PGUID b f f 704 704	16 814 816 tintervallt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 813 (  "<"	   PGNSP PGUID b f f 704 704	16 814 816 tintervallt scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than");
-DATA(insert OID = 814 (  ">"	   PGNSP PGUID b f f 704 704	16 813 815 tintervalgt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 814 (  ">"	   PGNSP PGUID b f f 704 704	16 813 815 tintervalgt scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than");
-DATA(insert OID = 815 (  "<="	   PGNSP PGUID b f f 704 704	16 816 814 tintervalle scalarltsel scalarltjoinsel ));
+DATA(insert OID = 815 (  "<="	   PGNSP PGUID b f f 704 704	16 816 814 tintervalle scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than or equal");
-DATA(insert OID = 816 (  ">="	   PGNSP PGUID b f f 704 704	16 815 813 tintervalge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 816 (  ">="	   PGNSP PGUID b f f 704 704	16 815 813 tintervalge scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than or equal");
 
-DATA(insert OID = 843 (  "*"	   PGNSP PGUID b f f	790  700	790 845   0 cash_mul_flt4 - - ));
+DATA(insert OID = 843 (  "*"	   PGNSP PGUID b f f	790  700	790 845   0 cash_mul_flt4 - - "---"));
 DESCR("multiply");
-DATA(insert OID = 844 (  "/"	   PGNSP PGUID b f f	790  700	790   0   0 cash_div_flt4 - - ));
+DATA(insert OID = 844 (  "/"	   PGNSP PGUID b f f	790  700	790   0   0 cash_div_flt4 - - "---"));
 DESCR("divide");
-DATA(insert OID = 845 (  "*"	   PGNSP PGUID b f f	700  790	790 843   0 flt4_mul_cash - - ));
+DATA(insert OID = 845 (  "*"	   PGNSP PGUID b f f	700  790	790 843   0 flt4_mul_cash - - "---"));
 DESCR("multiply");
 
-DATA(insert OID = 900 (  "="	   PGNSP PGUID b t f	790  790	16 900 901 cash_eq eqsel eqjoinsel ));
+DATA(insert OID = 900 (  "="	   PGNSP PGUID b t f	790  790	16 900 901 cash_eq eqsel eqjoinsel "mhf"));
 DESCR("equal");
-DATA(insert OID = 901 (  "<>"	   PGNSP PGUID b f f	790  790	16 901 900 cash_ne neqsel neqjoinsel ));
+DATA(insert OID = 901 (  "<>"	   PGNSP PGUID b f f	790  790	16 901 900 cash_ne neqsel neqjoinsel "mhf"));
 DESCR("not equal");
-DATA(insert OID = 902 (  "<"	   PGNSP PGUID b f f	790  790	16 903 905 cash_lt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 902 (  "<"	   PGNSP PGUID b f f	790  790	16 903 905 cash_lt scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than");
-DATA(insert OID = 903 (  ">"	   PGNSP PGUID b f f	790  790	16 902 904 cash_gt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 903 (  ">"	   PGNSP PGUID b f f	790  790	16 902 904 cash_gt scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than");
-DATA(insert OID = 904 (  "<="	   PGNSP PGUID b f f	790  790	16 905 903 cash_le scalarltsel scalarltjoinsel ));
+DATA(insert OID = 904 (  "<="	   PGNSP PGUID b f f	790  790	16 905 903 cash_le scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than or equal");
-DATA(insert OID = 905 (  ">="	   PGNSP PGUID b f f	790  790	16 904 902 cash_ge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 905 (  ">="	   PGNSP PGUID b f f	790  790	16 904 902 cash_ge scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than or equal");
-DATA(insert OID = 906 (  "+"	   PGNSP PGUID b f f	790  790	790 906   0 cash_pl - - ));
+DATA(insert OID = 906 (  "+"	   PGNSP PGUID b f f	790  790	790 906   0 cash_pl - - "---"));
 DESCR("add");
-DATA(insert OID = 907 (  "-"	   PGNSP PGUID b f f	790  790	790   0   0 cash_mi - - ));
+DATA(insert OID = 907 (  "-"	   PGNSP PGUID b f f	790  790	790   0   0 cash_mi - - "---"));
 DESCR("subtract");
-DATA(insert OID = 908 (  "*"	   PGNSP PGUID b f f	790  701	790 916   0 cash_mul_flt8 - - ));
+DATA(insert OID = 908 (  "*"	   PGNSP PGUID b f f	790  701	790 916   0 cash_mul_flt8 - - "---"));
 DESCR("multiply");
-DATA(insert OID = 909 (  "/"	   PGNSP PGUID b f f	790  701	790   0   0 cash_div_flt8 - - ));
+DATA(insert OID = 909 (  "/"	   PGNSP PGUID b f f	790  701	790   0   0 cash_div_flt8 - - "---"));
 DESCR("divide");
-DATA(insert OID = 912 (  "*"	   PGNSP PGUID b f f	790  23		790 917   0 cash_mul_int4 - - ));
+DATA(insert OID = 912 (  "*"	   PGNSP PGUID b f f	790  23		790 917   0 cash_mul_int4 - - "---"));
 DESCR("multiply");
-DATA(insert OID = 913 (  "/"	   PGNSP PGUID b f f	790  23		790   0   0 cash_div_int4 - - ));
+DATA(insert OID = 913 (  "/"	   PGNSP PGUID b f f	790  23		790   0   0 cash_div_int4 - - "---"));
 DESCR("divide");
-DATA(insert OID = 914 (  "*"	   PGNSP PGUID b f f	790  21		790 918   0 cash_mul_int2 - - ));
+DATA(insert OID = 914 (  "*"	   PGNSP PGUID b f f	790  21		790 918   0 cash_mul_int2 - - "---"));
 DESCR("multiply");
-DATA(insert OID = 915 (  "/"	   PGNSP PGUID b f f	790  21		790   0   0 cash_div_int2 - - ));
+DATA(insert OID = 915 (  "/"	   PGNSP PGUID b f f	790  21		790   0   0 cash_div_int2 - - "---"));
 DESCR("divide");
-DATA(insert OID = 916 (  "*"	   PGNSP PGUID b f f	701  790	790 908   0 flt8_mul_cash - - ));
+DATA(insert OID = 916 (  "*"	   PGNSP PGUID b f f	701  790	790 908   0 flt8_mul_cash - - "---"));
 DESCR("multiply");
-DATA(insert OID = 917 (  "*"	   PGNSP PGUID b f f	23	790		790 912   0 int4_mul_cash - - ));
+DATA(insert OID = 917 (  "*"	   PGNSP PGUID b f f	23	790		790 912   0 int4_mul_cash - - "---"));
 DESCR("multiply");
-DATA(insert OID = 918 (  "*"	   PGNSP PGUID b f f	21	790		790 914   0 int2_mul_cash - - ));
+DATA(insert OID = 918 (  "*"	   PGNSP PGUID b f f	21	790		790 914   0 int2_mul_cash - - "---"));
 DESCR("multiply");
-DATA(insert OID = 3825 ( "/"	   PGNSP PGUID b f f	790 790		701   0   0 cash_div_cash - - ));
+DATA(insert OID = 3825 ( "/"	   PGNSP PGUID b f f	790 790		701   0   0 cash_div_cash - - "---"));
 DESCR("divide");
 
-DATA(insert OID = 965 (  "^"	   PGNSP PGUID b f f	701  701	701 0 0 dpow - - ));
+DATA(insert OID = 965 (  "^"	   PGNSP PGUID b f f	701  701	701 0 0 dpow - - "---"));
 DESCR("exponentiation");
-DATA(insert OID = 966 (  "+"	   PGNSP PGUID b f f 1034 1033 1034 0 0 aclinsert - - ));
+DATA(insert OID = 966 (  "+"	   PGNSP PGUID b f f 1034 1033 1034 0 0 aclinsert - - "---"));
 DESCR("add/update ACL item");
-DATA(insert OID = 967 (  "-"	   PGNSP PGUID b f f 1034 1033 1034 0 0 aclremove - - ));
+DATA(insert OID = 967 (  "-"	   PGNSP PGUID b f f 1034 1033 1034 0 0 aclremove - - "---"));
 DESCR("remove ACL item");
-DATA(insert OID = 968 (  "@>"	   PGNSP PGUID b f f 1034 1033	 16 0 0 aclcontains - - ));
+DATA(insert OID = 968 (  "@>"	   PGNSP PGUID b f f 1034 1033	 16 0 0 aclcontains - - "---"));
 DESCR("contains");
-DATA(insert OID = 974 (  "="	   PGNSP PGUID b f t 1033 1033	 16 974 0 aclitemeq eqsel eqjoinsel ));
+DATA(insert OID = 974 (  "="	   PGNSP PGUID b f t 1033 1033	 16 974 0 aclitemeq eqsel eqjoinsel "mhf"));
 DESCR("equal");
 
 /* additional geometric operators - thomas 1997-07-09 */
-DATA(insert OID =  969 (  "@@"	   PGNSP PGUID l f f	0  601	600    0  0 lseg_center - - ));
+DATA(insert OID =  969 (  "@@"	   PGNSP PGUID l f f	0  601	600    0  0 lseg_center - - "---"));
 DESCR("center of");
-DATA(insert OID =  970 (  "@@"	   PGNSP PGUID l f f	0  602	600    0  0 path_center - - ));
+DATA(insert OID =  970 (  "@@"	   PGNSP PGUID l f f	0  602	600    0  0 path_center - - "---"));
 DESCR("center of");
-DATA(insert OID =  971 (  "@@"	   PGNSP PGUID l f f	0  604	600    0  0 poly_center - - ));
+DATA(insert OID =  971 (  "@@"	   PGNSP PGUID l f f	0  604	600    0  0 poly_center - - "---"));
 DESCR("center of");
 
-DATA(insert OID = 1054 ( "="	   PGNSP PGUID b t t 1042 1042	 16 1054 1057 bpchareq eqsel eqjoinsel ));
+DATA(insert OID = 1054 ( "="	   PGNSP PGUID b t t 1042 1042	 16 1054 1057 bpchareq eqsel eqjoinsel "mhf"));
 DESCR("equal");
 
-DATA(insert OID = 1055 ( "~"	   PGNSP PGUID b f f 1042 25	 16    0 1056 bpcharregexeq regexeqsel regexeqjoinsel ));
+DATA(insert OID = 1055 ( "~"	   PGNSP PGUID b f f 1042 25	 16    0 1056 bpcharregexeq regexeqsel regexeqjoinsel "mhf"));
 DESCR("matches regular expression, case-sensitive");
 #define OID_BPCHAR_REGEXEQ_OP		1055
-DATA(insert OID = 1056 ( "!~"	   PGNSP PGUID b f f 1042 25	 16    0 1055 bpcharregexne regexnesel regexnejoinsel ));
+DATA(insert OID = 1056 ( "!~"	   PGNSP PGUID b f f 1042 25	 16    0 1055 bpcharregexne regexnesel regexnejoinsel "---"));
 DESCR("does not match regular expression, case-sensitive");
-DATA(insert OID = 1057 ( "<>"	   PGNSP PGUID b f f 1042 1042	 16 1057 1054 bpcharne neqsel neqjoinsel ));
+DATA(insert OID = 1057 ( "<>"	   PGNSP PGUID b f f 1042 1042	 16 1057 1054 bpcharne neqsel neqjoinsel "mhf"));
 DESCR("not equal");
-DATA(insert OID = 1058 ( "<"	   PGNSP PGUID b f f 1042 1042	 16 1060 1061 bpcharlt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1058 ( "<"	   PGNSP PGUID b f f 1042 1042	 16 1060 1061 bpcharlt scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than");
-DATA(insert OID = 1059 ( "<="	   PGNSP PGUID b f f 1042 1042	 16 1061 1060 bpcharle scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1059 ( "<="	   PGNSP PGUID b f f 1042 1042	 16 1061 1060 bpcharle scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than or equal");
-DATA(insert OID = 1060 ( ">"	   PGNSP PGUID b f f 1042 1042	 16 1058 1059 bpchargt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 1060 ( ">"	   PGNSP PGUID b f f 1042 1042	 16 1058 1059 bpchargt scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than");
-DATA(insert OID = 1061 ( ">="	   PGNSP PGUID b f f 1042 1042	 16 1059 1058 bpcharge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 1061 ( ">="	   PGNSP PGUID b f f 1042 1042	 16 1059 1058 bpcharge scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than or equal");
 
 /* generic array comparison operators */
-DATA(insert OID = 1070 (  "="	   PGNSP PGUID b t t 2277 2277 16 1070 1071 array_eq eqsel eqjoinsel ));
+DATA(insert OID = 1070 (  "="	   PGNSP PGUID b t t 2277 2277 16 1070 1071 array_eq eqsel eqjoinsel "mhf"));
 DESCR("equal");
 #define ARRAY_EQ_OP 1070
-DATA(insert OID = 1071 (  "<>"	   PGNSP PGUID b f f 2277 2277 16 1071 1070 array_ne neqsel neqjoinsel ));
+DATA(insert OID = 1071 (  "<>"	   PGNSP PGUID b f f 2277 2277 16 1071 1070 array_ne neqsel neqjoinsel "mhf"));
 DESCR("not equal");
-DATA(insert OID = 1072 (  "<"	   PGNSP PGUID b f f 2277 2277 16 1073 1075 array_lt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1072 (  "<"	   PGNSP PGUID b f f 2277 2277 16 1073 1075 array_lt scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than");
 #define ARRAY_LT_OP 1072
-DATA(insert OID = 1073 (  ">"	   PGNSP PGUID b f f 2277 2277 16 1072 1074 array_gt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 1073 (  ">"	   PGNSP PGUID b f f 2277 2277 16 1072 1074 array_gt scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than");
 #define ARRAY_GT_OP 1073
-DATA(insert OID = 1074 (  "<="	   PGNSP PGUID b f f 2277 2277 16 1075 1073 array_le scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1074 (  "<="	   PGNSP PGUID b f f 2277 2277 16 1075 1073 array_le scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than or equal");
-DATA(insert OID = 1075 (  ">="	   PGNSP PGUID b f f 2277 2277 16 1074 1072 array_ge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 1075 (  ">="	   PGNSP PGUID b f f 2277 2277 16 1074 1072 array_ge scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than or equal");
 
 /* date operators */
-DATA(insert OID = 1076 ( "+"	   PGNSP PGUID b f f	1082	1186 1114 2551 0 date_pl_interval - - ));
+DATA(insert OID = 1076 ( "+"	   PGNSP PGUID b f f	1082	1186 1114 2551 0 date_pl_interval - - "---"));
 DESCR("add");
-DATA(insert OID = 1077 ( "-"	   PGNSP PGUID b f f	1082	1186 1114 0 0 date_mi_interval - - ));
+DATA(insert OID = 1077 ( "-"	   PGNSP PGUID b f f	1082	1186 1114 0 0 date_mi_interval - - "---"));
 DESCR("subtract");
-DATA(insert OID = 1093 ( "="	   PGNSP PGUID b t t	1082	1082   16 1093 1094 date_eq eqsel eqjoinsel ));
+DATA(insert OID = 1093 ( "="	   PGNSP PGUID b t t	1082	1082   16 1093 1094 date_eq eqsel eqjoinsel "mhf"));
 DESCR("equal");
-DATA(insert OID = 1094 ( "<>"	   PGNSP PGUID b f f	1082	1082   16 1094 1093 date_ne neqsel neqjoinsel ));
+DATA(insert OID = 1094 ( "<>"	   PGNSP PGUID b f f	1082	1082   16 1094 1093 date_ne neqsel neqjoinsel "mhf"));
 DESCR("not equal");
-DATA(insert OID = 1095 ( "<"	   PGNSP PGUID b f f	1082	1082   16 1097 1098 date_lt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1095 ( "<"	   PGNSP PGUID b f f	1082	1082   16 1097 1098 date_lt scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than");
-DATA(insert OID = 1096 ( "<="	   PGNSP PGUID b f f	1082	1082   16 1098 1097 date_le scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1096 ( "<="	   PGNSP PGUID b f f	1082	1082   16 1098 1097 date_le scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than or equal");
-DATA(insert OID = 1097 ( ">"	   PGNSP PGUID b f f	1082	1082   16 1095 1096 date_gt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 1097 ( ">"	   PGNSP PGUID b f f	1082	1082   16 1095 1096 date_gt scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than");
-DATA(insert OID = 1098 ( ">="	   PGNSP PGUID b f f	1082	1082   16 1096 1095 date_ge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 1098 ( ">="	   PGNSP PGUID b f f	1082	1082   16 1096 1095 date_ge scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than or equal");
-DATA(insert OID = 1099 ( "-"	   PGNSP PGUID b f f	1082	1082   23 0 0 date_mi - - ));
+DATA(insert OID = 1099 ( "-"	   PGNSP PGUID b f f	1082	1082   23 0 0 date_mi - - "---"));
 DESCR("subtract");
-DATA(insert OID = 1100 ( "+"	   PGNSP PGUID b f f	1082	  23 1082 2555 0 date_pli - - ));
+DATA(insert OID = 1100 ( "+"	   PGNSP PGUID b f f	1082	  23 1082 2555 0 date_pli - - "---"));
 DESCR("add");
-DATA(insert OID = 1101 ( "-"	   PGNSP PGUID b f f	1082	  23 1082 0 0 date_mii - - ));
+DATA(insert OID = 1101 ( "-"	   PGNSP PGUID b f f	1082	  23 1082 0 0 date_mii - - "---"));
 DESCR("subtract");
 
 /* time operators */
-DATA(insert OID = 1108 ( "="	   PGNSP PGUID b t t	1083	1083  16 1108 1109 time_eq eqsel eqjoinsel ));
+DATA(insert OID = 1108 ( "="	   PGNSP PGUID b t t	1083	1083  16 1108 1109 time_eq eqsel eqjoinsel "mhf"));
 DESCR("equal");
-DATA(insert OID = 1109 ( "<>"	   PGNSP PGUID b f f	1083	1083  16 1109 1108 time_ne neqsel neqjoinsel ));
+DATA(insert OID = 1109 ( "<>"	   PGNSP PGUID b f f	1083	1083  16 1109 1108 time_ne neqsel neqjoinsel "mhf"));
 DESCR("not equal");
-DATA(insert OID = 1110 ( "<"	   PGNSP PGUID b f f	1083	1083  16 1112 1113 time_lt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1110 ( "<"	   PGNSP PGUID b f f	1083	1083  16 1112 1113 time_lt scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than");
-DATA(insert OID = 1111 ( "<="	   PGNSP PGUID b f f	1083	1083  16 1113 1112 time_le scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1111 ( "<="	   PGNSP PGUID b f f	1083	1083  16 1113 1112 time_le scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than or equal");
-DATA(insert OID = 1112 ( ">"	   PGNSP PGUID b f f	1083	1083  16 1110 1111 time_gt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 1112 ( ">"	   PGNSP PGUID b f f	1083	1083  16 1110 1111 time_gt scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than");
-DATA(insert OID = 1113 ( ">="	   PGNSP PGUID b f f	1083	1083  16 1111 1110 time_ge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 1113 ( ">="	   PGNSP PGUID b f f	1083	1083  16 1111 1110 time_ge scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than or equal");
 
 /* timetz operators */
-DATA(insert OID = 1550 ( "="	   PGNSP PGUID b t t	1266 1266	16 1550 1551 timetz_eq eqsel eqjoinsel ));
+DATA(insert OID = 1550 ( "="	   PGNSP PGUID b t t	1266 1266	16 1550 1551 timetz_eq eqsel eqjoinsel "mhf"));
 DESCR("equal");
-DATA(insert OID = 1551 ( "<>"	   PGNSP PGUID b f f	1266 1266	16 1551 1550 timetz_ne neqsel neqjoinsel ));
+DATA(insert OID = 1551 ( "<>"	   PGNSP PGUID b f f	1266 1266	16 1551 1550 timetz_ne neqsel neqjoinsel "mhf"));
 DESCR("not equal");
-DATA(insert OID = 1552 ( "<"	   PGNSP PGUID b f f	1266 1266	16 1554 1555 timetz_lt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1552 ( "<"	   PGNSP PGUID b f f	1266 1266	16 1554 1555 timetz_lt scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than");
-DATA(insert OID = 1553 ( "<="	   PGNSP PGUID b f f	1266 1266	16 1555 1554 timetz_le scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1553 ( "<="	   PGNSP PGUID b f f	1266 1266	16 1555 1554 timetz_le scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than or equal");
-DATA(insert OID = 1554 ( ">"	   PGNSP PGUID b f f	1266 1266	16 1552 1553 timetz_gt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 1554 ( ">"	   PGNSP PGUID b f f	1266 1266	16 1552 1553 timetz_gt scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than");
-DATA(insert OID = 1555 ( ">="	   PGNSP PGUID b f f	1266 1266	16 1553 1552 timetz_ge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 1555 ( ">="	   PGNSP PGUID b f f	1266 1266	16 1553 1552 timetz_ge scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than or equal");
 
 /* float48 operators */
-DATA(insert OID = 1116 (  "+"		PGNSP PGUID b f f 700 701 701 1126	 0 float48pl - - ));
+DATA(insert OID = 1116 (  "+"		PGNSP PGUID b f f 700 701 701 1126	 0 float48pl - - "---"));
 DESCR("add");
-DATA(insert OID = 1117 (  "-"		PGNSP PGUID b f f 700 701 701  0	 0 float48mi - - ));
+DATA(insert OID = 1117 (  "-"		PGNSP PGUID b f f 700 701 701  0	 0 float48mi - - "---"));
 DESCR("subtract");
-DATA(insert OID = 1118 (  "/"		PGNSP PGUID b f f 700 701 701  0	 0 float48div - - ));
+DATA(insert OID = 1118 (  "/"		PGNSP PGUID b f f 700 701 701  0	 0 float48div - - "---"));
 DESCR("divide");
-DATA(insert OID = 1119 (  "*"		PGNSP PGUID b f f 700 701 701 1129	 0 float48mul - - ));
+DATA(insert OID = 1119 (  "*"		PGNSP PGUID b f f 700 701 701 1129	 0 float48mul - - "---"));
 DESCR("multiply");
-DATA(insert OID = 1120 (  "="		PGNSP PGUID b t t  700	701  16 1130 1121 float48eq eqsel eqjoinsel ));
+DATA(insert OID = 1120 (  "="		PGNSP PGUID b t t  700	701  16 1130 1121 float48eq eqsel eqjoinsel "mhf"));
 DESCR("equal");
-DATA(insert OID = 1121 (  "<>"		PGNSP PGUID b f f  700	701  16 1131 1120 float48ne neqsel neqjoinsel ));
+DATA(insert OID = 1121 (  "<>"		PGNSP PGUID b f f  700	701  16 1131 1120 float48ne neqsel neqjoinsel "mhf"));
 DESCR("not equal");
-DATA(insert OID = 1122 (  "<"		PGNSP PGUID b f f  700	701  16 1133 1125 float48lt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1122 (  "<"		PGNSP PGUID b f f  700	701  16 1133 1125 float48lt scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than");
-DATA(insert OID = 1123 (  ">"		PGNSP PGUID b f f  700	701  16 1132 1124 float48gt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 1123 (  ">"		PGNSP PGUID b f f  700	701  16 1132 1124 float48gt scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than");
-DATA(insert OID = 1124 (  "<="		PGNSP PGUID b f f  700	701  16 1135 1123 float48le scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1124 (  "<="		PGNSP PGUID b f f  700	701  16 1135 1123 float48le scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than or equal");
-DATA(insert OID = 1125 (  ">="		PGNSP PGUID b f f  700	701  16 1134 1122 float48ge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 1125 (  ">="		PGNSP PGUID b f f  700	701  16 1134 1122 float48ge scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than or equal");
 
 /* float84 operators */
-DATA(insert OID = 1126 (  "+"		PGNSP PGUID b f f 701 700 701 1116	 0 float84pl - - ));
+DATA(insert OID = 1126 (  "+"		PGNSP PGUID b f f 701 700 701 1116	 0 float84pl - - "---"));
 DESCR("add");
-DATA(insert OID = 1127 (  "-"		PGNSP PGUID b f f 701 700 701  0	 0 float84mi - - ));
+DATA(insert OID = 1127 (  "-"		PGNSP PGUID b f f 701 700 701  0	 0 float84mi - - "---"));
 DESCR("subtract");
-DATA(insert OID = 1128 (  "/"		PGNSP PGUID b f f 701 700 701  0	 0 float84div - - ));
+DATA(insert OID = 1128 (  "/"		PGNSP PGUID b f f 701 700 701  0	 0 float84div - - "---"));
 DESCR("divide");
-DATA(insert OID = 1129 (  "*"		PGNSP PGUID b f f 701 700 701 1119	 0 float84mul - - ));
+DATA(insert OID = 1129 (  "*"		PGNSP PGUID b f f 701 700 701 1119	 0 float84mul - - "---"));
 DESCR("multiply");
-DATA(insert OID = 1130 (  "="		PGNSP PGUID b t t  701	700  16 1120 1131 float84eq eqsel eqjoinsel ));
+DATA(insert OID = 1130 (  "="		PGNSP PGUID b t t  701	700  16 1120 1131 float84eq eqsel eqjoinsel "mhf"));
 DESCR("equal");
-DATA(insert OID = 1131 (  "<>"		PGNSP PGUID b f f  701	700  16 1121 1130 float84ne neqsel neqjoinsel ));
+DATA(insert OID = 1131 (  "<>"		PGNSP PGUID b f f  701	700  16 1121 1130 float84ne neqsel neqjoinsel "mhf"));
 DESCR("not equal");
-DATA(insert OID = 1132 (  "<"		PGNSP PGUID b f f  701	700  16 1123 1135 float84lt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1132 (  "<"		PGNSP PGUID b f f  701	700  16 1123 1135 float84lt scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than");
-DATA(insert OID = 1133 (  ">"		PGNSP PGUID b f f  701	700  16 1122 1134 float84gt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 1133 (  ">"		PGNSP PGUID b f f  701	700  16 1122 1134 float84gt scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than");
-DATA(insert OID = 1134 (  "<="		PGNSP PGUID b f f  701	700  16 1125 1133 float84le scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1134 (  "<="		PGNSP PGUID b f f  701	700  16 1125 1133 float84le scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than or equal");
-DATA(insert OID = 1135 (  ">="		PGNSP PGUID b f f  701	700  16 1124 1132 float84ge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 1135 (  ">="		PGNSP PGUID b f f  701	700  16 1124 1132 float84ge scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than or equal");
 
 
 /* LIKE hacks by Keith Parks. */
-DATA(insert OID = 1207 (  "~~"	  PGNSP PGUID b f f  19 25	16 0 1208 namelike likesel likejoinsel ));
+DATA(insert OID = 1207 (  "~~"	  PGNSP PGUID b f f  19 25	16 0 1208 namelike likesel likejoinsel "---"));
 DESCR("matches LIKE expression");
 #define OID_NAME_LIKE_OP		1207
-DATA(insert OID = 1208 (  "!~~"   PGNSP PGUID b f f  19 25	16 0 1207 namenlike nlikesel nlikejoinsel ));
+DATA(insert OID = 1208 (  "!~~"   PGNSP PGUID b f f  19 25	16 0 1207 namenlike nlikesel nlikejoinsel "---"));
 DESCR("does not match LIKE expression");
-DATA(insert OID = 1209 (  "~~"	  PGNSP PGUID b f f  25 25	16 0 1210 textlike likesel likejoinsel ));
+DATA(insert OID = 1209 (  "~~"	  PGNSP PGUID b f f  25 25	16 0 1210 textlike likesel likejoinsel "---"));
 DESCR("matches LIKE expression");
 #define OID_TEXT_LIKE_OP		1209
-DATA(insert OID = 1210 (  "!~~"   PGNSP PGUID b f f  25 25	16 0 1209 textnlike nlikesel nlikejoinsel ));
+DATA(insert OID = 1210 (  "!~~"   PGNSP PGUID b f f  25 25	16 0 1209 textnlike nlikesel nlikejoinsel "---"));
 DESCR("does not match LIKE expression");
-DATA(insert OID = 1211 (  "~~"	  PGNSP PGUID b f f  1042 25	16 0 1212 bpcharlike likesel likejoinsel ));
+DATA(insert OID = 1211 (  "~~"	  PGNSP PGUID b f f  1042 25	16 0 1212 bpcharlike likesel likejoinsel "---"));
 DESCR("matches LIKE expression");
 #define OID_BPCHAR_LIKE_OP		1211
-DATA(insert OID = 1212 (  "!~~"   PGNSP PGUID b f f  1042 25	16 0 1211 bpcharnlike nlikesel nlikejoinsel ));
+DATA(insert OID = 1212 (  "!~~"   PGNSP PGUID b f f  1042 25	16 0 1211 bpcharnlike nlikesel nlikejoinsel "---"));
 DESCR("does not match LIKE expression");
 
 /* case-insensitive regex hacks */
-DATA(insert OID = 1226 (  "~*"		 PGNSP PGUID b f f	19	25	16 0 1227 nameicregexeq icregexeqsel icregexeqjoinsel ));
+DATA(insert OID = 1226 (  "~*"		 PGNSP PGUID b f f	19	25	16 0 1227 nameicregexeq icregexeqsel icregexeqjoinsel "mhf"));
 DESCR("matches regular expression, case-insensitive");
 #define OID_NAME_ICREGEXEQ_OP		1226
-DATA(insert OID = 1227 (  "!~*"		 PGNSP PGUID b f f	19	25	16 0 1226 nameicregexne icregexnesel icregexnejoinsel ));
+DATA(insert OID = 1227 (  "!~*"		 PGNSP PGUID b f f	19	25	16 0 1226 nameicregexne icregexnesel icregexnejoinsel "---"));
 DESCR("does not match regular expression, case-insensitive");
-DATA(insert OID = 1228 (  "~*"		 PGNSP PGUID b f f	25	25	16 0 1229 texticregexeq icregexeqsel icregexeqjoinsel ));
+DATA(insert OID = 1228 (  "~*"		 PGNSP PGUID b f f	25	25	16 0 1229 texticregexeq icregexeqsel icregexeqjoinsel "mhf"));
 DESCR("matches regular expression, case-insensitive");
 #define OID_TEXT_ICREGEXEQ_OP		1228
-DATA(insert OID = 1229 (  "!~*"		 PGNSP PGUID b f f	25	25	16 0 1228 texticregexne icregexnesel icregexnejoinsel ));
+DATA(insert OID = 1229 (  "!~*"		 PGNSP PGUID b f f	25	25	16 0 1228 texticregexne icregexnesel icregexnejoinsel "---"));
 DESCR("does not match regular expression, case-insensitive");
-DATA(insert OID = 1234 (  "~*"		PGNSP PGUID b f f  1042  25  16 0 1235 bpcharicregexeq icregexeqsel icregexeqjoinsel ));
+DATA(insert OID = 1234 (  "~*"		PGNSP PGUID b f f  1042  25  16 0 1235 bpcharicregexeq icregexeqsel icregexeqjoinsel "mhf"));
 DESCR("matches regular expression, case-insensitive");
 #define OID_BPCHAR_ICREGEXEQ_OP		1234
-DATA(insert OID = 1235 ( "!~*"		PGNSP PGUID b f f  1042  25  16 0 1234 bpcharicregexne icregexnesel icregexnejoinsel ));
+DATA(insert OID = 1235 ( "!~*"		PGNSP PGUID b f f  1042  25  16 0 1234 bpcharicregexne icregexnesel icregexnejoinsel "---"));
 DESCR("does not match regular expression, case-insensitive");
 
 /* timestamptz operators */
-DATA(insert OID = 1320 (  "="	   PGNSP PGUID b t t 1184 1184	 16 1320 1321 timestamptz_eq eqsel eqjoinsel ));
+DATA(insert OID = 1320 (  "="	   PGNSP PGUID b t t 1184 1184	 16 1320 1321 timestamptz_eq eqsel eqjoinsel "mhf"));
 DESCR("equal");
-DATA(insert OID = 1321 (  "<>"	   PGNSP PGUID b f f 1184 1184	 16 1321 1320 timestamptz_ne neqsel neqjoinsel ));
+DATA(insert OID = 1321 (  "<>"	   PGNSP PGUID b f f 1184 1184	 16 1321 1320 timestamptz_ne neqsel neqjoinsel "mhf"));
 DESCR("not equal");
-DATA(insert OID = 1322 (  "<"	   PGNSP PGUID b f f 1184 1184	 16 1324 1325 timestamptz_lt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1322 (  "<"	   PGNSP PGUID b f f 1184 1184	 16 1324 1325 timestamptz_lt scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than");
-DATA(insert OID = 1323 (  "<="	   PGNSP PGUID b f f 1184 1184	 16 1325 1324 timestamptz_le scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1323 (  "<="	   PGNSP PGUID b f f 1184 1184	 16 1325 1324 timestamptz_le scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than or equal");
-DATA(insert OID = 1324 (  ">"	   PGNSP PGUID b f f 1184 1184	 16 1322 1323 timestamptz_gt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 1324 (  ">"	   PGNSP PGUID b f f 1184 1184	 16 1322 1323 timestamptz_gt scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than");
-DATA(insert OID = 1325 (  ">="	   PGNSP PGUID b f f 1184 1184	 16 1323 1322 timestamptz_ge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 1325 (  ">="	   PGNSP PGUID b f f 1184 1184	 16 1323 1322 timestamptz_ge scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than or equal");
-DATA(insert OID = 1327 (  "+"	   PGNSP PGUID b f f 1184 1186 1184  2554 0 timestamptz_pl_interval - - ));
+DATA(insert OID = 1327 (  "+"	   PGNSP PGUID b f f 1184 1186 1184  2554 0 timestamptz_pl_interval - - "---"));
 DESCR("add");
-DATA(insert OID = 1328 (  "-"	   PGNSP PGUID b f f 1184 1184 1186  0	0 timestamptz_mi - - ));
+DATA(insert OID = 1328 (  "-"	   PGNSP PGUID b f f 1184 1184 1186  0	0 timestamptz_mi - - "---"));
 DESCR("subtract");
-DATA(insert OID = 1329 (  "-"	   PGNSP PGUID b f f 1184 1186 1184  0	0 timestamptz_mi_interval - - ));
+DATA(insert OID = 1329 (  "-"	   PGNSP PGUID b f f 1184 1186 1184  0	0 timestamptz_mi_interval - - "---"));
 DESCR("subtract");
 
 /* interval operators */
-DATA(insert OID = 1330 (  "="	   PGNSP PGUID b t t 1186 1186	 16 1330 1331 interval_eq eqsel eqjoinsel ));
+DATA(insert OID = 1330 (  "="	   PGNSP PGUID b t t 1186 1186	 16 1330 1331 interval_eq eqsel eqjoinsel "mhf"));
 DESCR("equal");
-DATA(insert OID = 1331 (  "<>"	   PGNSP PGUID b f f 1186 1186	 16 1331 1330 interval_ne neqsel neqjoinsel ));
+DATA(insert OID = 1331 (  "<>"	   PGNSP PGUID b f f 1186 1186	 16 1331 1330 interval_ne neqsel neqjoinsel "mhf"));
 DESCR("not equal");
-DATA(insert OID = 1332 (  "<"	   PGNSP PGUID b f f 1186 1186	 16 1334 1335 interval_lt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1332 (  "<"	   PGNSP PGUID b f f 1186 1186	 16 1334 1335 interval_lt scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than");
-DATA(insert OID = 1333 (  "<="	   PGNSP PGUID b f f 1186 1186	 16 1335 1334 interval_le scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1333 (  "<="	   PGNSP PGUID b f f 1186 1186	 16 1335 1334 interval_le scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than or equal");
-DATA(insert OID = 1334 (  ">"	   PGNSP PGUID b f f 1186 1186	 16 1332 1333 interval_gt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 1334 (  ">"	   PGNSP PGUID b f f 1186 1186	 16 1332 1333 interval_gt scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than");
-DATA(insert OID = 1335 (  ">="	   PGNSP PGUID b f f 1186 1186	 16 1333 1332 interval_ge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 1335 (  ">="	   PGNSP PGUID b f f 1186 1186	 16 1333 1332 interval_ge scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than or equal");
 
-DATA(insert OID = 1336 (  "-"	   PGNSP PGUID l f f	0 1186 1186    0	0 interval_um - - ));
+DATA(insert OID = 1336 (  "-"	   PGNSP PGUID l f f	0 1186 1186    0	0 interval_um - - "---"));
 DESCR("negate");
-DATA(insert OID = 1337 (  "+"	   PGNSP PGUID b f f 1186 1186 1186 1337	0 interval_pl - - ));
+DATA(insert OID = 1337 (  "+"	   PGNSP PGUID b f f 1186 1186 1186 1337	0 interval_pl - - "---"));
 DESCR("add");
-DATA(insert OID = 1338 (  "-"	   PGNSP PGUID b f f 1186 1186 1186    0	0 interval_mi - - ));
+DATA(insert OID = 1338 (  "-"	   PGNSP PGUID b f f 1186 1186 1186    0	0 interval_mi - - "---"));
 DESCR("subtract");
 
-DATA(insert OID = 1360 (  "+"	   PGNSP PGUID b f f 1082 1083 1114 1363 0 datetime_pl - - ));
+DATA(insert OID = 1360 (  "+"	   PGNSP PGUID b f f 1082 1083 1114 1363 0 datetime_pl - - "---"));
 DESCR("convert date and time to timestamp");
-DATA(insert OID = 1361 (  "+"	   PGNSP PGUID b f f 1082 1266 1184 1366 0 datetimetz_pl - - ));
+DATA(insert OID = 1361 (  "+"	   PGNSP PGUID b f f 1082 1266 1184 1366 0 datetimetz_pl - - "---"));
 DESCR("convert date and time with time zone to timestamp with time zone");
-DATA(insert OID = 1363 (  "+"	   PGNSP PGUID b f f 1083 1082 1114 1360 0 timedate_pl - - ));
+DATA(insert OID = 1363 (  "+"	   PGNSP PGUID b f f 1083 1082 1114 1360 0 timedate_pl - - "---"));
 DESCR("convert time and date to timestamp");
-DATA(insert OID = 1366 (  "+"	   PGNSP PGUID b f f 1266 1082 1184 1361 0 timetzdate_pl - - ));
+DATA(insert OID = 1366 (  "+"	   PGNSP PGUID b f f 1266 1082 1184 1361 0 timetzdate_pl - - "---"));
 DESCR("convert time with time zone and date to timestamp with time zone");
 
-DATA(insert OID = 1399 (  "-"	   PGNSP PGUID b f f 1083 1083 1186  0	0 time_mi_time - - ));
+DATA(insert OID = 1399 (  "-"	   PGNSP PGUID b f f 1083 1083 1186  0	0 time_mi_time - - "---"));
 DESCR("subtract");
 
 /* additional geometric operators - thomas 97/04/18 */
-DATA(insert OID = 1420 (  "@@"	  PGNSP PGUID l f f  0	718 600   0    0 circle_center - - ));
+DATA(insert OID = 1420 (  "@@"	  PGNSP PGUID l f f  0	718 600   0    0 circle_center - - "---"));
 DESCR("center of");
-DATA(insert OID = 1500 (  "="	  PGNSP PGUID b f f  718	718 16 1500 1501 circle_eq eqsel eqjoinsel ));
+DATA(insert OID = 1500 (  "="	  PGNSP PGUID b f f  718	718 16 1500 1501 circle_eq eqsel eqjoinsel "mhf"));
 DESCR("equal by area");
-DATA(insert OID = 1501 (  "<>"	  PGNSP PGUID b f f  718	718 16 1501 1500 circle_ne neqsel neqjoinsel ));
+DATA(insert OID = 1501 (  "<>"	  PGNSP PGUID b f f  718	718 16 1501 1500 circle_ne neqsel neqjoinsel "mhf"));
 DESCR("not equal by area");
-DATA(insert OID = 1502 (  "<"	  PGNSP PGUID b f f  718	718 16 1503 1505 circle_lt areasel areajoinsel ));
+DATA(insert OID = 1502 (  "<"	  PGNSP PGUID b f f  718	718 16 1503 1505 circle_lt areasel areajoinsel "---"));
 DESCR("less than by area");
-DATA(insert OID = 1503 (  ">"	  PGNSP PGUID b f f  718	718 16 1502 1504 circle_gt areasel areajoinsel ));
+DATA(insert OID = 1503 (  ">"	  PGNSP PGUID b f f  718	718 16 1502 1504 circle_gt areasel areajoinsel "---"));
 DESCR("greater than by area");
-DATA(insert OID = 1504 (  "<="	  PGNSP PGUID b f f  718	718 16 1505 1503 circle_le areasel areajoinsel ));
+DATA(insert OID = 1504 (  "<="	  PGNSP PGUID b f f  718	718 16 1505 1503 circle_le areasel areajoinsel "---"));
 DESCR("less than or equal by area");
-DATA(insert OID = 1505 (  ">="	  PGNSP PGUID b f f  718	718 16 1504 1502 circle_ge areasel areajoinsel ));
+DATA(insert OID = 1505 (  ">="	  PGNSP PGUID b f f  718	718 16 1504 1502 circle_ge areasel areajoinsel "---"));
 DESCR("greater than or equal by area");
 
-DATA(insert OID = 1506 (  "<<"	  PGNSP PGUID b f f  718	718 16	  0    0 circle_left positionsel positionjoinsel ));
+DATA(insert OID = 1506 (  "<<"	  PGNSP PGUID b f f  718	718 16	  0    0 circle_left positionsel positionjoinsel "---"));
 DESCR("is left of");
-DATA(insert OID = 1507 (  "&<"	  PGNSP PGUID b f f  718	718 16	  0    0 circle_overleft positionsel positionjoinsel ));
+DATA(insert OID = 1507 (  "&<"	  PGNSP PGUID b f f  718	718 16	  0    0 circle_overleft positionsel positionjoinsel "---"));
 DESCR("overlaps or is left of");
-DATA(insert OID = 1508 (  "&>"	  PGNSP PGUID b f f  718	718 16	  0    0 circle_overright positionsel positionjoinsel ));
+DATA(insert OID = 1508 (  "&>"	  PGNSP PGUID b f f  718	718 16	  0    0 circle_overright positionsel positionjoinsel "---"));
 DESCR("overlaps or is right of");
-DATA(insert OID = 1509 (  ">>"	  PGNSP PGUID b f f  718	718 16	  0    0 circle_right positionsel positionjoinsel ));
+DATA(insert OID = 1509 (  ">>"	  PGNSP PGUID b f f  718	718 16	  0    0 circle_right positionsel positionjoinsel "---"));
 DESCR("is right of");
-DATA(insert OID = 1510 (  "<@"	  PGNSP PGUID b f f  718	718 16 1511    0 circle_contained contsel contjoinsel ));
+DATA(insert OID = 1510 (  "<@"	  PGNSP PGUID b f f  718	718 16 1511    0 circle_contained contsel contjoinsel "---"));
 DESCR("is contained by");
-DATA(insert OID = 1511 (  "@>"	  PGNSP PGUID b f f  718	718 16 1510    0 circle_contain contsel contjoinsel ));
+DATA(insert OID = 1511 (  "@>"	  PGNSP PGUID b f f  718	718 16 1510    0 circle_contain contsel contjoinsel "---"));
 DESCR("contains");
-DATA(insert OID = 1512 (  "~="	  PGNSP PGUID b f f  718	718 16 1512    0 circle_same eqsel eqjoinsel ));
+DATA(insert OID = 1512 (  "~="	  PGNSP PGUID b f f  718	718 16 1512    0 circle_same eqsel eqjoinsel "mhf"));
 DESCR("same as");
-DATA(insert OID = 1513 (  "&&"	  PGNSP PGUID b f f  718	718 16 1513    0 circle_overlap areasel areajoinsel ));
+DATA(insert OID = 1513 (  "&&"	  PGNSP PGUID b f f  718	718 16 1513    0 circle_overlap areasel areajoinsel "---"));
 DESCR("overlaps");
-DATA(insert OID = 1514 (  "|>>"   PGNSP PGUID b f f  718	718 16	  0    0 circle_above positionsel positionjoinsel ));
+DATA(insert OID = 1514 (  "|>>"   PGNSP PGUID b f f  718	718 16	  0    0 circle_above positionsel positionjoinsel "---"));
 DESCR("is above");
-DATA(insert OID = 1515 (  "<<|"   PGNSP PGUID b f f  718	718 16	  0    0 circle_below positionsel positionjoinsel ));
+DATA(insert OID = 1515 (  "<<|"   PGNSP PGUID b f f  718	718 16	  0    0 circle_below positionsel positionjoinsel "---"));
 DESCR("is below");
 
-DATA(insert OID = 1516 (  "+"	  PGNSP PGUID b f f  718	600  718	  0    0 circle_add_pt - - ));
+DATA(insert OID = 1516 (  "+"	  PGNSP PGUID b f f  718	600  718	  0    0 circle_add_pt - - "---"));
 DESCR("add");
-DATA(insert OID = 1517 (  "-"	  PGNSP PGUID b f f  718	600  718	  0    0 circle_sub_pt - - ));
+DATA(insert OID = 1517 (  "-"	  PGNSP PGUID b f f  718	600  718	  0    0 circle_sub_pt - - "---"));
 DESCR("subtract");
-DATA(insert OID = 1518 (  "*"	  PGNSP PGUID b f f  718	600  718	  0    0 circle_mul_pt - - ));
+DATA(insert OID = 1518 (  "*"	  PGNSP PGUID b f f  718	600  718	  0    0 circle_mul_pt - - "---"));
 DESCR("multiply");
-DATA(insert OID = 1519 (  "/"	  PGNSP PGUID b f f  718	600  718	  0    0 circle_div_pt - - ));
+DATA(insert OID = 1519 (  "/"	  PGNSP PGUID b f f  718	600  718	  0    0 circle_div_pt - - "---"));
 DESCR("divide");
 
-DATA(insert OID = 1520 (  "<->"   PGNSP PGUID b f f  718	718  701   1520    0 circle_distance - - ));
+DATA(insert OID = 1520 (  "<->"   PGNSP PGUID b f f  718	718  701   1520    0 circle_distance - - "---"));
 DESCR("distance between");
-DATA(insert OID = 1521 (  "#"	  PGNSP PGUID l f f  0		604   23	  0    0 poly_npoints - - ));
+DATA(insert OID = 1521 (  "#"	  PGNSP PGUID l f f  0		604   23	  0    0 poly_npoints - - "---"));
 DESCR("number of points");
-DATA(insert OID = 1522 (  "<->"   PGNSP PGUID b f f  600	718  701   3291    0 dist_pc - - ));
+DATA(insert OID = 1522 (  "<->"   PGNSP PGUID b f f  600	718  701   3291    0 dist_pc - - "---"));
 DESCR("distance between");
-DATA(insert OID = 3291 (  "<->"   PGNSP PGUID b f f  718	600  701   1522    0 dist_cpoint - - ));
+DATA(insert OID = 3291 (  "<->"   PGNSP PGUID b f f  718	600  701   1522    0 dist_cpoint - - "---"));
 DESCR("distance between");
-DATA(insert OID = 3276 (  "<->"   PGNSP PGUID b f f  600	604  701   3289    0 dist_ppoly - - ));
+DATA(insert OID = 3276 (  "<->"   PGNSP PGUID b f f  600	604  701   3289    0 dist_ppoly - - "---"));
 DESCR("distance between");
-DATA(insert OID = 3289 (  "<->"   PGNSP PGUID b f f  604	600  701   3276    0 dist_polyp - - ));
+DATA(insert OID = 3289 (  "<->"   PGNSP PGUID b f f  604	600  701   3276    0 dist_polyp - - "---"));
 DESCR("distance between");
-DATA(insert OID = 1523 (  "<->"   PGNSP PGUID b f f  718	604  701	  0    0 dist_cpoly - - ));
+DATA(insert OID = 1523 (  "<->"   PGNSP PGUID b f f  718	604  701	  0    0 dist_cpoly - - "---"));
 DESCR("distance between");
 
 /* additional geometric operators - thomas 1997-07-09 */
-DATA(insert OID = 1524 (  "<->"   PGNSP PGUID b f f  628	603  701	  0  0 dist_lb - - ));
+DATA(insert OID = 1524 (  "<->"   PGNSP PGUID b f f  628	603  701	  0  0 dist_lb - - "---"));
 DESCR("distance between");
 
-DATA(insert OID = 1525 (  "?#"	  PGNSP PGUID b f f  601	601 16 1525  0 lseg_intersect - - ));
+DATA(insert OID = 1525 (  "?#"	  PGNSP PGUID b f f  601	601 16 1525  0 lseg_intersect - - "---"));
 DESCR("intersect");
-DATA(insert OID = 1526 (  "?||"   PGNSP PGUID b f f  601	601 16 1526  0 lseg_parallel - - ));
+DATA(insert OID = 1526 (  "?||"   PGNSP PGUID b f f  601	601 16 1526  0 lseg_parallel - - "---"));
 DESCR("parallel");
-DATA(insert OID = 1527 (  "?-|"   PGNSP PGUID b f f  601	601 16 1527  0 lseg_perp - - ));
+DATA(insert OID = 1527 (  "?-|"   PGNSP PGUID b f f  601	601 16 1527  0 lseg_perp - - "---"));
 DESCR("perpendicular");
-DATA(insert OID = 1528 (  "?-"	  PGNSP PGUID l f f  0	601 16	  0  0 lseg_horizontal - - ));
+DATA(insert OID = 1528 (  "?-"	  PGNSP PGUID l f f  0	601 16	  0  0 lseg_horizontal - - "---"));
 DESCR("horizontal");
-DATA(insert OID = 1529 (  "?|"	  PGNSP PGUID l f f  0	601 16	  0  0 lseg_vertical - - ));
+DATA(insert OID = 1529 (  "?|"	  PGNSP PGUID l f f  0	601 16	  0  0 lseg_vertical - - "---"));
 DESCR("vertical");
-DATA(insert OID = 1535 (  "="	  PGNSP PGUID b f f  601	601 16 1535 1586 lseg_eq eqsel eqjoinsel ));
+DATA(insert OID = 1535 (  "="	  PGNSP PGUID b f f  601	601 16 1535 1586 lseg_eq eqsel eqjoinsel "mhf"));
 DESCR("equal");
-DATA(insert OID = 1536 (  "#"	  PGNSP PGUID b f f  601	601  600 1536  0 lseg_interpt - - ));
+DATA(insert OID = 1536 (  "#"	  PGNSP PGUID b f f  601	601  600 1536  0 lseg_interpt - - "---"));
 DESCR("intersection point");
-DATA(insert OID = 1537 (  "?#"	  PGNSP PGUID b f f  601	628 16	  0  0 inter_sl - - ));
+DATA(insert OID = 1537 (  "?#"	  PGNSP PGUID b f f  601	628 16	  0  0 inter_sl - - "---"));
 DESCR("intersect");
-DATA(insert OID = 1538 (  "?#"	  PGNSP PGUID b f f  601	603 16	  0  0 inter_sb - - ));
+DATA(insert OID = 1538 (  "?#"	  PGNSP PGUID b f f  601	603 16	  0  0 inter_sb - - "---"));
 DESCR("intersect");
-DATA(insert OID = 1539 (  "?#"	  PGNSP PGUID b f f  628	603 16	  0  0 inter_lb - - ));
+DATA(insert OID = 1539 (  "?#"	  PGNSP PGUID b f f  628	603 16	  0  0 inter_lb - - "---"));
 DESCR("intersect");
 
-DATA(insert OID = 1546 (  "<@"	  PGNSP PGUID b f f  600	628 16	  0  0 on_pl - - ));
+DATA(insert OID = 1546 (  "<@"	  PGNSP PGUID b f f  600	628 16	  0  0 on_pl - - "---"));
 DESCR("point on line");
-DATA(insert OID = 1547 (  "<@"	  PGNSP PGUID b f f  600	601 16	  0  0 on_ps - - ));
+DATA(insert OID = 1547 (  "<@"	  PGNSP PGUID b f f  600	601 16	  0  0 on_ps - - "---"));
 DESCR("is contained by");
-DATA(insert OID = 1548 (  "<@"	  PGNSP PGUID b f f  601	628 16	  0  0 on_sl - - ));
+DATA(insert OID = 1548 (  "<@"	  PGNSP PGUID b f f  601	628 16	  0  0 on_sl - - "---"));
 DESCR("lseg on line");
-DATA(insert OID = 1549 (  "<@"	  PGNSP PGUID b f f  601	603 16	  0  0 on_sb - - ));
+DATA(insert OID = 1549 (  "<@"	  PGNSP PGUID b f f  601	603 16	  0  0 on_sb - - "---"));
 DESCR("is contained by");
 
-DATA(insert OID = 1557 (  "##"	  PGNSP PGUID b f f  600	628  600	  0  0 close_pl - - ));
+DATA(insert OID = 1557 (  "##"	  PGNSP PGUID b f f  600	628  600	  0  0 close_pl - - "---"));
 DESCR("closest point to A on B");
-DATA(insert OID = 1558 (  "##"	  PGNSP PGUID b f f  600	601  600	  0  0 close_ps - - ));
+DATA(insert OID = 1558 (  "##"	  PGNSP PGUID b f f  600	601  600	  0  0 close_ps - - "---"));
 DESCR("closest point to A on B");
-DATA(insert OID = 1559 (  "##"	  PGNSP PGUID b f f  600	603  600	  0  0 close_pb - - ));
+DATA(insert OID = 1559 (  "##"	  PGNSP PGUID b f f  600	603  600	  0  0 close_pb - - "---"));
 DESCR("closest point to A on B");
 
-DATA(insert OID = 1566 (  "##"	  PGNSP PGUID b f f  601	628  600	  0  0 close_sl - - ));
+DATA(insert OID = 1566 (  "##"	  PGNSP PGUID b f f  601	628  600	  0  0 close_sl - - "---"));
 DESCR("closest point to A on B");
-DATA(insert OID = 1567 (  "##"	  PGNSP PGUID b f f  601	603  600	  0  0 close_sb - - ));
+DATA(insert OID = 1567 (  "##"	  PGNSP PGUID b f f  601	603  600	  0  0 close_sb - - "---"));
 DESCR("closest point to A on B");
-DATA(insert OID = 1568 (  "##"	  PGNSP PGUID b f f  628	603  600	  0  0 close_lb - - ));
+DATA(insert OID = 1568 (  "##"	  PGNSP PGUID b f f  628	603  600	  0  0 close_lb - - "---"));
 DESCR("closest point to A on B");
-DATA(insert OID = 1577 (  "##"	  PGNSP PGUID b f f  628	601  600	  0  0 close_ls - - ));
+DATA(insert OID = 1577 (  "##"	  PGNSP PGUID b f f  628	601  600	  0  0 close_ls - - "---"));
 DESCR("closest point to A on B");
-DATA(insert OID = 1578 (  "##"	  PGNSP PGUID b f f  601	601  600	  0  0 close_lseg - - ));
+DATA(insert OID = 1578 (  "##"	  PGNSP PGUID b f f  601	601  600	  0  0 close_lseg - - "---"));
 DESCR("closest point to A on B");
-DATA(insert OID = 1583 (  "*"	  PGNSP PGUID b f f 1186	701 1186	1584 0 interval_mul - - ));
+DATA(insert OID = 1583 (  "*"	  PGNSP PGUID b f f 1186	701 1186	1584 0 interval_mul - - "---"));
 DESCR("multiply");
-DATA(insert OID = 1584 (  "*"	  PGNSP PGUID b f f  701 1186 1186	1583 0 mul_d_interval - - ));
+DATA(insert OID = 1584 (  "*"	  PGNSP PGUID b f f  701 1186 1186	1583 0 mul_d_interval - - "---"));
 DESCR("multiply");
-DATA(insert OID = 1585 (  "/"	  PGNSP PGUID b f f 1186	701 1186	  0  0 interval_div - - ));
+DATA(insert OID = 1585 (  "/"	  PGNSP PGUID b f f 1186	701 1186	  0  0 interval_div - - "---"));
 DESCR("divide");
 
-DATA(insert OID = 1586 (  "<>"	  PGNSP PGUID b f f  601	601 16 1586 1535 lseg_ne neqsel neqjoinsel ));
+DATA(insert OID = 1586 (  "<>"	  PGNSP PGUID b f f  601	601 16 1586 1535 lseg_ne neqsel neqjoinsel "mhf"));
 DESCR("not equal");
-DATA(insert OID = 1587 (  "<"	  PGNSP PGUID b f f  601	601 16 1589 1590 lseg_lt - - ));
+DATA(insert OID = 1587 (  "<"	  PGNSP PGUID b f f  601	601 16 1589 1590 lseg_lt - - "---"));
 DESCR("less than by length");
-DATA(insert OID = 1588 (  "<="	  PGNSP PGUID b f f  601	601 16 1590 1589 lseg_le - - ));
+DATA(insert OID = 1588 (  "<="	  PGNSP PGUID b f f  601	601 16 1590 1589 lseg_le - - "---"));
 DESCR("less than or equal by length");
-DATA(insert OID = 1589 (  ">"	  PGNSP PGUID b f f  601	601 16 1587 1588 lseg_gt - - ));
+DATA(insert OID = 1589 (  ">"	  PGNSP PGUID b f f  601	601 16 1587 1588 lseg_gt - - "---"));
 DESCR("greater than by length");
-DATA(insert OID = 1590 (  ">="	  PGNSP PGUID b f f  601	601 16 1588 1587 lseg_ge - - ));
+DATA(insert OID = 1590 (  ">="	  PGNSP PGUID b f f  601	601 16 1588 1587 lseg_ge - - "---"));
 DESCR("greater than or equal by length");
 
-DATA(insert OID = 1591 (  "@-@"   PGNSP PGUID l f f 0  601	701    0  0 lseg_length - - ));
+DATA(insert OID = 1591 (  "@-@"   PGNSP PGUID l f f 0  601	701    0  0 lseg_length - - "---"));
 DESCR("distance between endpoints");
 
-DATA(insert OID = 1611 (  "?#"	  PGNSP PGUID b f f  628	628 16 1611  0 line_intersect - - ));
+DATA(insert OID = 1611 (  "?#"	  PGNSP PGUID b f f  628	628 16 1611  0 line_intersect - - "---"));
 DESCR("intersect");
-DATA(insert OID = 1612 (  "?||"   PGNSP PGUID b f f  628	628 16 1612  0 line_parallel - - ));
+DATA(insert OID = 1612 (  "?||"   PGNSP PGUID b f f  628	628 16 1612  0 line_parallel - - "---"));
 DESCR("parallel");
-DATA(insert OID = 1613 (  "?-|"   PGNSP PGUID b f f  628	628 16 1613  0 line_perp - - ));
+DATA(insert OID = 1613 (  "?-|"   PGNSP PGUID b f f  628	628 16 1613  0 line_perp - - "---"));
 DESCR("perpendicular");
-DATA(insert OID = 1614 (  "?-"	  PGNSP PGUID l f f  0	628 16	  0  0 line_horizontal - - ));
+DATA(insert OID = 1614 (  "?-"	  PGNSP PGUID l f f  0	628 16	  0  0 line_horizontal - - "---"));
 DESCR("horizontal");
-DATA(insert OID = 1615 (  "?|"	  PGNSP PGUID l f f  0	628 16	  0  0 line_vertical - - ));
+DATA(insert OID = 1615 (  "?|"	  PGNSP PGUID l f f  0	628 16	  0  0 line_vertical - - "---"));
 DESCR("vertical");
-DATA(insert OID = 1616 (  "="	  PGNSP PGUID b f f  628	628 16 1616  0 line_eq eqsel eqjoinsel ));
+DATA(insert OID = 1616 (  "="	  PGNSP PGUID b f f  628	628 16 1616  0 line_eq eqsel eqjoinsel "mhf"));
 DESCR("equal");
-DATA(insert OID = 1617 (  "#"	  PGNSP PGUID b f f  628	628  600 1617  0 line_interpt - - ));
+DATA(insert OID = 1617 (  "#"	  PGNSP PGUID b f f  628	628  600 1617  0 line_interpt - - "---"));
 DESCR("intersection point");
 
 /* MAC type */
-DATA(insert OID = 1220 (  "="	   PGNSP PGUID b t t 829 829	 16 1220 1221 macaddr_eq eqsel eqjoinsel ));
+DATA(insert OID = 1220 (  "="	   PGNSP PGUID b t t 829 829	 16 1220 1221 macaddr_eq eqsel eqjoinsel "mhf"));
 DESCR("equal");
-DATA(insert OID = 1221 (  "<>"	   PGNSP PGUID b f f 829 829	 16 1221 1220 macaddr_ne neqsel neqjoinsel ));
+DATA(insert OID = 1221 (  "<>"	   PGNSP PGUID b f f 829 829	 16 1221 1220 macaddr_ne neqsel neqjoinsel "mhf"));
 DESCR("not equal");
-DATA(insert OID = 1222 (  "<"	   PGNSP PGUID b f f 829 829	 16 1224 1225 macaddr_lt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1222 (  "<"	   PGNSP PGUID b f f 829 829	 16 1224 1225 macaddr_lt scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than");
-DATA(insert OID = 1223 (  "<="	   PGNSP PGUID b f f 829 829	 16 1225 1224 macaddr_le scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1223 (  "<="	   PGNSP PGUID b f f 829 829	 16 1225 1224 macaddr_le scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than or equal");
-DATA(insert OID = 1224 (  ">"	   PGNSP PGUID b f f 829 829	 16 1222 1223 macaddr_gt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 1224 (  ">"	   PGNSP PGUID b f f 829 829	 16 1222 1223 macaddr_gt scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than");
-DATA(insert OID = 1225 (  ">="	   PGNSP PGUID b f f 829 829	 16 1223 1222 macaddr_ge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 1225 (  ">="	   PGNSP PGUID b f f 829 829	 16 1223 1222 macaddr_ge scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than or equal");
 
-DATA(insert OID = 3147 (  "~"	   PGNSP PGUID l f f	  0 829 829 0 0 macaddr_not - - ));
+DATA(insert OID = 3147 (  "~"	   PGNSP PGUID l f f	  0 829 829 0 0 macaddr_not - - "---"));
 DESCR("bitwise not");
-DATA(insert OID = 3148 (  "&"	   PGNSP PGUID b f f	829 829 829 0 0 macaddr_and - - ));
+DATA(insert OID = 3148 (  "&"	   PGNSP PGUID b f f	829 829 829 0 0 macaddr_and - - "---"));
 DESCR("bitwise and");
-DATA(insert OID = 3149 (  "|"	   PGNSP PGUID b f f	829 829 829 0 0 macaddr_or - - ));
+DATA(insert OID = 3149 (  "|"	   PGNSP PGUID b f f	829 829 829 0 0 macaddr_or - - "---"));
 DESCR("bitwise or");
 
 /* INET type (these also support CIDR via implicit cast) */
-DATA(insert OID = 1201 (  "="	   PGNSP PGUID b t t 869 869	 16 1201 1202 network_eq eqsel eqjoinsel ));
+DATA(insert OID = 1201 (  "="	   PGNSP PGUID b t t 869 869	 16 1201 1202 network_eq eqsel eqjoinsel "mhf"));
 DESCR("equal");
-DATA(insert OID = 1202 (  "<>"	   PGNSP PGUID b f f 869 869	 16 1202 1201 network_ne neqsel neqjoinsel ));
+DATA(insert OID = 1202 (  "<>"	   PGNSP PGUID b f f 869 869	 16 1202 1201 network_ne neqsel neqjoinsel "mhf"));
 DESCR("not equal");
-DATA(insert OID = 1203 (  "<"	   PGNSP PGUID b f f 869 869	 16 1205 1206 network_lt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1203 (  "<"	   PGNSP PGUID b f f 869 869	 16 1205 1206 network_lt scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than");
-DATA(insert OID = 1204 (  "<="	   PGNSP PGUID b f f 869 869	 16 1206 1205 network_le scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1204 (  "<="	   PGNSP PGUID b f f 869 869	 16 1206 1205 network_le scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than or equal");
-DATA(insert OID = 1205 (  ">"	   PGNSP PGUID b f f 869 869	 16 1203 1204 network_gt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 1205 (  ">"	   PGNSP PGUID b f f 869 869	 16 1203 1204 network_gt scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than");
-DATA(insert OID = 1206 (  ">="	   PGNSP PGUID b f f 869 869	 16 1204 1203 network_ge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 1206 (  ">="	   PGNSP PGUID b f f 869 869	 16 1204 1203 network_ge scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than or equal");
-DATA(insert OID = 931  (  "<<"	   PGNSP PGUID b f f 869 869	 16 933		0 network_sub networksel networkjoinsel ));
+DATA(insert OID = 931  (  "<<"	   PGNSP PGUID b f f 869 869	 16 933		0 network_sub networksel networkjoinsel "---"));
 DESCR("is subnet");
 #define OID_INET_SUB_OP			931
-DATA(insert OID = 932  (  "<<="    PGNSP PGUID b f f 869 869	 16 934		0 network_subeq networksel networkjoinsel ));
+DATA(insert OID = 932  (  "<<="    PGNSP PGUID b f f 869 869	 16 934		0 network_subeq networksel networkjoinsel "---"));
 DESCR("is subnet or equal");
 #define OID_INET_SUBEQ_OP		932
-DATA(insert OID = 933  (  ">>"	   PGNSP PGUID b f f 869 869	 16 931		0 network_sup networksel networkjoinsel ));
+DATA(insert OID = 933  (  ">>"	   PGNSP PGUID b f f 869 869	 16 931		0 network_sup networksel networkjoinsel "---"));
 DESCR("is supernet");
 #define OID_INET_SUP_OP			933
-DATA(insert OID = 934  (  ">>="    PGNSP PGUID b f f 869 869	 16 932		0 network_supeq networksel networkjoinsel ));
+DATA(insert OID = 934  (  ">>="    PGNSP PGUID b f f 869 869	 16 932		0 network_supeq networksel networkjoinsel "---"));
 DESCR("is supernet or equal");
 #define OID_INET_SUPEQ_OP		934
-DATA(insert OID = 3552	(  "&&"    PGNSP PGUID b f f 869 869	 16 3552	0 network_overlap networksel networkjoinsel ));
+DATA(insert OID = 3552	(  "&&"    PGNSP PGUID b f f 869 869	 16 3552	0 network_overlap networksel networkjoinsel "---"));
 DESCR("overlaps (is subnet or supernet)");
 #define OID_INET_OVERLAP_OP		3552
 
-DATA(insert OID = 2634 (  "~"	   PGNSP PGUID l f f	  0 869 869 0 0 inetnot - - ));
+DATA(insert OID = 2634 (  "~"	   PGNSP PGUID l f f	  0 869 869 0 0 inetnot - - "---"));
 DESCR("bitwise not");
-DATA(insert OID = 2635 (  "&"	   PGNSP PGUID b f f	869 869 869 0 0 inetand - - ));
+DATA(insert OID = 2635 (  "&"	   PGNSP PGUID b f f	869 869 869 0 0 inetand - - "---"));
 DESCR("bitwise and");
-DATA(insert OID = 2636 (  "|"	   PGNSP PGUID b f f	869 869 869 0 0 inetor - - ));
+DATA(insert OID = 2636 (  "|"	   PGNSP PGUID b f f	869 869 869 0 0 inetor - - "---"));
 DESCR("bitwise or");
-DATA(insert OID = 2637 (  "+"	   PGNSP PGUID b f f	869  20 869 2638 0 inetpl - - ));
+DATA(insert OID = 2637 (  "+"	   PGNSP PGUID b f f	869  20 869 2638 0 inetpl - - "---"));
 DESCR("add");
-DATA(insert OID = 2638 (  "+"	   PGNSP PGUID b f f	 20 869 869 2637 0 int8pl_inet - - ));
+DATA(insert OID = 2638 (  "+"	   PGNSP PGUID b f f	 20 869 869 2637 0 int8pl_inet - - "---"));
 DESCR("add");
-DATA(insert OID = 2639 (  "-"	   PGNSP PGUID b f f	869  20 869 0 0 inetmi_int8 - - ));
+DATA(insert OID = 2639 (  "-"	   PGNSP PGUID b f f	869  20 869 0 0 inetmi_int8 - - "---"));
 DESCR("subtract");
-DATA(insert OID = 2640 (  "-"	   PGNSP PGUID b f f	869 869  20 0 0 inetmi - - ));
+DATA(insert OID = 2640 (  "-"	   PGNSP PGUID b f f	869 869  20 0 0 inetmi - - "---"));
 DESCR("subtract");
 
 /* case-insensitive LIKE hacks */
-DATA(insert OID = 1625 (  "~~*"   PGNSP PGUID b f f  19 25	16 0 1626 nameiclike iclikesel iclikejoinsel ));
+DATA(insert OID = 1625 (  "~~*"   PGNSP PGUID b f f  19 25	16 0 1626 nameiclike iclikesel iclikejoinsel "---"));
 DESCR("matches LIKE expression, case-insensitive");
 #define OID_NAME_ICLIKE_OP		1625
-DATA(insert OID = 1626 (  "!~~*"  PGNSP PGUID b f f  19 25	16 0 1625 nameicnlike icnlikesel icnlikejoinsel ));
+DATA(insert OID = 1626 (  "!~~*"  PGNSP PGUID b f f  19 25	16 0 1625 nameicnlike icnlikesel icnlikejoinsel "---"));
 DESCR("does not match LIKE expression, case-insensitive");
-DATA(insert OID = 1627 (  "~~*"   PGNSP PGUID b f f  25 25	16 0 1628 texticlike iclikesel iclikejoinsel ));
+DATA(insert OID = 1627 (  "~~*"   PGNSP PGUID b f f  25 25	16 0 1628 texticlike iclikesel iclikejoinsel "---"));
 DESCR("matches LIKE expression, case-insensitive");
 #define OID_TEXT_ICLIKE_OP		1627
-DATA(insert OID = 1628 (  "!~~*"  PGNSP PGUID b f f  25 25	16 0 1627 texticnlike icnlikesel icnlikejoinsel ));
+DATA(insert OID = 1628 (  "!~~*"  PGNSP PGUID b f f  25 25	16 0 1627 texticnlike icnlikesel icnlikejoinsel "---"));
 DESCR("does not match LIKE expression, case-insensitive");
-DATA(insert OID = 1629 (  "~~*"   PGNSP PGUID b f f  1042 25	16 0 1630 bpchariclike iclikesel iclikejoinsel ));
+DATA(insert OID = 1629 (  "~~*"   PGNSP PGUID b f f  1042 25	16 0 1630 bpchariclike iclikesel iclikejoinsel "---"));
 DESCR("matches LIKE expression, case-insensitive");
 #define OID_BPCHAR_ICLIKE_OP	1629
-DATA(insert OID = 1630 (  "!~~*"  PGNSP PGUID b f f  1042 25	16 0 1629 bpcharicnlike icnlikesel icnlikejoinsel ));
+DATA(insert OID = 1630 (  "!~~*"  PGNSP PGUID b f f  1042 25	16 0 1629 bpcharicnlike icnlikesel icnlikejoinsel "---"));
 DESCR("does not match LIKE expression, case-insensitive");
 
 /* NUMERIC type - OID's 1700-1799 */
-DATA(insert OID = 1751 (  "-"	   PGNSP PGUID l f f	0 1700 1700    0	0 numeric_uminus - - ));
+DATA(insert OID = 1751 (  "-"	   PGNSP PGUID l f f	0 1700 1700    0	0 numeric_uminus - - "---"));
 DESCR("negate");
-DATA(insert OID = 1752 (  "="	   PGNSP PGUID b t t 1700 1700	 16 1752 1753 numeric_eq eqsel eqjoinsel ));
+DATA(insert OID = 1752 (  "="	   PGNSP PGUID b t t 1700 1700	 16 1752 1753 numeric_eq eqsel eqjoinsel "mhf"));
 DESCR("equal");
-DATA(insert OID = 1753 (  "<>"	   PGNSP PGUID b f f 1700 1700	 16 1753 1752 numeric_ne neqsel neqjoinsel ));
+DATA(insert OID = 1753 (  "<>"	   PGNSP PGUID b f f 1700 1700	 16 1753 1752 numeric_ne neqsel neqjoinsel "mhf"));
 DESCR("not equal");
-DATA(insert OID = 1754 (  "<"	   PGNSP PGUID b f f 1700 1700	 16 1756 1757 numeric_lt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1754 (  "<"	   PGNSP PGUID b f f 1700 1700	 16 1756 1757 numeric_lt scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than");
-DATA(insert OID = 1755 (  "<="	   PGNSP PGUID b f f 1700 1700	 16 1757 1756 numeric_le scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1755 (  "<="	   PGNSP PGUID b f f 1700 1700	 16 1757 1756 numeric_le scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than or equal");
-DATA(insert OID = 1756 (  ">"	   PGNSP PGUID b f f 1700 1700	 16 1754 1755 numeric_gt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 1756 (  ">"	   PGNSP PGUID b f f 1700 1700	 16 1754 1755 numeric_gt scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than");
-DATA(insert OID = 1757 (  ">="	   PGNSP PGUID b f f 1700 1700	 16 1755 1754 numeric_ge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 1757 (  ">="	   PGNSP PGUID b f f 1700 1700	 16 1755 1754 numeric_ge scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than or equal");
-DATA(insert OID = 1758 (  "+"	   PGNSP PGUID b f f 1700 1700 1700 1758	0 numeric_add - - ));
+DATA(insert OID = 1758 (  "+"	   PGNSP PGUID b f f 1700 1700 1700 1758	0 numeric_add - - "---"));
 DESCR("add");
-DATA(insert OID = 1759 (  "-"	   PGNSP PGUID b f f 1700 1700 1700    0	0 numeric_sub - - ));
+DATA(insert OID = 1759 (  "-"	   PGNSP PGUID b f f 1700 1700 1700    0	0 numeric_sub - - "---"));
 DESCR("subtract");
-DATA(insert OID = 1760 (  "*"	   PGNSP PGUID b f f 1700 1700 1700 1760	0 numeric_mul - - ));
+DATA(insert OID = 1760 (  "*"	   PGNSP PGUID b f f 1700 1700 1700 1760	0 numeric_mul - - "---"));
 DESCR("multiply");
-DATA(insert OID = 1761 (  "/"	   PGNSP PGUID b f f 1700 1700 1700    0	0 numeric_div - - ));
+DATA(insert OID = 1761 (  "/"	   PGNSP PGUID b f f 1700 1700 1700    0	0 numeric_div - - "---"));
 DESCR("divide");
-DATA(insert OID = 1762 (  "%"	   PGNSP PGUID b f f 1700 1700 1700    0	0 numeric_mod - - ));
+DATA(insert OID = 1762 (  "%"	   PGNSP PGUID b f f 1700 1700 1700    0	0 numeric_mod - - "---"));
 DESCR("modulus");
-DATA(insert OID = 1038 (  "^"	   PGNSP PGUID b f f 1700 1700 1700    0	0 numeric_power - - ));
+DATA(insert OID = 1038 (  "^"	   PGNSP PGUID b f f 1700 1700 1700    0	0 numeric_power - - "---"));
 DESCR("exponentiation");
-DATA(insert OID = 1763 (  "@"	   PGNSP PGUID l f f	0 1700 1700    0	0 numeric_abs - - ));
+DATA(insert OID = 1763 (  "@"	   PGNSP PGUID l f f	0 1700 1700    0	0 numeric_abs - - "---"));
 DESCR("absolute value");
 
-DATA(insert OID = 1784 (  "="	  PGNSP PGUID b t f 1560 1560 16 1784 1785 biteq eqsel eqjoinsel ));
+DATA(insert OID = 1784 (  "="	  PGNSP PGUID b t f 1560 1560 16 1784 1785 biteq eqsel eqjoinsel "mhf"));
 DESCR("equal");
-DATA(insert OID = 1785 (  "<>"	  PGNSP PGUID b f f 1560 1560 16 1785 1784 bitne neqsel neqjoinsel ));
+DATA(insert OID = 1785 (  "<>"	  PGNSP PGUID b f f 1560 1560 16 1785 1784 bitne neqsel neqjoinsel "mhf"));
 DESCR("not equal");
-DATA(insert OID = 1786 (  "<"	  PGNSP PGUID b f f 1560 1560 16 1787 1789 bitlt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1786 (  "<"	  PGNSP PGUID b f f 1560 1560 16 1787 1789 bitlt scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than");
-DATA(insert OID = 1787 (  ">"	  PGNSP PGUID b f f 1560 1560 16 1786 1788 bitgt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 1787 (  ">"	  PGNSP PGUID b f f 1560 1560 16 1786 1788 bitgt scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than");
-DATA(insert OID = 1788 (  "<="	  PGNSP PGUID b f f 1560 1560 16 1789 1787 bitle scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1788 (  "<="	  PGNSP PGUID b f f 1560 1560 16 1789 1787 bitle scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than or equal");
-DATA(insert OID = 1789 (  ">="	  PGNSP PGUID b f f 1560 1560 16 1788 1786 bitge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 1789 (  ">="	  PGNSP PGUID b f f 1560 1560 16 1788 1786 bitge scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than or equal");
-DATA(insert OID = 1791 (  "&"	  PGNSP PGUID b f f 1560 1560 1560 1791  0 bitand - - ));
+DATA(insert OID = 1791 (  "&"	  PGNSP PGUID b f f 1560 1560 1560 1791  0 bitand - - "---"));
 DESCR("bitwise and");
-DATA(insert OID = 1792 (  "|"	  PGNSP PGUID b f f 1560 1560 1560 1792  0 bitor - - ));
+DATA(insert OID = 1792 (  "|"	  PGNSP PGUID b f f 1560 1560 1560 1792  0 bitor - - "---"));
 DESCR("bitwise or");
-DATA(insert OID = 1793 (  "#"	  PGNSP PGUID b f f 1560 1560 1560 1793  0 bitxor - - ));
+DATA(insert OID = 1793 (  "#"	  PGNSP PGUID b f f 1560 1560 1560 1793  0 bitxor - - "---"));
 DESCR("bitwise exclusive or");
-DATA(insert OID = 1794 (  "~"	  PGNSP PGUID l f f    0 1560 1560	  0  0 bitnot - - ));
+DATA(insert OID = 1794 (  "~"	  PGNSP PGUID l f f    0 1560 1560	  0  0 bitnot - - "---"));
 DESCR("bitwise not");
-DATA(insert OID = 1795 (  "<<"	  PGNSP PGUID b f f 1560   23 1560	  0  0 bitshiftleft - - ));
+DATA(insert OID = 1795 (  "<<"	  PGNSP PGUID b f f 1560   23 1560	  0  0 bitshiftleft - - "---"));
 DESCR("bitwise shift left");
-DATA(insert OID = 1796 (  ">>"	  PGNSP PGUID b f f 1560   23 1560	  0  0 bitshiftright - - ));
+DATA(insert OID = 1796 (  ">>"	  PGNSP PGUID b f f 1560   23 1560	  0  0 bitshiftright - - "---"));
 DESCR("bitwise shift right");
-DATA(insert OID = 1797 (  "||"	  PGNSP PGUID b f f 1562 1562 1562	  0  0 bitcat - - ));
+DATA(insert OID = 1797 (  "||"	  PGNSP PGUID b f f 1562 1562 1562	  0  0 bitcat - - "---"));
 DESCR("concatenate");
 
-DATA(insert OID = 1800 (  "+"	   PGNSP PGUID b f f 1083 1186 1083  1849 0 time_pl_interval - - ));
+DATA(insert OID = 1800 (  "+"	   PGNSP PGUID b f f 1083 1186 1083  1849 0 time_pl_interval - - "---"));
 DESCR("add");
-DATA(insert OID = 1801 (  "-"	   PGNSP PGUID b f f 1083 1186 1083  0	0 time_mi_interval - - ));
+DATA(insert OID = 1801 (  "-"	   PGNSP PGUID b f f 1083 1186 1083  0	0 time_mi_interval - - "---"));
 DESCR("subtract");
-DATA(insert OID = 1802 (  "+"	   PGNSP PGUID b f f 1266 1186 1266  2552 0 timetz_pl_interval - - ));
+DATA(insert OID = 1802 (  "+"	   PGNSP PGUID b f f 1266 1186 1266  2552 0 timetz_pl_interval - - "---"));
 DESCR("add");
-DATA(insert OID = 1803 (  "-"	   PGNSP PGUID b f f 1266 1186 1266  0	0 timetz_mi_interval - - ));
+DATA(insert OID = 1803 (  "-"	   PGNSP PGUID b f f 1266 1186 1266  0	0 timetz_mi_interval - - "---"));
 DESCR("subtract");
 
-DATA(insert OID = 1804 (  "="	  PGNSP PGUID b t f 1562 1562 16 1804 1805 varbiteq eqsel eqjoinsel ));
+DATA(insert OID = 1804 (  "="	  PGNSP PGUID b t f 1562 1562 16 1804 1805 varbiteq eqsel eqjoinsel "mhf"));
 DESCR("equal");
-DATA(insert OID = 1805 (  "<>"	  PGNSP PGUID b f f 1562 1562 16 1805 1804 varbitne neqsel neqjoinsel ));
+DATA(insert OID = 1805 (  "<>"	  PGNSP PGUID b f f 1562 1562 16 1805 1804 varbitne neqsel neqjoinsel "mhf"));
 DESCR("not equal");
-DATA(insert OID = 1806 (  "<"	  PGNSP PGUID b f f 1562 1562 16 1807 1809 varbitlt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1806 (  "<"	  PGNSP PGUID b f f 1562 1562 16 1807 1809 varbitlt scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than");
-DATA(insert OID = 1807 (  ">"	  PGNSP PGUID b f f 1562 1562 16 1806 1808 varbitgt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 1807 (  ">"	  PGNSP PGUID b f f 1562 1562 16 1806 1808 varbitgt scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than");
-DATA(insert OID = 1808 (  "<="	  PGNSP PGUID b f f 1562 1562 16 1809 1807 varbitle scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1808 (  "<="	  PGNSP PGUID b f f 1562 1562 16 1809 1807 varbitle scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than or equal");
-DATA(insert OID = 1809 (  ">="	  PGNSP PGUID b f f 1562 1562 16 1808 1806 varbitge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 1809 (  ">="	  PGNSP PGUID b f f 1562 1562 16 1808 1806 varbitge scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than or equal");
 
-DATA(insert OID = 1849 (  "+"	   PGNSP PGUID b f f 1186 1083 1083  1800 0 interval_pl_time - - ));
+DATA(insert OID = 1849 (  "+"	   PGNSP PGUID b f f 1186 1083 1083  1800 0 interval_pl_time - - "---"));
 DESCR("add");
 
-DATA(insert OID = 1862 ( "="	   PGNSP PGUID b t t	21	20	16 1868  1863 int28eq eqsel eqjoinsel ));
+DATA(insert OID = 1862 ( "="	   PGNSP PGUID b t t	21	20	16 1868  1863 int28eq eqsel eqjoinsel "mhf"));
 DESCR("equal");
-DATA(insert OID = 1863 ( "<>"	   PGNSP PGUID b f f	21	20	16 1869  1862 int28ne neqsel neqjoinsel ));
+DATA(insert OID = 1863 ( "<>"	   PGNSP PGUID b f f	21	20	16 1869  1862 int28ne neqsel neqjoinsel "mhf"));
 DESCR("not equal");
-DATA(insert OID = 1864 ( "<"	   PGNSP PGUID b f f	21	20	16 1871  1867 int28lt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1864 ( "<"	   PGNSP PGUID b f f	21	20	16 1871  1867 int28lt scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than");
-DATA(insert OID = 1865 ( ">"	   PGNSP PGUID b f f	21	20	16 1870  1866 int28gt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 1865 ( ">"	   PGNSP PGUID b f f	21	20	16 1870  1866 int28gt scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than");
-DATA(insert OID = 1866 ( "<="	   PGNSP PGUID b f f	21	20	16 1873  1865 int28le scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1866 ( "<="	   PGNSP PGUID b f f	21	20	16 1873  1865 int28le scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than or equal");
-DATA(insert OID = 1867 ( ">="	   PGNSP PGUID b f f	21	20	16 1872  1864 int28ge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 1867 ( ">="	   PGNSP PGUID b f f	21	20	16 1872  1864 int28ge scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than or equal");
 
-DATA(insert OID = 1868 ( "="	   PGNSP PGUID b t t	20	21	16	1862 1869 int82eq eqsel eqjoinsel ));
+DATA(insert OID = 1868 ( "="	   PGNSP PGUID b t t	20	21	16	1862 1869 int82eq eqsel eqjoinsel "mhf"));
 DESCR("equal");
-DATA(insert OID = 1869 ( "<>"	   PGNSP PGUID b f f	20	21	16	1863 1868 int82ne neqsel neqjoinsel ));
+DATA(insert OID = 1869 ( "<>"	   PGNSP PGUID b f f	20	21	16	1863 1868 int82ne neqsel neqjoinsel "mhf"));
 DESCR("not equal");
-DATA(insert OID = 1870 ( "<"	   PGNSP PGUID b f f	20	21	16	1865 1873 int82lt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1870 ( "<"	   PGNSP PGUID b f f	20	21	16	1865 1873 int82lt scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than");
-DATA(insert OID = 1871 ( ">"	   PGNSP PGUID b f f	20	21	16	1864 1872 int82gt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 1871 ( ">"	   PGNSP PGUID b f f	20	21	16	1864 1872 int82gt scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than");
-DATA(insert OID = 1872 ( "<="	   PGNSP PGUID b f f	20	21	16	1867 1871 int82le scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1872 ( "<="	   PGNSP PGUID b f f	20	21	16	1867 1871 int82le scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than or equal");
-DATA(insert OID = 1873 ( ">="	   PGNSP PGUID b f f	20	21	16	1866 1870 int82ge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 1873 ( ">="	   PGNSP PGUID b f f	20	21	16	1866 1870 int82ge scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than or equal");
 
-DATA(insert OID = 1874 ( "&"	   PGNSP PGUID b f f	21	21	21	1874  0 int2and - - ));
+DATA(insert OID = 1874 ( "&"	   PGNSP PGUID b f f	21	21	21	1874  0 int2and - - "---"));
 DESCR("bitwise and");
-DATA(insert OID = 1875 ( "|"	   PGNSP PGUID b f f	21	21	21	1875  0 int2or - - ));
+DATA(insert OID = 1875 ( "|"	   PGNSP PGUID b f f	21	21	21	1875  0 int2or - - "---"));
 DESCR("bitwise or");
-DATA(insert OID = 1876 ( "#"	   PGNSP PGUID b f f	21	21	21	1876  0 int2xor - - ));
+DATA(insert OID = 1876 ( "#"	   PGNSP PGUID b f f	21	21	21	1876  0 int2xor - - "---"));
 DESCR("bitwise exclusive or");
-DATA(insert OID = 1877 ( "~"	   PGNSP PGUID l f f	 0	21	21	 0	  0 int2not - - ));
+DATA(insert OID = 1877 ( "~"	   PGNSP PGUID l f f	 0	21	21	 0	  0 int2not - - "---"));
 DESCR("bitwise not");
-DATA(insert OID = 1878 ( "<<"	   PGNSP PGUID b f f	21	23	21	 0	  0 int2shl - - ));
+DATA(insert OID = 1878 ( "<<"	   PGNSP PGUID b f f	21	23	21	 0	  0 int2shl - - "---"));
 DESCR("bitwise shift left");
-DATA(insert OID = 1879 ( ">>"	   PGNSP PGUID b f f	21	23	21	 0	  0 int2shr - - ));
+DATA(insert OID = 1879 ( ">>"	   PGNSP PGUID b f f	21	23	21	 0	  0 int2shr - - "---"));
 DESCR("bitwise shift right");
 
-DATA(insert OID = 1880 ( "&"	   PGNSP PGUID b f f	23	23	23	1880  0 int4and - - ));
+DATA(insert OID = 1880 ( "&"	   PGNSP PGUID b f f	23	23	23	1880  0 int4and - - "---"));
 DESCR("bitwise and");
-DATA(insert OID = 1881 ( "|"	   PGNSP PGUID b f f	23	23	23	1881  0 int4or - - ));
+DATA(insert OID = 1881 ( "|"	   PGNSP PGUID b f f	23	23	23	1881  0 int4or - - "---"));
 DESCR("bitwise or");
-DATA(insert OID = 1882 ( "#"	   PGNSP PGUID b f f	23	23	23	1882  0 int4xor - - ));
+DATA(insert OID = 1882 ( "#"	   PGNSP PGUID b f f	23	23	23	1882  0 int4xor - - "---"));
 DESCR("bitwise exclusive or");
-DATA(insert OID = 1883 ( "~"	   PGNSP PGUID l f f	 0	23	23	 0	  0 int4not - - ));
+DATA(insert OID = 1883 ( "~"	   PGNSP PGUID l f f	 0	23	23	 0	  0 int4not - - "---"));
 DESCR("bitwise not");
-DATA(insert OID = 1884 ( "<<"	   PGNSP PGUID b f f	23	23	23	 0	  0 int4shl - - ));
+DATA(insert OID = 1884 ( "<<"	   PGNSP PGUID b f f	23	23	23	 0	  0 int4shl - - "---"));
 DESCR("bitwise shift left");
-DATA(insert OID = 1885 ( ">>"	   PGNSP PGUID b f f	23	23	23	 0	  0 int4shr - - ));
+DATA(insert OID = 1885 ( ">>"	   PGNSP PGUID b f f	23	23	23	 0	  0 int4shr - - "---"));
 DESCR("bitwise shift right");
 
-DATA(insert OID = 1886 ( "&"	   PGNSP PGUID b f f	20	20	20	1886  0 int8and - - ));
+DATA(insert OID = 1886 ( "&"	   PGNSP PGUID b f f	20	20	20	1886  0 int8and - - "---"));
 DESCR("bitwise and");
-DATA(insert OID = 1887 ( "|"	   PGNSP PGUID b f f	20	20	20	1887  0 int8or - - ));
+DATA(insert OID = 1887 ( "|"	   PGNSP PGUID b f f	20	20	20	1887  0 int8or - - "---"));
 DESCR("bitwise or");
-DATA(insert OID = 1888 ( "#"	   PGNSP PGUID b f f	20	20	20	1888  0 int8xor - - ));
+DATA(insert OID = 1888 ( "#"	   PGNSP PGUID b f f	20	20	20	1888  0 int8xor - - "---"));
 DESCR("bitwise exclusive or");
-DATA(insert OID = 1889 ( "~"	   PGNSP PGUID l f f	 0	20	20	 0	  0 int8not - - ));
+DATA(insert OID = 1889 ( "~"	   PGNSP PGUID l f f	 0	20	20	 0	  0 int8not - - "---"));
 DESCR("bitwise not");
-DATA(insert OID = 1890 ( "<<"	   PGNSP PGUID b f f	20	23	20	 0	  0 int8shl - - ));
+DATA(insert OID = 1890 ( "<<"	   PGNSP PGUID b f f	20	23	20	 0	  0 int8shl - - "---"));
 DESCR("bitwise shift left");
-DATA(insert OID = 1891 ( ">>"	   PGNSP PGUID b f f	20	23	20	 0	  0 int8shr - - ));
+DATA(insert OID = 1891 ( ">>"	   PGNSP PGUID b f f	20	23	20	 0	  0 int8shr - - "---"));
 DESCR("bitwise shift right");
 
-DATA(insert OID = 1916 (  "+"	   PGNSP PGUID l f f	 0	20	20	0	0 int8up - - ));
+DATA(insert OID = 1916 (  "+"	   PGNSP PGUID l f f	 0	20	20	0	0 int8up - - "---"));
 DESCR("unary plus");
-DATA(insert OID = 1917 (  "+"	   PGNSP PGUID l f f	 0	21	21	0	0 int2up - - ));
+DATA(insert OID = 1917 (  "+"	   PGNSP PGUID l f f	 0	21	21	0	0 int2up - - "---"));
 DESCR("unary plus");
-DATA(insert OID = 1918 (  "+"	   PGNSP PGUID l f f	 0	23	23	0	0 int4up - - ));
+DATA(insert OID = 1918 (  "+"	   PGNSP PGUID l f f	 0	23	23	0	0 int4up - - "---"));
 DESCR("unary plus");
-DATA(insert OID = 1919 (  "+"	   PGNSP PGUID l f f	 0	700 700 0	0 float4up - - ));
+DATA(insert OID = 1919 (  "+"	   PGNSP PGUID l f f	 0	700 700 0	0 float4up - - "---"));
 DESCR("unary plus");
-DATA(insert OID = 1920 (  "+"	   PGNSP PGUID l f f	 0	701 701 0	0 float8up - - ));
+DATA(insert OID = 1920 (  "+"	   PGNSP PGUID l f f	 0	701 701 0	0 float8up - - "---"));
 DESCR("unary plus");
-DATA(insert OID = 1921 (  "+"	   PGNSP PGUID l f f	 0 1700 1700	0	0 numeric_uplus - - ));
+DATA(insert OID = 1921 (  "+"	   PGNSP PGUID l f f	 0 1700 1700	0	0 numeric_uplus - - "---"));
 DESCR("unary plus");
 
 /* bytea operators */
-DATA(insert OID = 1955 ( "="	   PGNSP PGUID b t t 17 17	16 1955 1956 byteaeq eqsel eqjoinsel ));
+DATA(insert OID = 1955 ( "="	   PGNSP PGUID b t t 17 17	16 1955 1956 byteaeq eqsel eqjoinsel "mhf"));
 DESCR("equal");
-DATA(insert OID = 1956 ( "<>"	   PGNSP PGUID b f f 17 17	16 1956 1955 byteane neqsel neqjoinsel ));
+DATA(insert OID = 1956 ( "<>"	   PGNSP PGUID b f f 17 17	16 1956 1955 byteane neqsel neqjoinsel "mhf"));
 DESCR("not equal");
-DATA(insert OID = 1957 ( "<"	   PGNSP PGUID b f f 17 17	16 1959 1960 bytealt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1957 ( "<"	   PGNSP PGUID b f f 17 17	16 1959 1960 bytealt scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than");
-DATA(insert OID = 1958 ( "<="	   PGNSP PGUID b f f 17 17	16 1960 1959 byteale scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1958 ( "<="	   PGNSP PGUID b f f 17 17	16 1960 1959 byteale scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than or equal");
-DATA(insert OID = 1959 ( ">"	   PGNSP PGUID b f f 17 17	16 1957 1958 byteagt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 1959 ( ">"	   PGNSP PGUID b f f 17 17	16 1957 1958 byteagt scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than");
-DATA(insert OID = 1960 ( ">="	   PGNSP PGUID b f f 17 17	16 1958 1957 byteage scalargtsel scalargtjoinsel ));
+DATA(insert OID = 1960 ( ">="	   PGNSP PGUID b f f 17 17	16 1958 1957 byteage scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than or equal");
 
-DATA(insert OID = 2016 (  "~~"	   PGNSP PGUID b f f 17 17	16 0	2017 bytealike likesel likejoinsel ));
+DATA(insert OID = 2016 (  "~~"	   PGNSP PGUID b f f 17 17	16 0	2017 bytealike likesel likejoinsel "---"));
 DESCR("matches LIKE expression");
 #define OID_BYTEA_LIKE_OP		2016
-DATA(insert OID = 2017 (  "!~~"    PGNSP PGUID b f f 17 17	16 0	2016 byteanlike nlikesel nlikejoinsel ));
+DATA(insert OID = 2017 (  "!~~"    PGNSP PGUID b f f 17 17	16 0	2016 byteanlike nlikesel nlikejoinsel "---"));
 DESCR("does not match LIKE expression");
-DATA(insert OID = 2018 (  "||"	   PGNSP PGUID b f f 17 17	17 0	0	 byteacat - - ));
+DATA(insert OID = 2018 (  "||"	   PGNSP PGUID b f f 17 17	17 0	0	 byteacat - - "---"));
 DESCR("concatenate");
 
 /* timestamp operators */
-DATA(insert OID = 2060 (  "="	   PGNSP PGUID b t t 1114 1114	 16 2060 2061 timestamp_eq eqsel eqjoinsel ));
+DATA(insert OID = 2060 (  "="	   PGNSP PGUID b t t 1114 1114	 16 2060 2061 timestamp_eq eqsel eqjoinsel "mhf"));
 DESCR("equal");
-DATA(insert OID = 2061 (  "<>"	   PGNSP PGUID b f f 1114 1114	 16 2061 2060 timestamp_ne neqsel neqjoinsel ));
+DATA(insert OID = 2061 (  "<>"	   PGNSP PGUID b f f 1114 1114	 16 2061 2060 timestamp_ne neqsel neqjoinsel "mhf"));
 DESCR("not equal");
-DATA(insert OID = 2062 (  "<"	   PGNSP PGUID b f f 1114 1114	 16 2064 2065 timestamp_lt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 2062 (  "<"	   PGNSP PGUID b f f 1114 1114	 16 2064 2065 timestamp_lt scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than");
-DATA(insert OID = 2063 (  "<="	   PGNSP PGUID b f f 1114 1114	 16 2065 2064 timestamp_le scalarltsel scalarltjoinsel ));
+DATA(insert OID = 2063 (  "<="	   PGNSP PGUID b f f 1114 1114	 16 2065 2064 timestamp_le scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than or equal");
-DATA(insert OID = 2064 (  ">"	   PGNSP PGUID b f f 1114 1114	 16 2062 2063 timestamp_gt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 2064 (  ">"	   PGNSP PGUID b f f 1114 1114	 16 2062 2063 timestamp_gt scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than");
-DATA(insert OID = 2065 (  ">="	   PGNSP PGUID b f f 1114 1114	 16 2063 2062 timestamp_ge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 2065 (  ">="	   PGNSP PGUID b f f 1114 1114	 16 2063 2062 timestamp_ge scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than or equal");
-DATA(insert OID = 2066 (  "+"	   PGNSP PGUID b f f 1114 1186 1114  2553 0 timestamp_pl_interval - - ));
+DATA(insert OID = 2066 (  "+"	   PGNSP PGUID b f f 1114 1186 1114  2553 0 timestamp_pl_interval - - "---"));
 DESCR("add");
-DATA(insert OID = 2067 (  "-"	   PGNSP PGUID b f f 1114 1114 1186  0	0 timestamp_mi - - ));
+DATA(insert OID = 2067 (  "-"	   PGNSP PGUID b f f 1114 1114 1186  0	0 timestamp_mi - - "---"));
 DESCR("subtract");
-DATA(insert OID = 2068 (  "-"	   PGNSP PGUID b f f 1114 1186 1114  0	0 timestamp_mi_interval - - ));
+DATA(insert OID = 2068 (  "-"	   PGNSP PGUID b f f 1114 1186 1114  0	0 timestamp_mi_interval - - "---"));
 DESCR("subtract");
 
 /* character-by-character (not collation order) comparison operators for character types */
 
-DATA(insert OID = 2314 ( "~<~"	PGNSP PGUID b f f 25 25 16 2318 2317 text_pattern_lt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 2314 ( "~<~"	PGNSP PGUID b f f 25 25 16 2318 2317 text_pattern_lt scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than");
-DATA(insert OID = 2315 ( "~<=~" PGNSP PGUID b f f 25 25 16 2317 2318 text_pattern_le scalarltsel scalarltjoinsel ));
+DATA(insert OID = 2315 ( "~<=~" PGNSP PGUID b f f 25 25 16 2317 2318 text_pattern_le scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than or equal");
-DATA(insert OID = 2317 ( "~>=~" PGNSP PGUID b f f 25 25 16 2315 2314 text_pattern_ge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 2317 ( "~>=~" PGNSP PGUID b f f 25 25 16 2315 2314 text_pattern_ge scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than or equal");
-DATA(insert OID = 2318 ( "~>~"	PGNSP PGUID b f f 25 25 16 2314 2315 text_pattern_gt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 2318 ( "~>~"	PGNSP PGUID b f f 25 25 16 2314 2315 text_pattern_gt scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than");
 
-DATA(insert OID = 2326 ( "~<~"	PGNSP PGUID b f f 1042 1042 16 2330 2329 bpchar_pattern_lt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 2326 ( "~<~"	PGNSP PGUID b f f 1042 1042 16 2330 2329 bpchar_pattern_lt scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than");
-DATA(insert OID = 2327 ( "~<=~" PGNSP PGUID b f f 1042 1042 16 2329 2330 bpchar_pattern_le scalarltsel scalarltjoinsel ));
+DATA(insert OID = 2327 ( "~<=~" PGNSP PGUID b f f 1042 1042 16 2329 2330 bpchar_pattern_le scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than or equal");
-DATA(insert OID = 2329 ( "~>=~" PGNSP PGUID b f f 1042 1042 16 2327 2326 bpchar_pattern_ge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 2329 ( "~>=~" PGNSP PGUID b f f 1042 1042 16 2327 2326 bpchar_pattern_ge scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than or equal");
-DATA(insert OID = 2330 ( "~>~"	PGNSP PGUID b f f 1042 1042 16 2326 2327 bpchar_pattern_gt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 2330 ( "~>~"	PGNSP PGUID b f f 1042 1042 16 2326 2327 bpchar_pattern_gt scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than");
 
 /* crosstype operations for date vs. timestamp and timestamptz */
 
-DATA(insert OID = 2345 ( "<"	   PGNSP PGUID b f f	1082	1114   16 2375 2348 date_lt_timestamp scalarltsel scalarltjoinsel ));
+DATA(insert OID = 2345 ( "<"	   PGNSP PGUID b f f	1082	1114   16 2375 2348 date_lt_timestamp scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than");
-DATA(insert OID = 2346 ( "<="	   PGNSP PGUID b f f	1082	1114   16 2374 2349 date_le_timestamp scalarltsel scalarltjoinsel ));
+DATA(insert OID = 2346 ( "<="	   PGNSP PGUID b f f	1082	1114   16 2374 2349 date_le_timestamp scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than or equal");
-DATA(insert OID = 2347 ( "="	   PGNSP PGUID b t f	1082	1114   16 2373 2350 date_eq_timestamp eqsel eqjoinsel ));
+DATA(insert OID = 2347 ( "="	   PGNSP PGUID b t f	1082	1114   16 2373 2350 date_eq_timestamp eqsel eqjoinsel "mhf"));
 DESCR("equal");
-DATA(insert OID = 2348 ( ">="	   PGNSP PGUID b f f	1082	1114   16 2372 2345 date_ge_timestamp scalargtsel scalargtjoinsel ));
+DATA(insert OID = 2348 ( ">="	   PGNSP PGUID b f f	1082	1114   16 2372 2345 date_ge_timestamp scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than or equal");
-DATA(insert OID = 2349 ( ">"	   PGNSP PGUID b f f	1082	1114   16 2371 2346 date_gt_timestamp scalargtsel scalargtjoinsel ));
+DATA(insert OID = 2349 ( ">"	   PGNSP PGUID b f f	1082	1114   16 2371 2346 date_gt_timestamp scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than");
-DATA(insert OID = 2350 ( "<>"	   PGNSP PGUID b f f	1082	1114   16 2376 2347 date_ne_timestamp neqsel neqjoinsel ));
+DATA(insert OID = 2350 ( "<>"	   PGNSP PGUID b f f	1082	1114   16 2376 2347 date_ne_timestamp neqsel neqjoinsel "mhf"));
 DESCR("not equal");
 
-DATA(insert OID = 2358 ( "<"	   PGNSP PGUID b f f	1082	1184   16 2388 2361 date_lt_timestamptz scalarltsel scalarltjoinsel ));
+DATA(insert OID = 2358 ( "<"	   PGNSP PGUID b f f	1082	1184   16 2388 2361 date_lt_timestamptz scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than");
-DATA(insert OID = 2359 ( "<="	   PGNSP PGUID b f f	1082	1184   16 2387 2362 date_le_timestamptz scalarltsel scalarltjoinsel ));
+DATA(insert OID = 2359 ( "<="	   PGNSP PGUID b f f	1082	1184   16 2387 2362 date_le_timestamptz scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than or equal");
-DATA(insert OID = 2360 ( "="	   PGNSP PGUID b t f	1082	1184   16 2386 2363 date_eq_timestamptz eqsel eqjoinsel ));
+DATA(insert OID = 2360 ( "="	   PGNSP PGUID b t f	1082	1184   16 2386 2363 date_eq_timestamptz eqsel eqjoinsel "mhf"));
 DESCR("equal");
-DATA(insert OID = 2361 ( ">="	   PGNSP PGUID b f f	1082	1184   16 2385 2358 date_ge_timestamptz scalargtsel scalargtjoinsel ));
+DATA(insert OID = 2361 ( ">="	   PGNSP PGUID b f f	1082	1184   16 2385 2358 date_ge_timestamptz scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than or equal");
-DATA(insert OID = 2362 ( ">"	   PGNSP PGUID b f f	1082	1184   16 2384 2359 date_gt_timestamptz scalargtsel scalargtjoinsel ));
+DATA(insert OID = 2362 ( ">"	   PGNSP PGUID b f f	1082	1184   16 2384 2359 date_gt_timestamptz scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than");
-DATA(insert OID = 2363 ( "<>"	   PGNSP PGUID b f f	1082	1184   16 2389 2360 date_ne_timestamptz neqsel neqjoinsel ));
+DATA(insert OID = 2363 ( "<>"	   PGNSP PGUID b f f	1082	1184   16 2389 2360 date_ne_timestamptz neqsel neqjoinsel "mhf"));
 DESCR("not equal");
 
-DATA(insert OID = 2371 ( "<"	   PGNSP PGUID b f f	1114	1082   16 2349 2374 timestamp_lt_date scalarltsel scalarltjoinsel ));
+DATA(insert OID = 2371 ( "<"	   PGNSP PGUID b f f	1114	1082   16 2349 2374 timestamp_lt_date scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than");
-DATA(insert OID = 2372 ( "<="	   PGNSP PGUID b f f	1114	1082   16 2348 2375 timestamp_le_date scalarltsel scalarltjoinsel ));
+DATA(insert OID = 2372 ( "<="	   PGNSP PGUID b f f	1114	1082   16 2348 2375 timestamp_le_date scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than or equal");
-DATA(insert OID = 2373 ( "="	   PGNSP PGUID b t f	1114	1082   16 2347 2376 timestamp_eq_date eqsel eqjoinsel ));
+DATA(insert OID = 2373 ( "="	   PGNSP PGUID b t f	1114	1082   16 2347 2376 timestamp_eq_date eqsel eqjoinsel "mhf"));
 DESCR("equal");
-DATA(insert OID = 2374 ( ">="	   PGNSP PGUID b f f	1114	1082   16 2346 2371 timestamp_ge_date scalargtsel scalargtjoinsel ));
+DATA(insert OID = 2374 ( ">="	   PGNSP PGUID b f f	1114	1082   16 2346 2371 timestamp_ge_date scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than or equal");
-DATA(insert OID = 2375 ( ">"	   PGNSP PGUID b f f	1114	1082   16 2345 2372 timestamp_gt_date scalargtsel scalargtjoinsel ));
+DATA(insert OID = 2375 ( ">"	   PGNSP PGUID b f f	1114	1082   16 2345 2372 timestamp_gt_date scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than");
-DATA(insert OID = 2376 ( "<>"	   PGNSP PGUID b f f	1114	1082   16 2350 2373 timestamp_ne_date neqsel neqjoinsel ));
+DATA(insert OID = 2376 ( "<>"	   PGNSP PGUID b f f	1114	1082   16 2350 2373 timestamp_ne_date neqsel neqjoinsel "mhf"));
 DESCR("not equal");
 
-DATA(insert OID = 2384 ( "<"	   PGNSP PGUID b f f	1184	1082   16 2362 2387 timestamptz_lt_date scalarltsel scalarltjoinsel ));
+DATA(insert OID = 2384 ( "<"	   PGNSP PGUID b f f	1184	1082   16 2362 2387 timestamptz_lt_date scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than");
-DATA(insert OID = 2385 ( "<="	   PGNSP PGUID b f f	1184	1082   16 2361 2388 timestamptz_le_date scalarltsel scalarltjoinsel ));
+DATA(insert OID = 2385 ( "<="	   PGNSP PGUID b f f	1184	1082   16 2361 2388 timestamptz_le_date scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than or equal");
-DATA(insert OID = 2386 ( "="	   PGNSP PGUID b t f	1184	1082   16 2360 2389 timestamptz_eq_date eqsel eqjoinsel ));
+DATA(insert OID = 2386 ( "="	   PGNSP PGUID b t f	1184	1082   16 2360 2389 timestamptz_eq_date eqsel eqjoinsel "mhf"));
 DESCR("equal");
-DATA(insert OID = 2387 ( ">="	   PGNSP PGUID b f f	1184	1082   16 2359 2384 timestamptz_ge_date scalargtsel scalargtjoinsel ));
+DATA(insert OID = 2387 ( ">="	   PGNSP PGUID b f f	1184	1082   16 2359 2384 timestamptz_ge_date scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than or equal");
-DATA(insert OID = 2388 ( ">"	   PGNSP PGUID b f f	1184	1082   16 2358 2385 timestamptz_gt_date scalargtsel scalargtjoinsel ));
+DATA(insert OID = 2388 ( ">"	   PGNSP PGUID b f f	1184	1082   16 2358 2385 timestamptz_gt_date scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than");
-DATA(insert OID = 2389 ( "<>"	   PGNSP PGUID b f f	1184	1082   16 2363 2386 timestamptz_ne_date neqsel neqjoinsel ));
+DATA(insert OID = 2389 ( "<>"	   PGNSP PGUID b f f	1184	1082   16 2363 2386 timestamptz_ne_date neqsel neqjoinsel "mhf"));
 DESCR("not equal");
 
 /* crosstype operations for timestamp vs. timestamptz */
 
-DATA(insert OID = 2534 ( "<"	   PGNSP PGUID b f f	1114	1184   16 2544 2537 timestamp_lt_timestamptz scalarltsel scalarltjoinsel ));
+DATA(insert OID = 2534 ( "<"	   PGNSP PGUID b f f	1114	1184   16 2544 2537 timestamp_lt_timestamptz scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than");
-DATA(insert OID = 2535 ( "<="	   PGNSP PGUID b f f	1114	1184   16 2543 2538 timestamp_le_timestamptz scalarltsel scalarltjoinsel ));
+DATA(insert OID = 2535 ( "<="	   PGNSP PGUID b f f	1114	1184   16 2543 2538 timestamp_le_timestamptz scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than or equal");
-DATA(insert OID = 2536 ( "="	   PGNSP PGUID b t f	1114	1184   16 2542 2539 timestamp_eq_timestamptz eqsel eqjoinsel ));
+DATA(insert OID = 2536 ( "="	   PGNSP PGUID b t f	1114	1184   16 2542 2539 timestamp_eq_timestamptz eqsel eqjoinsel "mhf"));
 DESCR("equal");
-DATA(insert OID = 2537 ( ">="	   PGNSP PGUID b f f	1114	1184   16 2541 2534 timestamp_ge_timestamptz scalargtsel scalargtjoinsel ));
+DATA(insert OID = 2537 ( ">="	   PGNSP PGUID b f f	1114	1184   16 2541 2534 timestamp_ge_timestamptz scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than or equal");
-DATA(insert OID = 2538 ( ">"	   PGNSP PGUID b f f	1114	1184   16 2540 2535 timestamp_gt_timestamptz scalargtsel scalargtjoinsel ));
+DATA(insert OID = 2538 ( ">"	   PGNSP PGUID b f f	1114	1184   16 2540 2535 timestamp_gt_timestamptz scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than");
-DATA(insert OID = 2539 ( "<>"	   PGNSP PGUID b f f	1114	1184   16 2545 2536 timestamp_ne_timestamptz neqsel neqjoinsel ));
+DATA(insert OID = 2539 ( "<>"	   PGNSP PGUID b f f	1114	1184   16 2545 2536 timestamp_ne_timestamptz neqsel neqjoinsel "mhf"));
 DESCR("not equal");
 
-DATA(insert OID = 2540 ( "<"	   PGNSP PGUID b f f	1184	1114   16 2538 2543 timestamptz_lt_timestamp scalarltsel scalarltjoinsel ));
+DATA(insert OID = 2540 ( "<"	   PGNSP PGUID b f f	1184	1114   16 2538 2543 timestamptz_lt_timestamp scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than");
-DATA(insert OID = 2541 ( "<="	   PGNSP PGUID b f f	1184	1114   16 2537 2544 timestamptz_le_timestamp scalarltsel scalarltjoinsel ));
+DATA(insert OID = 2541 ( "<="	   PGNSP PGUID b f f	1184	1114   16 2537 2544 timestamptz_le_timestamp scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than or equal");
-DATA(insert OID = 2542 ( "="	   PGNSP PGUID b t f	1184	1114   16 2536 2545 timestamptz_eq_timestamp eqsel eqjoinsel ));
+DATA(insert OID = 2542 ( "="	   PGNSP PGUID b t f	1184	1114   16 2536 2545 timestamptz_eq_timestamp eqsel eqjoinsel "mhf"));
 DESCR("equal");
-DATA(insert OID = 2543 ( ">="	   PGNSP PGUID b f f	1184	1114   16 2535 2540 timestamptz_ge_timestamp scalargtsel scalargtjoinsel ));
+DATA(insert OID = 2543 ( ">="	   PGNSP PGUID b f f	1184	1114   16 2535 2540 timestamptz_ge_timestamp scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than or equal");
-DATA(insert OID = 2544 ( ">"	   PGNSP PGUID b f f	1184	1114   16 2534 2541 timestamptz_gt_timestamp scalargtsel scalargtjoinsel ));
+DATA(insert OID = 2544 ( ">"	   PGNSP PGUID b f f	1184	1114   16 2534 2541 timestamptz_gt_timestamp scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than");
-DATA(insert OID = 2545 ( "<>"	   PGNSP PGUID b f f	1184	1114   16 2539 2542 timestamptz_ne_timestamp neqsel neqjoinsel ));
+DATA(insert OID = 2545 ( "<>"	   PGNSP PGUID b f f	1184	1114   16 2539 2542 timestamptz_ne_timestamp neqsel neqjoinsel "mhf"));
 DESCR("not equal");
 
 /* formerly-missing interval + datetime operators */
-DATA(insert OID = 2551 (  "+"	   PGNSP PGUID b f f	1186 1082 1114 1076 0 interval_pl_date - - ));
+DATA(insert OID = 2551 (  "+"	   PGNSP PGUID b f f	1186 1082 1114 1076 0 interval_pl_date - - "---"));
 DESCR("add");
-DATA(insert OID = 2552 (  "+"	   PGNSP PGUID b f f	1186 1266 1266 1802 0 interval_pl_timetz - - ));
+DATA(insert OID = 2552 (  "+"	   PGNSP PGUID b f f	1186 1266 1266 1802 0 interval_pl_timetz - - "---"));
 DESCR("add");
-DATA(insert OID = 2553 (  "+"	   PGNSP PGUID b f f	1186 1114 1114 2066 0 interval_pl_timestamp - - ));
+DATA(insert OID = 2553 (  "+"	   PGNSP PGUID b f f	1186 1114 1114 2066 0 interval_pl_timestamp - - "---"));
 DESCR("add");
-DATA(insert OID = 2554 (  "+"	   PGNSP PGUID b f f	1186 1184 1184 1327 0 interval_pl_timestamptz - - ));
+DATA(insert OID = 2554 (  "+"	   PGNSP PGUID b f f	1186 1184 1184 1327 0 interval_pl_timestamptz - - "---"));
 DESCR("add");
-DATA(insert OID = 2555 (  "+"	   PGNSP PGUID b f f	23	 1082 1082 1100 0 integer_pl_date - - ));
+DATA(insert OID = 2555 (  "+"	   PGNSP PGUID b f f	23	 1082 1082 1100 0 integer_pl_date - - "---"));
 DESCR("add");
 
 /* new operators for Y-direction rtree opfamilies */
-DATA(insert OID = 2570 (  "<<|"    PGNSP PGUID b f f 603 603	16	 0	 0 box_below positionsel positionjoinsel ));
+DATA(insert OID = 2570 (  "<<|"    PGNSP PGUID b f f 603 603	16	 0	 0 box_below positionsel positionjoinsel "---"));
 DESCR("is below");
-DATA(insert OID = 2571 (  "&<|"    PGNSP PGUID b f f 603 603	16	 0	 0 box_overbelow positionsel positionjoinsel ));
+DATA(insert OID = 2571 (  "&<|"    PGNSP PGUID b f f 603 603	16	 0	 0 box_overbelow positionsel positionjoinsel "---"));
 DESCR("overlaps or is below");
-DATA(insert OID = 2572 (  "|&>"    PGNSP PGUID b f f 603 603	16	 0	 0 box_overabove positionsel positionjoinsel ));
+DATA(insert OID = 2572 (  "|&>"    PGNSP PGUID b f f 603 603	16	 0	 0 box_overabove positionsel positionjoinsel "---"));
 DESCR("overlaps or is above");
-DATA(insert OID = 2573 (  "|>>"    PGNSP PGUID b f f 603 603	16	 0	 0 box_above positionsel positionjoinsel ));
+DATA(insert OID = 2573 (  "|>>"    PGNSP PGUID b f f 603 603	16	 0	 0 box_above positionsel positionjoinsel "---"));
 DESCR("is above");
-DATA(insert OID = 2574 (  "<<|"    PGNSP PGUID b f f 604 604	16	 0	 0 poly_below positionsel positionjoinsel ));
+DATA(insert OID = 2574 (  "<<|"    PGNSP PGUID b f f 604 604	16	 0	 0 poly_below positionsel positionjoinsel "---"));
 DESCR("is below");
-DATA(insert OID = 2575 (  "&<|"    PGNSP PGUID b f f 604 604	16	 0	 0 poly_overbelow positionsel positionjoinsel ));
+DATA(insert OID = 2575 (  "&<|"    PGNSP PGUID b f f 604 604	16	 0	 0 poly_overbelow positionsel positionjoinsel "---"));
 DESCR("overlaps or is below");
-DATA(insert OID = 2576 (  "|&>"    PGNSP PGUID b f f 604 604	16	 0	 0 poly_overabove positionsel positionjoinsel ));
+DATA(insert OID = 2576 (  "|&>"    PGNSP PGUID b f f 604 604	16	 0	 0 poly_overabove positionsel positionjoinsel "---"));
 DESCR("overlaps or is above");
-DATA(insert OID = 2577 (  "|>>"    PGNSP PGUID b f f 604 604	16	 0	 0 poly_above positionsel positionjoinsel ));
+DATA(insert OID = 2577 (  "|>>"    PGNSP PGUID b f f 604 604	16	 0	 0 poly_above positionsel positionjoinsel "---"));
 DESCR("is above");
-DATA(insert OID = 2589 (  "&<|"    PGNSP PGUID b f f 718 718	16	 0	 0 circle_overbelow positionsel positionjoinsel ));
+DATA(insert OID = 2589 (  "&<|"    PGNSP PGUID b f f 718 718	16	 0	 0 circle_overbelow positionsel positionjoinsel "---"));
 DESCR("overlaps or is below");
-DATA(insert OID = 2590 (  "|&>"    PGNSP PGUID b f f 718 718	16	 0	 0 circle_overabove positionsel positionjoinsel ));
+DATA(insert OID = 2590 (  "|&>"    PGNSP PGUID b f f 718 718	16	 0	 0 circle_overabove positionsel positionjoinsel "---"));
 DESCR("overlaps or is above");
 
 /* overlap/contains/contained for arrays */
-DATA(insert OID = 2750 (  "&&"	   PGNSP PGUID b f f 2277 2277	16 2750  0 arrayoverlap arraycontsel arraycontjoinsel ));
+DATA(insert OID = 2750 (  "&&"	   PGNSP PGUID b f f 2277 2277	16 2750  0 arrayoverlap arraycontsel arraycontjoinsel "---"));
 DESCR("overlaps");
 #define OID_ARRAY_OVERLAP_OP	2750
-DATA(insert OID = 2751 (  "@>"	   PGNSP PGUID b f f 2277 2277	16 2752  0 arraycontains arraycontsel arraycontjoinsel ));
+DATA(insert OID = 2751 (  "@>"	   PGNSP PGUID b f f 2277 2277	16 2752  0 arraycontains arraycontsel arraycontjoinsel "---"));
 DESCR("contains");
 #define OID_ARRAY_CONTAINS_OP	2751
-DATA(insert OID = 2752 (  "<@"	   PGNSP PGUID b f f 2277 2277	16 2751  0 arraycontained arraycontsel arraycontjoinsel ));
+DATA(insert OID = 2752 (  "<@"	   PGNSP PGUID b f f 2277 2277	16 2751  0 arraycontained arraycontsel arraycontjoinsel "---"));
 DESCR("is contained by");
 #define OID_ARRAY_CONTAINED_OP	2752
 
 /* capturing operators to preserve pre-8.3 behavior of text concatenation */
-DATA(insert OID = 2779 (  "||"	   PGNSP PGUID b f f 25 2776	25	 0 0 textanycat - - ));
+DATA(insert OID = 2779 (  "||"	   PGNSP PGUID b f f 25 2776	25	 0 0 textanycat - - "---"));
 DESCR("concatenate");
-DATA(insert OID = 2780 (  "||"	   PGNSP PGUID b f f 2776 25	25	 0 0 anytextcat - - ));
+DATA(insert OID = 2780 (  "||"	   PGNSP PGUID b f f 2776 25	25	 0 0 anytextcat - - "---"));
 DESCR("concatenate");
 
 /* obsolete names for contains/contained-by operators; remove these someday */
-DATA(insert OID = 2860 (  "@"	   PGNSP PGUID b f f 604 604	16 2861  0 poly_contained contsel contjoinsel ));
+DATA(insert OID = 2860 (  "@"	   PGNSP PGUID b f f 604 604	16 2861  0 poly_contained contsel contjoinsel "---"));
 DESCR("deprecated, use <@ instead");
-DATA(insert OID = 2861 (  "~"	   PGNSP PGUID b f f 604 604	16 2860  0 poly_contain contsel contjoinsel ));
+DATA(insert OID = 2861 (  "~"	   PGNSP PGUID b f f 604 604	16 2860  0 poly_contain contsel contjoinsel "---"));
 DESCR("deprecated, use @> instead");
-DATA(insert OID = 2862 (  "@"	   PGNSP PGUID b f f 603 603	16 2863  0 box_contained contsel contjoinsel ));
+DATA(insert OID = 2862 (  "@"	   PGNSP PGUID b f f 603 603	16 2863  0 box_contained contsel contjoinsel "---"));
 DESCR("deprecated, use <@ instead");
-DATA(insert OID = 2863 (  "~"	   PGNSP PGUID b f f 603 603	16 2862  0 box_contain contsel contjoinsel ));
+DATA(insert OID = 2863 (  "~"	   PGNSP PGUID b f f 603 603	16 2862  0 box_contain contsel contjoinsel "---"));
 DESCR("deprecated, use @> instead");
-DATA(insert OID = 2864 (  "@"	   PGNSP PGUID b f f 718 718	16 2865  0 circle_contained contsel contjoinsel ));
+DATA(insert OID = 2864 (  "@"	   PGNSP PGUID b f f 718 718	16 2865  0 circle_contained contsel contjoinsel "---"));
 DESCR("deprecated, use <@ instead");
-DATA(insert OID = 2865 (  "~"	   PGNSP PGUID b f f 718 718	16 2864  0 circle_contain contsel contjoinsel ));
+DATA(insert OID = 2865 (  "~"	   PGNSP PGUID b f f 718 718	16 2864  0 circle_contain contsel contjoinsel "---"));
 DESCR("deprecated, use @> instead");
-DATA(insert OID = 2866 (  "@"	   PGNSP PGUID b f f 600 603	16	 0	 0 on_pb - - ));
+DATA(insert OID = 2866 (  "@"	   PGNSP PGUID b f f 600 603	16	 0	 0 on_pb - - "---"));
 DESCR("deprecated, use <@ instead");
-DATA(insert OID = 2867 (  "@"	   PGNSP PGUID b f f 600 602	16 2868  0 on_ppath - - ));
+DATA(insert OID = 2867 (  "@"	   PGNSP PGUID b f f 600 602	16 2868  0 on_ppath - - "---"));
 DESCR("deprecated, use <@ instead");
-DATA(insert OID = 2868 (  "~"	   PGNSP PGUID b f f 602 600	 16  2867  0 path_contain_pt - - ));
+DATA(insert OID = 2868 (  "~"	   PGNSP PGUID b f f 602 600	 16  2867  0 path_contain_pt - - "---"));
 DESCR("deprecated, use @> instead");
-DATA(insert OID = 2869 (  "@"	   PGNSP PGUID b f f 600 604	 16  2870  0 pt_contained_poly - - ));
+DATA(insert OID = 2869 (  "@"	   PGNSP PGUID b f f 600 604	 16  2870  0 pt_contained_poly - - "---"));
 DESCR("deprecated, use <@ instead");
-DATA(insert OID = 2870 (  "~"	   PGNSP PGUID b f f 604 600	 16  2869  0 poly_contain_pt - - ));
+DATA(insert OID = 2870 (  "~"	   PGNSP PGUID b f f 604 600	 16  2869  0 poly_contain_pt - - "---"));
 DESCR("deprecated, use @> instead");
-DATA(insert OID = 2871 (  "@"	   PGNSP PGUID b f f 600 718	 16  2872  0 pt_contained_circle - - ));
+DATA(insert OID = 2871 (  "@"	   PGNSP PGUID b f f 600 718	 16  2872  0 pt_contained_circle - - "---"));
 DESCR("deprecated, use <@ instead");
-DATA(insert OID = 2872 (  "~"	   PGNSP PGUID b f f 718 600	 16  2871  0 circle_contain_pt - - ));
+DATA(insert OID = 2872 (  "~"	   PGNSP PGUID b f f 718 600	 16  2871  0 circle_contain_pt - - "---"));
 DESCR("deprecated, use @> instead");
-DATA(insert OID = 2873 (  "@"	   PGNSP PGUID b f f 600 628 16   0  0 on_pl - - ));
+DATA(insert OID = 2873 (  "@"	   PGNSP PGUID b f f 600 628 16   0  0 on_pl - - "---"));
 DESCR("deprecated, use <@ instead");
-DATA(insert OID = 2874 (  "@"	   PGNSP PGUID b f f 600 601 16   0  0 on_ps - - ));
+DATA(insert OID = 2874 (  "@"	   PGNSP PGUID b f f 600 601 16   0  0 on_ps - - "---"));
 DESCR("deprecated, use <@ instead");
-DATA(insert OID = 2875 (  "@"	   PGNSP PGUID b f f 601 628 16   0  0 on_sl - - ));
+DATA(insert OID = 2875 (  "@"	   PGNSP PGUID b f f 601 628 16   0  0 on_sl - - "---"));
 DESCR("deprecated, use <@ instead");
-DATA(insert OID = 2876 (  "@"	   PGNSP PGUID b f f 601 603 16   0  0 on_sb - - ));
+DATA(insert OID = 2876 (  "@"	   PGNSP PGUID b f f 601 603 16   0  0 on_sb - - "---"));
 DESCR("deprecated, use <@ instead");
-DATA(insert OID = 2877 (  "~"	   PGNSP PGUID b f f 1034 1033	 16 0 0 aclcontains - - ));
+DATA(insert OID = 2877 (  "~"	   PGNSP PGUID b f f 1034 1033	 16 0 0 aclcontains - - "---"));
 DESCR("deprecated, use @> instead");
 
 /* uuid operators */
-DATA(insert OID = 2972 (  "="	   PGNSP PGUID b t t 2950 2950 16 2972 2973 uuid_eq eqsel eqjoinsel ));
+DATA(insert OID = 2972 (  "="	   PGNSP PGUID b t t 2950 2950 16 2972 2973 uuid_eq eqsel eqjoinsel "mhf"));
 DESCR("equal");
-DATA(insert OID = 2973 (  "<>"	   PGNSP PGUID b f f 2950 2950 16 2973 2972 uuid_ne neqsel neqjoinsel ));
+DATA(insert OID = 2973 (  "<>"	   PGNSP PGUID b f f 2950 2950 16 2973 2972 uuid_ne neqsel neqjoinsel "mhf"));
 DESCR("not equal");
-DATA(insert OID = 2974 (  "<"	   PGNSP PGUID b f f 2950 2950 16 2975 2977 uuid_lt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 2974 (  "<"	   PGNSP PGUID b f f 2950 2950 16 2975 2977 uuid_lt scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than");
-DATA(insert OID = 2975 (  ">"	   PGNSP PGUID b f f 2950 2950 16 2974 2976 uuid_gt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 2975 (  ">"	   PGNSP PGUID b f f 2950 2950 16 2974 2976 uuid_gt scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than");
-DATA(insert OID = 2976 (  "<="	   PGNSP PGUID b f f 2950 2950 16 2977 2975 uuid_le scalarltsel scalarltjoinsel ));
+DATA(insert OID = 2976 (  "<="	   PGNSP PGUID b f f 2950 2950 16 2977 2975 uuid_le scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than or equal");
-DATA(insert OID = 2977 (  ">="	   PGNSP PGUID b f f 2950 2950 16 2976 2974 uuid_ge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 2977 (  ">="	   PGNSP PGUID b f f 2950 2950 16 2976 2974 uuid_ge scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than or equal");
 
 /* pg_lsn operators */
-DATA(insert OID = 3222 (  "="	   PGNSP PGUID b t t 3220 3220 16 3222 3223 pg_lsn_eq eqsel eqjoinsel ));
+DATA(insert OID = 3222 (  "="	   PGNSP PGUID b t t 3220 3220 16 3222 3223 pg_lsn_eq eqsel eqjoinsel "mhf"));
 DESCR("equal");
-DATA(insert OID = 3223 (  "<>"	   PGNSP PGUID b f f 3220 3220 16 3223 3222 pg_lsn_ne neqsel neqjoinsel ));
+DATA(insert OID = 3223 (  "<>"	   PGNSP PGUID b f f 3220 3220 16 3223 3222 pg_lsn_ne neqsel neqjoinsel "mhf"));
 DESCR("not equal");
-DATA(insert OID = 3224 (  "<"	   PGNSP PGUID b f f 3220 3220 16 3225 3227 pg_lsn_lt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 3224 (  "<"	   PGNSP PGUID b f f 3220 3220 16 3225 3227 pg_lsn_lt scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than");
-DATA(insert OID = 3225 (  ">"	   PGNSP PGUID b f f 3220 3220 16 3224 3226 pg_lsn_gt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 3225 (  ">"	   PGNSP PGUID b f f 3220 3220 16 3224 3226 pg_lsn_gt scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than");
-DATA(insert OID = 3226 (  "<="	   PGNSP PGUID b f f 3220 3220 16 3227 3225 pg_lsn_le scalarltsel scalarltjoinsel ));
+DATA(insert OID = 3226 (  "<="	   PGNSP PGUID b f f 3220 3220 16 3227 3225 pg_lsn_le scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than or equal");
-DATA(insert OID = 3227 (  ">="	   PGNSP PGUID b f f 3220 3220 16 3226 3224 pg_lsn_ge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 3227 (  ">="	   PGNSP PGUID b f f 3220 3220 16 3226 3224 pg_lsn_ge scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than or equal");
-DATA(insert OID = 3228 (  "-"	   PGNSP PGUID b f f 3220 3220 1700    0	0 pg_lsn_mi - - ));
+DATA(insert OID = 3228 (  "-"	   PGNSP PGUID b f f 3220 3220 1700    0	0 pg_lsn_mi - - "---"));
 DESCR("minus");
 
 /* enum operators */
-DATA(insert OID = 3516 (  "="	   PGNSP PGUID b t t 3500 3500 16 3516 3517 enum_eq eqsel eqjoinsel ));
+DATA(insert OID = 3516 (  "="	   PGNSP PGUID b t t 3500 3500 16 3516 3517 enum_eq eqsel eqjoinsel "mhf"));
 DESCR("equal");
-DATA(insert OID = 3517 (  "<>"	   PGNSP PGUID b f f 3500 3500 16 3517 3516 enum_ne neqsel neqjoinsel ));
+DATA(insert OID = 3517 (  "<>"	   PGNSP PGUID b f f 3500 3500 16 3517 3516 enum_ne neqsel neqjoinsel "mhf"));
 DESCR("not equal");
-DATA(insert OID = 3518 (  "<"	   PGNSP PGUID b f f 3500 3500 16 3519 3521 enum_lt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 3518 (  "<"	   PGNSP PGUID b f f 3500 3500 16 3519 3521 enum_lt scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than");
-DATA(insert OID = 3519 (  ">"	   PGNSP PGUID b f f 3500 3500 16 3518 3520 enum_gt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 3519 (  ">"	   PGNSP PGUID b f f 3500 3500 16 3518 3520 enum_gt scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than");
-DATA(insert OID = 3520 (  "<="	   PGNSP PGUID b f f 3500 3500 16 3521 3519 enum_le scalarltsel scalarltjoinsel ));
+DATA(insert OID = 3520 (  "<="	   PGNSP PGUID b f f 3500 3500 16 3521 3519 enum_le scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than or equal");
-DATA(insert OID = 3521 (  ">="	   PGNSP PGUID b f f 3500 3500 16 3520 3518 enum_ge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 3521 (  ">="	   PGNSP PGUID b f f 3500 3500 16 3520 3518 enum_ge scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than or equal");
 
 /*
  * tsearch operations
  */
-DATA(insert OID = 3627 (  "<"	   PGNSP PGUID b f f 3614	 3614	 16 3632 3631	 tsvector_lt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 3627 (  "<"	   PGNSP PGUID b f f 3614	 3614	 16 3632 3631	 tsvector_lt scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than");
-DATA(insert OID = 3628 (  "<="	   PGNSP PGUID b f f 3614	 3614	 16 3631 3632	 tsvector_le scalarltsel scalarltjoinsel ));
+DATA(insert OID = 3628 (  "<="	   PGNSP PGUID b f f 3614	 3614	 16 3631 3632	 tsvector_le scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than or equal");
-DATA(insert OID = 3629 (  "="	   PGNSP PGUID b t f 3614	 3614	 16 3629 3630	 tsvector_eq eqsel eqjoinsel ));
+DATA(insert OID = 3629 (  "="	   PGNSP PGUID b t f 3614	 3614	 16 3629 3630	 tsvector_eq eqsel eqjoinsel "mhf"));
 DESCR("equal");
-DATA(insert OID = 3630 (  "<>"	   PGNSP PGUID b f f 3614	 3614	 16 3630 3629	 tsvector_ne neqsel neqjoinsel ));
+DATA(insert OID = 3630 (  "<>"	   PGNSP PGUID b f f 3614	 3614	 16 3630 3629	 tsvector_ne neqsel neqjoinsel "mhf"));
 DESCR("not equal");
-DATA(insert OID = 3631 (  ">="	   PGNSP PGUID b f f 3614	 3614	 16 3628 3627	 tsvector_ge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 3631 (  ">="	   PGNSP PGUID b f f 3614	 3614	 16 3628 3627	 tsvector_ge scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than or equal");
-DATA(insert OID = 3632 (  ">"	   PGNSP PGUID b f f 3614	 3614	 16 3627 3628	 tsvector_gt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 3632 (  ">"	   PGNSP PGUID b f f 3614	 3614	 16 3627 3628	 tsvector_gt scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than");
-DATA(insert OID = 3633 (  "||"	   PGNSP PGUID b f f 3614	 3614	 3614  0	0	 tsvector_concat   -	-	  ));
+DATA(insert OID = 3633 (  "||"	   PGNSP PGUID b f f 3614	 3614	 3614  0	0	 tsvector_concat   -	-	  "---"));
 DESCR("concatenate");
-DATA(insert OID = 3636 (  "@@"	   PGNSP PGUID b f f 3614	 3615	 16 3637	0	 ts_match_vq   tsmatchsel tsmatchjoinsel ));
+DATA(insert OID = 3636 (  "@@"	   PGNSP PGUID b f f 3614	 3615	 16 3637	0	 ts_match_vq   tsmatchsel tsmatchjoinsel "---"));
 DESCR("text search match");
-DATA(insert OID = 3637 (  "@@"	   PGNSP PGUID b f f 3615	 3614	 16 3636	0	 ts_match_qv   tsmatchsel tsmatchjoinsel ));
+DATA(insert OID = 3637 (  "@@"	   PGNSP PGUID b f f 3615	 3614	 16 3636	0	 ts_match_qv   tsmatchsel tsmatchjoinsel "---"));
 DESCR("text search match");
-DATA(insert OID = 3660 (  "@@@"    PGNSP PGUID b f f 3614	 3615	 16 3661	0	 ts_match_vq   tsmatchsel tsmatchjoinsel ));
+DATA(insert OID = 3660 (  "@@@"    PGNSP PGUID b f f 3614	 3615	 16 3661	0	 ts_match_vq   tsmatchsel tsmatchjoinsel "---"));
 DESCR("deprecated, use @@ instead");
-DATA(insert OID = 3661 (  "@@@"    PGNSP PGUID b f f 3615	 3614	 16 3660	0	 ts_match_qv   tsmatchsel tsmatchjoinsel ));
+DATA(insert OID = 3661 (  "@@@"    PGNSP PGUID b f f 3615	 3614	 16 3660	0	 ts_match_qv   tsmatchsel tsmatchjoinsel "---"));
 DESCR("deprecated, use @@ instead");
-DATA(insert OID = 3674 (  "<"	   PGNSP PGUID b f f 3615	 3615	 16 3679 3678	 tsquery_lt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 3674 (  "<"	   PGNSP PGUID b f f 3615	 3615	 16 3679 3678	 tsquery_lt scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than");
-DATA(insert OID = 3675 (  "<="	   PGNSP PGUID b f f 3615	 3615	 16 3678 3679	 tsquery_le scalarltsel scalarltjoinsel ));
+DATA(insert OID = 3675 (  "<="	   PGNSP PGUID b f f 3615	 3615	 16 3678 3679	 tsquery_le scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than or equal");
-DATA(insert OID = 3676 (  "="	   PGNSP PGUID b t f 3615	 3615	 16 3676 3677	 tsquery_eq eqsel eqjoinsel ));
+DATA(insert OID = 3676 (  "="	   PGNSP PGUID b t f 3615	 3615	 16 3676 3677	 tsquery_eq eqsel eqjoinsel "mhf"));
 DESCR("equal");
-DATA(insert OID = 3677 (  "<>"	   PGNSP PGUID b f f 3615	 3615	 16 3677 3676	 tsquery_ne neqsel neqjoinsel ));
+DATA(insert OID = 3677 (  "<>"	   PGNSP PGUID b f f 3615	 3615	 16 3677 3676	 tsquery_ne neqsel neqjoinsel "mhf"));
 DESCR("not equal");
-DATA(insert OID = 3678 (  ">="	   PGNSP PGUID b f f 3615	 3615	 16 3675 3674	 tsquery_ge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 3678 (  ">="	   PGNSP PGUID b f f 3615	 3615	 16 3675 3674	 tsquery_ge scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than or equal");
-DATA(insert OID = 3679 (  ">"	   PGNSP PGUID b f f 3615	 3615	 16 3674 3675	 tsquery_gt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 3679 (  ">"	   PGNSP PGUID b f f 3615	 3615	 16 3674 3675	 tsquery_gt scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than");
-DATA(insert OID = 3680 (  "&&"	   PGNSP PGUID b f f 3615	 3615	 3615  0	0	 tsquery_and   -	-	  ));
+DATA(insert OID = 3680 (  "&&"	   PGNSP PGUID b f f 3615	 3615	 3615  0	0	 tsquery_and   -	-	  "---"));
 DESCR("AND-concatenate");
-DATA(insert OID = 3681 (  "||"	   PGNSP PGUID b f f 3615	 3615	 3615  0	0	 tsquery_or   -		-	  ));
+DATA(insert OID = 3681 (  "||"	   PGNSP PGUID b f f 3615	 3615	 3615  0	0	 tsquery_or   -		-	  "---"));
 DESCR("OR-concatenate");
-DATA(insert OID = 3682 (  "!!"	   PGNSP PGUID l f f 0		 3615	 3615  0	0	 tsquery_not   -	-	  ));
+DATA(insert OID = 3682 (  "!!"	   PGNSP PGUID l f f 0		 3615	 3615  0	0	 tsquery_not   -	-	  "---"));
 DESCR("NOT tsquery");
-DATA(insert OID = 3693 (  "@>"	   PGNSP PGUID b f f 3615	 3615	 16 3694	0	 tsq_mcontains	contsel    contjoinsel	 ));
+DATA(insert OID = 3693 (  "@>"	   PGNSP PGUID b f f 3615	 3615	 16 3694	0	 tsq_mcontains	contsel    contjoinsel	 "---"));
 DESCR("contains");
-DATA(insert OID = 3694 (  "<@"	   PGNSP PGUID b f f 3615	 3615	 16 3693	0	 tsq_mcontained contsel    contjoinsel	 ));
+DATA(insert OID = 3694 (  "<@"	   PGNSP PGUID b f f 3615	 3615	 16 3693	0	 tsq_mcontained contsel    contjoinsel	 "---"));
 DESCR("is contained by");
-DATA(insert OID = 3762 (  "@@"	   PGNSP PGUID b f f 25		 25		 16    0	0	 ts_match_tt	contsel    contjoinsel	 ));
+DATA(insert OID = 3762 (  "@@"	   PGNSP PGUID b f f 25		 25		 16    0	0	 ts_match_tt	contsel    contjoinsel	 "---"));
 DESCR("text search match");
-DATA(insert OID = 3763 (  "@@"	   PGNSP PGUID b f f 25		 3615	 16    0	0	 ts_match_tq	contsel    contjoinsel	 ));
+DATA(insert OID = 3763 (  "@@"	   PGNSP PGUID b f f 25		 3615	 16    0	0	 ts_match_tq	contsel    contjoinsel	 "---"));
 DESCR("text search match");
 
 /* generic record comparison operators */
-DATA(insert OID = 2988 (  "="	   PGNSP PGUID b t f 2249 2249 16 2988 2989 record_eq eqsel eqjoinsel ));
+DATA(insert OID = 2988 (  "="	   PGNSP PGUID b t f 2249 2249 16 2988 2989 record_eq eqsel eqjoinsel "mhf"));
 DESCR("equal");
 #define RECORD_EQ_OP 2988
-DATA(insert OID = 2989 (  "<>"	   PGNSP PGUID b f f 2249 2249 16 2989 2988 record_ne neqsel neqjoinsel ));
+DATA(insert OID = 2989 (  "<>"	   PGNSP PGUID b f f 2249 2249 16 2989 2988 record_ne neqsel neqjoinsel "mhf"));
 DESCR("not equal");
-DATA(insert OID = 2990 (  "<"	   PGNSP PGUID b f f 2249 2249 16 2991 2993 record_lt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 2990 (  "<"	   PGNSP PGUID b f f 2249 2249 16 2991 2993 record_lt scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than");
 #define RECORD_LT_OP 2990
-DATA(insert OID = 2991 (  ">"	   PGNSP PGUID b f f 2249 2249 16 2990 2992 record_gt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 2991 (  ">"	   PGNSP PGUID b f f 2249 2249 16 2990 2992 record_gt scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than");
 #define RECORD_GT_OP 2991
-DATA(insert OID = 2992 (  "<="	   PGNSP PGUID b f f 2249 2249 16 2993 2991 record_le scalarltsel scalarltjoinsel ));
+DATA(insert OID = 2992 (  "<="	   PGNSP PGUID b f f 2249 2249 16 2993 2991 record_le scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than or equal");
-DATA(insert OID = 2993 (  ">="	   PGNSP PGUID b f f 2249 2249 16 2992 2990 record_ge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 2993 (  ">="	   PGNSP PGUID b f f 2249 2249 16 2992 2990 record_ge scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than or equal");
 
 /* byte-oriented tests for identical rows and fast sorting */
-DATA(insert OID = 3188 (  "*="	   PGNSP PGUID b t f 2249 2249 16 3188 3189 record_image_eq eqsel eqjoinsel ));
+DATA(insert OID = 3188 (  "*="	   PGNSP PGUID b t f 2249 2249 16 3188 3189 record_image_eq eqsel eqjoinsel "mhf"));
 DESCR("identical");
-DATA(insert OID = 3189 (  "*<>"   PGNSP PGUID b f f 2249 2249 16 3189 3188 record_image_ne neqsel neqjoinsel ));
+DATA(insert OID = 3189 (  "*<>"   PGNSP PGUID b f f 2249 2249 16 3189 3188 record_image_ne neqsel neqjoinsel "mhf"));
 DESCR("not identical");
-DATA(insert OID = 3190 (  "*<"	   PGNSP PGUID b f f 2249 2249 16 3191 3193 record_image_lt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 3190 (  "*<"	   PGNSP PGUID b f f 2249 2249 16 3191 3193 record_image_lt scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than");
-DATA(insert OID = 3191 (  "*>"	   PGNSP PGUID b f f 2249 2249 16 3190 3192 record_image_gt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 3191 (  "*>"	   PGNSP PGUID b f f 2249 2249 16 3190 3192 record_image_gt scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than");
-DATA(insert OID = 3192 (  "*<="   PGNSP PGUID b f f 2249 2249 16 3193 3191 record_image_le scalarltsel scalarltjoinsel ));
+DATA(insert OID = 3192 (  "*<="   PGNSP PGUID b f f 2249 2249 16 3193 3191 record_image_le scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than or equal");
-DATA(insert OID = 3193 (  "*>="   PGNSP PGUID b f f 2249 2249 16 3192 3190 record_image_ge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 3193 (  "*>="   PGNSP PGUID b f f 2249 2249 16 3192 3190 record_image_ge scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than or equal");
 
 /* generic range type operators */
-DATA(insert OID = 3882 (  "="	   PGNSP PGUID b t t 3831 3831 16 3882 3883 range_eq eqsel eqjoinsel ));
+DATA(insert OID = 3882 (  "="	   PGNSP PGUID b t t 3831 3831 16 3882 3883 range_eq eqsel eqjoinsel "mhf"));
 DESCR("equal");
-DATA(insert OID = 3883 (  "<>"	   PGNSP PGUID b f f 3831 3831 16 3883 3882 range_ne neqsel neqjoinsel ));
+DATA(insert OID = 3883 (  "<>"	   PGNSP PGUID b f f 3831 3831 16 3883 3882 range_ne neqsel neqjoinsel "mhf"));
 DESCR("not equal");
-DATA(insert OID = 3884 (  "<"	   PGNSP PGUID b f f 3831 3831 16 3887 3886 range_lt rangesel scalarltjoinsel ));
+DATA(insert OID = 3884 (  "<"	   PGNSP PGUID b f f 3831 3831 16 3887 3886 range_lt rangesel scalarltjoinsel "---"));
 DESCR("less than");
 #define OID_RANGE_LESS_OP 3884
-DATA(insert OID = 3885 (  "<="	   PGNSP PGUID b f f 3831 3831 16 3886 3887 range_le rangesel scalarltjoinsel ));
+DATA(insert OID = 3885 (  "<="	   PGNSP PGUID b f f 3831 3831 16 3886 3887 range_le rangesel scalarltjoinsel "---"));
 DESCR("less than or equal");
 #define OID_RANGE_LESS_EQUAL_OP 3885
-DATA(insert OID = 3886 (  ">="	   PGNSP PGUID b f f 3831 3831 16 3885 3884 range_ge rangesel scalargtjoinsel ));
+DATA(insert OID = 3886 (  ">="	   PGNSP PGUID b f f 3831 3831 16 3885 3884 range_ge rangesel scalargtjoinsel "---"));
 DESCR("greater than or equal");
 #define OID_RANGE_GREATER_EQUAL_OP 3886
-DATA(insert OID = 3887 (  ">"	   PGNSP PGUID b f f 3831 3831 16 3884 3885 range_gt rangesel scalargtjoinsel ));
+DATA(insert OID = 3887 (  ">"	   PGNSP PGUID b f f 3831 3831 16 3884 3885 range_gt rangesel scalargtjoinsel "---"));
 DESCR("greater than");
 #define OID_RANGE_GREATER_OP 3887
-DATA(insert OID = 3888 (  "&&"	   PGNSP PGUID b f f 3831 3831 16 3888 0 range_overlaps rangesel areajoinsel ));
+DATA(insert OID = 3888 (  "&&"	   PGNSP PGUID b f f 3831 3831 16 3888 0 range_overlaps rangesel areajoinsel "---"));
 DESCR("overlaps");
 #define OID_RANGE_OVERLAP_OP 3888
-DATA(insert OID = 3889 (  "@>"	   PGNSP PGUID b f f 3831 2283 16 3891 0 range_contains_elem rangesel contjoinsel ));
+DATA(insert OID = 3889 (  "@>"	   PGNSP PGUID b f f 3831 2283 16 3891 0 range_contains_elem rangesel contjoinsel "---"));
 DESCR("contains");
 #define OID_RANGE_CONTAINS_ELEM_OP 3889
-DATA(insert OID = 3890 (  "@>"	   PGNSP PGUID b f f 3831 3831 16 3892 0 range_contains rangesel contjoinsel ));
+DATA(insert OID = 3890 (  "@>"	   PGNSP PGUID b f f 3831 3831 16 3892 0 range_contains rangesel contjoinsel "---"));
 DESCR("contains");
 #define OID_RANGE_CONTAINS_OP 3890
-DATA(insert OID = 3891 (  "<@"	   PGNSP PGUID b f f 2283 3831 16 3889 0 elem_contained_by_range rangesel contjoinsel ));
+DATA(insert OID = 3891 (  "<@"	   PGNSP PGUID b f f 2283 3831 16 3889 0 elem_contained_by_range rangesel contjoinsel "---"));
 DESCR("is contained by");
 #define OID_RANGE_ELEM_CONTAINED_OP 3891
-DATA(insert OID = 3892 (  "<@"	   PGNSP PGUID b f f 3831 3831 16 3890 0 range_contained_by rangesel contjoinsel ));
+DATA(insert OID = 3892 (  "<@"	   PGNSP PGUID b f f 3831 3831 16 3890 0 range_contained_by rangesel contjoinsel "---"));
 DESCR("is contained by");
 #define OID_RANGE_CONTAINED_OP 3892
-DATA(insert OID = 3893 (  "<<"	   PGNSP PGUID b f f 3831 3831 16 3894 0 range_before rangesel scalarltjoinsel ));
+DATA(insert OID = 3893 (  "<<"	   PGNSP PGUID b f f 3831 3831 16 3894 0 range_before rangesel scalarltjoinsel "---"));
 DESCR("is left of");
 #define OID_RANGE_LEFT_OP 3893
-DATA(insert OID = 3894 (  ">>"	   PGNSP PGUID b f f 3831 3831 16 3893 0 range_after rangesel scalargtjoinsel ));
+DATA(insert OID = 3894 (  ">>"	   PGNSP PGUID b f f 3831 3831 16 3893 0 range_after rangesel scalargtjoinsel "---"));
 DESCR("is right of");
 #define OID_RANGE_RIGHT_OP 3894
-DATA(insert OID = 3895 (  "&<"	   PGNSP PGUID b f f 3831 3831 16 0 0 range_overleft rangesel scalarltjoinsel ));
+DATA(insert OID = 3895 (  "&<"	   PGNSP PGUID b f f 3831 3831 16 0 0 range_overleft rangesel scalarltjoinsel "---"));
 DESCR("overlaps or is left of");
 #define OID_RANGE_OVERLAPS_LEFT_OP 3895
-DATA(insert OID = 3896 (  "&>"	   PGNSP PGUID b f f 3831 3831 16 0 0 range_overright rangesel scalargtjoinsel ));
+DATA(insert OID = 3896 (  "&>"	   PGNSP PGUID b f f 3831 3831 16 0 0 range_overright rangesel scalargtjoinsel "---"));
 DESCR("overlaps or is right of");
 #define OID_RANGE_OVERLAPS_RIGHT_OP 3896
-DATA(insert OID = 3897 (  "-|-"    PGNSP PGUID b f f 3831 3831 16 3897 0 range_adjacent contsel contjoinsel ));
+DATA(insert OID = 3897 (  "-|-"    PGNSP PGUID b f f 3831 3831 16 3897 0 range_adjacent contsel contjoinsel "---"));
 DESCR("is adjacent to");
-DATA(insert OID = 3898 (  "+"	   PGNSP PGUID b f f 3831 3831 3831 3898 0 range_union - - ));
+DATA(insert OID = 3898 (  "+"	   PGNSP PGUID b f f 3831 3831 3831 3898 0 range_union - - "---"));
 DESCR("range union");
-DATA(insert OID = 3899 (  "-"	   PGNSP PGUID b f f 3831 3831 3831 0 0 range_minus - - ));
+DATA(insert OID = 3899 (  "-"	   PGNSP PGUID b f f 3831 3831 3831 0 0 range_minus - - "---"));
 DESCR("range difference");
-DATA(insert OID = 3900 (  "*"	   PGNSP PGUID b f f 3831 3831 3831 3900 0 range_intersect - - ));
+DATA(insert OID = 3900 (  "*"	   PGNSP PGUID b f f 3831 3831 3831 3900 0 range_intersect - - "---"));
 DESCR("range intersection");
-DATA(insert OID = 3962 (  "->"	   PGNSP PGUID b f f 114 25 114 0 0 json_object_field - - ));
+DATA(insert OID = 3962 (  "->"	   PGNSP PGUID b f f 114 25 114 0 0 json_object_field - - "---"));
 DESCR("get json object field");
-DATA(insert OID = 3963 (  "->>"    PGNSP PGUID b f f 114 25 25 0 0 json_object_field_text - - ));
+DATA(insert OID = 3963 (  "->>"    PGNSP PGUID b f f 114 25 25 0 0 json_object_field_text - - "---"));
 DESCR("get json object field as text");
-DATA(insert OID = 3964 (  "->"	   PGNSP PGUID b f f 114 23 114 0 0 json_array_element - - ));
+DATA(insert OID = 3964 (  "->"	   PGNSP PGUID b f f 114 23 114 0 0 json_array_element - - "---"));
 DESCR("get json array element");
-DATA(insert OID = 3965 (  "->>"    PGNSP PGUID b f f 114 23 25 0 0 json_array_element_text - - ));
+DATA(insert OID = 3965 (  "->>"    PGNSP PGUID b f f 114 23 25 0 0 json_array_element_text - - "---"));
 DESCR("get json array element as text");
-DATA(insert OID = 3966 (  "#>"	   PGNSP PGUID b f f 114 1009 114 0 0 json_extract_path - - ));
+DATA(insert OID = 3966 (  "#>"	   PGNSP PGUID b f f 114 1009 114 0 0 json_extract_path - - "---"));
 DESCR("get value from json with path elements");
-DATA(insert OID = 3967 (  "#>>"    PGNSP PGUID b f f 114 1009 25 0 0 json_extract_path_text - - ));
+DATA(insert OID = 3967 (  "#>>"    PGNSP PGUID b f f 114 1009 25 0 0 json_extract_path_text - - "---"));
 DESCR("get value from json as text with path elements");
-DATA(insert OID = 3211 (  "->"	   PGNSP PGUID b f f 3802 25 3802 0 0 jsonb_object_field - - ));
+DATA(insert OID = 3211 (  "->"	   PGNSP PGUID b f f 3802 25 3802 0 0 jsonb_object_field - - "---"));
 DESCR("get jsonb object field");
-DATA(insert OID = 3477 (  "->>"    PGNSP PGUID b f f 3802 25 25 0 0 jsonb_object_field_text - - ));
+DATA(insert OID = 3477 (  "->>"    PGNSP PGUID b f f 3802 25 25 0 0 jsonb_object_field_text - - "---"));
 DESCR("get jsonb object field as text");
-DATA(insert OID = 3212 (  "->"	   PGNSP PGUID b f f 3802 23 3802 0 0 jsonb_array_element - - ));
+DATA(insert OID = 3212 (  "->"	   PGNSP PGUID b f f 3802 23 3802 0 0 jsonb_array_element - - "---"));
 DESCR("get jsonb array element");
-DATA(insert OID = 3481 (  "->>"    PGNSP PGUID b f f 3802 23 25 0 0 jsonb_array_element_text - - ));
+DATA(insert OID = 3481 (  "->>"    PGNSP PGUID b f f 3802 23 25 0 0 jsonb_array_element_text - - "---"));
 DESCR("get jsonb array element as text");
-DATA(insert OID = 3213 (  "#>"	   PGNSP PGUID b f f 3802 1009 3802 0 0 jsonb_extract_path - - ));
+DATA(insert OID = 3213 (  "#>"	   PGNSP PGUID b f f 3802 1009 3802 0 0 jsonb_extract_path - - "---"));
 DESCR("get value from jsonb with path elements");
-DATA(insert OID = 3206 (  "#>>"    PGNSP PGUID b f f 3802 1009 25 0 0 jsonb_extract_path_text - - ));
+DATA(insert OID = 3206 (  "#>>"    PGNSP PGUID b f f 3802 1009 25 0 0 jsonb_extract_path_text - - "---"));
 DESCR("get value from jsonb as text with path elements");
-DATA(insert OID = 3240 (  "="	 PGNSP PGUID b t t 3802 3802  16 3240 3241 jsonb_eq eqsel eqjoinsel ));
+DATA(insert OID = 3240 (  "="	 PGNSP PGUID b t t 3802 3802  16 3240 3241 jsonb_eq eqsel eqjoinsel "mhf"));
 DESCR("equal");
-DATA(insert OID = 3241 (  "<>"	 PGNSP PGUID b f f 3802 3802  16 3241 3240 jsonb_ne neqsel neqjoinsel ));
+DATA(insert OID = 3241 (  "<>"	 PGNSP PGUID b f f 3802 3802  16 3241 3240 jsonb_ne neqsel neqjoinsel "mhf"));
 DESCR("not equal");
-DATA(insert OID = 3242 (  "<"		PGNSP PGUID b f f 3802 3802 16 3243 3245 jsonb_lt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 3242 (  "<"		PGNSP PGUID b f f 3802 3802 16 3243 3245 jsonb_lt scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than");
-DATA(insert OID = 3243 (  ">"		PGNSP PGUID b f f 3802 3802 16 3242 3244 jsonb_gt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 3243 (  ">"		PGNSP PGUID b f f 3802 3802 16 3242 3244 jsonb_gt scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than");
-DATA(insert OID = 3244 (  "<="	PGNSP PGUID b f f 3802 3802 16 3245 3243 jsonb_le scalarltsel scalarltjoinsel ));
+DATA(insert OID = 3244 (  "<="	PGNSP PGUID b f f 3802 3802 16 3245 3243 jsonb_le scalarltsel scalarltjoinsel "mh-"));
 DESCR("less than or equal");
-DATA(insert OID = 3245 (  ">="	PGNSP PGUID b f f 3802 3802 16 3244 3242 jsonb_ge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 3245 (  ">="	PGNSP PGUID b f f 3802 3802 16 3244 3242 jsonb_ge scalargtsel scalargtjoinsel "mh-"));
 DESCR("greater than or equal");
-DATA(insert OID = 3246 (  "@>"	   PGNSP PGUID b f f 3802 3802 16 3250 0 jsonb_contains contsel contjoinsel ));
+DATA(insert OID = 3246 (  "@>"	   PGNSP PGUID b f f 3802 3802 16 3250 0 jsonb_contains contsel contjoinsel "---"));
 DESCR("contains");
-DATA(insert OID = 3247 (  "?"	   PGNSP PGUID b f f 3802 25 16 0 0 jsonb_exists contsel contjoinsel ));
+DATA(insert OID = 3247 (  "?"	   PGNSP PGUID b f f 3802 25 16 0 0 jsonb_exists contsel contjoinsel "---"));
 DESCR("exists");
-DATA(insert OID = 3248 (  "?|"	   PGNSP PGUID b f f 3802 1009 16 0 0 jsonb_exists_any contsel contjoinsel ));
+DATA(insert OID = 3248 (  "?|"	   PGNSP PGUID b f f 3802 1009 16 0 0 jsonb_exists_any contsel contjoinsel "---"));
 DESCR("exists any");
-DATA(insert OID = 3249 (  "?&"	   PGNSP PGUID b f f 3802 1009 16 0 0 jsonb_exists_all contsel contjoinsel ));
+DATA(insert OID = 3249 (  "?&"	   PGNSP PGUID b f f 3802 1009 16 0 0 jsonb_exists_all contsel contjoinsel "---"));
 DESCR("exists all");
-DATA(insert OID = 3250 (  "<@"	   PGNSP PGUID b f f 3802 3802 16 3246 0 jsonb_contained contsel contjoinsel ));
+DATA(insert OID = 3250 (  "<@"	   PGNSP PGUID b f f 3802 3802 16 3246 0 jsonb_contained contsel contjoinsel "---"));
 DESCR("is contained by");
-DATA(insert OID = 3284 (  "||"	   PGNSP PGUID b f f 3802 3802 3802 0 0 jsonb_concat - - ));
+DATA(insert OID = 3284 (  "||"	   PGNSP PGUID b f f 3802 3802 3802 0 0 jsonb_concat - - "---"));
 DESCR("concatenate");
-DATA(insert OID = 3285 (  "-"	   PGNSP PGUID b f f 3802 25 3802 0 0 3302 - - ));
+DATA(insert OID = 3285 (  "-"	   PGNSP PGUID b f f 3802 25 3802 0 0 3302 - - "---"));
 DESCR("delete object field");
-DATA(insert OID = 3286 (  "-"	   PGNSP PGUID b f f 3802 23 3802 0 0 3303 - - ));
+DATA(insert OID = 3286 (  "-"	   PGNSP PGUID b f f 3802 23 3802 0 0 3303 - - "---"));
 DESCR("delete array element");
-DATA(insert OID = 3287 (  "#-"	   PGNSP PGUID b f f 3802 1009 3802 0 0 jsonb_delete_path - - ));
+DATA(insert OID = 3287 (  "#-"	   PGNSP PGUID b f f 3802 1009 3802 0 0 jsonb_delete_path - - "---"));
 DESCR("delete path");
 
 /*
diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h
index 9254f85..9865a9c 100644
--- a/src/include/nodes/nodes.h
+++ b/src/include/nodes/nodes.h
@@ -250,6 +250,7 @@ typedef enum NodeTag
 	T_MinMaxAggInfo,
 	T_PlannerParamItem,
 	T_MVStatisticInfo,
+	T_RestrictStatData,
 
 	/*
 	 * TAGS FOR MEMORY NODES (memnodes.h)
diff --git a/src/include/nodes/relation.h b/src/include/nodes/relation.h
index 1979cdf..b78ee5d 100644
--- a/src/include/nodes/relation.h
+++ b/src/include/nodes/relation.h
@@ -15,12 +15,12 @@
 #define RELATION_H
 
 #include "access/sdir.h"
+#include "access/htup.h"
 #include "lib/stringinfo.h"
 #include "nodes/params.h"
 #include "nodes/parsenodes.h"
 #include "storage/block.h"
 
-
 /*
  * Relids
  *		Set of relation identifiers (indexes into the rangetable).
@@ -1341,6 +1341,26 @@ typedef struct RestrictInfo
 	Selectivity right_bucketsize;		/* avg bucketsize of right side */
 } RestrictInfo;
 
+typedef struct bm_mvstat
+{
+	Bitmapset *attrs;
+	MVStatisticInfo *stats;
+	int			mvkind;
+} bm_mvstat;
+
+typedef struct RestrictStatData
+{
+	NodeTag			type;
+	BoolExprType	 boolop;
+	Node			*clause;
+	Node			*mvclause;
+	Node			*nonmvclause;
+	List			*children;
+	List			*mvstats;
+	Bitmapset		*mvattrs;
+	List			*unusedrinfos;
+} RestrictStatData;
+
 /*
  * Since mergejoinscansel() is a relatively expensive function, and would
  * otherwise be invoked many times while planning a large join tree,
diff --git a/src/include/optimizer/cost.h b/src/include/optimizer/cost.h
index 6bfd338..24003ae 100644
--- a/src/include/optimizer/cost.h
+++ b/src/include/optimizer/cost.h
@@ -183,13 +183,11 @@ extern Selectivity clauselist_selectivity(PlannerInfo *root,
 					   List *clauses,
 					   int varRelid,
 					   JoinType jointype,
-					   SpecialJoinInfo *sjinfo,
-					   List *conditions);
+					   SpecialJoinInfo *sjinfo);
 extern Selectivity clause_selectivity(PlannerInfo *root,
 				   Node *clause,
 				   int varRelid,
 				   JoinType jointype,
-				   SpecialJoinInfo *sjinfo,
-				   List *conditions);
+				   SpecialJoinInfo *sjinfo);
 
 #endif   /* COST_H */
diff --git a/src/include/utils/lsyscache.h b/src/include/utils/lsyscache.h
index a40c9b1..bb9d68b 100644
--- a/src/include/utils/lsyscache.h
+++ b/src/include/utils/lsyscache.h
@@ -84,6 +84,7 @@ extern Oid	get_commutator(Oid opno);
 extern Oid	get_negator(Oid opno);
 extern RegProcedure get_oprrest(Oid opno);
 extern RegProcedure get_oprjoin(Oid opno);
+extern int get_oprmvstat(Oid opno);
 extern char *get_func_name(Oid funcid);
 extern Oid	get_func_namespace(Oid funcid);
 extern Oid	get_func_rettype(Oid funcid);
diff --git a/src/include/utils/mvstats.h b/src/include/utils/mvstats.h
index f2fbc11..a08fd58 100644
--- a/src/include/utils/mvstats.h
+++ b/src/include/utils/mvstats.h
@@ -34,6 +34,9 @@ extern int mvstat_search_type;
 
 #define MVSTATS_MAX_DIMENSIONS	8		/* max number of attributes */
 
+#define MVSTATISTIC_MCV  1
+#define MVSTATISTIC_HIST 2
+#define MVSTATISTIC_FDEP 4
 
 /*
  * Functional dependencies, tracking column-level relationships (values
-- 
1.8.3.1

