From 2fdf9e0be6b474e38e516007b5ac5274ecef514d Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Wed, 13 Apr 2005 16:50:55 +0000 Subject: [PATCH] Change addRangeTableEntryForRelation() to take a Relation pointer instead of just a relation OID, thereby not having to open the relation for itself. This actually saves code rather than adding it for most of the existing callers, which had the rel open already. The main point though is to be able to use this rather than plain addRangeTableEntry in setTargetTable, thus saving one relation_openrv/relation_close cycle for every INSERT, UPDATE, or DELETE. Seems to provide a several percent win on simple INSERTs. --- src/backend/catalog/heap.c | 9 ++++---- src/backend/commands/tablecmds.c | 6 ++--- src/backend/commands/view.c | 12 +++++++--- src/backend/parser/analyze.c | 36 +++++++++++++++-------------- src/backend/parser/parse_clause.c | 5 ++-- src/backend/parser/parse_relation.c | 30 ++++-------------------- src/include/parser/parse_relation.h | 4 ++-- 7 files changed, 45 insertions(+), 57 deletions(-) diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index 0616eab589..4c314c1e8b 100644 --- a/src/backend/catalog/heap.c +++ b/src/backend/catalog/heap.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.281 2005/03/20 22:00:51 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.282 2005/04/13 16:50:54 tgl Exp $ * * * INTERFACE ROUTINES @@ -1482,7 +1482,6 @@ AddRelationRawConstraints(Relation rel, List *rawConstraints) { List *cookedConstraints = NIL; - char *relname = RelationGetRelationName(rel); TupleDesc tupleDesc; TupleConstr *oldconstr; int numoldchecks; @@ -1517,8 +1516,8 @@ AddRelationRawConstraints(Relation rel, */ pstate = make_parsestate(NULL); rte = addRangeTableEntryForRelation(pstate, - RelationGetRelid(rel), - makeAlias(relname, NIL), + rel, + NULL, false, true); addRTEtoQuery(pstate, rte, true, true); @@ -1576,7 +1575,7 @@ AddRelationRawConstraints(Relation rel, ereport(ERROR, (errcode(ERRCODE_INVALID_COLUMN_REFERENCE), errmsg("only table \"%s\" can be referenced in check constraint", - relname))); + RelationGetRelationName(rel)))); /* * No subplans or aggregates, either... diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 21655e7d61..79e36c64e7 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.152 2005/03/29 00:16:57 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.153 2005/04/13 16:50:54 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -4732,8 +4732,8 @@ ATPrepAlterColumnType(List **wqueue, /* Expression must be able to access vars of old table */ rte = addRangeTableEntryForRelation(pstate, - RelationGetRelid(rel), - makeAlias(RelationGetRelationName(rel), NIL), + rel, + NULL, false, true); addRTEtoQuery(pstate, rte, false, true); diff --git a/src/backend/commands/view.c b/src/backend/commands/view.c index 21609e063f..81421f2a7b 100644 --- a/src/backend/commands/view.c +++ b/src/backend/commands/view.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/view.c,v 1.88 2005/04/06 16:34:04 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/commands/view.c,v 1.89 2005/04/13 16:50:54 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -329,6 +329,7 @@ DefineViewRules(const RangeVar *view, Query *viewParse, bool replace) static Query * UpdateRangeTableOfViewParse(Oid viewOid, Query *viewParse) { + Relation viewRel; List *new_rt; RangeTblEntry *rt_entry1, *rt_entry2; @@ -343,14 +344,17 @@ UpdateRangeTableOfViewParse(Oid viewOid, Query *viewParse) */ viewParse = (Query *) copyObject(viewParse); + /* need to open the rel for addRangeTableEntryForRelation */ + viewRel = relation_open(viewOid, AccessShareLock); + /* * Create the 2 new range table entries and form the new range * table... OLD first, then NEW.... */ - rt_entry1 = addRangeTableEntryForRelation(NULL, viewOid, + rt_entry1 = addRangeTableEntryForRelation(NULL, viewRel, makeAlias("*OLD*", NIL), false, false); - rt_entry2 = addRangeTableEntryForRelation(NULL, viewOid, + rt_entry2 = addRangeTableEntryForRelation(NULL, viewRel, makeAlias("*NEW*", NIL), false, false); /* Must override addRangeTableEntry's default access-check flags */ @@ -366,6 +370,8 @@ UpdateRangeTableOfViewParse(Oid viewOid, Query *viewParse) */ OffsetVarNodes((Node *) viewParse, 2, 0); + relation_close(viewRel, AccessShareLock); + return viewParse; } diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c index 4dad0ae80a..03f53db2c9 100644 --- a/src/backend/parser/analyze.c +++ b/src/backend/parser/analyze.c @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.318 2005/04/07 01:51:38 neilc Exp $ + * $PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.319 2005/04/13 16:50:54 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1536,6 +1536,7 @@ transformRuleStmt(ParseState *pstate, RuleStmt *stmt, List **extras_before, List **extras_after) { Query *qry; + Relation rel; RangeTblEntry *oldrte; RangeTblEntry *newrte; @@ -1547,11 +1548,9 @@ transformRuleStmt(ParseState *pstate, RuleStmt *stmt, * To avoid deadlock, make sure the first thing we do is grab * AccessExclusiveLock on the target relation. This will be needed by * DefineQueryRewrite(), and we don't want to grab a lesser lock - * beforehand. We don't need to hold a refcount on the relcache - * entry, however. + * beforehand. */ - heap_close(heap_openrv(stmt->relation, AccessExclusiveLock), - NoLock); + rel = heap_openrv(stmt->relation, AccessExclusiveLock); /* * NOTE: 'OLD' must always have a varno equal to 1 and 'NEW' equal to @@ -1559,12 +1558,12 @@ transformRuleStmt(ParseState *pstate, RuleStmt *stmt, * rule qualification. */ Assert(pstate->p_rtable == NIL); - oldrte = addRangeTableEntry(pstate, stmt->relation, - makeAlias("*OLD*", NIL), - false, true); - newrte = addRangeTableEntry(pstate, stmt->relation, - makeAlias("*NEW*", NIL), - false, true); + oldrte = addRangeTableEntryForRelation(pstate, rel, + makeAlias("*OLD*", NIL), + false, true); + newrte = addRangeTableEntryForRelation(pstate, rel, + makeAlias("*NEW*", NIL), + false, true); /* Must override addRangeTableEntry's default access-check flags */ oldrte->requiredPerms = 0; newrte->requiredPerms = 0; @@ -1659,12 +1658,12 @@ transformRuleStmt(ParseState *pstate, RuleStmt *stmt, * or they won't be accessible at all. We decide later * whether to put them in the joinlist. */ - oldrte = addRangeTableEntry(sub_pstate, stmt->relation, - makeAlias("*OLD*", NIL), - false, false); - newrte = addRangeTableEntry(sub_pstate, stmt->relation, - makeAlias("*NEW*", NIL), - false, false); + oldrte = addRangeTableEntryForRelation(sub_pstate, rel, + makeAlias("*OLD*", NIL), + false, false); + newrte = addRangeTableEntryForRelation(sub_pstate, rel, + makeAlias("*NEW*", NIL), + false, false); oldrte->requiredPerms = 0; newrte->requiredPerms = 0; addRTEtoQuery(sub_pstate, oldrte, false, true); @@ -1791,6 +1790,9 @@ transformRuleStmt(ParseState *pstate, RuleStmt *stmt, stmt->actions = newactions; } + /* Close relation, but keep the exclusive lock */ + heap_close(rel, NoLock); + return qry; } diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c index 6d13e485b2..42960d4376 100644 --- a/src/backend/parser/parse_clause.c +++ b/src/backend/parser/parse_clause.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/parse_clause.c,v 1.139 2005/04/06 16:34:06 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_clause.c,v 1.140 2005/04/13 16:50:55 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -144,7 +144,8 @@ setTargetTable(ParseState *pstate, RangeVar *relation, /* * Now build an RTE. */ - rte = addRangeTableEntry(pstate, relation, NULL, inh, false); + rte = addRangeTableEntryForRelation(pstate, pstate->p_target_relation, + NULL, inh, false); pstate->p_target_rangetblentry = rte; /* assume new rte is at end */ diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c index edd59917e9..b68ae00515 100644 --- a/src/backend/parser/parse_relation.c +++ b/src/backend/parser/parse_relation.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/parse_relation.c,v 1.105 2005/04/07 01:51:39 neilc Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_relation.c,v 1.106 2005/04/13 16:50:55 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -809,34 +809,21 @@ addRangeTableEntry(ParseState *pstate, * Add an entry for a relation to the pstate's range table (p_rtable). * * This is just like addRangeTableEntry() except that it makes an RTE - * given a relation OID instead of a RangeVar reference. - * - * Note that an alias clause *must* be supplied. + * given an already-open relation instead of a RangeVar reference. */ RangeTblEntry * addRangeTableEntryForRelation(ParseState *pstate, - Oid relid, + Relation rel, Alias *alias, bool inh, bool inFromCl) { RangeTblEntry *rte = makeNode(RangeTblEntry); - char *refname = alias->aliasname; - LOCKMODE lockmode; - Relation rel; + char *refname = alias ? alias->aliasname : RelationGetRelationName(rel); rte->rtekind = RTE_RELATION; rte->alias = alias; - - /* - * Get the rel's relcache entry. This access ensures that we have an - * up-to-date relcache entry for the rel. Since this is typically the - * first access to a rel in a statement, be careful to get the right - * access level depending on whether we're doing SELECT FOR UPDATE. - */ - lockmode = isForUpdate(pstate, refname) ? RowShareLock : AccessShareLock; - rel = heap_open(relid, lockmode); - rte->relid = relid; + rte->relid = RelationGetRelid(rel); /* * Build the list of effective column names using user-supplied @@ -845,13 +832,6 @@ addRangeTableEntryForRelation(ParseState *pstate, rte->eref = makeAlias(refname, NIL); buildRelationAliases(rel->rd_att, alias, rte->eref); - /* - * Drop the rel refcount, but keep the access lock till end of - * transaction so that the table can't be deleted or have its schema - * modified underneath us. - */ - heap_close(rel, NoLock); - /*---------- * Flags: * - this RTE should be expanded to include descendant tables, diff --git a/src/include/parser/parse_relation.h b/src/include/parser/parse_relation.h index 2af4fbed33..6d1d923282 100644 --- a/src/include/parser/parse_relation.h +++ b/src/include/parser/parse_relation.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/parser/parse_relation.h,v 1.48 2004/12/31 22:03:38 pgsql Exp $ + * $PostgreSQL: pgsql/src/include/parser/parse_relation.h,v 1.49 2005/04/13 16:50:55 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -45,7 +45,7 @@ extern RangeTblEntry *addRangeTableEntry(ParseState *pstate, bool inh, bool inFromCl); extern RangeTblEntry *addRangeTableEntryForRelation(ParseState *pstate, - Oid relid, + Relation rel, Alias *alias, bool inh, bool inFromCl);