From fa6c6c40c253e18bc7e03c78ed4d85ec6f83b701 Mon Sep 17 00:00:00 2001
From: Emre Hasegeli <emre@hasegeli.com>
Date: Sun, 22 Mar 2015 17:41:26 +0100
Subject: [PATCH 5/7] box vs point operators

---
 src/backend/utils/adt/geo_ops.c          | 115 ++++++++++++++++++++++++++++---
 src/bin/initdb/initdb.c                  |   1 +
 src/include/catalog/pg_operator.h        |  20 ++++++
 src/include/catalog/pg_proc.h            |   8 +++
 src/include/utils/geo_decls.h            |   8 +++
 src/test/regress/expected/opr_sanity.out |   4 +-
 src/test/regress/sql/opr_sanity.sql      |   4 +-
 7 files changed, 148 insertions(+), 12 deletions(-)

diff --git a/src/backend/utils/adt/geo_ops.c b/src/backend/utils/adt/geo_ops.c
index 39a7855..382d925 100644
--- a/src/backend/utils/adt/geo_ops.c
+++ b/src/backend/utils/adt/geo_ops.c
@@ -767,20 +767,125 @@ Datum
 box_ge(PG_FUNCTION_ARGS)
 {
 	BOX		   *box1 = PG_GETARG_BOX_P(0);
 	BOX		   *box2 = PG_GETARG_BOX_P(1);
 
 	PG_RETURN_BOOL(FPge(box_ar(box1), box_ar(box2)));
 }
 
 
 /*----------------------------------------------------------
+ *	Relational operators for BOX vs Point
+ *---------------------------------------------------------*/
+
+/*		box_left_pt		-		is box strictly left of point?
+ */
+Datum
+box_left_pt(PG_FUNCTION_ARGS)
+{
+	BOX		   *box = PG_GETARG_BOX_P(0);
+	Point	   *pt = PG_GETARG_POINT_P(1);
+
+	PG_RETURN_BOOL(box->high.x < pt->x);
+}
+
+/*		box_overleft_pt	-		is the right edge of box at or left of point?
+ */
+Datum
+box_overleft_pt(PG_FUNCTION_ARGS)
+{
+	BOX		   *box = PG_GETARG_BOX_P(0);
+	Point	   *pt = PG_GETARG_POINT_P(1);
+
+	PG_RETURN_BOOL(box->low.x <= pt->x);
+}
+
+/*		box_right_pt	-		is box strictly right of point?
+ */
+Datum
+box_right_pt(PG_FUNCTION_ARGS)
+{
+	BOX		   *box = PG_GETARG_BOX_P(0);
+	Point	   *pt = PG_GETARG_POINT_P(1);
+
+	PG_RETURN_BOOL(box->low.x > pt->x);
+}
+
+/*		box_overright_pt -		is the left edge of box at or right of point?
+ */
+Datum
+box_overright_pt(PG_FUNCTION_ARGS)
+{
+	BOX		   *box = PG_GETARG_BOX_P(0);
+	Point	   *pt = PG_GETARG_POINT_P(1);
+
+	PG_RETURN_BOOL(box->high.x >= pt->x);
+}
+
+/*		box_below_pt	-		is box strictly below point?
+ */
+Datum
+box_below_pt(PG_FUNCTION_ARGS)
+{
+	BOX		   *box = PG_GETARG_BOX_P(0);
+	Point	   *pt = PG_GETARG_POINT_P(1);
+
+	PG_RETURN_BOOL(box->high.y < pt->y);
+}
+
+/*		box_overbelow_pt -		is the upper edge of box at or below point?
+ */
+Datum
+box_overbelow_pt(PG_FUNCTION_ARGS)
+{
+	BOX		   *box = PG_GETARG_BOX_P(0);
+	Point	   *pt = PG_GETARG_POINT_P(1);
+
+	PG_RETURN_BOOL(box->low.y <= pt->y);
+}
+
+/*		box_above_pt	-		is box strictly above point?
+ */
+Datum
+box_above_pt(PG_FUNCTION_ARGS)
+{
+	BOX		   *box = PG_GETARG_BOX_P(0);
+	Point	   *pt = PG_GETARG_POINT_P(1);
+
+	PG_RETURN_BOOL(box->low.y > pt->y);
+}
+
+/*		box_overabove_pt -		is the lower edge of box at or above point?
+ */
+Datum
+box_overabove_pt(PG_FUNCTION_ARGS)
+{
+	BOX		   *box = PG_GETARG_BOX_P(0);
+	Point	   *pt = PG_GETARG_POINT_P(1);
+
+	PG_RETURN_BOOL(box->high.y >= pt->y);
+}
+
+/*		box_contain_pt	-		does box contain point?
+ */
+Datum
+box_contain_pt(PG_FUNCTION_ARGS)
+{
+	BOX		   *box = PG_GETARG_BOX_P(0);
+	Point	   *pt = PG_GETARG_POINT_P(1);
+
+	PG_RETURN_BOOL(pt->x <= box->high.x && pt->x >= box->low.x &&
+				   pt->y <= box->high.y && pt->y >= box->low.y);
+}
+
+
+/*----------------------------------------------------------
  *	"Arithmetic" operators on boxes.
  *---------------------------------------------------------*/
 
 /*		box_area		-		returns the area of the box.
  */
 Datum
 box_area(PG_FUNCTION_ARGS)
 {
 	BOX		   *box = PG_GETARG_BOX_P(0);
 
@@ -3205,30 +3310,20 @@ on_ps_internal(Point *pt, LSEG *lseg)
 Datum
 on_pb(PG_FUNCTION_ARGS)
 {
 	Point	   *pt = PG_GETARG_POINT_P(0);
 	BOX		   *box = PG_GETARG_BOX_P(1);
 
 	PG_RETURN_BOOL(pt->x <= box->high.x && pt->x >= box->low.x &&
 				   pt->y <= box->high.y && pt->y >= box->low.y);
 }
 
-Datum
-box_contain_pt(PG_FUNCTION_ARGS)
-{
-	BOX		   *box = PG_GETARG_BOX_P(0);
-	Point	   *pt = PG_GETARG_POINT_P(1);
-
-	PG_RETURN_BOOL(pt->x <= box->high.x && pt->x >= box->low.x &&
-				   pt->y <= box->high.y && pt->y >= box->low.y);
-}
-
 /* on_ppath -
  *		Whether a point lies within (on) a polyline.
  *		If open, we have to (groan) check each segment.
  * (uses same algorithm as for point intersecting segment - tgl 1997-07-09)
  *		If closed, we use the old O(n) ray method for point-in-polygon.
  *				The ray is horizontal, from pt out to the right.
  *				Each segment that crosses the ray counts as an
  *				intersection; note that an endpoint or edge may touch
  *				but not cross.
  *				(we can do p-in-p in lg(n), but it takes preprocessing)
diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c
index 8694920..e60528e 100644
--- a/src/bin/initdb/initdb.c
+++ b/src/bin/initdb/initdb.c
@@ -1875,20 +1875,21 @@ setup_description(void)
 	/* Create default descriptions for operator implementation functions */
 	PG_CMD_PUTS("WITH funcdescs AS ( "
 				"SELECT p.oid as p_oid, oprname, "
 			  "coalesce(obj_description(o.oid, 'pg_operator'),'') as opdesc "
 				"FROM pg_proc p JOIN pg_operator o ON oprcode = p.oid ) "
 				"INSERT INTO pg_description "
 				"  SELECT p_oid, 'pg_proc'::regclass, 0, "
 				"    'implementation of ' || oprname || ' operator' "
 				"  FROM funcdescs "
 				"  WHERE opdesc NOT LIKE 'deprecated%' AND "
+				"  opdesc NOT LIKE 'same as %' AND "
 				"  NOT EXISTS (SELECT 1 FROM pg_description "
 		  "    WHERE objoid = p_oid AND classoid = 'pg_proc'::regclass);\n");
 
 	PG_CMD_CLOSE;
 
 	check_ok();
 }
 
 #ifdef HAVE_LOCALE_T
 /*
diff --git a/src/include/catalog/pg_operator.h b/src/include/catalog/pg_operator.h
index e22eb27..2984242 100644
--- a/src/include/catalog/pg_operator.h
+++ b/src/include/catalog/pg_operator.h
@@ -252,22 +252,42 @@ DESCR("is above");
 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 ));
 DESCR("is right of");
 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 ));
 DESCR("same as");
 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 = 4092 ( "<<"	   PGNSP PGUID b f f 603 600	16	 0	 0 box_left_pt positionsel positionjoinsel ));
+DESCR("is left of");
+DATA(insert OID = 4093 ( "&<"	   PGNSP PGUID b f f 603 600	16	 0	 0 box_overleft_pt positionsel positionjoinsel ));
+DESCR("overlaps or is left of");
+DATA(insert OID = 4094 ( ">>"	   PGNSP PGUID b f f 603 600	16	 0	 0 box_right_pt positionsel positionjoinsel ));
+DESCR("is right of");
+DATA(insert OID = 4095 ( "&>"	   PGNSP PGUID b f f 603 600	16	 0	 0 box_overright_pt positionsel positionjoinsel ));
+DESCR("overlaps or is right of");
+DATA(insert OID = 4096 ( "<<|"	   PGNSP PGUID b f f 603 600	16	 0	 0 box_below_pt positionsel positionjoinsel ));
+DESCR("is below");
+DATA(insert OID = 4097 ( "&<|"	   PGNSP PGUID b f f 603 600	16	 0	 0 box_overbelow_pt positionsel positionjoinsel ));
+DESCR("overlaps or is below");
+DATA(insert OID = 4098 ( "|>>"	   PGNSP PGUID b f f 603 600	16	 0	 0 box_above_pt positionsel positionjoinsel ));
+DESCR("is above");
+DATA(insert OID = 4099 ( "|&>"	   PGNSP PGUID b f f 603 600	16	 0	 0 box_overabove_pt positionsel positionjoinsel ));
+DESCR("overlaps or is above");
 DATA(insert OID = 433 (  "@>"	   PGNSP PGUID b f f 603 600	16 511	 0 box_contain_pt contsel contjoinsel ));
 DESCR("contains");
+DATA(insert OID = 4100 ( "&&"	   PGNSP PGUID b f f 603 600	16 4101	 0 box_contain_pt contsel contjoinsel ));
+DESCR("same as @>");
+DATA(insert OID = 4101 ( "&&"	   PGNSP PGUID b f f 600 603	16 4100	 0 on_pb contsel contjoinsel ));
+DESCR("same as <@");
 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 - - ));
 DESCR("center of");
 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 - - ));
 DESCR("distance between");
 DATA(insert OID = 518 (  "<>"	   PGNSP PGUID b f f	23	23	16 518	96 int4ne neqsel neqjoinsel ));
 DESCR("not equal");
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index dcf00b2..1245428 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -336,20 +336,28 @@ DATA(insert OID = 182 (  int24mi		   PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 23
 DATA(insert OID = 183 (  int42mi		   PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 23 "23 21" _null_ _null_ _null_ _null_ _null_ int42mi _null_ _null_ _null_ ));
 DATA(insert OID = 184 (  oideq			   PGNSP PGUID 12 1 0 0 0 f f f t t f i 2 0 16 "26 26" _null_ _null_ _null_ _null_ _null_ oideq _null_ _null_ _null_ ));
 DATA(insert OID = 185 (  oidne			   PGNSP PGUID 12 1 0 0 0 f f f t t f i 2 0 16 "26 26" _null_ _null_ _null_ _null_ _null_ oidne _null_ _null_ _null_ ));
 DATA(insert OID = 186 (  box_same		   PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "603 603" _null_ _null_ _null_ _null_ _null_ box_same _null_ _null_ _null_ ));
 DATA(insert OID = 187 (  box_contain	   PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "603 603" _null_ _null_ _null_ _null_ _null_ box_contain _null_ _null_ _null_ ));
 DATA(insert OID = 188 (  box_left		   PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "603 603" _null_ _null_ _null_ _null_ _null_ box_left _null_ _null_ _null_ ));
 DATA(insert OID = 189 (  box_overleft	   PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "603 603" _null_ _null_ _null_ _null_ _null_ box_overleft _null_ _null_ _null_ ));
 DATA(insert OID = 190 (  box_overright	   PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "603 603" _null_ _null_ _null_ _null_ _null_ box_overright _null_ _null_ _null_ ));
 DATA(insert OID = 191 (  box_right		   PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "603 603" _null_ _null_ _null_ _null_ _null_ box_right _null_ _null_ _null_ ));
 DATA(insert OID = 192 (  box_contained	   PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "603 603" _null_ _null_ _null_ _null_ _null_ box_contained _null_ _null_ _null_ ));
+DATA(insert OID = 4083 (  box_left_pt	   PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "603 600" _null_ _null_ _null_ _null_ _null_ box_left_pt _null_ _null_ _null_ ));
+DATA(insert OID = 4084 (  box_overleft_pt  PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "603 600" _null_ _null_ _null_ _null_ _null_ box_overleft_pt _null_ _null_ _null_ ));
+DATA(insert OID = 4085 (  box_right_pt	   PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "603 600" _null_ _null_ _null_ _null_ _null_ box_right_pt _null_ _null_ _null_ ));
+DATA(insert OID = 4086 (  box_overright_pt PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "603 600" _null_ _null_ _null_ _null_ _null_ box_overright_pt _null_ _null_ _null_ ));
+DATA(insert OID = 4087 (  box_below_pt	   PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "603 600" _null_ _null_ _null_ _null_ _null_ box_below_pt _null_ _null_ _null_ ));
+DATA(insert OID = 4088 (  box_overbelow_pt PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "603 600" _null_ _null_ _null_ _null_ _null_ box_overbelow_pt _null_ _null_ _null_ ));
+DATA(insert OID = 4089 (  box_above_pt	   PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "603 600" _null_ _null_ _null_ _null_ _null_ box_above_pt _null_ _null_ _null_ ));
+DATA(insert OID = 4090 (  box_overabove_pt PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "603 600" _null_ _null_ _null_ _null_ _null_ box_overabove_pt _null_ _null_ _null_ ));
 DATA(insert OID = 193 (  box_contain_pt    PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "603 600" _null_ _null_ _null_ _null_ _null_ box_contain_pt _null_ _null_ _null_ ));
 
 DATA(insert OID = 195 (  pg_node_tree_in	PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 194 "2275" _null_ _null_ _null_ _null_ _null_ pg_node_tree_in _null_ _null_ _null_ ));
 DESCR("I/O");
 DATA(insert OID = 196 (  pg_node_tree_out	PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 2275 "194" _null_ _null_ _null_ _null_ _null_ pg_node_tree_out _null_ _null_ _null_ ));
 DESCR("I/O");
 DATA(insert OID = 197 (  pg_node_tree_recv	PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 194 "2281" _null_ _null_ _null_ _null_ _null_ pg_node_tree_recv _null_ _null_ _null_ ));
 DESCR("I/O");
 DATA(insert OID = 198 (  pg_node_tree_send	PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 17 "194" _null_ _null_ _null_ _null_ _null_	pg_node_tree_send _null_ _null_ _null_ ));
 DESCR("I/O");
diff --git a/src/include/utils/geo_decls.h b/src/include/utils/geo_decls.h
index 4377baa..69a78e8 100644
--- a/src/include/utils/geo_decls.h
+++ b/src/include/utils/geo_decls.h
@@ -275,20 +275,28 @@ extern Datum box_overlap(PG_FUNCTION_ARGS);
 extern Datum box_left(PG_FUNCTION_ARGS);
 extern Datum box_overleft(PG_FUNCTION_ARGS);
 extern Datum box_right(PG_FUNCTION_ARGS);
 extern Datum box_overright(PG_FUNCTION_ARGS);
 extern Datum box_below(PG_FUNCTION_ARGS);
 extern Datum box_overbelow(PG_FUNCTION_ARGS);
 extern Datum box_above(PG_FUNCTION_ARGS);
 extern Datum box_overabove(PG_FUNCTION_ARGS);
 extern Datum box_contained(PG_FUNCTION_ARGS);
 extern Datum box_contain(PG_FUNCTION_ARGS);
+extern Datum box_left_pt(PG_FUNCTION_ARGS);
+extern Datum box_overleft_pt(PG_FUNCTION_ARGS);
+extern Datum box_right_pt(PG_FUNCTION_ARGS);
+extern Datum box_overright_pt(PG_FUNCTION_ARGS);
+extern Datum box_below_pt(PG_FUNCTION_ARGS);
+extern Datum box_overbelow_pt(PG_FUNCTION_ARGS);
+extern Datum box_above_pt(PG_FUNCTION_ARGS);
+extern Datum box_overabove_pt(PG_FUNCTION_ARGS);
 extern Datum box_contain_pt(PG_FUNCTION_ARGS);
 extern Datum box_below_eq(PG_FUNCTION_ARGS);
 extern Datum box_above_eq(PG_FUNCTION_ARGS);
 extern Datum box_lt(PG_FUNCTION_ARGS);
 extern Datum box_gt(PG_FUNCTION_ARGS);
 extern Datum box_eq(PG_FUNCTION_ARGS);
 extern Datum box_le(PG_FUNCTION_ARGS);
 extern Datum box_ge(PG_FUNCTION_ARGS);
 extern Datum box_area(PG_FUNCTION_ARGS);
 extern Datum box_width(PG_FUNCTION_ARGS);
diff --git a/src/test/regress/expected/opr_sanity.out b/src/test/regress/expected/opr_sanity.out
index 6b248f2..200fd58 100644
--- a/src/test/regress/expected/opr_sanity.out
+++ b/src/test/regress/expected/opr_sanity.out
@@ -1068,54 +1068,56 @@ FROM pg_operator as p1 LEFT JOIN pg_description as d
 WHERE d.classoid IS NULL AND p1.oid <= 9999;
  oid | oprname 
 -----+---------
 (0 rows)
 
 -- Check that operators' underlying functions have suitable comments,
 -- namely 'implementation of XXX operator'.  (Note: it's not necessary to
 -- put such comments into pg_proc.h; initdb will generate them as needed.)
 -- In some cases involving legacy names for operators, there are multiple
 -- operators referencing the same pg_proc entry, so ignore operators whose
--- comments say they are deprecated.
+-- comments say they are deprecated or same as other operator.
 -- We also have a few functions that are both operator support and meant to
 -- be called directly; those should have comments matching their operator.
 WITH funcdescs AS (
   SELECT p.oid as p_oid, proname, o.oid as o_oid,
     obj_description(p.oid, 'pg_proc') as prodesc,
     'implementation of ' || oprname || ' operator' as expecteddesc,
     obj_description(o.oid, 'pg_operator') as oprdesc
   FROM pg_proc p JOIN pg_operator o ON oprcode = p.oid
   WHERE o.oid <= 9999
 )
 SELECT * FROM funcdescs
   WHERE prodesc IS DISTINCT FROM expecteddesc
     AND oprdesc NOT LIKE 'deprecated%'
+    AND oprdesc NOT LIKE 'same as %'
     AND prodesc IS DISTINCT FROM oprdesc;
  p_oid | proname | o_oid | prodesc | expecteddesc | oprdesc 
 -------+---------+-------+---------+--------------+---------
 (0 rows)
 
 -- Show all the operator-implementation functions that have their own
 -- comments.  This should happen only in cases where the function and
 -- operator syntaxes are both documented at the user level.
 -- This should be a pretty short list; it's mostly legacy cases.
 WITH funcdescs AS (
   SELECT p.oid as p_oid, proname, o.oid as o_oid,
     obj_description(p.oid, 'pg_proc') as prodesc,
     'implementation of ' || oprname || ' operator' as expecteddesc,
     obj_description(o.oid, 'pg_operator') as oprdesc
   FROM pg_proc p JOIN pg_operator o ON oprcode = p.oid
   WHERE o.oid <= 9999
 )
 SELECT p_oid, proname, prodesc FROM funcdescs
   WHERE prodesc IS DISTINCT FROM expecteddesc
     AND oprdesc NOT LIKE 'deprecated%'
+    AND oprdesc NOT LIKE 'same as %'
 ORDER BY 1;
  p_oid |         proname         |                     prodesc                     
 -------+-------------------------+-------------------------------------------------
    378 | array_append            | append element onto end of array
    379 | array_prepend           | prepend element onto front of array
   1035 | aclinsert               | add/update ACL item
   1036 | aclremove               | remove ACL item
   1037 | aclcontains             | contains
   3217 | jsonb_extract_path      | get value from jsonb with path elements
   3940 | jsonb_extract_path_text | get value from jsonb as text with path elements
diff --git a/src/test/regress/sql/opr_sanity.sql b/src/test/regress/sql/opr_sanity.sql
index 7159a83..2c20763 100644
--- a/src/test/regress/sql/opr_sanity.sql
+++ b/src/test/regress/sql/opr_sanity.sql
@@ -628,51 +628,53 @@ WHERE p1.oprjoin = p2.oid AND
 SELECT p1.oid, p1.oprname
 FROM pg_operator as p1 LEFT JOIN pg_description as d
      ON p1.tableoid = d.classoid and p1.oid = d.objoid and d.objsubid = 0
 WHERE d.classoid IS NULL AND p1.oid <= 9999;
 
 -- Check that operators' underlying functions have suitable comments,
 -- namely 'implementation of XXX operator'.  (Note: it's not necessary to
 -- put such comments into pg_proc.h; initdb will generate them as needed.)
 -- In some cases involving legacy names for operators, there are multiple
 -- operators referencing the same pg_proc entry, so ignore operators whose
--- comments say they are deprecated.
+-- comments say they are deprecated or same as other operator.
 -- We also have a few functions that are both operator support and meant to
 -- be called directly; those should have comments matching their operator.
 WITH funcdescs AS (
   SELECT p.oid as p_oid, proname, o.oid as o_oid,
     obj_description(p.oid, 'pg_proc') as prodesc,
     'implementation of ' || oprname || ' operator' as expecteddesc,
     obj_description(o.oid, 'pg_operator') as oprdesc
   FROM pg_proc p JOIN pg_operator o ON oprcode = p.oid
   WHERE o.oid <= 9999
 )
 SELECT * FROM funcdescs
   WHERE prodesc IS DISTINCT FROM expecteddesc
     AND oprdesc NOT LIKE 'deprecated%'
+    AND oprdesc NOT LIKE 'same as %'
     AND prodesc IS DISTINCT FROM oprdesc;
 
 -- Show all the operator-implementation functions that have their own
 -- comments.  This should happen only in cases where the function and
 -- operator syntaxes are both documented at the user level.
 -- This should be a pretty short list; it's mostly legacy cases.
 WITH funcdescs AS (
   SELECT p.oid as p_oid, proname, o.oid as o_oid,
     obj_description(p.oid, 'pg_proc') as prodesc,
     'implementation of ' || oprname || ' operator' as expecteddesc,
     obj_description(o.oid, 'pg_operator') as oprdesc
   FROM pg_proc p JOIN pg_operator o ON oprcode = p.oid
   WHERE o.oid <= 9999
 )
 SELECT p_oid, proname, prodesc FROM funcdescs
   WHERE prodesc IS DISTINCT FROM expecteddesc
     AND oprdesc NOT LIKE 'deprecated%'
+    AND oprdesc NOT LIKE 'same as %'
 ORDER BY 1;
 
 
 -- **************** pg_aggregate ****************
 
 -- Look for illegal values in pg_aggregate fields.
 
 SELECT ctid, aggfnoid::oid
 FROM pg_aggregate as p1
 WHERE aggfnoid = 0 OR aggtransfn = 0 OR
-- 
2.3.2

