Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commita635c08

Browse files
committed
Add support for cross-type hashing in hash index searches and hash joins.
Hashing for aggregation purposes still needs work, so it's not time tomark any cross-type operators as hashable for general use, but these caseswork if the operators are so marked by hand in the system catalogs.
1 parente8cd6f1 commita635c08

File tree

12 files changed

+240
-82
lines changed

12 files changed

+240
-82
lines changed

‎src/backend/access/hash/hashsearch.c

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/access/hash/hashsearch.c,v 1.47 2007/01/20 18:43:35 neilc Exp $
11+
* $PostgreSQL: pgsql/src/backend/access/hash/hashsearch.c,v 1.48 2007/01/30 01:33:36 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -115,6 +115,7 @@ _hash_first(IndexScanDesc scan, ScanDirection dir)
115115
{
116116
Relationrel=scan->indexRelation;
117117
HashScanOpaqueso= (HashScanOpaque)scan->opaque;
118+
ScanKeycur;
118119
uint32hashkey;
119120
Bucketbucket;
120121
BlockNumberblkno;
@@ -143,18 +144,37 @@ _hash_first(IndexScanDesc scan, ScanDirection dir)
143144
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
144145
errmsg("hash indexes do not support whole-index scans")));
145146

147+
/* There may be more than one index qual, but we hash only the first */
148+
cur=&scan->keyData[0];
149+
150+
/* We support only single-column hash indexes */
151+
Assert(cur->sk_attno==1);
152+
/* And there's only one operator strategy, too */
153+
Assert(cur->sk_strategy==HTEqualStrategyNumber);
154+
146155
/*
147156
* If the constant in the index qual is NULL, assume it cannot match any
148157
* items in the index.
149158
*/
150-
if (scan->keyData[0].sk_flags&SK_ISNULL)
159+
if (cur->sk_flags&SK_ISNULL)
151160
return false;
152161

153162
/*
154163
* Okay to compute the hash key. We want to do this before acquiring any
155164
* locks, in case a user-defined hash function happens to be slow.
165+
*
166+
* If scankey operator is not a cross-type comparison, we can use the
167+
* cached hash function; otherwise gotta look it up in the catalogs.
168+
*
169+
* We support the convention that sk_subtype == InvalidOid means the
170+
* opclass input type; this is a hack to simplify life for ScanKeyInit().
156171
*/
157-
hashkey=_hash_datum2hashkey(rel,scan->keyData[0].sk_argument);
172+
if (cur->sk_subtype==rel->rd_opcintype[0]||
173+
cur->sk_subtype==InvalidOid)
174+
hashkey=_hash_datum2hashkey(rel,cur->sk_argument);
175+
else
176+
hashkey=_hash_datum2hashkey_type(rel,cur->sk_argument,
177+
cur->sk_subtype);
158178

159179
/*
160180
* Acquire shared split lock so we can compute the target bucket safely

‎src/backend/access/hash/hashutil.c

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/access/hash/hashutil.c,v 1.50 2007/01/05 22:19:22 momjian Exp $
11+
* $PostgreSQL: pgsql/src/backend/access/hash/hashutil.c,v 1.51 2007/01/30 01:33:36 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -18,6 +18,7 @@
1818
#include"access/hash.h"
1919
#include"access/reloptions.h"
2020
#include"executor/execdebug.h"
21+
#include"utils/lsyscache.h"
2122

2223

2324
/*
@@ -63,6 +64,9 @@ _hash_checkqual(IndexScanDesc scan, IndexTuple itup)
6364

6465
/*
6566
* _hash_datum2hashkey -- given a Datum, call the index's hash procedure
67+
*
68+
* The Datum is assumed to be of the index's column type, so we can use the
69+
* "primary" hash procedure that's tracked for us by the generic index code.
6670
*/
6771
uint32
6872
_hash_datum2hashkey(Relationrel,Datumkey)
@@ -75,6 +79,31 @@ _hash_datum2hashkey(Relation rel, Datum key)
7579
returnDatumGetUInt32(FunctionCall1(procinfo,key));
7680
}
7781

82+
/*
83+
* _hash_datum2hashkey_type -- given a Datum of a specified type,
84+
*hash it in a fashion compatible with this index
85+
*
86+
* This is much more expensive than _hash_datum2hashkey, so use it only in
87+
* cross-type situations.
88+
*/
89+
uint32
90+
_hash_datum2hashkey_type(Relationrel,Datumkey,Oidkeytype)
91+
{
92+
RegProcedurehash_proc;
93+
94+
/* XXX assumes index has only one attribute */
95+
hash_proc=get_opfamily_proc(rel->rd_opfamily[0],
96+
keytype,
97+
keytype,
98+
HASHPROC);
99+
if (!RegProcedureIsValid(hash_proc))
100+
elog(ERROR,"missing support function %d(%u,%u) for index \"%s\"",
101+
HASHPROC,keytype,keytype,
102+
RelationGetRelationName(rel));
103+
104+
returnDatumGetUInt32(OidFunctionCall1(hash_proc,key));
105+
}
106+
78107
/*
79108
* _hash_hashkey2bucket -- determine which bucket the hashkey maps to.
80109
*/

‎src/backend/executor/execGrouping.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/executor/execGrouping.c,v 1.23 2007/01/10 18:06:02 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/executor/execGrouping.c,v 1.24 2007/01/30 01:33:36 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -224,15 +224,18 @@ execTuplesHashPrepare(int numCols,
224224
{
225225
Oideq_opr=eqOperators[i];
226226
Oideq_function;
227-
Oidhash_function;
227+
Oidleft_hash_function;
228+
Oidright_hash_function;
228229

229230
eq_function=get_opcode(eq_opr);
230-
hash_function=get_op_hash_function(eq_opr);
231-
if (!OidIsValid(hash_function))/* should not happen */
231+
if (!get_op_hash_functions(eq_opr,
232+
&left_hash_function,&right_hash_function))
232233
elog(ERROR,"could not find hash function for hash operator %u",
233234
eq_opr);
235+
/* For the moment, we're not supporting cross-type cases here */
236+
Assert(left_hash_function==right_hash_function);
234237
fmgr_info(eq_function,&(*eqFunctions)[i]);
235-
fmgr_info(hash_function,&(*hashFunctions)[i]);
238+
fmgr_info(right_hash_function,&(*hashFunctions)[i]);
236239
}
237240
}
238241

‎src/backend/executor/nodeHash.c

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/executor/nodeHash.c,v 1.109 2007/01/28 23:21:26 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/executor/nodeHash.c,v 1.110 2007/01/30 01:33:36 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -94,7 +94,7 @@ MultiExecHash(HashState *node)
9494
break;
9595
/* We have to compute the hash value */
9696
econtext->ecxt_innertuple=slot;
97-
if (ExecHashGetHashValue(hashtable,econtext,hashkeys, false,
97+
if (ExecHashGetHashValue(hashtable,econtext,hashkeys, false, false,
9898
&hashvalue))
9999
{
100100
ExecHashTableInsert(hashtable,slot,hashvalue);
@@ -267,19 +267,23 @@ ExecHashTableCreate(Hash *node, List *hashOperators)
267267
* Also remember whether the join operators are strict.
268268
*/
269269
nkeys=list_length(hashOperators);
270-
hashtable->hashfunctions= (FmgrInfo*)palloc(nkeys*sizeof(FmgrInfo));
270+
hashtable->outer_hashfunctions=
271+
(FmgrInfo*)palloc(nkeys*sizeof(FmgrInfo));
272+
hashtable->inner_hashfunctions=
273+
(FmgrInfo*)palloc(nkeys*sizeof(FmgrInfo));
271274
hashtable->hashStrict= (bool*)palloc(nkeys*sizeof(bool));
272275
i=0;
273276
foreach(ho,hashOperators)
274277
{
275278
Oidhashop=lfirst_oid(ho);
276-
Oidhashfn;
279+
Oidleft_hashfn;
280+
Oidright_hashfn;
277281

278-
hashfn=get_op_hash_function(hashop);
279-
if (!OidIsValid(hashfn))
282+
if (!get_op_hash_functions(hashop,&left_hashfn,&right_hashfn))
280283
elog(ERROR,"could not find hash function for hash operator %u",
281284
hashop);
282-
fmgr_info(hashfn,&hashtable->hashfunctions[i]);
285+
fmgr_info(left_hashfn,&hashtable->outer_hashfunctions[i]);
286+
fmgr_info(right_hashfn,&hashtable->inner_hashfunctions[i]);
283287
hashtable->hashStrict[i]=op_strict(hashop);
284288
i++;
285289
}
@@ -674,10 +678,12 @@ bool
674678
ExecHashGetHashValue(HashJoinTablehashtable,
675679
ExprContext*econtext,
676680
List*hashkeys,
681+
boolouter_tuple,
677682
boolkeep_nulls,
678683
uint32*hashvalue)
679684
{
680685
uint32hashkey=0;
686+
FmgrInfo*hashfunctions;
681687
ListCell*hk;
682688
inti=0;
683689
MemoryContextoldContext;
@@ -690,6 +696,11 @@ ExecHashGetHashValue(HashJoinTable hashtable,
690696

691697
oldContext=MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
692698

699+
if (outer_tuple)
700+
hashfunctions=hashtable->outer_hashfunctions;
701+
else
702+
hashfunctions=hashtable->inner_hashfunctions;
703+
693704
foreach(hk,hashkeys)
694705
{
695706
ExprState*keyexpr= (ExprState*)lfirst(hk);
@@ -728,8 +739,7 @@ ExecHashGetHashValue(HashJoinTable hashtable,
728739
/* Compute the hash function */
729740
uint32hkey;
730741

731-
hkey=DatumGetUInt32(FunctionCall1(&hashtable->hashfunctions[i],
732-
keyval));
742+
hkey=DatumGetUInt32(FunctionCall1(&hashfunctions[i],keyval));
733743
hashkey ^=hkey;
734744
}
735745

‎src/backend/executor/nodeHashjoin.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/executor/nodeHashjoin.c,v 1.87 2007/01/28 23:21:26 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/executor/nodeHashjoin.c,v 1.88 2007/01/30 01:33:36 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -569,6 +569,7 @@ ExecHashJoinOuterGetTuple(PlanState *outerNode,
569569
econtext->ecxt_outertuple=slot;
570570
if (ExecHashGetHashValue(hashtable,econtext,
571571
hjstate->hj_OuterHashKeys,
572+
true,/* outer tuple */
572573
(hjstate->js.jointype==JOIN_LEFT),
573574
hashvalue))
574575
{

‎src/backend/executor/nodeSubplan.c

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1994, Regents of the University of California
88
*
99
* IDENTIFICATION
10-
* $PostgreSQL: pgsql/src/backend/executor/nodeSubplan.c,v 1.82 2007/01/05 22:19:28 momjian Exp $
10+
* $PostgreSQL: pgsql/src/backend/executor/nodeSubplan.c,v 1.83 2007/01/30 01:33:36 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -792,7 +792,8 @@ ExecInitSubPlan(SubPlanState *node, EState *estate, int eflags)
792792
Expr*expr;
793793
TargetEntry*tle;
794794
GenericExprState*tlestate;
795-
Oidhashfn;
795+
Oidleft_hashfn;
796+
Oidright_hashfn;
796797

797798
Assert(IsA(fstate,FuncExprState));
798799
Assert(IsA(opexpr,OpExpr));
@@ -830,12 +831,14 @@ ExecInitSubPlan(SubPlanState *node, EState *estate, int eflags)
830831
fmgr_info(opexpr->opfuncid,&node->eqfunctions[i-1]);
831832
node->eqfunctions[i-1].fn_expr= (Node*)opexpr;
832833

833-
/* Lookup the associated hashfunction */
834-
hashfn=get_op_hash_function(opexpr->opno);
835-
if (!OidIsValid(hashfn))
834+
/* Lookup the associated hashfunctions */
835+
if (!get_op_hash_functions(opexpr->opno,
836+
&left_hashfn,&right_hashfn))
836837
elog(ERROR,"could not find hash function for hash operator %u",
837838
opexpr->opno);
838-
fmgr_info(hashfn,&node->hashfunctions[i-1]);
839+
/* For the moment, not supporting cross-type cases */
840+
Assert(left_hashfn==right_hashfn);
841+
fmgr_info(right_hashfn,&node->hashfunctions[i-1]);
839842

840843
i++;
841844
}

‎src/backend/optimizer/plan/createplan.c

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
*
1111
*
1212
* IDENTIFICATION
13-
* $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.223 2007/01/22 01:35:20 tgl Exp $
13+
* $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.224 2007/01/30 01:33:36 tgl Exp $
1414
*
1515
*-------------------------------------------------------------------------
1616
*/
@@ -716,10 +716,10 @@ create_unique_plan(PlannerInfo *root, UniquePath *best_path)
716716
numGroups= (long)Min(best_path->rows, (double)LONG_MAX);
717717

718718
/*
719-
* Get the(presumedhashable) equality operators for the Agg node
720-
*to use.Normally these are the same as the IN clause operators,
721-
*but ifthose are cross-type operators then the equality operators
722-
*arethe ones for the IN clause operators' RHS datatype.
719+
* Get the hashable equality operators for the Agg node to use.
720+
* Normally these are the same as the IN clause operators, but if
721+
* those are cross-type operators then the equality operators are
722+
* the ones for the IN clause operators' RHS datatype.
723723
*/
724724
groupOperators= (Oid*)palloc(numGroupCols*sizeof(Oid));
725725
groupColPos=0;
@@ -728,8 +728,7 @@ create_unique_plan(PlannerInfo *root, UniquePath *best_path)
728728
Oidin_oper=lfirst_oid(l);
729729
Oideq_oper;
730730

731-
eq_oper=get_compatible_hash_operator(in_oper, false);
732-
if (!OidIsValid(eq_oper))/* shouldn't happen */
731+
if (!get_compatible_hash_operators(in_oper,NULL,&eq_oper))
733732
elog(ERROR,"could not find compatible hash operator for operator %u",
734733
in_oper);
735734
groupOperators[groupColPos++]=eq_oper;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp