aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/ruleutils.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2005-06-03 23:05:30 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2005-06-03 23:05:30 +0000
commitba42002461a82ff5aba240611fe5a2366b0f1f86 (patch)
tree904791114a5a2505b5a5bdf58d14551b916bf325 /src/backend/utils/adt/ruleutils.c
parent7e209f6ce3a4eb2cba877e5e76597ecdb1596c2e (diff)
downloadpostgresql-ba42002461a82ff5aba240611fe5a2366b0f1f86.tar.gz
postgresql-ba42002461a82ff5aba240611fe5a2366b0f1f86.zip
Revise handling of dropped columns in JOIN alias lists to avoid a
performance problem pointed out by phil@vodafone: to wit, we were spending O(N^2) time to check dropped-ness in an N-deep join tree, even in the case where the tree was freshly constructed and couldn't possibly mention any dropped columns. Instead of recursing in get_rte_attribute_is_dropped(), change the data structure definition: the joinaliasvars list of a JOIN RTE must have a NULL Const instead of a Var at any position that references a now-dropped column. This costs nothing during normal parse-rewrite-plan path, and instead we have a linear-time update to make when loading a stored rule that might contain now-dropped columns. While at it, move the responsibility for acquring locks on relations referenced by rules into this separate function (which I therefore chose to call AcquireRewriteLocks). This saves effort --- namely, duplicated lock grabs in parser and rewriter --- in the normal path at a cost of one extra non-locked heap_open() in the stored-rule path; seems a good tradeoff. A fringe benefit is that it is now *much* clearer that we acquire lock on relations referenced in rules before we make any rewriter decisions based on their properties. (I don't know of any bug of that ilk, but it wasn't exactly clear before.)
Diffstat (limited to 'src/backend/utils/adt/ruleutils.c')
-rw-r--r--src/backend/utils/adt/ruleutils.c17
1 files changed, 15 insertions, 2 deletions
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index be53f7373d9..c6de4df714a 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -3,7 +3,7 @@
* back to source text
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.198 2005/05/31 03:03:59 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.199 2005/06/03 23:05:29 tgl Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
@@ -67,6 +67,7 @@
#include "parser/parse_oper.h"
#include "parser/parse_type.h"
#include "parser/parsetree.h"
+#include "rewrite/rewriteHandler.h"
#include "rewrite/rewriteManip.h"
#include "rewrite/rewriteSupport.h"
#include "utils/array.h"
@@ -1661,6 +1662,9 @@ make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc,
*/
query = getInsertSelectQuery(query, NULL);
+ /* Must acquire locks right away; see notes in get_query_def() */
+ AcquireRewriteLocks(query);
+
context.buf = buf;
context.namespaces = list_make1(&dpns);
context.varprefix = (list_length(query->rtable) != 1);
@@ -1795,6 +1799,14 @@ get_query_def(Query *query, StringInfo buf, List *parentnamespace,
deparse_context context;
deparse_namespace dpns;
+ /*
+ * Before we begin to examine the query, acquire locks on referenced
+ * relations, and fix up deleted columns in JOIN RTEs. This ensures
+ * consistent results. Note we assume it's OK to scribble on the
+ * passed querytree!
+ */
+ AcquireRewriteLocks(query);
+
context.buf = buf;
context.namespaces = lcons(&dpns, list_copy(parentnamespace));
context.varprefix = (parentnamespace != NIL ||
@@ -4245,6 +4257,7 @@ get_from_clause_alias(Alias *alias, int varno,
Query *query, deparse_context *context)
{
StringInfo buf = context->buf;
+ RangeTblEntry *rte = rt_fetch(varno, query->rtable);
ListCell *col;
AttrNumber attnum;
bool first = true;
@@ -4256,7 +4269,7 @@ get_from_clause_alias(Alias *alias, int varno,
foreach(col, alias->colnames)
{
attnum++;
- if (get_rte_attribute_is_dropped(query->rtable, varno, attnum))
+ if (get_rte_attribute_is_dropped(rte, attnum))
continue;
if (first)
{