Skip to content

Commit 1f1ca18

Browse files
committed
Make inet/cidr << and <<= operators indexable. From Alex Pilosov <alex@pilosoft.com>.
1 parent 2917f0a commit 1f1ca18

File tree

6 files changed

+237
-16
lines changed

6 files changed

+237
-16
lines changed

src/backend/optimizer/path/indxpath.c

Lines changed: 115 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
*
1010
*
1111
* IDENTIFICATION
12-
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.106 2001/06/05 17:13:51 tgl Exp $
12+
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.107 2001/06/17 02:05:19 tgl Exp $
1313
*
1414
*-------------------------------------------------------------------------
1515
*/
@@ -95,6 +95,7 @@ static bool match_special_index_operator(Expr *clause, Oid opclass, Oid relam,
9595
bool indexkey_on_left);
9696
static List *prefix_quals(Var *leftop, Oid expr_op,
9797
char *prefix, Pattern_Prefix_Status pstatus);
98+
static List *network_prefix_quals(Var *leftop, Oid expr_op, Datum rightop);
9899
static Oid find_operator(const char *opname, Oid datatype);
99100
static Datum string_to_datum(const char *str, Oid datatype);
100101
static Const *string_to_const(const char *str, Oid datatype);
@@ -1761,6 +1762,13 @@ match_special_index_operator(Expr *clause, Oid opclass, Oid relam,
17611762
pfree(patt);
17621763
}
17631764
break;
1765+
1766+
case OID_INET_SUB_OP:
1767+
case OID_INET_SUBEQ_OP:
1768+
case OID_CIDR_SUB_OP:
1769+
case OID_CIDR_SUBEQ_OP:
1770+
isIndexable = true;
1771+
break;
17641772
}
17651773

17661774
/* done if the expression doesn't look indexable */
@@ -1810,6 +1818,22 @@ match_special_index_operator(Expr *clause, Oid opclass, Oid relam,
18101818
!op_class(find_operator("<", NAMEOID), opclass, relam))
18111819
isIndexable = false;
18121820
break;
1821+
1822+
case OID_INET_SUB_OP:
1823+
case OID_INET_SUBEQ_OP:
1824+
/* for SUB we actually need ">" not ">=", but this should do */
1825+
if (!op_class(find_operator(">=", INETOID), opclass, relam) ||
1826+
!op_class(find_operator("<=", INETOID), opclass, relam))
1827+
isIndexable = false;
1828+
break;
1829+
1830+
case OID_CIDR_SUB_OP:
1831+
case OID_CIDR_SUBEQ_OP:
1832+
/* for SUB we actually need ">" not ">=", but this should do */
1833+
if (!op_class(find_operator(">=", CIDROID), opclass, relam) ||
1834+
!op_class(find_operator("<=", CIDROID), opclass, relam))
1835+
isIndexable = false;
1836+
break;
18131837
}
18141838

18151839
return isIndexable;
@@ -1924,6 +1948,16 @@ expand_indexqual_conditions(List *indexquals)
19241948
pfree(patt);
19251949
break;
19261950

1951+
case OID_INET_SUB_OP:
1952+
case OID_INET_SUBEQ_OP:
1953+
case OID_CIDR_SUB_OP:
1954+
case OID_CIDR_SUBEQ_OP:
1955+
constvalue = ((Const *) rightop)->constvalue;
1956+
resultquals = nconc(resultquals,
1957+
network_prefix_quals(leftop, expr_op,
1958+
constvalue));
1959+
break;
1960+
19271961
default:
19281962
resultquals = lappend(resultquals, clause);
19291963
break;
@@ -2037,6 +2071,86 @@ prefix_quals(Var *leftop, Oid expr_op,
20372071
return result;
20382072
}
20392073

2074+
/*
2075+
* Given a leftop and a rightop, and a inet-class sup/sub operator,
2076+
* generate suitable indexqual condition(s). expr_op is the original
2077+
* operator.
2078+
*/
2079+
static List *
2080+
network_prefix_quals(Var *leftop, Oid expr_op, Datum rightop)
2081+
{
2082+
bool is_eq;
2083+
char *opr1name;
2084+
Datum opr1right;
2085+
Datum opr2right;
2086+
Oid opr1oid;
2087+
Oid opr2oid;
2088+
List *result;
2089+
Oid datatype;
2090+
Oper *op;
2091+
Expr *expr;
2092+
2093+
switch (expr_op)
2094+
{
2095+
case OID_INET_SUB_OP:
2096+
datatype = INETOID;
2097+
is_eq = false;
2098+
break;
2099+
case OID_INET_SUBEQ_OP:
2100+
datatype = INETOID;
2101+
is_eq = true;
2102+
break;
2103+
case OID_CIDR_SUB_OP:
2104+
datatype = CIDROID;
2105+
is_eq = false;
2106+
break;
2107+
case OID_CIDR_SUBEQ_OP:
2108+
datatype = CIDROID;
2109+
is_eq = true;
2110+
break;
2111+
default:
2112+
elog(ERROR, "network_prefix_quals: unexpected operator %u",
2113+
expr_op);
2114+
return NIL;
2115+
}
2116+
2117+
/*
2118+
* create clause "key >= network_scan_first( rightop )", or ">"
2119+
* if the operator disallows equality.
2120+
*/
2121+
2122+
opr1name = is_eq ? ">=" : ">";
2123+
opr1oid = find_operator(opr1name, datatype);
2124+
if (opr1oid == InvalidOid)
2125+
elog(ERROR, "network_prefix_quals: no %s operator for type %u",
2126+
opr1name, datatype);
2127+
2128+
opr1right = network_scan_first( rightop );
2129+
2130+
op = makeOper(opr1oid, InvalidOid, BOOLOID);
2131+
expr = make_opclause(op, leftop,
2132+
(Var *) makeConst(datatype, -1, opr1right,
2133+
false, false, false, false));
2134+
result = makeList1(expr);
2135+
2136+
/* create clause "key <= network_scan_last( rightop )" */
2137+
2138+
opr2oid = find_operator("<=", datatype);
2139+
if (opr2oid == InvalidOid)
2140+
elog(ERROR, "network_prefix_quals: no <= operator for type %u",
2141+
datatype);
2142+
2143+
opr2right = network_scan_last( rightop );
2144+
2145+
op = makeOper(opr2oid, InvalidOid, BOOLOID);
2146+
expr = make_opclause(op, leftop,
2147+
(Var *) makeConst(datatype, -1, opr2right,
2148+
false, false, false, false));
2149+
result = lappend(result, expr);
2150+
2151+
return result;
2152+
}
2153+
20402154
/*
20412155
* Handy subroutines for match_special_index_operator() and friends.
20422156
*/

src/backend/utils/adt/network.c

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* is for IP V4 CIDR notation, but prepared for V6: just
44
* add the necessary bits where the comments indicate.
55
*
6-
* $Header: /cvsroot/pgsql/src/backend/utils/adt/network.c,v 1.31 2001/06/13 21:08:59 momjian Exp $
6+
* $Header: /cvsroot/pgsql/src/backend/utils/adt/network.c,v 1.32 2001/06/17 02:05:20 tgl Exp $
77
*
88
* Jon Postel RIP 16 Oct 1998
99
*/
@@ -707,3 +707,31 @@ v4addressOK(unsigned long a1, int bits)
707707
return true;
708708
return false;
709709
}
710+
711+
712+
/*
713+
* These functions are used by planner to generate indexscan limits
714+
* for clauses a << b and a <<= b
715+
*/
716+
717+
/* return the minimal value for an IP on a given network */
718+
Datum
719+
network_scan_first(Datum in)
720+
{
721+
return DirectFunctionCall1(network_network, in);
722+
}
723+
724+
/*
725+
* return "last" IP on a given network. It's the broadcast address,
726+
* however, masklen has to be set to 32, since
727+
* 192.168.0.255/24 is considered less than 192.168.0.255/32
728+
*
729+
* NB: this is not IPv6 ready ...
730+
*/
731+
Datum
732+
network_scan_last(Datum in)
733+
{
734+
return DirectFunctionCall2(inet_set_masklen,
735+
DirectFunctionCall1(network_broadcast, in),
736+
Int32GetDatum(32));
737+
}

src/include/catalog/pg_operator.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
99
* Portions Copyright (c) 1994, Regents of the University of California
1010
*
11-
* $Id: pg_operator.h,v 1.90 2001/06/10 22:32:35 tgl Exp $
11+
* $Id: pg_operator.h,v 1.91 2001/06/17 02:05:20 tgl Exp $
1212
*
1313
* NOTES
1414
* the genbki.sh script reads this file and generates .bki
@@ -674,9 +674,13 @@ DATA(insert OID = 1204 ( "<=" PGUID 0 b t f 869 869 16 1206 1205 0 0
674674
DATA(insert OID = 1205 ( ">" PGUID 0 b t f 869 869 16 1203 1204 0 0 network_gt scalargtsel scalargtjoinsel ));
675675
DATA(insert OID = 1206 ( ">=" PGUID 0 b t f 869 869 16 1204 1203 0 0 network_ge scalargtsel scalargtjoinsel ));
676676
DATA(insert OID = 931 ( "<<" PGUID 0 b t f 869 869 16 933 0 0 0 network_sub - - ));
677+
#define OID_INET_SUB_OP 931
677678
DATA(insert OID = 932 ( "<<=" PGUID 0 b t f 869 869 16 934 0 0 0 network_subeq - - ));
679+
#define OID_INET_SUBEQ_OP 932
678680
DATA(insert OID = 933 ( ">>" PGUID 0 b t f 869 869 16 931 0 0 0 network_sup - - ));
681+
#define OID_INET_SUP_OP 933
679682
DATA(insert OID = 934 ( ">>=" PGUID 0 b t f 869 869 16 932 0 0 0 network_supeq - - ));
683+
#define OID_INET_SUPEQ_OP 934
680684

681685
/* CIDR type */
682686
DATA(insert OID = 820 ( "=" PGUID 0 b t f 650 650 16 820 821 822 822 network_eq eqsel eqjoinsel ));
@@ -686,9 +690,13 @@ DATA(insert OID = 823 ( "<=" PGUID 0 b t f 650 650 16 825 824 0 0 netwo
686690
DATA(insert OID = 824 ( ">" PGUID 0 b t f 650 650 16 822 823 0 0 network_gt scalargtsel scalargtjoinsel ));
687691
DATA(insert OID = 825 ( ">=" PGUID 0 b t f 650 650 16 823 822 0 0 network_ge scalargtsel scalargtjoinsel ));
688692
DATA(insert OID = 826 ( "<<" PGUID 0 b t f 650 650 16 828 0 0 0 network_sub - - ));
693+
#define OID_CIDR_SUB_OP 826
689694
DATA(insert OID = 827 ( "<<=" PGUID 0 b t f 650 650 16 1004 0 0 0 network_subeq - - ));
695+
#define OID_CIDR_SUBEQ_OP 827
690696
DATA(insert OID = 828 ( ">>" PGUID 0 b t f 650 650 16 826 0 0 0 network_sup - - ));
697+
#define OID_CIDR_SUP_OP 828
691698
DATA(insert OID = 1004 ( ">>=" PGUID 0 b t f 650 650 16 827 0 0 0 network_supeq - - ));
699+
#define OID_CIDR_SUPEQ_OP 1004
692700

693701
/* case-insensitive LIKE hacks */
694702
DATA(insert OID = 1625 ( "~~*" PGUID 0 b t f 19 25 16 0 1626 0 0 nameiclike iclikesel iclikejoinsel ));

src/include/utils/builtins.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $Id: builtins.h,v 1.154 2001/06/14 01:09:22 tgl Exp $
10+
* $Id: builtins.h,v 1.155 2001/06/17 02:05:20 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -527,6 +527,8 @@ extern double convert_network_to_scalar(Datum value, Oid typid);
527527
extern Datum text_cidr(PG_FUNCTION_ARGS);
528528
extern Datum text_inet(PG_FUNCTION_ARGS);
529529
extern Datum inet_set_masklen(PG_FUNCTION_ARGS);
530+
extern Datum network_scan_first(Datum in);
531+
extern Datum network_scan_last(Datum in);
530532

531533
/* mac.c */
532534
extern Datum macaddr_in(PG_FUNCTION_ARGS);

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy