aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer/path/hashutils.c
blob: cdbd9b6d9014b9eba868cf8158ccd0c52be7dce5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
/*-------------------------------------------------------------------------
 *
 * hashutils.c--
 *    Utilities for finding applicable merge clauses and pathkeys
 *
 * Copyright (c) 1994, Regents of the University of California
 *
 *
 * IDENTIFICATION
 *    $Header: /cvsroot/pgsql/src/backend/optimizer/path/Attic/hashutils.c,v 1.1.1.1 1996/07/09 06:21:35 scrappy Exp $
 *
 *-------------------------------------------------------------------------
 */
#include "postgres.h"
#include "nodes/pg_list.h"
#include "nodes/relation.h"

#include "optimizer/internal.h"
#include "optimizer/paths.h"
#include "optimizer/clauses.h"


static HInfo *match_hashop_hashinfo(Oid hashop, List *hashinfo_list);

/*    
 * group-clauses-by-hashop--
 *    If a join clause node in 'clauseinfo-list' is hashjoinable, store
 *    it within a hashinfo node containing other clause nodes with the same
 *    hash operator.
 *    
 * 'clauseinfo-list' is the list of clauseinfo nodes
 * 'inner-relid' is the relid of the inner join relation
 *    
 * Returns the new list of hashinfo nodes.
 *    
 */
List *
group_clauses_by_hashop(List *clauseinfo_list,
			int inner_relid)
{
    List *hashinfo_list = NIL;
    CInfo *clauseinfo = (CInfo*)NULL;
    List *i = NIL;
    Oid hashjoinop = 0;
    
    foreach (i,clauseinfo_list) {
	clauseinfo = (CInfo*)lfirst(i);
	hashjoinop = clauseinfo->hashjoinoperator;
	
	/*
	 * Create a new hashinfo node and add it to 'hashinfo-list' if one
	 * does not yet exist for this hash operator.
	 */
	if (hashjoinop ) {
	    HInfo *xhashinfo = (HInfo*)NULL;
	    Expr *clause = clauseinfo->clause;
	    Var *leftop = get_leftop(clause);
	    Var *rightop = get_rightop(clause);
	    JoinKey *keys = (JoinKey*)NULL;
	    
	    xhashinfo = 
		match_hashop_hashinfo(hashjoinop,hashinfo_list);
	    
	    if (inner_relid == leftop->varno){
		keys = makeNode(JoinKey);
		keys->outer = rightop;
		keys->inner = leftop;
	    } else {
		keys = makeNode(JoinKey);
		keys->outer = leftop;
		keys->inner = rightop;
	    }
	    
	    if (xhashinfo==NULL) {
		xhashinfo = makeNode(HInfo);
		xhashinfo->hashop = hashjoinop;

		xhashinfo->jmethod.jmkeys = NIL;
		xhashinfo->jmethod.clauses = NIL;

		/* XXX was push  */
		hashinfo_list = lappend(hashinfo_list,xhashinfo);
		hashinfo_list = nreverse(hashinfo_list);
	    }

	    xhashinfo->jmethod.clauses =
		lcons(clause, xhashinfo->jmethod.clauses);

	    xhashinfo->jmethod.jmkeys =
		lcons(keys, xhashinfo->jmethod.jmkeys);
	}
    }
    return(hashinfo_list);
}


/*    
 * match-hashop-hashinfo--
 *    Searches the list 'hashinfo-list' for a hashinfo node whose hash op
 *    field equals 'hashop'.
 *    
 * Returns the node if it exists.
 *    
 */
static HInfo *
match_hashop_hashinfo(Oid hashop, List *hashinfo_list)
{
    Oid key = 0;
    HInfo *xhashinfo = (HInfo*)NULL;
    List *i = NIL;
    
    foreach( i, hashinfo_list) {
	xhashinfo = (HInfo*)lfirst(i);
	key = xhashinfo->hashop;
	if (hashop == key) {	/* found */
	    return(xhashinfo);	/* should be a hashinfo node ! */
	}
    }
    return((HInfo*)NIL);
}