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

Commitab05eed

Browse files
committed
Add support for cross-type hashing in hashed subplans (hashed IN/NOT IN cases
that aren't turned into true joins). Since this is the last missing bit ofinfrastructure, go ahead and fill out the hash integer_ops and float_opsopfamilies with cross-type operators. The operator family project is nowDONE ... er, except for documentation ...
1 parentb70e536 commitab05eed

File tree

11 files changed

+219
-72
lines changed

11 files changed

+219
-72
lines changed

‎src/backend/executor/execGrouping.c

Lines changed: 73 additions & 11 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.24 2007/01/30 01:33:36 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/executor/execGrouping.c,v 1.25 2007/02/06 02:59:11 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -178,7 +178,7 @@ execTuplesUnequal(TupleTableSlot *slot1,
178178
/*
179179
* execTuplesMatchPrepare
180180
*Look up the equality functions needed for execTuplesMatch or
181-
*execTuplesUnequal.
181+
*execTuplesUnequal, given an array of equality operator OIDs.
182182
*
183183
* The result is a palloc'd array.
184184
*/
@@ -208,6 +208,8 @@ execTuplesMatchPrepare(int numCols,
208208
* This is similar to execTuplesMatchPrepare, but we also need to find the
209209
* hash functions associated with the equality operators. *eqFunctions and
210210
* *hashFunctions receive the palloc'd result arrays.
211+
*
212+
* Note: we expect that the given operators are not cross-type comparisons.
211213
*/
212214
void
213215
execTuplesHashPrepare(intnumCols,
@@ -232,7 +234,7 @@ execTuplesHashPrepare(int numCols,
232234
&left_hash_function,&right_hash_function))
233235
elog(ERROR,"could not find hash function for hash operator %u",
234236
eq_opr);
235-
/*For the moment, we're not supporting cross-type cases here */
237+
/*We're not supporting cross-type cases here */
236238
Assert(left_hash_function==right_hash_function);
237239
fmgr_info(eq_function,&(*eqFunctions)[i]);
238240
fmgr_info(right_hash_function,&(*hashFunctions)[i]);
@@ -259,7 +261,9 @@ execTuplesHashPrepare(int numCols,
259261
*tablecxt: memory context in which to store table and table entries
260262
*tempcxt: short-lived context for evaluation hash and comparison functions
261263
*
262-
* The function arrays may be made with execTuplesHashPrepare().
264+
* The function arrays may be made with execTuplesHashPrepare(). Note they
265+
* are not cross-type functions, but expect to see the table datatype(s)
266+
* on both sides.
263267
*
264268
* Note that keyColIdx, eqfunctions, and hashfunctions must be allocated in
265269
* storage that will live as long as the hashtable does.
@@ -282,13 +286,15 @@ BuildTupleHashTable(int numCols, AttrNumber *keyColIdx,
282286

283287
hashtable->numCols=numCols;
284288
hashtable->keyColIdx=keyColIdx;
285-
hashtable->eqfunctions=eqfunctions;
286-
hashtable->hashfunctions=hashfunctions;
289+
hashtable->tab_hash_funcs=hashfunctions;
290+
hashtable->tab_eq_funcs=eqfunctions;
287291
hashtable->tablecxt=tablecxt;
288292
hashtable->tempcxt=tempcxt;
289293
hashtable->entrysize=entrysize;
290294
hashtable->tableslot=NULL;/* will be made on first lookup */
291295
hashtable->inputslot=NULL;
296+
hashtable->in_hash_funcs=NULL;
297+
hashtable->cur_eq_funcs=NULL;
292298

293299
MemSet(&hash_ctl,0,sizeof(hash_ctl));
294300
hash_ctl.keysize=sizeof(TupleHashEntryData);
@@ -305,7 +311,7 @@ BuildTupleHashTable(int numCols, AttrNumber *keyColIdx,
305311

306312
/*
307313
* Find or create a hashtable entry for the tuple group containing the
308-
* given tuple.
314+
* given tuple. The tuple must be the same type as the hashtable entries.
309315
*
310316
* If isnew is NULL, we do not create new entries; we return NULL if no
311317
* match is found.
@@ -351,6 +357,9 @@ LookupTupleHashEntry(TupleHashTable hashtable, TupleTableSlot *slot,
351357
* invoke this code re-entrantly.
352358
*/
353359
hashtable->inputslot=slot;
360+
hashtable->in_hash_funcs=hashtable->tab_hash_funcs;
361+
hashtable->cur_eq_funcs=hashtable->tab_eq_funcs;
362+
354363
saveCurHT=CurTupleHashTable;
355364
CurTupleHashTable=hashtable;
356365

@@ -394,6 +403,55 @@ LookupTupleHashEntry(TupleHashTable hashtable, TupleTableSlot *slot,
394403
returnentry;
395404
}
396405

406+
/*
407+
* Search for a hashtable entry matching the given tuple. No entry is
408+
* created if there's not a match. This is similar to the non-creating
409+
* case of LookupTupleHashEntry, except that it supports cross-type
410+
* comparisons, in which the given tuple is not of the same type as the
411+
* table entries. The caller must provide the hash functions to use for
412+
* the input tuple, as well as the equality functions, since these may be
413+
* different from the table's internal functions.
414+
*/
415+
TupleHashEntry
416+
FindTupleHashEntry(TupleHashTablehashtable,TupleTableSlot*slot,
417+
FmgrInfo*eqfunctions,
418+
FmgrInfo*hashfunctions)
419+
{
420+
TupleHashEntryentry;
421+
MemoryContextoldContext;
422+
TupleHashTablesaveCurHT;
423+
TupleHashEntryDatadummy;
424+
425+
/* Need to run the hash functions in short-lived context */
426+
oldContext=MemoryContextSwitchTo(hashtable->tempcxt);
427+
428+
/*
429+
* Set up data needed by hash and match functions
430+
*
431+
* We save and restore CurTupleHashTable just in case someone manages to
432+
* invoke this code re-entrantly.
433+
*/
434+
hashtable->inputslot=slot;
435+
hashtable->in_hash_funcs=hashfunctions;
436+
hashtable->cur_eq_funcs=eqfunctions;
437+
438+
saveCurHT=CurTupleHashTable;
439+
CurTupleHashTable=hashtable;
440+
441+
/* Search the hash table */
442+
dummy.firstTuple=NULL;/* flag to reference inputslot */
443+
entry= (TupleHashEntry)hash_search(hashtable->hashtab,
444+
&dummy,
445+
HASH_FIND,
446+
NULL);
447+
448+
CurTupleHashTable=saveCurHT;
449+
450+
MemoryContextSwitchTo(oldContext);
451+
452+
returnentry;
453+
}
454+
397455
/*
398456
* Compute the hash value for a tuple
399457
*
@@ -418,20 +476,23 @@ TupleHashTableHash(const void *key, Size keysize)
418476
TupleHashTablehashtable=CurTupleHashTable;
419477
intnumCols=hashtable->numCols;
420478
AttrNumber*keyColIdx=hashtable->keyColIdx;
479+
FmgrInfo*hashfunctions;
421480
uint32hashkey=0;
422481
inti;
423482

424483
if (tuple==NULL)
425484
{
426485
/* Process the current input tuple for the table */
427486
slot=hashtable->inputslot;
487+
hashfunctions=hashtable->in_hash_funcs;
428488
}
429489
else
430490
{
431491
/* Process a tuple already stored in the table */
432492
/* (this case never actually occurs in current dynahash.c code) */
433493
slot=hashtable->tableslot;
434494
ExecStoreMinimalTuple(tuple,slot, false);
495+
hashfunctions=hashtable->tab_hash_funcs;
435496
}
436497

437498
for (i=0;i<numCols;i++)
@@ -449,7 +510,7 @@ TupleHashTableHash(const void *key, Size keysize)
449510
{
450511
uint32hkey;
451512

452-
hkey=DatumGetUInt32(FunctionCall1(&hashtable->hashfunctions[i],
513+
hkey=DatumGetUInt32(FunctionCall1(&hashfunctions[i],
453514
attr));
454515
hashkey ^=hkey;
455516
}
@@ -493,11 +554,12 @@ TupleHashTableMatch(const void *key1, const void *key2, Size keysize)
493554
Assert(tuple2==NULL);
494555
slot2=hashtable->inputslot;
495556

496-
if (execTuplesMatch(slot1,
497-
slot2,
557+
/* For crosstype comparisons, the inputslot must be first */
558+
if (execTuplesMatch(slot2,
559+
slot1,
498560
hashtable->numCols,
499561
hashtable->keyColIdx,
500-
hashtable->eqfunctions,
562+
hashtable->cur_eq_funcs,
501563
hashtable->tempcxt))
502564
return0;
503565
else

‎src/backend/executor/nodeSubplan.c

Lines changed: 32 additions & 18 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.84 2007/02/02 00:07:03 tgl Exp $
10+
* $PostgreSQL: pgsql/src/backend/executor/nodeSubplan.c,v 1.85 2007/02/06 02:59:11 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -139,7 +139,10 @@ ExecHashSubPlan(SubPlanState *node,
139139
if (slotNoNulls(slot))
140140
{
141141
if (node->havehashrows&&
142-
LookupTupleHashEntry(node->hashtable,slot,NULL)!=NULL)
142+
FindTupleHashEntry(node->hashtable,
143+
slot,
144+
node->cur_eq_funcs,
145+
node->lhs_hash_funcs)!=NULL)
143146
{
144147
ExecClearTuple(slot);
145148
returnBoolGetDatum(true);
@@ -453,8 +456,8 @@ buildSubPlanHash(SubPlanState *node)
453456

454457
node->hashtable=BuildTupleHashTable(ncols,
455458
node->keyColIdx,
456-
node->eqfunctions,
457-
node->hashfunctions,
459+
node->tab_eq_funcs,
460+
node->tab_hash_funcs,
458461
nbuckets,
459462
sizeof(TupleHashEntryData),
460463
node->tablecxt,
@@ -472,8 +475,8 @@ buildSubPlanHash(SubPlanState *node)
472475
}
473476
node->hashnulls=BuildTupleHashTable(ncols,
474477
node->keyColIdx,
475-
node->eqfunctions,
476-
node->hashfunctions,
478+
node->tab_eq_funcs,
479+
node->tab_hash_funcs,
477480
nbuckets,
478481
sizeof(TupleHashEntryData),
479482
node->tablecxt,
@@ -573,9 +576,9 @@ findPartialMatch(TupleHashTable hashtable, TupleTableSlot *slot)
573576
while ((entry=ScanTupleHashTable(&hashiter))!=NULL)
574577
{
575578
ExecStoreMinimalTuple(entry->firstTuple,hashtable->tableslot, false);
576-
if (!execTuplesUnequal(hashtable->tableslot,slot,
579+
if (!execTuplesUnequal(slot,hashtable->tableslot,
577580
numCols,keyColIdx,
578-
hashtable->eqfunctions,
581+
hashtable->cur_eq_funcs,
579582
hashtable->tempcxt))
580583
return true;
581584
}
@@ -653,8 +656,10 @@ ExecInitSubPlan(SubPlanState *node, EState *estate, int eflags)
653656
node->tablecxt=NULL;
654657
node->innerecontext=NULL;
655658
node->keyColIdx=NULL;
656-
node->eqfunctions=NULL;
657-
node->hashfunctions=NULL;
659+
node->tab_hash_funcs=NULL;
660+
node->tab_eq_funcs=NULL;
661+
node->lhs_hash_funcs=NULL;
662+
node->cur_eq_funcs=NULL;
658663

659664
/*
660665
* create an EState for the subplan
@@ -781,8 +786,10 @@ ExecInitSubPlan(SubPlanState *node, EState *estate, int eflags)
781786

782787
lefttlist=righttlist=NIL;
783788
leftptlist=rightptlist=NIL;
784-
node->eqfunctions= (FmgrInfo*)palloc(ncols*sizeof(FmgrInfo));
785-
node->hashfunctions= (FmgrInfo*)palloc(ncols*sizeof(FmgrInfo));
789+
node->tab_hash_funcs= (FmgrInfo*)palloc(ncols*sizeof(FmgrInfo));
790+
node->tab_eq_funcs= (FmgrInfo*)palloc(ncols*sizeof(FmgrInfo));
791+
node->lhs_hash_funcs= (FmgrInfo*)palloc(ncols*sizeof(FmgrInfo));
792+
node->cur_eq_funcs= (FmgrInfo*)palloc(ncols*sizeof(FmgrInfo));
786793
i=1;
787794
foreach(l,oplist)
788795
{
@@ -792,6 +799,7 @@ ExecInitSubPlan(SubPlanState *node, EState *estate, int eflags)
792799
Expr*expr;
793800
TargetEntry*tle;
794801
GenericExprState*tlestate;
802+
Oidrhs_eq_oper;
795803
Oidleft_hashfn;
796804
Oidright_hashfn;
797805

@@ -827,18 +835,24 @@ ExecInitSubPlan(SubPlanState *node, EState *estate, int eflags)
827835
righttlist=lappend(righttlist,tlestate);
828836
rightptlist=lappend(rightptlist,tle);
829837

830-
/* Lookup the combining function */
831-
fmgr_info(opexpr->opfuncid,&node->eqfunctions[i-1]);
832-
node->eqfunctions[i-1].fn_expr= (Node*)opexpr;
838+
/* Lookup the equality function (potentially cross-type) */
839+
fmgr_info(opexpr->opfuncid,&node->cur_eq_funcs[i-1]);
840+
node->cur_eq_funcs[i-1].fn_expr= (Node*)opexpr;
841+
842+
/* Look up the equality function for the RHS type */
843+
if (!get_compatible_hash_operators(opexpr->opno,
844+
NULL,&rhs_eq_oper))
845+
elog(ERROR,"could not find compatible hash operator for operator %u",
846+
opexpr->opno);
847+
fmgr_info(get_opcode(rhs_eq_oper),&node->tab_eq_funcs[i-1]);
833848

834849
/* Lookup the associated hash functions */
835850
if (!get_op_hash_functions(opexpr->opno,
836851
&left_hashfn,&right_hashfn))
837852
elog(ERROR,"could not find hash function for hash operator %u",
838853
opexpr->opno);
839-
/* For the moment, not supporting cross-type cases */
840-
Assert(left_hashfn==right_hashfn);
841-
fmgr_info(right_hashfn,&node->hashfunctions[i-1]);
854+
fmgr_info(left_hashfn,&node->lhs_hash_funcs[i-1]);
855+
fmgr_info(right_hashfn,&node->tab_hash_funcs[i-1]);
842856

843857
i++;
844858
}

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

Lines changed: 7 additions & 12 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/optimizer/plan/subselect.c,v 1.117 2007/01/10 18:06:03 tgl Exp $
10+
* $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.118 2007/02/06 02:59:11 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -598,17 +598,13 @@ subplan_is_hashable(SubLink *slink, SubPlan *node)
598598
return false;
599599

600600
/*
601-
* The combining operators must be hashable, strict,andself-commutative.
601+
* The combining operators must be hashableandstrict.
602602
* The need for hashability is obvious, since we want to use hashing.
603603
* Without strictness, behavior in the presence of nulls is too
604-
* unpredictable. (We actually must assume even more than plain
605-
* strictness, see nodeSubplan.c for details.)And commutativity ensures
606-
* that the left and right datatypes are the same; this allows us to
607-
* assume that the combining operators are equality for the righthand
608-
* datatype, so that they can be used to compare righthand tuples as well
609-
* as comparing lefthand to righthand tuples. (This last restriction
610-
* could be relaxed by using two different sets of operators with the hash
611-
* table, but there is no obvious usefulness to that at present.)
604+
* unpredictable. We actually must assume even more than plain
605+
* strictness: they can't yield NULL for non-null inputs, either
606+
* (see nodeSubplan.c). However, hash indexes and hash joins assume
607+
* that too.
612608
*/
613609
if (IsA(slink->testexpr,OpExpr))
614610
{
@@ -644,8 +640,7 @@ hash_ok_operator(OpExpr *expr)
644640
if (!HeapTupleIsValid(tup))
645641
elog(ERROR,"cache lookup failed for operator %u",opid);
646642
optup= (Form_pg_operator)GETSTRUCT(tup);
647-
if (!optup->oprcanhash||optup->oprcom!=opid||
648-
!func_strict(optup->oprcode))
643+
if (!optup->oprcanhash|| !func_strict(optup->oprcode))
649644
{
650645
ReleaseSysCache(tup);
651646
return false;

‎src/backend/optimizer/util/pathnode.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/optimizer/util/pathnode.c,v 1.137 2007/01/20 20:45:39 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/optimizer/util/pathnode.c,v 1.138 2007/02/06 02:59:12 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -1070,7 +1070,7 @@ distinct_col_search(int colno, List *colnos, List *opids)
10701070
* We assume hashed aggregation will work if each IN operator is marked
10711071
* hashjoinable. If the IN operators are cross-type, this could conceivably
10721072
* fail: the aggregation will need a hashable equality operator for the RHS
1073-
* datatype --- but it's pretty hard to conceive of a hashopclass that has
1073+
* datatype --- but it's pretty hard to conceive of a hashopfamily that has
10741074
* cross-type hashing without support for hashing the individual types, so
10751075
* we don't expend cycles here to support the case. We could check
10761076
* get_compatible_hash_operator() instead of just op_hashjoinable(), but the

‎src/include/catalog/catversion.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
3838
* Portions Copyright (c) 1994, Regents of the University of California
3939
*
40-
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.380 2007/02/05 04:22:18 tgl Exp $
40+
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.381 2007/02/06 02:59:12 tgl Exp $
4141
*
4242
*-------------------------------------------------------------------------
4343
*/
@@ -53,6 +53,6 @@
5353
*/
5454

5555
/*yyyymmddN */
56-
#defineCATALOG_VERSION_NO200702041
56+
#defineCATALOG_VERSION_NO200702051
5757

5858
#endif

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp