From 3b6db1f445e14bd189ebc99ce1e5535a1c624613 Mon Sep 17 00:00:00 2001 From: Alvaro Herrera Date: Tue, 5 May 2015 15:22:24 -0300 Subject: [PATCH] Add geometry/range functions to support BRIN inclusion This commit adds the following functions: box(point) -> box bound_box(box, box) -> box inet_same_family(inet, inet) -> bool inet_merge(inet, inet) -> cidr range_merge(anyrange, anyrange) -> anyrange The first of these is also used to implement a new assignment cast from point to box. These functions are the first part of a base to implement an "inclusion" operator class for BRIN, for multidimensional data types. Author: Emre Hasegeli Reviewed by: Andreas Karlsson --- doc/src/sgml/func.sgml | 47 +++++++++++++++++++++ src/backend/utils/adt/geo_ops.c | 39 +++++++++++++++++ src/backend/utils/adt/network.c | 52 +++++++++++++++++++++++ src/backend/utils/adt/rangetypes.c | 54 ++++++++++++++++++------ src/include/catalog/catversion.h | 2 +- src/include/catalog/pg_cast.h | 1 + src/include/catalog/pg_proc.h | 10 +++++ src/include/utils/builtins.h | 2 + src/include/utils/geo_decls.h | 2 + src/include/utils/rangetypes.h | 1 + src/test/regress/expected/geometry.out | 34 +++++++++++++++ src/test/regress/expected/geometry_1.out | 34 +++++++++++++++ src/test/regress/expected/geometry_2.out | 34 +++++++++++++++ src/test/regress/expected/inet.out | 28 ++++++++++++ src/test/regress/expected/rangetypes.out | 20 ++++++++- src/test/regress/sql/geometry.sql | 6 +++ src/test/regress/sql/inet.sql | 7 +++ src/test/regress/sql/rangetypes.sql | 6 ++- 18 files changed, 363 insertions(+), 16 deletions(-) diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index e6f2129f38..fb39731604 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -8295,6 +8295,12 @@ CREATE TYPE rainbow AS ENUM ('red', 'orange', 'yellow', 'green', 'blue', 'purple circle to box box(circle '((0,0),2.0)') + + box(point) + box + point to empty box + box(point '(0,0)') + box(point, point) box @@ -8307,6 +8313,12 @@ CREATE TYPE rainbow AS ENUM ('red', 'orange', 'yellow', 'green', 'blue', 'purple polygon to box box(polygon '((0,0),(1,1),(2,0))') + + bound_box(box, box) + box + boxes to bounding box + bound_box(box '((0,0),(1,1))', box '((3,3),(4,4))') + @@ -8734,6 +8746,30 @@ CREATE TYPE rainbow AS ENUM ('red', 'orange', 'yellow', 'green', 'blue', 'purple text(inet '192.168.1.5') 192.168.1.5/32 + + + + inet_same_family + + inet_same_family(inet, inet) + + boolean + are the addresses from the same family? + inet_same_family('192.168.1.5/24', '::1') + false + + + + + inet_merge + + inet_merge(inet, inet) + + cidr + the smallest network which includes both of the given networks + inet_merge('192.168.1.5/24', '192.168.2.5/24') + 192.168.0.0/22 + @@ -12090,6 +12126,17 @@ NULL baz(3 rows) upper_inf('(,)'::daterange) true + + + + range_merge(anyrange, anyrange) + + + anyrange + the smallest range which includes both of the given ranges + range_merge('[1,2)'::int4range, '[3,4)'::int4range) + [1,4) + diff --git a/src/backend/utils/adt/geo_ops.c b/src/backend/utils/adt/geo_ops.c index 6cb6be5c5f..39a7855241 100644 --- a/src/backend/utils/adt/geo_ops.c +++ b/src/backend/utils/adt/geo_ops.c @@ -4227,6 +4227,45 @@ box_div(PG_FUNCTION_ARGS) PG_RETURN_BOX_P(result); } +/* + * Convert point to empty box + */ +Datum +point_box(PG_FUNCTION_ARGS) +{ + Point *pt = PG_GETARG_POINT_P(0); + BOX *box; + + box = (BOX *) palloc(sizeof(BOX)); + + box->high.x = pt->x; + box->low.x = pt->x; + box->high.y = pt->y; + box->low.y = pt->y; + + PG_RETURN_BOX_P(box); +} + +/* + * Smallest bounding box that includes both of the given boxes + */ +Datum +boxes_bound_box(PG_FUNCTION_ARGS) +{ + BOX *box1 = PG_GETARG_BOX_P(0), + *box2 = PG_GETARG_BOX_P(1), + *container; + + container = (BOX *) palloc(sizeof(BOX)); + + container->high.x = Max(box1->high.x, box2->high.x); + container->low.x = Min(box1->low.x, box2->low.x); + container->high.y = Max(box1->high.y, box2->high.y); + container->low.y = Min(box1->low.y, box2->low.y); + + PG_RETURN_BOX_P(container); +} + /*********************************************************************** ** diff --git a/src/backend/utils/adt/network.c b/src/backend/utils/adt/network.c index 3a705da619..1f8469a2cb 100644 --- a/src/backend/utils/adt/network.c +++ b/src/backend/utils/adt/network.c @@ -887,6 +887,58 @@ network_hostmask(PG_FUNCTION_ARGS) PG_RETURN_INET_P(dst); } +/* + * Returns true if the addresses are from the same family, or false. Used to + * check that we can create a network which contains both of the networks. + */ +Datum +inet_same_family(PG_FUNCTION_ARGS) +{ + inet *a1 = PG_GETARG_INET_PP(0); + inet *a2 = PG_GETARG_INET_PP(1); + + PG_RETURN_BOOL(ip_family(a1) == ip_family(a2)); +} + +/* + * Returns the smallest CIDR which contains both of the inputs. + */ +Datum +inet_merge(PG_FUNCTION_ARGS) +{ + inet *a1 = PG_GETARG_INET_PP(0), + *a2 = PG_GETARG_INET_PP(1), + *result; + int commonbits; + + if (ip_family(a1) != ip_family(a2)) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("cannot merge addresses from different families"))); + + commonbits = bitncommon(ip_addr(a1), ip_addr(a2), + Min(ip_bits(a1), ip_bits(a2))); + + /* Make sure any unused bits are zeroed. */ + result = (inet *) palloc0(sizeof(inet)); + + ip_family(result) = ip_family(a1); + ip_bits(result) = commonbits; + + /* Clone appropriate bytes of the address. */ + if (commonbits > 0) + memcpy(ip_addr(result), ip_addr(a1), (commonbits + 7) / 8); + + /* Clean any unwanted bits in the last partial byte. */ + if (commonbits % 8 != 0) + ip_addr(result)[commonbits / 8] &= ~(0xFF >> (commonbits % 8)); + + /* Set varlena header correctly. */ + SET_INET_VARSIZE(result); + + PG_RETURN_INET_P(result); +} + /* * Convert a value of a network datatype to an approximate scalar value. * This is used for estimating selectivities of inequality operators diff --git a/src/backend/utils/adt/rangetypes.c b/src/backend/utils/adt/rangetypes.c index c037b05f93..aaf4cb6810 100644 --- a/src/backend/utils/adt/rangetypes.c +++ b/src/backend/utils/adt/rangetypes.c @@ -1006,13 +1006,14 @@ range_minus(PG_FUNCTION_ARGS) PG_RETURN_NULL(); } -/* set union */ -Datum -range_union(PG_FUNCTION_ARGS) +/* + * Set union. If strict is true, it is an error that the two input ranges + * are not adjacent or overlapping. + */ +static RangeType * +range_union_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2, + bool strict) { - RangeType *r1 = PG_GETARG_RANGE(0); - RangeType *r2 = PG_GETARG_RANGE(1); - TypeCacheEntry *typcache; RangeBound lower1, lower2; RangeBound upper1, @@ -1026,19 +1027,18 @@ range_union(PG_FUNCTION_ARGS) if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2)) elog(ERROR, "range types do not match"); - typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1)); - range_deserialize(typcache, r1, &lower1, &upper1, &empty1); range_deserialize(typcache, r2, &lower2, &upper2, &empty2); /* if either is empty, the other is the correct answer */ if (empty1) - PG_RETURN_RANGE(r2); + return r2; if (empty2) - PG_RETURN_RANGE(r1); + return r1; - if (!DatumGetBool(range_overlaps(fcinfo)) && - !DatumGetBool(range_adjacent(fcinfo))) + if (strict && + !DatumGetBool(range_overlaps_internal(typcache, r1, r2)) && + !DatumGetBool(range_adjacent_internal(typcache, r1, r2))) ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION), errmsg("result of range union would not be contiguous"))); @@ -1053,7 +1053,35 @@ range_union(PG_FUNCTION_ARGS) else result_upper = &upper2; - PG_RETURN_RANGE(make_range(typcache, result_lower, result_upper, false)); + return make_range(typcache, result_lower, result_upper, false); +} + +Datum +range_union(PG_FUNCTION_ARGS) +{ + RangeType *r1 = PG_GETARG_RANGE(0); + RangeType *r2 = PG_GETARG_RANGE(1); + TypeCacheEntry *typcache; + + typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1)); + + PG_RETURN_RANGE(range_union_internal(typcache, r1, r2, true)); +} + +/* + * range merge: like set union, except also allow and account for non-adjacent + * input ranges. + */ +Datum +range_merge(PG_FUNCTION_ARGS) +{ + RangeType *r1 = PG_GETARG_RANGE(0); + RangeType *r2 = PG_GETARG_RANGE(1); + TypeCacheEntry *typcache; + + typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1)); + + PG_RETURN_RANGE(range_union_internal(typcache, r1, r2, false)); } /* set intersection */ diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index e8334025e1..e8320daedb 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 201504291 +#define CATALOG_VERSION_NO 201505051 #endif diff --git a/src/include/catalog/pg_cast.h b/src/include/catalog/pg_cast.h index c49fe263bb..259071ed2a 100644 --- a/src/include/catalog/pg_cast.h +++ b/src/include/catalog/pg_cast.h @@ -273,6 +273,7 @@ DATA(insert ( 703 23 0 e b )); /* * Geometric category */ +DATA(insert ( 600 603 4091 a f )); DATA(insert ( 601 600 1532 e f )); DATA(insert ( 602 600 1533 e f )); DATA(insert ( 602 604 1449 a f )); diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index 0a0b2bbdd2..bd67d72797 100644 --- a/src/include/catalog/pg_proc.h +++ b/src/include/catalog/pg_proc.h @@ -1140,6 +1140,8 @@ DATA(insert OID = 978 ( box_distance PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 DATA(insert OID = 979 ( area PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 701 "602" _null_ _null_ _null_ _null_ _null_ path_area _null_ _null_ _null_ )); DESCR("area of a closed path"); DATA(insert OID = 980 ( box_intersect PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 603 "603 603" _null_ _null_ _null_ _null_ _null_ box_intersect _null_ _null_ _null_ )); +DATA(insert OID = 4067 ( bound_box PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 603 "603 603" _null_ _null_ _null_ _null_ _null_ boxes_bound_box _null_ _null_ _null_ )); +DESCR("bounding box of two boxes"); DATA(insert OID = 981 ( diagonal PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 601 "603" _null_ _null_ _null_ _null_ _null_ box_diagonal _null_ _null_ _null_ )); DESCR("box diagonal"); DATA(insert OID = 982 ( path_n_lt PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "602 602" _null_ _null_ _null_ _null_ _null_ path_n_lt _null_ _null_ _null_ )); @@ -1744,6 +1746,8 @@ DESCR("convert vertex count and circle to polygon"); DATA(insert OID = 1476 ( dist_pc PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 701 "600 718" _null_ _null_ _null_ _null_ _null_ dist_pc _null_ _null_ _null_ )); DATA(insert OID = 1477 ( circle_contain_pt PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "718 600" _null_ _null_ _null_ _null_ _null_ circle_contain_pt _null_ _null_ _null_ )); DATA(insert OID = 1478 ( pt_contained_circle PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "600 718" _null_ _null_ _null_ _null_ _null_ pt_contained_circle _null_ _null_ _null_ )); +DATA(insert OID = 4091 ( box PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 603 "600" _null_ _null_ _null_ _null_ _null_ point_box _null_ _null_ _null_ )); +DESCR("convert point to empty box"); DATA(insert OID = 1479 ( circle PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 718 "603" _null_ _null_ _null_ _null_ _null_ box_circle _null_ _null_ _null_ )); DESCR("convert box to circle"); DATA(insert OID = 1480 ( box PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 603 "718" _null_ _null_ _null_ _null_ _null_ circle_box _null_ _null_ _null_ )); @@ -2232,6 +2236,10 @@ DATA(insert OID = 2630 ( inetpl PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 869 DATA(insert OID = 2631 ( int8pl_inet PGNSP PGUID 14 1 0 0 0 f f f f t f i 2 0 869 "20 869" _null_ _null_ _null_ _null_ _null_ "select $2 + $1" _null_ _null_ _null_ )); DATA(insert OID = 2632 ( inetmi_int8 PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 869 "869 20" _null_ _null_ _null_ _null_ _null_ inetmi_int8 _null_ _null_ _null_ )); DATA(insert OID = 2633 ( inetmi PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 20 "869 869" _null_ _null_ _null_ _null_ _null_ inetmi _null_ _null_ _null_ )); +DATA(insert OID = 4071 ( inet_same_family PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "869 869" _null_ _null_ _null_ _null_ _null_ inet_same_family _null_ _null_ _null_ )); +DESCR("are the addresses from the same family?"); +DATA(insert OID = 4063 ( inet_merge PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 650 "869 869" _null_ _null_ _null_ _null_ _null_ inet_merge _null_ _null_ _null_ )); +DESCR("the smallest network which includes both of the given networks"); /* GiST support for inet and cidr */ DATA(insert OID = 3553 ( inet_gist_consistent PGNSP PGUID 12 1 0 0 0 f f f f t f i 5 0 16 "2281 869 23 26 2281" _null_ _null_ _null_ _null_ _null_ inet_gist_consistent _null_ _null_ _null_ )); @@ -4937,6 +4945,8 @@ DATA(insert OID = 3866 ( range_overright PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 DESCR("implementation of &> operator"); DATA(insert OID = 3867 ( range_union PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 3831 "3831 3831" _null_ _null_ _null_ _null_ _null_ range_union _null_ _null_ _null_ )); DESCR("implementation of + operator"); +DATA(insert OID = 4057 ( range_merge PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 3831 "3831 3831" _null_ _null_ _null_ _null_ _null_ range_merge _null_ _null_ _null_ )); +DESCR("the smallest range which includes both of the given ranges"); DATA(insert OID = 3868 ( range_intersect PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 3831 "3831 3831" _null_ _null_ _null_ _null_ _null_ range_intersect _null_ _null_ _null_ )); DESCR("implementation of * operator"); DATA(insert OID = 3869 ( range_minus PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 3831 "3831 3831" _null_ _null_ _null_ _null_ _null_ range_minus _null_ _null_ _null_ )); diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h index 33a453f602..e8104f01a1 100644 --- a/src/include/utils/builtins.h +++ b/src/include/utils/builtins.h @@ -942,6 +942,8 @@ extern Datum inetpl(PG_FUNCTION_ARGS); extern Datum inetmi_int8(PG_FUNCTION_ARGS); extern Datum inetmi(PG_FUNCTION_ARGS); extern void clean_ipv6_addr(int addr_family, char *addr); +extern Datum inet_same_family(PG_FUNCTION_ARGS); +extern Datum inet_merge(PG_FUNCTION_ARGS); /* mac.c */ extern Datum macaddr_in(PG_FUNCTION_ARGS); diff --git a/src/include/utils/geo_decls.h b/src/include/utils/geo_decls.h index 2a91620db7..4377baa645 100644 --- a/src/include/utils/geo_decls.h +++ b/src/include/utils/geo_decls.h @@ -302,6 +302,8 @@ extern Datum box_add(PG_FUNCTION_ARGS); extern Datum box_sub(PG_FUNCTION_ARGS); extern Datum box_mul(PG_FUNCTION_ARGS); extern Datum box_div(PG_FUNCTION_ARGS); +extern Datum point_box(PG_FUNCTION_ARGS); +extern Datum boxes_bound_box(PG_FUNCTION_ARGS); /* public path routines */ extern Datum path_area(PG_FUNCTION_ARGS); diff --git a/src/include/utils/rangetypes.h b/src/include/utils/rangetypes.h index 43c80f493c..00a3efedc6 100644 --- a/src/include/utils/rangetypes.h +++ b/src/include/utils/rangetypes.h @@ -211,6 +211,7 @@ extern Datum range_gist_compress(PG_FUNCTION_ARGS); extern Datum range_gist_decompress(PG_FUNCTION_ARGS); extern Datum range_gist_fetch(PG_FUNCTION_ARGS); extern Datum range_gist_union(PG_FUNCTION_ARGS); +extern Datum range_merge(PG_FUNCTION_ARGS); extern Datum range_gist_penalty(PG_FUNCTION_ARGS); extern Datum range_gist_picksplit(PG_FUNCTION_ARGS); extern Datum range_gist_same(PG_FUNCTION_ARGS); diff --git a/src/test/regress/expected/geometry.out b/src/test/regress/expected/geometry.out index 21ad555c79..1271395d4e 100644 --- a/src/test/regress/expected/geometry.out +++ b/src/test/regress/expected/geometry.out @@ -278,6 +278,40 @@ SELECT '' AS twenty, b.f1 / p.f1 AS rotation | (0.3,0),(0.3,0) (20 rows) +SELECT f1::box + FROM POINT_TBL; + f1 +----------------------- + (0,0),(0,0) + (-10,0),(-10,0) + (-3,4),(-3,4) + (5.1,34.5),(5.1,34.5) + (-5,-12),(-5,-12) + (10,10),(10,10) +(6 rows) + +SELECT bound_box(a.f1, b.f1) + FROM BOX_TBL a, BOX_TBL b; + bound_box +--------------------- + (2,2),(0,0) + (3,3),(0,0) + (2.5,3.5),(0,0) + (3,3),(0,0) + (3,3),(0,0) + (3,3),(1,1) + (3,3.5),(1,1) + (3,3),(1,1) + (2.5,3.5),(0,0) + (3,3.5),(1,1) + (2.5,3.5),(2.5,2.5) + (3,3.5),(2.5,2.5) + (3,3),(0,0) + (3,3),(1,1) + (3,3.5),(2.5,2.5) + (3,3),(3,3) +(16 rows) + -- -- Paths -- diff --git a/src/test/regress/expected/geometry_1.out b/src/test/regress/expected/geometry_1.out index 65037dc8b0..fad246c2b9 100644 --- a/src/test/regress/expected/geometry_1.out +++ b/src/test/regress/expected/geometry_1.out @@ -278,6 +278,40 @@ SELECT '' AS twenty, b.f1 / p.f1 AS rotation | (0.3,0),(0.3,0) (20 rows) +SELECT f1::box + FROM POINT_TBL; + f1 +----------------------- + (0,0),(0,0) + (-10,0),(-10,0) + (-3,4),(-3,4) + (5.1,34.5),(5.1,34.5) + (-5,-12),(-5,-12) + (10,10),(10,10) +(6 rows) + +SELECT bound_box(a.f1, b.f1) + FROM BOX_TBL a, BOX_TBL b; + bound_box +--------------------- + (2,2),(0,0) + (3,3),(0,0) + (2.5,3.5),(0,0) + (3,3),(0,0) + (3,3),(0,0) + (3,3),(1,1) + (3,3.5),(1,1) + (3,3),(1,1) + (2.5,3.5),(0,0) + (3,3.5),(1,1) + (2.5,3.5),(2.5,2.5) + (3,3.5),(2.5,2.5) + (3,3),(0,0) + (3,3),(1,1) + (3,3.5),(2.5,2.5) + (3,3),(3,3) +(16 rows) + -- -- Paths -- diff --git a/src/test/regress/expected/geometry_2.out b/src/test/regress/expected/geometry_2.out index 1878a37b33..c938e66418 100644 --- a/src/test/regress/expected/geometry_2.out +++ b/src/test/regress/expected/geometry_2.out @@ -278,6 +278,40 @@ SELECT '' AS twenty, b.f1 / p.f1 AS rotation | (0.3,0),(0.3,0) (20 rows) +SELECT f1::box + FROM POINT_TBL; + f1 +----------------------- + (0,0),(0,0) + (-10,0),(-10,0) + (-3,4),(-3,4) + (5.1,34.5),(5.1,34.5) + (-5,-12),(-5,-12) + (10,10),(10,10) +(6 rows) + +SELECT bound_box(a.f1, b.f1) + FROM BOX_TBL a, BOX_TBL b; + bound_box +--------------------- + (2,2),(0,0) + (3,3),(0,0) + (2.5,3.5),(0,0) + (3,3),(0,0) + (3,3),(0,0) + (3,3),(1,1) + (3,3.5),(1,1) + (3,3),(1,1) + (2.5,3.5),(0,0) + (3,3.5),(1,1) + (2.5,3.5),(2.5,2.5) + (3,3.5),(2.5,2.5) + (3,3),(0,0) + (3,3),(1,1) + (3,3.5),(2.5,2.5) + (3,3),(3,3) +(16 rows) + -- -- Paths -- diff --git a/src/test/regress/expected/inet.out b/src/test/regress/expected/inet.out index d25e5e42a7..9447e03ab5 100644 --- a/src/test/regress/expected/inet.out +++ b/src/test/regress/expected/inet.out @@ -614,3 +614,31 @@ SELECT '127::1'::inet - '127::2'::inet; -1 (1 row) +-- insert one more row with addressed from different families +INSERT INTO INET_TBL (c, i) VALUES ('10', '10::/8'); +-- now, this one should fail +SELECT inet_merge(c, i) FROM INET_TBL; +ERROR: cannot merge addresses from different families +-- fix it by inet_same_family() condition +SELECT inet_merge(c, i) FROM INET_TBL WHERE inet_same_family(c, i); + inet_merge +----------------- + 192.168.1.0/24 + 192.168.1.0/24 + 192.168.1.0/24 + 192.168.1.0/24 + 192.168.1.0/24 + 192.168.1.0/24 + 10.0.0.0/8 + 10.0.0.0/8 + 10.1.2.3/32 + 10.1.2.0/24 + 10.1.0.0/16 + 10.0.0.0/8 + 10.0.0.0/7 + 8.0.0.0/6 + 10:23::/64 + 10:23::8000/113 + ::/24 +(17 rows) + diff --git a/src/test/regress/expected/rangetypes.out b/src/test/regress/expected/rangetypes.out index 8654e031da..23cdbc3902 100644 --- a/src/test/regress/expected/rangetypes.out +++ b/src/test/regress/expected/rangetypes.out @@ -480,8 +480,26 @@ select numrange(1.0, 2.0) + numrange(1.5, 3.0); [1.0,3.0) (1 row) -select numrange(1.0, 2.0) + numrange(2.5, 3.0); +select numrange(1.0, 2.0) + numrange(2.5, 3.0); -- should fail ERROR: result of range union would not be contiguous +select range_merge(numrange(1.0, 2.0), numrange(2.0, 3.0)); + range_merge +------------- + [1.0,3.0) +(1 row) + +select range_merge(numrange(1.0, 2.0), numrange(1.5, 3.0)); + range_merge +------------- + [1.0,3.0) +(1 row) + +select range_merge(numrange(1.0, 2.0), numrange(2.5, 3.0)); -- shouldn't fail + range_merge +------------- + [1.0,3.0) +(1 row) + select numrange(1.0, 2.0) * numrange(2.0, 3.0); ?column? ---------- diff --git a/src/test/regress/sql/geometry.sql b/src/test/regress/sql/geometry.sql index af7f8a51cc..1429ee772a 100644 --- a/src/test/regress/sql/geometry.sql +++ b/src/test/regress/sql/geometry.sql @@ -79,6 +79,12 @@ SELECT '' AS twenty, b.f1 / p.f1 AS rotation FROM BOX_TBL b, POINT_TBL p WHERE (p.f1 <-> point '(0,0)') >= 1; +SELECT f1::box + FROM POINT_TBL; + +SELECT bound_box(a.f1, b.f1) + FROM BOX_TBL a, BOX_TBL b; + -- -- Paths -- diff --git a/src/test/regress/sql/inet.sql b/src/test/regress/sql/inet.sql index 2034d3e86f..007741e935 100644 --- a/src/test/regress/sql/inet.sql +++ b/src/test/regress/sql/inet.sql @@ -116,3 +116,10 @@ SELECT '127::1'::inet - '126::2'::inet; -- but not these SELECT '127::1'::inet + 10000000000; SELECT '127::1'::inet - '127::2'::inet; + +-- insert one more row with addressed from different families +INSERT INTO INET_TBL (c, i) VALUES ('10', '10::/8'); +-- now, this one should fail +SELECT inet_merge(c, i) FROM INET_TBL; +-- fix it by inet_same_family() condition +SELECT inet_merge(c, i) FROM INET_TBL WHERE inet_same_family(c, i); diff --git a/src/test/regress/sql/rangetypes.sql b/src/test/regress/sql/rangetypes.sql index af1335264d..6d2696f7bf 100644 --- a/src/test/regress/sql/rangetypes.sql +++ b/src/test/regress/sql/rangetypes.sql @@ -108,7 +108,11 @@ select numrange(1.1, 2.2) < numrange(1.1, 1.2); select numrange(1.0, 2.0) + numrange(2.0, 3.0); select numrange(1.0, 2.0) + numrange(1.5, 3.0); -select numrange(1.0, 2.0) + numrange(2.5, 3.0); +select numrange(1.0, 2.0) + numrange(2.5, 3.0); -- should fail + +select range_merge(numrange(1.0, 2.0), numrange(2.0, 3.0)); +select range_merge(numrange(1.0, 2.0), numrange(1.5, 3.0)); +select range_merge(numrange(1.0, 2.0), numrange(2.5, 3.0)); -- shouldn't fail select numrange(1.0, 2.0) * numrange(2.0, 3.0); select numrange(1.0, 2.0) * numrange(1.5, 3.0);