Commit d4af2a64 authored by Tom Lane's avatar Tom Lane

Clean up the loose ends in selectivity estimation left by my patch for semi

and anti joins.  To do this, pass the SpecialJoinInfo struct for the current
join as an additional optional argument to operator join selectivity
estimation functions.  This allows the estimator to tell not only what kind
of join is being formed, but which variable is on which side of the join;
a requirement long recognized but not dealt with till now.  This also leaves
the door open for future improvements in the estimators, such as accounting
for the null-insertion effects of lower outer joins.  I didn't do anything
about that in the current patch but the information is in principle deducible
from what's passed.

The patch also clarifies the definition of join selectivity for semi/anti
joins: it's the fraction of the left input that has (at least one) match
in the right input.  This allows getting rid of some very fuzzy thinking
that I had committed in the original 7.4-era IN-optimization patch.
There's probably room to estimate this better than the present patch does,
but at least we know what to estimate.

Since I had to touch CREATE OPERATOR anyway to allow a variant signature
for join estimator functions, I took the opportunity to add a couple of
additional checks that were missing, per my recent message to -hackers:
* Check that estimator functions return float8;
* Require execute permission at the time of CREATE OPERATOR on the
operator's function as well as the estimator functions;
* Require ownership of any pre-existing operator that's modified by
the command.
I also moved the lookup of the functions out of OperatorCreate() and
into operatorcmds.c, since that seemed more consistent with most of
the other catalog object creation processes, eg CREATE TYPE.
parent 11846111
This diff is collapsed.
......@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/operatorcmds.c,v 1.40 2008/06/19 00:46:04 alvherre Exp $
* $PostgreSQL: pgsql/src/backend/commands/operatorcmds.c,v 1.41 2008/08/16 00:01:35 tgl Exp $
*
* DESCRIPTION
* The "DefineFoo" routines take the parse tree and pick out the
......@@ -39,8 +39,10 @@
#include "catalog/indexing.h"
#include "catalog/namespace.h"
#include "catalog/pg_operator.h"
#include "catalog/pg_type.h"
#include "commands/defrem.h"
#include "miscadmin.h"
#include "parser/parse_func.h"
#include "parser/parse_oper.h"
#include "parser/parse_type.h"
#include "utils/acl.h"
......@@ -76,6 +78,11 @@ DefineOperator(List *names, List *parameters)
List *negatorName = NIL; /* optional negator operator name */
List *restrictionName = NIL; /* optional restrict. sel. procedure */
List *joinName = NIL; /* optional join sel. procedure */
Oid functionOid; /* functions converted to OID */
Oid restrictionOid;
Oid joinOid;
Oid typeId[5]; /* only need up to 5 args here */
int nargs;
ListCell *pl;
/* Convert list of names to a name and namespace */
......@@ -154,6 +161,109 @@ DefineOperator(List *names, List *parameters)
if (typeName2)
typeId2 = typenameTypeId(NULL, typeName2, NULL);
if (!OidIsValid(typeId1) && !OidIsValid(typeId2))
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("at least one of leftarg or rightarg must be specified")));
/*
* Look up the operator's underlying function.
*/
if (!OidIsValid(typeId1))
{
typeId[0] = typeId2;
nargs = 1;
}
else if (!OidIsValid(typeId2))
{
typeId[0] = typeId1;
nargs = 1;
}
else
{
typeId[0] = typeId1;
typeId[1] = typeId2;
nargs = 2;
}
functionOid = LookupFuncName(functionName, nargs, typeId, false);
/*
* We require EXECUTE rights for the function. This isn't strictly
* necessary, since EXECUTE will be checked at any attempted use of
* the operator, but it seems like a good idea anyway.
*/
aclresult = pg_proc_aclcheck(functionOid, GetUserId(), ACL_EXECUTE);
if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, ACL_KIND_PROC,
NameListToString(functionName));
/*
* Look up restriction estimator if specified
*/
if (restrictionName)
{
typeId[0] = INTERNALOID; /* PlannerInfo */
typeId[1] = OIDOID; /* operator OID */
typeId[2] = INTERNALOID; /* args list */
typeId[3] = INT4OID; /* varRelid */
restrictionOid = LookupFuncName(restrictionName, 4, typeId, false);
/* estimators must return float8 */
if (get_func_rettype(restrictionOid) != FLOAT8OID)
ereport(ERROR,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
errmsg("restriction estimator function %s must return type \"float8\"",
NameListToString(restrictionName))));
/* Require EXECUTE rights for the estimator */
aclresult = pg_proc_aclcheck(restrictionOid, GetUserId(), ACL_EXECUTE);
if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, ACL_KIND_PROC,
NameListToString(restrictionName));
}
else
restrictionOid = InvalidOid;
/*
* Look up join estimator if specified
*/
if (joinName)
{
typeId[0] = INTERNALOID; /* PlannerInfo */
typeId[1] = OIDOID; /* operator OID */
typeId[2] = INTERNALOID; /* args list */
typeId[3] = INT2OID; /* jointype */
typeId[4] = INTERNALOID; /* SpecialJoinInfo */
/*
* As of Postgres 8.4, the preferred signature for join estimators
* has 5 arguments, but we still allow the old 4-argument form.
* Try the preferred form first.
*/
joinOid = LookupFuncName(joinName, 5, typeId, true);
if (!OidIsValid(joinOid))
joinOid = LookupFuncName(joinName, 4, typeId, true);
/* If not found, reference the 5-argument signature in error msg */
if (!OidIsValid(joinOid))
joinOid = LookupFuncName(joinName, 5, typeId, false);
/* estimators must return float8 */
if (get_func_rettype(joinOid) != FLOAT8OID)
ereport(ERROR,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
errmsg("join estimator function %s must return type \"float8\"",
NameListToString(joinName))));
/* Require EXECUTE rights for the estimator */
aclresult = pg_proc_aclcheck(joinOid, GetUserId(), ACL_EXECUTE);
if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, ACL_KIND_PROC,
NameListToString(joinName));
}
else
joinOid = InvalidOid;
/*
* now have OperatorCreate do all the work..
*/
......@@ -161,11 +271,11 @@ DefineOperator(List *names, List *parameters)
oprNamespace, /* namespace */
typeId1, /* left type id */
typeId2, /* right type id */
functionName, /* function for operator */
functionOid, /* function for operator */
commutatorName, /* optional commutator operator name */
negatorName, /* optional negator operator name */
restrictionName, /* optional restrict. sel. procedure */
joinName, /* optional join sel. procedure name */
restrictionOid, /* optional restrict. sel. procedure */
joinOid, /* optional join sel. procedure name */
canMerge, /* operator merges */
canHash); /* operator hashes */
}
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/path/clausesel.c,v 1.91 2008/08/14 18:47:59 tgl Exp $
* $PostgreSQL: pgsql/src/backend/optimizer/path/clausesel.c,v 1.92 2008/08/16 00:01:36 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -398,6 +398,50 @@ bms_is_subset_singleton(const Bitmapset *s, int x)
return false;
}
/*
* treat_as_join_clause -
* Decide whether an operator clause is to be handled by the
* restriction or join estimator. Subroutine for clause_selectivity().
*/
static inline bool
treat_as_join_clause(Node *clause, RestrictInfo *rinfo,
int varRelid, SpecialJoinInfo *sjinfo)
{
if (varRelid != 0)
{
/*
* Caller is forcing restriction mode (eg, because we are examining
* an inner indexscan qual).
*/
return false;
}
else if (sjinfo == NULL)
{
/*
* It must be a restriction clause, since it's being evaluated at
* a scan node.
*/
return false;
}
else
{
/*
* Otherwise, it's a join if there's more than one relation used.
* We can optimize this calculation if an rinfo was passed.
*
* XXX Since we know the clause is being evaluated at a join,
* the only way it could be single-relation is if it was delayed
* by outer joins. Although we can make use of the restriction
* qual estimators anyway, it seems likely that we ought to account
* for the probability of injected nulls somehow.
*/
if (rinfo)
return (bms_membership(rinfo->clause_relids) == BMS_MULTIPLE);
else
return (NumRelids(clause) > 1);
}
}
/*
* clause_selectivity -
......@@ -429,9 +473,6 @@ bms_is_subset_singleton(const Bitmapset *s, int x)
* root->join_info_list.
* 2. For an INNER join, sjinfo is just a transient struct, and only the
* relids and jointype fields in it can be trusted.
* 3. XXX sjinfo might be NULL even though it really is a join. This case
* will go away soon, but fixing it requires API changes for oprjoin and
* amcostestimate functions.
* It is possible for jointype to be different from sjinfo->jointype.
* This indicates we are considering a variant join: either with
* the LHS and RHS switched, or with one input unique-ified.
......@@ -603,36 +644,14 @@ clause_selectivity(PlannerInfo *root,
else if (is_opclause(clause) || IsA(clause, DistinctExpr))
{
Oid opno = ((OpExpr *) clause)->opno;
bool is_join_clause;
if (varRelid != 0)
{
/*
* If we are considering a nestloop join then all clauses are
* restriction clauses, since we are only interested in the one
* relation.
*/
is_join_clause = false;
}
else
{
/*
* Otherwise, it's a join if there's more than one relation used.
* We can optimize this calculation if an rinfo was passed.
*/
if (rinfo)
is_join_clause = (bms_membership(rinfo->clause_relids) ==
BMS_MULTIPLE);
else
is_join_clause = (NumRelids(clause) > 1);
}
if (is_join_clause)
if (treat_as_join_clause(clause, rinfo, varRelid, sjinfo))
{
/* Estimate selectivity for a join clause. */
s1 = join_selectivity(root, opno,
((OpExpr *) clause)->args,
jointype);
jointype,
sjinfo);
}
else
{
......@@ -671,35 +690,11 @@ clause_selectivity(PlannerInfo *root,
#endif
else if (IsA(clause, ScalarArrayOpExpr))
{
/* First, decide if it's a join clause, same as for OpExpr */
bool is_join_clause;
if (varRelid != 0)
{
/*
* If we are considering a nestloop join then all clauses are
* restriction clauses, since we are only interested in the one
* relation.
*/
is_join_clause = false;
}
else
{
/*
* Otherwise, it's a join if there's more than one relation used.
* We can optimize this calculation if an rinfo was passed.
*/
if (rinfo)
is_join_clause = (bms_membership(rinfo->clause_relids) ==
BMS_MULTIPLE);
else
is_join_clause = (NumRelids(clause) > 1);
}
/* Use node specific selectivity calculation function */
s1 = scalararraysel(root,
(ScalarArrayOpExpr *) clause,
is_join_clause,
treat_as_join_clause(clause, rinfo,
varRelid, sjinfo),
varRelid,
jointype,
sjinfo);
......
This diff is collapsed.
......@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/util/plancat.c,v 1.148 2008/07/13 20:45:47 tgl Exp $
* $PostgreSQL: pgsql/src/backend/optimizer/util/plancat.c,v 1.149 2008/08/16 00:01:36 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -830,7 +830,8 @@ Selectivity
join_selectivity(PlannerInfo *root,
Oid operator,
List *args,
JoinType jointype)
JoinType jointype,
SpecialJoinInfo *sjinfo)
{
RegProcedure oprjoin = get_oprjoin(operator);
float8 result;
......@@ -842,11 +843,12 @@ join_selectivity(PlannerInfo *root,
if (!oprjoin)
return (Selectivity) 0.5;
result = DatumGetFloat8(OidFunctionCall4(oprjoin,
result = DatumGetFloat8(OidFunctionCall5(oprjoin,
PointerGetDatum(root),
ObjectIdGetDatum(operator),
PointerGetDatum(args),
Int16GetDatum(jointype)));
Int16GetDatum(jointype),
PointerGetDatum(sjinfo)));
if (result < 0.0 || result > 1.0)
elog(ERROR, "invalid join selectivity: %f", result);
......
This diff is collapsed.
......@@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.477 2008/08/11 13:58:46 heikki Exp $
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.478 2008/08/16 00:01:37 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -53,6 +53,6 @@
*/
/* yyyymmddN */
#define CATALOG_VERSION_NO 200808111
#define CATALOG_VERSION_NO 200808141
#endif
......@@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/catalog/pg_operator.h,v 1.161 2008/07/14 00:51:45 tgl Exp $
* $PostgreSQL: pgsql/src/include/catalog/pg_operator.h,v 1.162 2008/08/16 00:01:37 tgl Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
......@@ -941,11 +941,11 @@ extern void OperatorCreate(const char *operatorName,
Oid operatorNamespace,
Oid leftTypeId,
Oid rightTypeId,
List *procedureName,
Oid procedureId,
List *commutatorName,
List *negatorName,
List *restrictionName,
List *joinName,
Oid restrictionId,
Oid joinId,
bool canMerge,
bool canHash);
......
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.509 2008/07/18 03:32:53 tgl Exp $
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.510 2008/08/16 00:01:37 tgl Exp $
*
* NOTES
* The script catalog/genbki.sh reads this file and generates .bki
......@@ -223,13 +223,13 @@ DATA(insert OID = 103 ( scalarltsel PGNSP PGUID 12 1 0 0 f f t f s 4 701 "22
DESCR("restriction selectivity of < and related operators on scalar datatypes");
DATA(insert OID = 104 ( scalargtsel PGNSP PGUID 12 1 0 0 f f t f s 4 701 "2281 26 2281 23" _null_ _null_ _null_ scalargtsel _null_ _null_ _null_ ));
DESCR("restriction selectivity of > and related operators on scalar datatypes");
DATA(insert OID = 105 ( eqjoinsel PGNSP PGUID 12 1 0 0 f f t f s 4 701 "2281 26 2281 21" _null_ _null_ _null_ eqjoinsel _null_ _null_ _null_ ));
DATA(insert OID = 105 ( eqjoinsel PGNSP PGUID 12 1 0 0 f f t f s 5 701 "2281 26 2281 21 2281" _null_ _null_ _null_ eqjoinsel _null_ _null_ _null_ ));
DESCR("join selectivity of = and related operators");
DATA(insert OID = 106 ( neqjoinsel PGNSP PGUID 12 1 0 0 f f t f s 4 701 "2281 26 2281 21" _null_ _null_ _null_ neqjoinsel _null_ _null_ _null_ ));
DATA(insert OID = 106 ( neqjoinsel PGNSP PGUID 12 1 0 0 f f t f s 5 701 "2281 26 2281 21 2281" _null_ _null_ _null_ neqjoinsel _null_ _null_ _null_ ));
DESCR("join selectivity of <> and related operators");
DATA(insert OID = 107 ( scalarltjoinsel PGNSP PGUID 12 1 0 0 f f t f s 4 701 "2281 26 2281 21" _null_ _null_ _null_ scalarltjoinsel _null_ _null_ _null_ ));
DATA(insert OID = 107 ( scalarltjoinsel PGNSP PGUID 12 1 0 0 f f t f s 5 701 "2281 26 2281 21 2281" _null_ _null_ _null_ scalarltjoinsel _null_ _null_ _null_ ));
DESCR("join selectivity of < and related operators on scalar datatypes");
DATA(insert OID = 108 ( scalargtjoinsel PGNSP PGUID 12 1 0 0 f f t f s 4 701 "2281 26 2281 21" _null_ _null_ _null_ scalargtjoinsel _null_ _null_ _null_ ));
DATA(insert OID = 108 ( scalargtjoinsel PGNSP PGUID 12 1 0 0 f f t f s 5 701 "2281 26 2281 21 2281" _null_ _null_ _null_ scalargtjoinsel _null_ _null_ _null_ ));
DESCR("join selectivity of > and related operators on scalar datatypes");
DATA(insert OID = 109 ( unknownin PGNSP PGUID 12 1 0 0 f f t f i 1 705 "2275" _null_ _null_ _null_ unknownin _null_ _null_ _null_ ));
......@@ -289,7 +289,7 @@ DATA(insert OID = 138 ( box_center PGNSP PGUID 12 1 0 0 f f t f i 1 600 "60
DESCR("center of");
DATA(insert OID = 139 ( areasel PGNSP PGUID 12 1 0 0 f f t f s 4 701 "2281 26 2281 23" _null_ _null_ _null_ areasel _null_ _null_ _null_ ));
DESCR("restriction selectivity for area-comparison operators");
DATA(insert OID = 140 ( areajoinsel PGNSP PGUID 12 1 0 0 f f t f s 4 701 "2281 26 2281 21" _null_ _null_ _null_ areajoinsel _null_ _null_ _null_ ));
DATA(insert OID = 140 ( areajoinsel PGNSP PGUID 12 1 0 0 f f t f s 5 701 "2281 26 2281 21 2281" _null_ _null_ _null_ areajoinsel _null_ _null_ _null_ ));
DESCR("join selectivity for area-comparison operators");
DATA(insert OID = 141 ( int4mul PGNSP PGUID 12 1 0 0 f f t f i 2 23 "23 23" _null_ _null_ _null_ int4mul _null_ _null_ _null_ ));
DESCR("multiply");
......@@ -1630,11 +1630,11 @@ DESCR("current clock time");
DATA(insert OID = 1300 ( positionsel PGNSP PGUID 12 1 0 0 f f t f s 4 701 "2281 26 2281 23" _null_ _null_ _null_ positionsel _null_ _null_ _null_ ));
DESCR("restriction selectivity for position-comparison operators");
DATA(insert OID = 1301 ( positionjoinsel PGNSP PGUID 12 1 0 0 f f t f s 4 701 "2281 26 2281 21" _null_ _null_ _null_ positionjoinsel _null_ _null_ _null_ ));
DATA(insert OID = 1301 ( positionjoinsel PGNSP PGUID 12 1 0 0 f f t f s 5 701 "2281 26 2281 21 2281" _null_ _null_ _null_ positionjoinsel _null_ _null_ _null_ ));
DESCR("join selectivity for position-comparison operators");
DATA(insert OID = 1302 ( contsel PGNSP PGUID 12 1 0 0 f f t f s 4 701 "2281 26 2281 23" _null_ _null_ _null_ contsel _null_ _null_ _null_ ));
DESCR("restriction selectivity for containment comparison operators");
DATA(insert OID = 1303 ( contjoinsel PGNSP PGUID 12 1 0 0 f f t f s 4 701 "2281 26 2281 21" _null_ _null_ _null_ contjoinsel _null_ _null_ _null_ ));
DATA(insert OID = 1303 ( contjoinsel PGNSP PGUID 12 1 0 0 f f t f s 5 701 "2281 26 2281 21 2281" _null_ _null_ _null_ contjoinsel _null_ _null_ _null_ ));
DESCR("join selectivity for containment comparison operators");
DATA(insert OID = 1304 ( overlaps PGNSP PGUID 12 1 0 0 f f f f i 4 16 "1184 1184 1184 1184" _null_ _null_ _null_ overlaps_timestamp _null_ _null_ _null_ ));
......@@ -2684,9 +2684,9 @@ DATA(insert OID = 1814 ( iclikesel PGNSP PGUID 12 1 0 0 f f t f s 4 701 "2281
DESCR("restriction selectivity of ILIKE");
DATA(insert OID = 1815 ( icnlikesel PGNSP PGUID 12 1 0 0 f f t f s 4 701 "2281 26 2281 23" _null_ _null_ _null_ icnlikesel _null_ _null_ _null_ ));
DESCR("restriction selectivity of NOT ILIKE");
DATA(insert OID = 1816 ( iclikejoinsel PGNSP PGUID 12 1 0 0 f f t f s 4 701 "2281 26 2281 21" _null_ _null_ _null_ iclikejoinsel _null_ _null_ _null_ ));
DATA(insert OID = 1816 ( iclikejoinsel PGNSP PGUID 12 1 0 0 f f t f s 5 701 "2281 26 2281 21 2281" _null_ _null_ _null_ iclikejoinsel _null_ _null_ _null_ ));
DESCR("join selectivity of ILIKE");
DATA(insert OID = 1817 ( icnlikejoinsel PGNSP PGUID 12 1 0 0 f f t f s 4 701 "2281 26 2281 21" _null_ _null_ _null_ icnlikejoinsel _null_ _null_ _null_ ));
DATA(insert OID = 1817 ( icnlikejoinsel PGNSP PGUID 12 1 0 0 f f t f s 5 701 "2281 26 2281 21 2281" _null_ _null_ _null_ icnlikejoinsel _null_ _null_ _null_ ));
DESCR("join selectivity of NOT ILIKE");
DATA(insert OID = 1818 ( regexeqsel PGNSP PGUID 12 1 0 0 f f t f s 4 701 "2281 26 2281 23" _null_ _null_ _null_ regexeqsel _null_ _null_ _null_ ));
DESCR("restriction selectivity of regex match");
......@@ -2700,17 +2700,17 @@ DATA(insert OID = 1822 ( nlikesel PGNSP PGUID 12 1 0 0 f f t f s 4 701 "2281 2
DESCR("restriction selectivity of NOT LIKE");
DATA(insert OID = 1823 ( icregexnesel PGNSP PGUID 12 1 0 0 f f t f s 4 701 "2281 26 2281 23" _null_ _null_ _null_ icregexnesel _null_ _null_ _null_ ));
DESCR("restriction selectivity of case-insensitive regex non-match");
DATA(insert OID = 1824 ( regexeqjoinsel PGNSP PGUID 12 1 0 0 f f t f s 4 701 "2281 26 2281 21" _null_ _null_ _null_ regexeqjoinsel _null_ _null_ _null_ ));
DATA(insert OID = 1824 ( regexeqjoinsel PGNSP PGUID 12 1 0 0 f f t f s 5 701 "2281 26 2281 21 2281" _null_ _null_ _null_ regexeqjoinsel _null_ _null_ _null_ ));
DESCR("join selectivity of regex match");
DATA(insert OID = 1825 ( likejoinsel PGNSP PGUID 12 1 0 0 f f t f s 4 701 "2281 26 2281 21" _null_ _null_ _null_ likejoinsel _null_ _null_ _null_ ));
DATA(insert OID = 1825 ( likejoinsel PGNSP PGUID 12 1 0 0 f f t f s 5 701 "2281 26 2281 21 2281" _null_ _null_ _null_ likejoinsel _null_ _null_ _null_ ));
DESCR("join selectivity of LIKE");
DATA(insert OID = 1826 ( icregexeqjoinsel PGNSP PGUID 12 1 0 0 f f t f s 4 701 "2281 26 2281 21" _null_ _null_ _null_ icregexeqjoinsel _null_ _null_ _null_ ));
DATA(insert OID = 1826 ( icregexeqjoinsel PGNSP PGUID 12 1 0 0 f f t f s 5 701 "2281 26 2281 21 2281" _null_ _null_ _null_ icregexeqjoinsel _null_ _null_ _null_ ));
DESCR("join selectivity of case-insensitive regex match");
DATA(insert OID = 1827 ( regexnejoinsel PGNSP PGUID 12 1 0 0 f f t f s 4 701 "2281 26 2281 21" _null_ _null_ _null_ regexnejoinsel _null_ _null_ _null_ ));
DATA(insert OID = 1827 ( regexnejoinsel PGNSP PGUID 12 1 0 0 f f t f s 5 701 "2281 26 2281 21 2281" _null_ _null_ _null_ regexnejoinsel _null_ _null_ _null_ ));
DESCR("join selectivity of regex non-match");
DATA(insert OID = 1828 ( nlikejoinsel PGNSP PGUID 12 1 0 0 f f t f s 4 701 "2281 26 2281 21" _null_ _null_ _null_ nlikejoinsel _null_ _null_ _null_ ));
DATA(insert OID = 1828 ( nlikejoinsel PGNSP PGUID 12 1 0 0 f f t f s 5 701 "2281 26 2281 21 2281" _null_ _null_ _null_ nlikejoinsel _null_ _null_ _null_ ));
DESCR("join selectivity of NOT LIKE");
DATA(insert OID = 1829 ( icregexnejoinsel PGNSP PGUID 12 1 0 0 f f t f s 4 701 "2281 26 2281 21" _null_ _null_ _null_ icregexnejoinsel _null_ _null_ _null_ ));
DATA(insert OID = 1829 ( icregexnejoinsel PGNSP PGUID 12 1 0 0 f f t f s 5 701 "2281 26 2281 21 2281" _null_ _null_ _null_ icregexnejoinsel _null_ _null_ _null_ ));
DESCR("join selectivity of case-insensitive regex non-match");
/* Aggregate-related functions */
......
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/optimizer/plancat.h,v 1.50 2008/06/19 00:46:06 alvherre Exp $
* $PostgreSQL: pgsql/src/include/optimizer/plancat.h,v 1.51 2008/08/16 00:01:38 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -50,6 +50,7 @@ extern Selectivity restriction_selectivity(PlannerInfo *root,
extern Selectivity join_selectivity(PlannerInfo *root,
Oid operator,
List *args,
JoinType jointype);
JoinType jointype,
SpecialJoinInfo *sjinfo);
#endif /* PLANCAT_H */
......@@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/utils/selfuncs.h,v 1.45 2008/08/14 18:48:00 tgl Exp $
* $PostgreSQL: pgsql/src/include/utils/selfuncs.h,v 1.46 2008/08/16 00:01:38 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -104,8 +104,10 @@ extern bool get_restriction_variable(PlannerInfo *root, List *args,
VariableStatData *vardata, Node **other,
bool *varonleft);
extern void get_join_variables(PlannerInfo *root, List *args,
SpecialJoinInfo *sjinfo,
VariableStatData *vardata1,
VariableStatData *vardata2);
VariableStatData *vardata2,
bool *join_is_reversed);
extern double get_variable_numdistinct(VariableStatData *vardata);
extern double mcv_selectivity(VariableStatData *vardata, FmgrInfo *opproc,
Datum constval, bool varonleft,
......
......@@ -543,17 +543,20 @@ WHERE p1.oprrest = p2.oid AND
-- If oprjoin is set, the operator must be a binary boolean op,
-- and it must link to a proc with the right signature
-- to be a join selectivity estimator.
-- The proc signature we want is: float8 proc(internal, oid, internal, int2)
-- The proc signature we want is: float8 proc(internal, oid, internal, int2, internal)
-- (Note: the old signature with only 4 args is still allowed, but no core
-- estimator should be using it.)
SELECT p1.oid, p1.oprname, p2.oid, p2.proname
FROM pg_operator AS p1, pg_proc AS p2
WHERE p1.oprjoin = p2.oid AND
(p1.oprkind != 'b' OR p1.oprresult != 'bool'::regtype OR
p2.prorettype != 'float8'::regtype OR p2.proretset OR
p2.pronargs != 4 OR
p2.pronargs != 5 OR
p2.proargtypes[0] != 'internal'::regtype OR
p2.proargtypes[1] != 'oid'::regtype OR
p2.proargtypes[2] != 'internal'::regtype OR
p2.proargtypes[3] != 'int2'::regtype);
p2.proargtypes[3] != 'int2'::regtype OR
p2.proargtypes[4] != 'internal'::regtype);
oid | oprname | oid | proname
-----+---------+-----+---------
(0 rows)
......
......@@ -444,18 +444,21 @@ WHERE p1.oprrest = p2.oid AND
-- If oprjoin is set, the operator must be a binary boolean op,
-- and it must link to a proc with the right signature
-- to be a join selectivity estimator.
-- The proc signature we want is: float8 proc(internal, oid, internal, int2)
-- The proc signature we want is: float8 proc(internal, oid, internal, int2, internal)
-- (Note: the old signature with only 4 args is still allowed, but no core
-- estimator should be using it.)
SELECT p1.oid, p1.oprname, p2.oid, p2.proname
FROM pg_operator AS p1, pg_proc AS p2
WHERE p1.oprjoin = p2.oid AND
(p1.oprkind != 'b' OR p1.oprresult != 'bool'::regtype OR
p2.prorettype != 'float8'::regtype OR p2.proretset OR
p2.pronargs != 4 OR
p2.pronargs != 5 OR
p2.proargtypes[0] != 'internal'::regtype OR
p2.proargtypes[1] != 'oid'::regtype OR
p2.proargtypes[2] != 'internal'::regtype OR
p2.proargtypes[3] != 'int2'::regtype);
p2.proargtypes[3] != 'int2'::regtype OR
p2.proargtypes[4] != 'internal'::regtype);
-- **************** pg_aggregate ****************
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment