1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-14 08:21:07 +03:00

Planner failed to be smart about binary-compatible expressions in pathkeys

and hash bucket-size estimation.  Issue has been there awhile but is more
critical in 7.4 because it affects varchar columns.  Per report from
Greg Stark.
This commit is contained in:
Tom Lane
2003-12-03 17:45:10 +00:00
parent 32580efafb
commit 7f8f7665fc
4 changed files with 64 additions and 13 deletions

View File

@ -49,7 +49,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.116 2003/11/29 19:51:50 pgsql Exp $
* $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.117 2003/12/03 17:45:07 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -1322,6 +1322,10 @@ estimate_hash_bucketsize(Query *root, Var *var, int nbuckets)
float4 *numbers;
int nnumbers;
/* Ignore any binary-compatible relabeling */
if (var && IsA(var, RelabelType))
var = (Var *) ((RelabelType *) var)->arg;
/*
* Lookup info about var's relation and attribute; if none available,
* return default estimate.

View File

@ -11,7 +11,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/path/pathkeys.c,v 1.54 2003/11/29 19:51:50 pgsql Exp $
* $PostgreSQL: pgsql/src/backend/optimizer/path/pathkeys.c,v 1.55 2003/12/03 17:45:07 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -25,12 +25,13 @@
#include "optimizer/tlist.h"
#include "optimizer/var.h"
#include "parser/parsetree.h"
#include "parser/parse_expr.h"
#include "parser/parse_func.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
static PathKeyItem *makePathKeyItem(Node *key, Oid sortop);
static PathKeyItem *makePathKeyItem(Node *key, Oid sortop, bool checkType);
static List *make_canonical_pathkey(Query *root, PathKeyItem *item);
static Var *find_indexkey_var(Query *root, RelOptInfo *rel,
AttrNumber varattno);
@ -41,10 +42,29 @@ static Var *find_indexkey_var(Query *root, RelOptInfo *rel,
* create a PathKeyItem node
*/
static PathKeyItem *
makePathKeyItem(Node *key, Oid sortop)
makePathKeyItem(Node *key, Oid sortop, bool checkType)
{
PathKeyItem *item = makeNode(PathKeyItem);
/*
* Some callers pass expressions that are not necessarily of the same
* type as the sort operator expects as input (for example when dealing
* with an index that uses binary-compatible operators). We must relabel
* these with the correct type so that the key expressions will be seen
* as equal() to expressions that have been correctly labeled.
*/
if (checkType)
{
Oid lefttype,
righttype;
op_input_types(sortop, &lefttype, &righttype);
if (exprType(key) != lefttype)
key = (Node *) makeRelabelType((Expr *) key,
lefttype, -1,
COERCE_DONTCARE);
}
item->key = key;
item->sortop = sortop;
return item;
@ -70,9 +90,11 @@ add_equijoined_keys(Query *root, RestrictInfo *restrictinfo)
{
Expr *clause = restrictinfo->clause;
PathKeyItem *item1 = makePathKeyItem(get_leftop(clause),
restrictinfo->left_sortop);
restrictinfo->left_sortop,
false);
PathKeyItem *item2 = makePathKeyItem(get_rightop(clause),
restrictinfo->right_sortop);
restrictinfo->right_sortop,
false);
List *newset,
*cursetlink;
@ -668,7 +690,7 @@ build_index_pathkeys(Query *root,
}
/* OK, make a sublist for this sort key */
item = makePathKeyItem(indexkey, sortop);
item = makePathKeyItem(indexkey, sortop, true);
cpathkey = make_canonical_pathkey(root, item);
/*
@ -785,7 +807,8 @@ build_subquery_pathkeys(Query *root, RelOptInfo *rel, Query *subquery)
tle->resdom->restypmod,
0);
outer_item = makePathKeyItem((Node *) outer_var,
sub_item->sortop);
sub_item->sortop,
true);
/* score = # of mergejoin peers */
score = count_canonical_peers(root, outer_item);
/* +1 if it matches the proper query_pathkeys item */
@ -893,7 +916,7 @@ make_pathkeys_for_sortclauses(List *sortclauses,
PathKeyItem *pathkey;
sortkey = get_sortgroupclause_expr(sortcl, tlist);
pathkey = makePathKeyItem(sortkey, sortcl->sortop);
pathkey = makePathKeyItem(sortkey, sortcl->sortop, true);
/*
* The pathkey becomes a one-element sublist, for now;
@ -937,7 +960,7 @@ cache_mergeclause_pathkeys(Query *root, RestrictInfo *restrictinfo)
{
oldcontext = MemoryContextSwitchTo(GetMemoryChunkContext(restrictinfo));
key = get_leftop(restrictinfo->clause);
item = makePathKeyItem(key, restrictinfo->left_sortop);
item = makePathKeyItem(key, restrictinfo->left_sortop, false);
restrictinfo->left_pathkey = make_canonical_pathkey(root, item);
MemoryContextSwitchTo(oldcontext);
}
@ -945,7 +968,7 @@ cache_mergeclause_pathkeys(Query *root, RestrictInfo *restrictinfo)
{
oldcontext = MemoryContextSwitchTo(GetMemoryChunkContext(restrictinfo));
key = get_rightop(restrictinfo->clause);
item = makePathKeyItem(key, restrictinfo->right_sortop);
item = makePathKeyItem(key, restrictinfo->right_sortop, false);
restrictinfo->right_pathkey = make_canonical_pathkey(root, item);
MemoryContextSwitchTo(oldcontext);
}