aboutsummaryrefslogtreecommitdiff
path: root/src/backend/rewrite/rewriteHandler.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2000-11-08 22:10:03 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2000-11-08 22:10:03 +0000
commit3908473c809d5c24940faebfabdad673f4302178 (patch)
tree6a1989499ee61771c7764afd2b24d12ebd25b8fb /src/backend/rewrite/rewriteHandler.c
parentebe0b236909732c75d665c73363bd4ac7a7aa138 (diff)
downloadpostgresql-3908473c809d5c24940faebfabdad673f4302178.tar.gz
postgresql-3908473c809d5c24940faebfabdad673f4302178.zip
Make DROP TABLE rollback-able: postpone physical file delete until commit.
(WAL logging for this is not done yet, however.) Clean up a number of really crufty things that are no longer needed now that DROP behaves nicely. Make temp table mapper do the right things when drop or rename affecting a temp table is rolled back. Also, remove "relation modified while in use" error check, in favor of locking tables at first reference and holding that lock throughout the statement.
Diffstat (limited to 'src/backend/rewrite/rewriteHandler.c')
-rw-r--r--src/backend/rewrite/rewriteHandler.c62
1 files changed, 48 insertions, 14 deletions
diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c
index d0fe6a5ee10..a0a9d5671e5 100644
--- a/src/backend/rewrite/rewriteHandler.c
+++ b/src/backend/rewrite/rewriteHandler.c
@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.82 2000/10/05 19:11:34 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.83 2000/11/08 22:09:59 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -363,14 +363,6 @@ static Query *
fireRIRrules(Query *parsetree)
{
int rt_index;
- RangeTblEntry *rte;
- Relation rel;
- List *locks;
- RuleLock *rules;
- RewriteRule *rule;
- bool relIsUsed;
- int i;
- List *l;
/*
* don't try to convert this into a foreach loop, because rtable list
@@ -379,6 +371,16 @@ fireRIRrules(Query *parsetree)
rt_index = 0;
while (rt_index < length(parsetree->rtable))
{
+ RangeTblEntry *rte;
+ Relation rel;
+ List *locks;
+ RuleLock *rules;
+ RewriteRule *rule;
+ LOCKMODE lockmode;
+ bool relIsUsed;
+ int i;
+ List *l;
+
++rt_index;
rte = rt_fetch(rt_index, parsetree->rtable);
@@ -406,11 +408,32 @@ fireRIRrules(Query *parsetree)
if (!relIsUsed && rt_index != parsetree->resultRelation)
continue;
- rel = heap_openr(rte->relname, AccessShareLock);
+ /*
+ * This may well be the first access to the relation during
+ * the current statement (it will be, if this Query was extracted
+ * from a rule or somehow got here other than via the parser).
+ * Therefore, grab the appropriate lock type for the relation,
+ * and do not release it until end of transaction. This protects
+ * the rewriter and planner against schema changes mid-query.
+ *
+ * If the relation is the query's result relation, then RewriteQuery()
+ * already got the right lock on it, so we need no additional lock.
+ * Otherwise, check to see if the relation is accessed FOR UPDATE
+ * or not.
+ */
+ if (rt_index == parsetree->resultRelation)
+ lockmode = NoLock;
+ else if (intMember(rt_index, parsetree->rowMarks))
+ lockmode = RowShareLock;
+ else
+ lockmode = AccessShareLock;
+
+ rel = heap_openr(rte->relname, lockmode);
+
rules = rel->rd_rules;
if (rules == NULL)
{
- heap_close(rel, AccessShareLock);
+ heap_close(rel, NoLock);
continue;
}
@@ -450,7 +473,7 @@ fireRIRrules(Query *parsetree)
relIsUsed);
}
- heap_close(rel, AccessShareLock);
+ heap_close(rel, NoLock);
}
/*
@@ -761,8 +784,19 @@ RewriteQuery(Query *parsetree, bool *instead_flag, List **qual_products)
* the statement is an update, insert or delete - fire rules on it.
*/
result_relation = parsetree->resultRelation;
+ Assert(result_relation != 0);
rt_entry = rt_fetch(result_relation, parsetree->rtable);
- rt_entry_relation = heap_openr(rt_entry->relname, AccessShareLock);
+
+ /*
+ * This may well be the first access to the result relation during
+ * the current statement (it will be, if this Query was extracted
+ * from a rule or somehow got here other than via the parser).
+ * Therefore, grab the appropriate lock type for a result relation,
+ * and do not release it until end of transaction. This protects the
+ * rewriter and planner against schema changes mid-query.
+ */
+ rt_entry_relation = heap_openr(rt_entry->relname, RowExclusiveLock);
+
rt_entry_locks = rt_entry_relation->rd_rules;
if (rt_entry_locks != NULL)
@@ -778,7 +812,7 @@ RewriteQuery(Query *parsetree, bool *instead_flag, List **qual_products)
qual_products);
}
- heap_close(rt_entry_relation, AccessShareLock);
+ heap_close(rt_entry_relation, NoLock); /* keep lock! */
return product_queries;
}