locks.c 3.5 KB
Newer Older
1 2 3 4 5 6 7 8
/*-------------------------------------------------------------------------
 *
 * locks.c--
 *
 * Copyright (c) 1994, Regents of the University of California
 *
 *
 * IDENTIFICATION
9
 *	  $Header: /cvsroot/pgsql/src/backend/rewrite/Attic/locks.c,v 1.8 1998/01/21 04:24:34 momjian Exp $
10 11 12 13 14 15 16
 *
 *-------------------------------------------------------------------------
 */
#include "postgres.h"			/* for oid defs */
#include "utils/elog.h"			/* for elog */
#include "nodes/pg_list.h"		/* lisp support package */
#include "nodes/parsenodes.h"
17
#include "nodes/primnodes.h"	/* Var node def */
18 19 20 21 22 23 24 25 26 27 28
#include "utils/syscache.h"		/* for SearchSysCache */
#include "rewrite/locks.h"		/* for rewrite specific lock defns */

/*
 * ThisLockWasTriggered
 *
 * walk the tree, if there we find a varnode,
 * we check the varattno against the attnum
 * if we find at least one such match, we return true
 * otherwise, we return false
 */
29
static bool
30 31
nodeThisLockWasTriggered(Node *node, int varno, AttrNumber attnum,
			int sublevels_up)
32
{
33 34 35
	if (node == NULL)
		return FALSE;
	switch (nodeTag(node))
36
	{
37 38 39
		case T_Var:
			{
				Var		   *var = (Var *) node;
40

41 42 43 44 45 46 47 48
				if (varno == var->varno &&
					(attnum == var->varattno || attnum == -1))
					return TRUE;
			}
			break;
		case T_Expr:
			{
				Expr	   *expr = (Expr *) node;
49

50 51
				return nodeThisLockWasTriggered((Node *) expr->args, varno,
						attnum, sublevels_up);
52 53 54 55 56
			}
			break;
		case T_TargetEntry:
			{
				TargetEntry *tle = (TargetEntry *) node;
57

58 59
				return nodeThisLockWasTriggered(tle->expr, varno, attnum,
									sublevels_up);
60 61
			}
			break;
62 63 64 65
		case T_Aggreg:
			{
				Aggreg *agg = (Aggreg *) node;

66 67
				return nodeThisLockWasTriggered(agg->target, varno, attnum,
								sublevels_up);
68 69
			}
			break;
70
		case T_List:
71
			{
72 73 74 75
				List	   *l;

				foreach(l, (List *) node)
				{
76 77
					if (nodeThisLockWasTriggered(lfirst(l), varno, attnum,
								sublevels_up))
78 79 80
						return TRUE;
				}
				return FALSE;
81
			}
82
			break;
83 84 85 86 87 88 89 90 91
		case T_SubLink:
			{
				SubLink		   *sublink = (SubLink *) node;
				Query		   *query = (Query *)sublink->subselect;

				return nodeThisLockWasTriggered(query->qual, varno, attnum,
									sublevels_up + 1);
			}
			break;
92 93
		default:
			break;
94
	}
95
	return (FALSE);
96 97 98 99
}

/*
 * thisLockWasTriggered -
100 101 102
 *	   walk the tree, if there we find a varnode, we check the varattno
 *	   against the attnum if we find at least one such match, we return true
 *	   otherwise, we return false
103
 */
104
static bool
105
thisLockWasTriggered(int varno,
106
					 AttrNumber attnum,
107
					 Query *parsetree)
108
{
109
	
110
	if (nodeThisLockWasTriggered(parsetree->qual, varno, attnum, 0))
111 112
		return true;

113
	if (nodeThisLockWasTriggered((Node *) parsetree->targetList, varno, attnum, 0))
114 115 116 117
		return true;

	return false;
		
118 119 120 121
}

/*
 * matchLocks -
122
 *	  match the list of locks and returns the matching rules
123
 */
124
List	   *
125
matchLocks(CmdType event,
126
		   RuleLock *rulelocks,
127
		   int varno,
128
		   Query *parsetree)
129
{
130 131 132
	List	   *real_locks = NIL;
	int			nlocks;
	int			i;
133 134 135 136 137 138 139 140 141 142

	Assert(rulelocks != NULL);	/* we get called iff there is some lock */
	Assert(parsetree != NULL);

	if (parsetree->commandType != CMD_SELECT)
	{
		if (parsetree->resultRelation != varno)
		{
			return (NULL);
		}
143 144
	}

145 146 147 148
	nlocks = rulelocks->numLocks;

	for (i = 0; i < nlocks; i++)
	{
149
		RewriteRule *oneLock = rulelocks->rules[i];
150 151 152 153 154 155 156 157 158 159 160

		if (oneLock->event == event)
		{
			if (parsetree->commandType != CMD_SELECT ||
				thisLockWasTriggered(varno,
									 oneLock->attrno,
									 parsetree))
			{
				real_locks = lappend(real_locks, oneLock);
			}
		}
161 162
	}

163 164
	return (real_locks);
}