aboutsummaryrefslogtreecommitdiff
path: root/src/backend/rewrite/locks.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2000-09-29 18:21:41 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2000-09-29 18:21:41 +0000
commit3a94e789f5c9537d804210be3cb26f7fb08e3b9e (patch)
treef1eac12405e3c0ded881d7dd7e59cec35b30c335 /src/backend/rewrite/locks.c
parent6f64c2e54a0b14154a335249f4dca91a39c61c50 (diff)
downloadpostgresql-3a94e789f5c9537d804210be3cb26f7fb08e3b9e.tar.gz
postgresql-3a94e789f5c9537d804210be3cb26f7fb08e3b9e.zip
Subselects in FROM clause, per ISO syntax: FROM (SELECT ...) [AS] alias.
(Don't forget that an alias is required.) Views reimplemented as expanding to subselect-in-FROM. Grouping, aggregates, DISTINCT in views actually work now (he says optimistically). No UNION support in subselects/views yet, but I have some ideas about that. Rule-related permissions checking moved out of rewriter and into executor. INITDB REQUIRED!
Diffstat (limited to 'src/backend/rewrite/locks.c')
-rw-r--r--src/backend/rewrite/locks.c268
1 files changed, 0 insertions, 268 deletions
diff --git a/src/backend/rewrite/locks.c b/src/backend/rewrite/locks.c
deleted file mode 100644
index 78fdad8960a..00000000000
--- a/src/backend/rewrite/locks.c
+++ /dev/null
@@ -1,268 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * locks.c
- *
- * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- *
- * IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/rewrite/Attic/locks.c,v 1.32 2000/09/12 21:07:02 tgl Exp $
- *
- *-------------------------------------------------------------------------
- */
-#include "postgres.h"
-
-#include "access/heapam.h"
-#include "catalog/pg_shadow.h"
-#include "optimizer/clauses.h"
-#include "rewrite/locks.h"
-#include "parser/parsetree.h"
-#include "utils/acl.h"
-#include "utils/syscache.h"
-
-
-/*
- * 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
- *
- * XXX this should be unified with attribute_used()
- */
-
-typedef struct
-{
- int varno;
- int attnum;
- int sublevels_up;
-} thisLockWasTriggered_context;
-
-static bool
-thisLockWasTriggered_walker(Node *node,
- thisLockWasTriggered_context *context)
-{
- if (node == NULL)
- return false;
- if (IsA(node, Var))
- {
- Var *var = (Var *) node;
-
- if (var->varlevelsup == context->sublevels_up &&
- var->varno == context->varno &&
- (var->varattno == context->attnum || context->attnum == -1))
- return true;
- return false;
- }
- if (IsA(node, Query))
- {
- /* Recurse into subselects */
- bool result;
-
- context->sublevels_up++;
- result = query_tree_walker((Query *) node, thisLockWasTriggered_walker,
- (void *) context);
- context->sublevels_up--;
- return result;
- }
- return expression_tree_walker(node, thisLockWasTriggered_walker,
- (void *) context);
-}
-
-static bool
-thisLockWasTriggered(int varno,
- int attnum,
- Query *parsetree)
-{
- thisLockWasTriggered_context context;
-
- context.varno = varno;
- context.attnum = attnum;
- context.sublevels_up = 0;
-
- return thisLockWasTriggered_walker((Node *) parsetree, &context);
-}
-
-/*
- * matchLocks -
- * match the list of locks and returns the matching rules
- */
-List *
-matchLocks(CmdType event,
- RuleLock *rulelocks,
- int varno,
- Query *parsetree)
-{
- List *real_locks = NIL;
- int nlocks;
- int i;
-
- 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;
- }
-
- nlocks = rulelocks->numLocks;
-
- for (i = 0; i < nlocks; i++)
- {
- RewriteRule *oneLock = rulelocks->rules[i];
-
- if (oneLock->event == event)
- {
- if (parsetree->commandType != CMD_SELECT ||
- thisLockWasTriggered(varno,
- oneLock->attrno,
- parsetree))
- real_locks = lappend(real_locks, oneLock);
- }
- }
-
- checkLockPerms(real_locks, parsetree, varno);
-
- return real_locks;
-}
-
-
-/*
- * Check the access permissions of tables that are referred to by a rule.
- * We want to check the access permissions using the userid of the rule's
- * owner, *not* of the current user (the one accessing the rule). So, we
- * do the permission check here and set skipAcl = TRUE in each of the rule's
- * RTEs, to prevent the executor from running another check with the current
- * user's ID.
- *
- * XXX This routine is called before the rule's query tree has been copied
- * out of the relcache entry where it is kept. Therefore, when we set
- * skipAcl = TRUE, we are destructively modifying the relcache entry for
- * the event relation! This seems fairly harmless because the relcache
- * querytree is only used as a source for the rewriter, but it's a tad
- * unclean anyway.
- *
- * Note that we must check permissions every time, even if skipAcl was
- * already set TRUE by a prior call. This ensures that we enforce the
- * current permission settings for each referenced table, even if they
- * have changed since the relcache entry was loaded.
- */
-
-typedef struct
-{
- Oid evowner;
-} checkLockPerms_context;
-
-static bool
-checkLockPerms_walker(Node *node,
- checkLockPerms_context *context)
-{
- if (node == NULL)
- return false;
- if (IsA(node, Query))
- {
- Query *qry = (Query *) node;
- int rtablength = length(qry->rtable);
- int i;
-
- /* Check all the RTEs in this query node, except OLD and NEW */
- for (i = 1; i <= rtablength; i++)
- {
- RangeTblEntry *rte = rt_fetch(i, qry->rtable);
- int32 reqperm;
- int32 aclcheck_res;
-
- if (strcmp(rte->eref->relname, "*NEW*") == 0)
- continue;
- if (strcmp(rte->eref->relname, "*OLD*") == 0)
- continue;
-
- if (i == qry->resultRelation)
- switch (qry->commandType)
- {
- case CMD_INSERT:
- reqperm = ACL_AP;
- break;
- default:
- reqperm = ACL_WR;
- break;
- }
- else
- reqperm = ACL_RD;
-
- aclcheck_res = pg_aclcheck(rte->relname,
- context->evowner,
- reqperm);
- if (aclcheck_res != ACLCHECK_OK)
- elog(ERROR, "%s: %s",
- rte->relname,
- aclcheck_error_strings[aclcheck_res]);
-
- /*
- * Mark RTE to prevent executor from checking again with the
- * current user's ID...
- */
- rte->skipAcl = true;
- }
-
- /* If there are sublinks, search for them and check their RTEs */
- if (qry->hasSubLinks)
- return query_tree_walker(qry, checkLockPerms_walker,
- (void *) context);
- return false;
- }
- return expression_tree_walker(node, checkLockPerms_walker,
- (void *) context);
-}
-
-void
-checkLockPerms(List *locks, Query *parsetree, int rt_index)
-{
- RangeTblEntry *rte;
- Relation ev_rel;
- HeapTuple usertup;
- Form_pg_shadow userform;
- checkLockPerms_context context;
- List *l;
-
- if (locks == NIL)
- return; /* nothing to check */
-
- /*
- * Get the userid of the rule's event relation owner
- */
- rte = rt_fetch(rt_index, parsetree->rtable);
- ev_rel = heap_openr(rte->relname, AccessShareLock);
- usertup = SearchSysCacheTuple(SHADOWSYSID,
- ObjectIdGetDatum(ev_rel->rd_rel->relowner),
- 0, 0, 0);
- if (!HeapTupleIsValid(usertup))
- elog(ERROR, "cache lookup for userid %d failed",
- ev_rel->rd_rel->relowner);
- userform = (Form_pg_shadow) GETSTRUCT(usertup);
- context.evowner = userform->usesysid;
- heap_close(ev_rel, AccessShareLock);
-
- /*
- * Check all the locks that should get fired on this query
- */
- foreach(l, locks)
- {
- RewriteRule *onelock = (RewriteRule *) lfirst(l);
- List *action;
-
- /*
- * In each lock check every action. We must scan the action
- * recursively in case there are any sub-queries within it.
- */
- foreach(action, onelock->actions)
- {
- Query *query = (Query *) lfirst(action);
-
- checkLockPerms_walker((Node *) query, &context);
- }
- }
-}