Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
P
Postgres FD Implementation
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Abuhujair Javed
Postgres FD Implementation
Commits
7b7df9f0
Commit
7b7df9f0
authored
Sep 28, 2008
by
Tom Lane
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add hooks to let plugins override the planner's lookups in pg_statistic.
Simon Riggs, with some editorialization by me.
parent
bc965e84
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
109 additions
and
23 deletions
+109
-23
src/backend/utils/adt/selfuncs.c
src/backend/utils/adt/selfuncs.c
+69
-16
src/backend/utils/cache/lsyscache.c
src/backend/utils/cache/lsyscache.c
+19
-3
src/include/utils/lsyscache.h
src/include/utils/lsyscache.h
+5
-1
src/include/utils/selfuncs.h
src/include/utils/selfuncs.h
+16
-3
No files found.
src/backend/utils/adt/selfuncs.c
View file @
7b7df9f0
...
@@ -15,7 +15,7 @@
...
@@ -15,7 +15,7 @@
*
*
*
*
* IDENTIFICATION
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/selfuncs.c,v 1.25
3 2008/08/25 22:42:34
tgl Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/selfuncs.c,v 1.25
4 2008/09/28 19:51:40
tgl Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
...
@@ -119,6 +119,10 @@
...
@@ -119,6 +119,10 @@
#include "utils/syscache.h"
#include "utils/syscache.h"
/* Hooks for plugins to get control when we ask for stats */
get_relation_stats_hook_type
get_relation_stats_hook
=
NULL
;
get_index_stats_hook_type
get_index_stats_hook
=
NULL
;
static
double
var_eq_const
(
VariableStatData
*
vardata
,
Oid
operator
,
static
double
var_eq_const
(
VariableStatData
*
vardata
,
Oid
operator
,
Datum
constval
,
bool
constisnull
,
Datum
constval
,
bool
constisnull
,
bool
varonleft
);
bool
varonleft
);
...
@@ -2935,7 +2939,7 @@ estimate_num_groups(PlannerInfo *root, List *groupExprs, double input_rows)
...
@@ -2935,7 +2939,7 @@ estimate_num_groups(PlannerInfo *root, List *groupExprs, double input_rows)
* complicated.
* complicated.
*/
*/
examine_variable
(
root
,
groupexpr
,
0
,
&
vardata
);
examine_variable
(
root
,
groupexpr
,
0
,
&
vardata
);
if
(
vardata
.
statsTuple
!=
NULL
||
vardata
.
isunique
)
if
(
HeapTupleIsValid
(
vardata
.
statsTuple
)
||
vardata
.
isunique
)
{
{
varinfos
=
add_unique_group_var
(
root
,
varinfos
,
varinfos
=
add_unique_group_var
(
root
,
varinfos
,
groupexpr
,
&
vardata
);
groupexpr
,
&
vardata
);
...
@@ -3942,6 +3946,7 @@ get_join_variables(PlannerInfo *root, List *args, SpecialJoinInfo *sjinfo,
...
@@ -3942,6 +3946,7 @@ get_join_variables(PlannerInfo *root, List *args, SpecialJoinInfo *sjinfo,
* subquery, not one in the current query).
* subquery, not one in the current query).
* statsTuple: the pg_statistic entry for the variable, if one exists;
* statsTuple: the pg_statistic entry for the variable, if one exists;
* otherwise NULL.
* otherwise NULL.
* freefunc: pointer to a function to release statsTuple with.
* vartype: exposed type of the expression; this should always match
* vartype: exposed type of the expression; this should always match
* the declared input type of the operator we are estimating for.
* the declared input type of the operator we are estimating for.
* atttype, atttypmod: type data to pass to get_attstatsslot(). This is
* atttype, atttypmod: type data to pass to get_attstatsslot(). This is
...
@@ -3986,7 +3991,18 @@ examine_variable(PlannerInfo *root, Node *node, int varRelid,
...
@@ -3986,7 +3991,18 @@ examine_variable(PlannerInfo *root, Node *node, int varRelid,
rte
=
root
->
simple_rte_array
[
var
->
varno
];
rte
=
root
->
simple_rte_array
[
var
->
varno
];
if
(
rte
->
inh
)
if
(
get_relation_stats_hook
&&
(
*
get_relation_stats_hook
)
(
root
,
rte
,
var
->
varattno
,
vardata
))
{
/*
* The hook took control of acquiring a stats tuple. If it
* did supply a tuple, it'd better have supplied a freefunc.
*/
if
(
HeapTupleIsValid
(
vardata
->
statsTuple
)
&&
!
vardata
->
freefunc
)
elog
(
ERROR
,
"no function provided to release variable stats with"
);
}
else
if
(
rte
->
inh
)
{
{
/*
/*
* XXX This means the Var represents a column of an append
* XXX This means the Var represents a column of an append
...
@@ -4000,6 +4016,7 @@ examine_variable(PlannerInfo *root, Node *node, int varRelid,
...
@@ -4000,6 +4016,7 @@ examine_variable(PlannerInfo *root, Node *node, int varRelid,
ObjectIdGetDatum
(
rte
->
relid
),
ObjectIdGetDatum
(
rte
->
relid
),
Int16GetDatum
(
var
->
varattno
),
Int16GetDatum
(
var
->
varattno
),
0
,
0
);
0
,
0
);
vardata
->
freefunc
=
ReleaseSysCache
;
}
}
else
else
{
{
...
@@ -4116,10 +4133,28 @@ examine_variable(PlannerInfo *root, Node *node, int varRelid,
...
@@ -4116,10 +4133,28 @@ examine_variable(PlannerInfo *root, Node *node, int varRelid,
index
->
indpred
==
NIL
)
index
->
indpred
==
NIL
)
vardata
->
isunique
=
true
;
vardata
->
isunique
=
true
;
/* Has it got stats? */
/* Has it got stats? */
vardata
->
statsTuple
=
SearchSysCache
(
STATRELATT
,
if
(
get_index_stats_hook
&&
ObjectIdGetDatum
(
index
->
indexoid
),
(
*
get_index_stats_hook
)
(
root
,
index
->
indexoid
,
Int16GetDatum
(
pos
+
1
),
pos
+
1
,
vardata
))
0
,
0
);
{
/*
* The hook took control of acquiring a stats
* tuple. If it did supply a tuple, it'd better
* have supplied a freefunc.
*/
if
(
HeapTupleIsValid
(
vardata
->
statsTuple
)
&&
!
vardata
->
freefunc
)
elog
(
ERROR
,
"no function provided to release variable stats with"
);
}
else
{
vardata
->
statsTuple
=
SearchSysCache
(
STATRELATT
,
ObjectIdGetDatum
(
index
->
indexoid
),
Int16GetDatum
(
pos
+
1
),
0
,
0
);
vardata
->
freefunc
=
ReleaseSysCache
;
}
if
(
vardata
->
statsTuple
)
if
(
vardata
->
statsTuple
)
break
;
break
;
}
}
...
@@ -5551,7 +5586,7 @@ btcostestimate(PG_FUNCTION_ARGS)
...
@@ -5551,7 +5586,7 @@ btcostestimate(PG_FUNCTION_ARGS)
double
*
indexCorrelation
=
(
double
*
)
PG_GETARG_POINTER
(
7
);
double
*
indexCorrelation
=
(
double
*
)
PG_GETARG_POINTER
(
7
);
Oid
relid
;
Oid
relid
;
AttrNumber
colnum
;
AttrNumber
colnum
;
HeapTuple
tuple
;
VariableStatData
vardata
;
double
numIndexTuples
;
double
numIndexTuples
;
List
*
indexBoundQuals
;
List
*
indexBoundQuals
;
int
indexcol
;
int
indexcol
;
...
@@ -5756,17 +5791,34 @@ btcostestimate(PG_FUNCTION_ARGS)
...
@@ -5756,17 +5791,34 @@ btcostestimate(PG_FUNCTION_ARGS)
colnum
=
1
;
colnum
=
1
;
}
}
tuple
=
SearchSysCache
(
STATRELATT
,
MemSet
(
&
vardata
,
0
,
sizeof
(
vardata
));
ObjectIdGetDatum
(
relid
),
Int16GetDatum
(
colnum
),
0
,
0
);
if
(
HeapTupleIsValid
(
tuple
))
if
(
get_index_stats_hook
&&
(
*
get_index_stats_hook
)
(
root
,
relid
,
colnum
,
&
vardata
))
{
/*
* The hook took control of acquiring a stats tuple. If it did supply
* a tuple, it'd better have supplied a freefunc.
*/
if
(
HeapTupleIsValid
(
vardata
.
statsTuple
)
&&
!
vardata
.
freefunc
)
elog
(
ERROR
,
"no function provided to release variable stats with"
);
}
else
{
vardata
.
statsTuple
=
SearchSysCache
(
STATRELATT
,
ObjectIdGetDatum
(
relid
),
Int16GetDatum
(
colnum
),
0
,
0
);
vardata
.
freefunc
=
ReleaseSysCache
;
}
if
(
HeapTupleIsValid
(
vardata
.
statsTuple
))
{
{
float4
*
numbers
;
float4
*
numbers
;
int
nnumbers
;
int
nnumbers
;
if
(
get_attstatsslot
(
t
uple
,
InvalidOid
,
0
,
if
(
get_attstatsslot
(
vardata
.
statsT
uple
,
InvalidOid
,
0
,
STATISTIC_KIND_CORRELATION
,
STATISTIC_KIND_CORRELATION
,
index
->
fwdsortop
[
0
],
index
->
fwdsortop
[
0
],
NULL
,
NULL
,
&
numbers
,
&
nnumbers
))
NULL
,
NULL
,
&
numbers
,
&
nnumbers
))
...
@@ -5783,7 +5835,7 @@ btcostestimate(PG_FUNCTION_ARGS)
...
@@ -5783,7 +5835,7 @@ btcostestimate(PG_FUNCTION_ARGS)
free_attstatsslot
(
InvalidOid
,
NULL
,
0
,
numbers
,
nnumbers
);
free_attstatsslot
(
InvalidOid
,
NULL
,
0
,
numbers
,
nnumbers
);
}
}
else
if
(
get_attstatsslot
(
t
uple
,
InvalidOid
,
0
,
else
if
(
get_attstatsslot
(
vardata
.
statsT
uple
,
InvalidOid
,
0
,
STATISTIC_KIND_CORRELATION
,
STATISTIC_KIND_CORRELATION
,
index
->
revsortop
[
0
],
index
->
revsortop
[
0
],
NULL
,
NULL
,
&
numbers
,
&
nnumbers
))
NULL
,
NULL
,
&
numbers
,
&
nnumbers
))
...
@@ -5800,9 +5852,10 @@ btcostestimate(PG_FUNCTION_ARGS)
...
@@ -5800,9 +5852,10 @@ btcostestimate(PG_FUNCTION_ARGS)
free_attstatsslot
(
InvalidOid
,
NULL
,
0
,
numbers
,
nnumbers
);
free_attstatsslot
(
InvalidOid
,
NULL
,
0
,
numbers
,
nnumbers
);
}
}
ReleaseSysCache
(
tuple
);
}
}
ReleaseVariableStats
(
vardata
);
PG_RETURN_VOID
();
PG_RETURN_VOID
();
}
}
...
...
src/backend/utils/cache/lsyscache.c
View file @
7b7df9f0
...
@@ -7,7 +7,7 @@
...
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/cache/lsyscache.c,v 1.1
59 2008/08/02 21:32:0
0 tgl Exp $
* $PostgreSQL: pgsql/src/backend/utils/cache/lsyscache.c,v 1.1
60 2008/09/28 19:51:4
0 tgl Exp $
*
*
* NOTES
* NOTES
* Eventually, the index information should go through here, too.
* Eventually, the index information should go through here, too.
...
@@ -35,6 +35,9 @@
...
@@ -35,6 +35,9 @@
#include "utils/lsyscache.h"
#include "utils/lsyscache.h"
#include "utils/syscache.h"
#include "utils/syscache.h"
/* Hook for plugins to get control in get_attavgwidth() */
get_attavgwidth_hook_type
get_attavgwidth_hook
=
NULL
;
/* ---------- AMOP CACHES ---------- */
/* ---------- AMOP CACHES ---------- */
...
@@ -2492,20 +2495,30 @@ get_typmodout(Oid typid)
...
@@ -2492,20 +2495,30 @@ get_typmodout(Oid typid)
*
*
* Given the table and attribute number of a column, get the average
* Given the table and attribute number of a column, get the average
* width of entries in the column. Return zero if no data available.
* width of entries in the column. Return zero if no data available.
*
* Calling a hook at this point looks somewhat strange, but is required
* because the optimizer calls this function without any other way for
* plug-ins to control the result.
*/
*/
int32
int32
get_attavgwidth
(
Oid
relid
,
AttrNumber
attnum
)
get_attavgwidth
(
Oid
relid
,
AttrNumber
attnum
)
{
{
HeapTuple
tp
;
HeapTuple
tp
;
int32
stawidth
;
if
(
get_attavgwidth_hook
)
{
stawidth
=
(
*
get_attavgwidth_hook
)
(
relid
,
attnum
);
if
(
stawidth
>
0
)
return
stawidth
;
}
tp
=
SearchSysCache
(
STATRELATT
,
tp
=
SearchSysCache
(
STATRELATT
,
ObjectIdGetDatum
(
relid
),
ObjectIdGetDatum
(
relid
),
Int16GetDatum
(
attnum
),
Int16GetDatum
(
attnum
),
0
,
0
);
0
,
0
);
if
(
HeapTupleIsValid
(
tp
))
if
(
HeapTupleIsValid
(
tp
))
{
{
int32
stawidth
=
((
Form_pg_statistic
)
GETSTRUCT
(
tp
))
->
stawidth
;
stawidth
=
((
Form_pg_statistic
)
GETSTRUCT
(
tp
))
->
stawidth
;
ReleaseSysCache
(
tp
);
ReleaseSysCache
(
tp
);
if
(
stawidth
>
0
)
if
(
stawidth
>
0
)
return
stawidth
;
return
stawidth
;
...
@@ -2523,6 +2536,9 @@ get_attavgwidth(Oid relid, AttrNumber attnum)
...
@@ -2523,6 +2536,9 @@ get_attavgwidth(Oid relid, AttrNumber attnum)
* already-looked-up tuple in the pg_statistic cache. We do this since
* already-looked-up tuple in the pg_statistic cache. We do this since
* most callers will want to extract more than one value from the cache
* most callers will want to extract more than one value from the cache
* entry, and we don't want to repeat the cache lookup unnecessarily.
* entry, and we don't want to repeat the cache lookup unnecessarily.
* Also, this API allows this routine to be used with statistics tuples
* that have been provided by a stats hook and didn't really come from
* pg_statistic.
*
*
* statstuple: pg_statistics tuple to be examined.
* statstuple: pg_statistics tuple to be examined.
* atttype: type OID of attribute (can be InvalidOid if values == NULL).
* atttype: type OID of attribute (can be InvalidOid if values == NULL).
...
...
src/include/utils/lsyscache.h
View file @
7b7df9f0
...
@@ -6,7 +6,7 @@
...
@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* $PostgreSQL: pgsql/src/include/utils/lsyscache.h,v 1.12
5 2008/08/02 21:32:01
tgl Exp $
* $PostgreSQL: pgsql/src/include/utils/lsyscache.h,v 1.12
6 2008/09/28 19:51:40
tgl Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
...
@@ -26,6 +26,10 @@ typedef enum IOFuncSelector
...
@@ -26,6 +26,10 @@ typedef enum IOFuncSelector
IOFunc_send
IOFunc_send
}
IOFuncSelector
;
}
IOFuncSelector
;
/* Hook for plugins to get control in get_attavgwidth() */
typedef
int32
(
*
get_attavgwidth_hook_type
)
(
Oid
relid
,
AttrNumber
attnum
);
extern
PGDLLIMPORT
get_attavgwidth_hook_type
get_attavgwidth_hook
;
extern
bool
op_in_opfamily
(
Oid
opno
,
Oid
opfamily
);
extern
bool
op_in_opfamily
(
Oid
opno
,
Oid
opfamily
);
extern
int
get_op_opfamily_strategy
(
Oid
opno
,
Oid
opfamily
);
extern
int
get_op_opfamily_strategy
(
Oid
opno
,
Oid
opfamily
);
extern
void
get_op_opfamily_properties
(
Oid
opno
,
Oid
opfamily
,
extern
void
get_op_opfamily_properties
(
Oid
opno
,
Oid
opfamily
,
...
...
src/include/utils/selfuncs.h
View file @
7b7df9f0
...
@@ -8,7 +8,7 @@
...
@@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* $PostgreSQL: pgsql/src/include/utils/selfuncs.h,v 1.4
6 2008/08/16 00:01:38
tgl Exp $
* $PostgreSQL: pgsql/src/include/utils/selfuncs.h,v 1.4
7 2008/09/28 19:51:40
tgl Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
...
@@ -64,12 +64,13 @@
...
@@ -64,12 +64,13 @@
/* Return data from examine_variable and friends */
/* Return data from examine_variable and friends */
typedef
struct
typedef
struct
VariableStatData
{
{
Node
*
var
;
/* the Var or expression tree */
Node
*
var
;
/* the Var or expression tree */
RelOptInfo
*
rel
;
/* Relation, or NULL if not identifiable */
RelOptInfo
*
rel
;
/* Relation, or NULL if not identifiable */
HeapTuple
statsTuple
;
/* pg_statistic tuple, or NULL if none */
HeapTuple
statsTuple
;
/* pg_statistic tuple, or NULL if none */
/* NB: if statsTuple!=NULL, it must be freed when caller is done */
/* NB: if statsTuple!=NULL, it must be freed when caller is done */
void
(
*
freefunc
)
(
HeapTuple
tuple
);
/* how to free statsTuple */
Oid
vartype
;
/* exposed type of expression */
Oid
vartype
;
/* exposed type of expression */
Oid
atttype
;
/* type to pass to get_attstatsslot */
Oid
atttype
;
/* type to pass to get_attstatsslot */
int32
atttypmod
;
/* typmod to pass to get_attstatsslot */
int32
atttypmod
;
/* typmod to pass to get_attstatsslot */
...
@@ -79,7 +80,7 @@ typedef struct
...
@@ -79,7 +80,7 @@ typedef struct
#define ReleaseVariableStats(vardata) \
#define ReleaseVariableStats(vardata) \
do { \
do { \
if (HeapTupleIsValid((vardata).statsTuple)) \
if (HeapTupleIsValid((vardata).statsTuple)) \
ReleaseSysCache
((vardata).statsTuple); \
(* (vardata).freefunc)
((vardata).statsTuple); \
} while(0)
} while(0)
...
@@ -97,6 +98,18 @@ typedef enum
...
@@ -97,6 +98,18 @@ typedef enum
/* selfuncs.c */
/* selfuncs.c */
/* Hooks for plugins to get control when we ask for stats */
typedef
bool
(
*
get_relation_stats_hook_type
)
(
PlannerInfo
*
root
,
RangeTblEntry
*
rte
,
AttrNumber
attnum
,
VariableStatData
*
vardata
);
extern
PGDLLIMPORT
get_relation_stats_hook_type
get_relation_stats_hook
;
typedef
bool
(
*
get_index_stats_hook_type
)
(
PlannerInfo
*
root
,
Oid
indexOid
,
AttrNumber
indexattnum
,
VariableStatData
*
vardata
);
extern
PGDLLIMPORT
get_index_stats_hook_type
get_index_stats_hook
;
extern
void
examine_variable
(
PlannerInfo
*
root
,
Node
*
node
,
int
varRelid
,
extern
void
examine_variable
(
PlannerInfo
*
root
,
Node
*
node
,
int
varRelid
,
VariableStatData
*
vardata
);
VariableStatData
*
vardata
);
extern
bool
get_restriction_variable
(
PlannerInfo
*
root
,
List
*
args
,
extern
bool
get_restriction_variable
(
PlannerInfo
*
root
,
List
*
args
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment