|
9 | 9 | *
|
10 | 10 | *
|
11 | 11 | * 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 $ |
13 | 13 | *
|
14 | 14 | *-------------------------------------------------------------------------
|
15 | 15 | */
|
@@ -95,6 +95,7 @@ static bool match_special_index_operator(Expr *clause, Oid opclass, Oid relam,
|
95 | 95 | bool indexkey_on_left);
|
96 | 96 | static List *prefix_quals(Var *leftop, Oid expr_op,
|
97 | 97 | char *prefix, Pattern_Prefix_Status pstatus);
|
| 98 | +static List *network_prefix_quals(Var *leftop, Oid expr_op, Datum rightop); |
98 | 99 | static Oid find_operator(const char *opname, Oid datatype);
|
99 | 100 | static Datum string_to_datum(const char *str, Oid datatype);
|
100 | 101 | static Const *string_to_const(const char *str, Oid datatype);
|
@@ -1761,6 +1762,13 @@ match_special_index_operator(Expr *clause, Oid opclass, Oid relam,
|
1761 | 1762 | pfree(patt);
|
1762 | 1763 | }
|
1763 | 1764 | 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; |
1764 | 1772 | }
|
1765 | 1773 |
|
1766 | 1774 | /* done if the expression doesn't look indexable */
|
@@ -1810,6 +1818,22 @@ match_special_index_operator(Expr *clause, Oid opclass, Oid relam,
|
1810 | 1818 | !op_class(find_operator("<", NAMEOID), opclass, relam))
|
1811 | 1819 | isIndexable = false;
|
1812 | 1820 | 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; |
1813 | 1837 | }
|
1814 | 1838 |
|
1815 | 1839 | return isIndexable;
|
@@ -1924,6 +1948,16 @@ expand_indexqual_conditions(List *indexquals)
|
1924 | 1948 | pfree(patt);
|
1925 | 1949 | break;
|
1926 | 1950 |
|
| 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 | + |
1927 | 1961 | default:
|
1928 | 1962 | resultquals = lappend(resultquals, clause);
|
1929 | 1963 | break;
|
@@ -2037,6 +2071,86 @@ prefix_quals(Var *leftop, Oid expr_op,
|
2037 | 2071 | return result;
|
2038 | 2072 | }
|
2039 | 2073 |
|
| 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 | + |
2040 | 2154 | /*
|
2041 | 2155 | * Handy subroutines for match_special_index_operator() and friends.
|
2042 | 2156 | */
|
|
0 commit comments