Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
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)