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
This commit is contained in:
parent
456ff08638
commit
3b6db1f445
@ -8295,6 +8295,12 @@ CREATE TYPE rainbow AS ENUM ('red', 'orange', 'yellow', 'green', 'blue', 'purple
|
|||||||
<entry>circle to box</entry>
|
<entry>circle to box</entry>
|
||||||
<entry><literal>box(circle '((0,0),2.0)')</literal></entry>
|
<entry><literal>box(circle '((0,0),2.0)')</literal></entry>
|
||||||
</row>
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry><literal><function>box(<type>point</type>)</function></literal></entry>
|
||||||
|
<entry><type>box</type></entry>
|
||||||
|
<entry>point to empty box</entry>
|
||||||
|
<entry><literal>box(point '(0,0)')</literal></entry>
|
||||||
|
</row>
|
||||||
<row>
|
<row>
|
||||||
<entry><literal><function>box(<type>point</type>, <type>point</type>)</function></literal></entry>
|
<entry><literal><function>box(<type>point</type>, <type>point</type>)</function></literal></entry>
|
||||||
<entry><type>box</type></entry>
|
<entry><type>box</type></entry>
|
||||||
@ -8307,6 +8313,12 @@ CREATE TYPE rainbow AS ENUM ('red', 'orange', 'yellow', 'green', 'blue', 'purple
|
|||||||
<entry>polygon to box</entry>
|
<entry>polygon to box</entry>
|
||||||
<entry><literal>box(polygon '((0,0),(1,1),(2,0))')</literal></entry>
|
<entry><literal>box(polygon '((0,0),(1,1),(2,0))')</literal></entry>
|
||||||
</row>
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry><literal><function>bound_box(<type>box</type>, <type>box</type>)</function></literal></entry>
|
||||||
|
<entry><type>box</type></entry>
|
||||||
|
<entry>boxes to bounding box</entry>
|
||||||
|
<entry><literal>bound_box(box '((0,0),(1,1))', box '((3,3),(4,4))')</literal></entry>
|
||||||
|
</row>
|
||||||
<row>
|
<row>
|
||||||
<entry>
|
<entry>
|
||||||
<indexterm>
|
<indexterm>
|
||||||
@ -8734,6 +8746,30 @@ CREATE TYPE rainbow AS ENUM ('red', 'orange', 'yellow', 'green', 'blue', 'purple
|
|||||||
<entry><literal>text(inet '192.168.1.5')</literal></entry>
|
<entry><literal>text(inet '192.168.1.5')</literal></entry>
|
||||||
<entry><literal>192.168.1.5/32</literal></entry>
|
<entry><literal>192.168.1.5/32</literal></entry>
|
||||||
</row>
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry>
|
||||||
|
<indexterm>
|
||||||
|
<primary>inet_same_family</primary>
|
||||||
|
</indexterm>
|
||||||
|
<literal><function>inet_same_family(<type>inet</type>, <type>inet</type>)</function></literal>
|
||||||
|
</entry>
|
||||||
|
<entry><type>boolean</type></entry>
|
||||||
|
<entry>are the addresses from the same family?</entry>
|
||||||
|
<entry><literal>inet_same_family('192.168.1.5/24', '::1')</literal></entry>
|
||||||
|
<entry><literal>false</literal></entry>
|
||||||
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry>
|
||||||
|
<indexterm>
|
||||||
|
<primary>inet_merge</primary>
|
||||||
|
</indexterm>
|
||||||
|
<literal><function>inet_merge(<type>inet</type>, <type>inet</type>)</function></literal>
|
||||||
|
</entry>
|
||||||
|
<entry><type>cidr</type></entry>
|
||||||
|
<entry>the smallest network which includes both of the given networks</entry>
|
||||||
|
<entry><literal>inet_merge('192.168.1.5/24', '192.168.2.5/24')</literal></entry>
|
||||||
|
<entry><literal>192.168.0.0/22</literal></entry>
|
||||||
|
</row>
|
||||||
</tbody>
|
</tbody>
|
||||||
</tgroup>
|
</tgroup>
|
||||||
</table>
|
</table>
|
||||||
@ -12090,6 +12126,17 @@ NULL baz</literallayout>(3 rows)</entry>
|
|||||||
<entry><literal>upper_inf('(,)'::daterange)</literal></entry>
|
<entry><literal>upper_inf('(,)'::daterange)</literal></entry>
|
||||||
<entry><literal>true</literal></entry>
|
<entry><literal>true</literal></entry>
|
||||||
</row>
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry>
|
||||||
|
<literal>
|
||||||
|
<function>range_merge</function>(<type>anyrange</type>, <type>anyrange</type>)
|
||||||
|
</literal>
|
||||||
|
</entry>
|
||||||
|
<entry><type>anyrange</type></entry>
|
||||||
|
<entry>the smallest range which includes both of the given ranges</entry>
|
||||||
|
<entry><literal>range_merge('[1,2)'::int4range, '[3,4)'::int4range)</literal></entry>
|
||||||
|
<entry><literal>[1,4)</literal></entry>
|
||||||
|
</row>
|
||||||
</tbody>
|
</tbody>
|
||||||
</tgroup>
|
</tgroup>
|
||||||
</table>
|
</table>
|
||||||
|
@ -4227,6 +4227,45 @@ box_div(PG_FUNCTION_ARGS)
|
|||||||
PG_RETURN_BOX_P(result);
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
**
|
**
|
||||||
|
@ -887,6 +887,58 @@ network_hostmask(PG_FUNCTION_ARGS)
|
|||||||
PG_RETURN_INET_P(dst);
|
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.
|
* Convert a value of a network datatype to an approximate scalar value.
|
||||||
* This is used for estimating selectivities of inequality operators
|
* This is used for estimating selectivities of inequality operators
|
||||||
|
@ -1006,13 +1006,14 @@ range_minus(PG_FUNCTION_ARGS)
|
|||||||
PG_RETURN_NULL();
|
PG_RETURN_NULL();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set union */
|
/*
|
||||||
Datum
|
* Set union. If strict is true, it is an error that the two input ranges
|
||||||
range_union(PG_FUNCTION_ARGS)
|
* 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,
|
RangeBound lower1,
|
||||||
lower2;
|
lower2;
|
||||||
RangeBound upper1,
|
RangeBound upper1,
|
||||||
@ -1026,19 +1027,18 @@ range_union(PG_FUNCTION_ARGS)
|
|||||||
if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
|
if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
|
||||||
elog(ERROR, "range types do not match");
|
elog(ERROR, "range types do not match");
|
||||||
|
|
||||||
typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
|
|
||||||
|
|
||||||
range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
|
range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
|
||||||
range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
|
range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
|
||||||
|
|
||||||
/* if either is empty, the other is the correct answer */
|
/* if either is empty, the other is the correct answer */
|
||||||
if (empty1)
|
if (empty1)
|
||||||
PG_RETURN_RANGE(r2);
|
return r2;
|
||||||
if (empty2)
|
if (empty2)
|
||||||
PG_RETURN_RANGE(r1);
|
return r1;
|
||||||
|
|
||||||
if (!DatumGetBool(range_overlaps(fcinfo)) &&
|
if (strict &&
|
||||||
!DatumGetBool(range_adjacent(fcinfo)))
|
!DatumGetBool(range_overlaps_internal(typcache, r1, r2)) &&
|
||||||
|
!DatumGetBool(range_adjacent_internal(typcache, r1, r2)))
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_DATA_EXCEPTION),
|
(errcode(ERRCODE_DATA_EXCEPTION),
|
||||||
errmsg("result of range union would not be contiguous")));
|
errmsg("result of range union would not be contiguous")));
|
||||||
@ -1053,7 +1053,35 @@ range_union(PG_FUNCTION_ARGS)
|
|||||||
else
|
else
|
||||||
result_upper = &upper2;
|
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 */
|
/* set intersection */
|
||||||
|
@ -53,6 +53,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* yyyymmddN */
|
/* yyyymmddN */
|
||||||
#define CATALOG_VERSION_NO 201504291
|
#define CATALOG_VERSION_NO 201505051
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -273,6 +273,7 @@ DATA(insert ( 703 23 0 e b ));
|
|||||||
/*
|
/*
|
||||||
* Geometric category
|
* Geometric category
|
||||||
*/
|
*/
|
||||||
|
DATA(insert ( 600 603 4091 a f ));
|
||||||
DATA(insert ( 601 600 1532 e f ));
|
DATA(insert ( 601 600 1532 e f ));
|
||||||
DATA(insert ( 602 600 1533 e f ));
|
DATA(insert ( 602 600 1533 e f ));
|
||||||
DATA(insert ( 602 604 1449 a f ));
|
DATA(insert ( 602 604 1449 a f ));
|
||||||
|
@ -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_ ));
|
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");
|
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 = 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_ ));
|
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");
|
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_ ));
|
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 = 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 = 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 = 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_ ));
|
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");
|
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_ ));
|
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 = 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 = 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 = 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 */
|
/* 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_ ));
|
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");
|
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_ ));
|
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");
|
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_ ));
|
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");
|
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_ ));
|
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_ ));
|
||||||
|
@ -942,6 +942,8 @@ extern Datum inetpl(PG_FUNCTION_ARGS);
|
|||||||
extern Datum inetmi_int8(PG_FUNCTION_ARGS);
|
extern Datum inetmi_int8(PG_FUNCTION_ARGS);
|
||||||
extern Datum inetmi(PG_FUNCTION_ARGS);
|
extern Datum inetmi(PG_FUNCTION_ARGS);
|
||||||
extern void clean_ipv6_addr(int addr_family, char *addr);
|
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 */
|
/* mac.c */
|
||||||
extern Datum macaddr_in(PG_FUNCTION_ARGS);
|
extern Datum macaddr_in(PG_FUNCTION_ARGS);
|
||||||
|
@ -302,6 +302,8 @@ extern Datum box_add(PG_FUNCTION_ARGS);
|
|||||||
extern Datum box_sub(PG_FUNCTION_ARGS);
|
extern Datum box_sub(PG_FUNCTION_ARGS);
|
||||||
extern Datum box_mul(PG_FUNCTION_ARGS);
|
extern Datum box_mul(PG_FUNCTION_ARGS);
|
||||||
extern Datum box_div(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 */
|
/* public path routines */
|
||||||
extern Datum path_area(PG_FUNCTION_ARGS);
|
extern Datum path_area(PG_FUNCTION_ARGS);
|
||||||
|
@ -211,6 +211,7 @@ extern Datum range_gist_compress(PG_FUNCTION_ARGS);
|
|||||||
extern Datum range_gist_decompress(PG_FUNCTION_ARGS);
|
extern Datum range_gist_decompress(PG_FUNCTION_ARGS);
|
||||||
extern Datum range_gist_fetch(PG_FUNCTION_ARGS);
|
extern Datum range_gist_fetch(PG_FUNCTION_ARGS);
|
||||||
extern Datum range_gist_union(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_penalty(PG_FUNCTION_ARGS);
|
||||||
extern Datum range_gist_picksplit(PG_FUNCTION_ARGS);
|
extern Datum range_gist_picksplit(PG_FUNCTION_ARGS);
|
||||||
extern Datum range_gist_same(PG_FUNCTION_ARGS);
|
extern Datum range_gist_same(PG_FUNCTION_ARGS);
|
||||||
|
@ -278,6 +278,40 @@ SELECT '' AS twenty, b.f1 / p.f1 AS rotation
|
|||||||
| (0.3,0),(0.3,0)
|
| (0.3,0),(0.3,0)
|
||||||
(20 rows)
|
(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
|
-- Paths
|
||||||
--
|
--
|
||||||
|
@ -278,6 +278,40 @@ SELECT '' AS twenty, b.f1 / p.f1 AS rotation
|
|||||||
| (0.3,0),(0.3,0)
|
| (0.3,0),(0.3,0)
|
||||||
(20 rows)
|
(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
|
-- Paths
|
||||||
--
|
--
|
||||||
|
@ -278,6 +278,40 @@ SELECT '' AS twenty, b.f1 / p.f1 AS rotation
|
|||||||
| (0.3,0),(0.3,0)
|
| (0.3,0),(0.3,0)
|
||||||
(20 rows)
|
(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
|
-- Paths
|
||||||
--
|
--
|
||||||
|
@ -614,3 +614,31 @@ SELECT '127::1'::inet - '127::2'::inet;
|
|||||||
-1
|
-1
|
||||||
(1 row)
|
(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)
|
||||||
|
|
||||||
|
@ -480,8 +480,26 @@ select numrange(1.0, 2.0) + numrange(1.5, 3.0);
|
|||||||
[1.0,3.0)
|
[1.0,3.0)
|
||||||
(1 row)
|
(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
|
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);
|
select numrange(1.0, 2.0) * numrange(2.0, 3.0);
|
||||||
?column?
|
?column?
|
||||||
----------
|
----------
|
||||||
|
@ -79,6 +79,12 @@ SELECT '' AS twenty, b.f1 / p.f1 AS rotation
|
|||||||
FROM BOX_TBL b, POINT_TBL p
|
FROM BOX_TBL b, POINT_TBL p
|
||||||
WHERE (p.f1 <-> point '(0,0)') >= 1;
|
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
|
-- Paths
|
||||||
--
|
--
|
||||||
|
@ -116,3 +116,10 @@ SELECT '127::1'::inet - '126::2'::inet;
|
|||||||
-- but not these
|
-- but not these
|
||||||
SELECT '127::1'::inet + 10000000000;
|
SELECT '127::1'::inet + 10000000000;
|
||||||
SELECT '127::1'::inet - '127::2'::inet;
|
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);
|
||||||
|
@ -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(2.0, 3.0);
|
||||||
select numrange(1.0, 2.0) + numrange(1.5, 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(2.0, 3.0);
|
||||||
select numrange(1.0, 2.0) * numrange(1.5, 3.0);
|
select numrange(1.0, 2.0) * numrange(1.5, 3.0);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user