1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-24 00:23:06 +03:00

Separate parse-analysis for utility commands out of parser/analyze.c

(which now deals only in optimizable statements), and put that code
into a new file parser/parse_utilcmd.c.  This helps clarify and enforce
the design rule that utility statements shouldn't be processed during
the regular parse analysis phase; all interpretation of their meaning
should happen after they are given to ProcessUtility to execute.
(We need this because we don't retain any locks for a utility statement
that's in a plan cache, nor have any way to detect that it's stale.)

We are also able to simplify the API for parse_analyze() and related
routines, because they will now always return exactly one Query structure.

In passing, fix bug #3403 concerning trying to add a serial column to
an existing temp table (this is largely Heikki's work, but we needed
all that restructuring to make it safe).
This commit is contained in:
Tom Lane
2007-06-23 22:12:52 +00:00
parent ec0bb02db8
commit 46379d6e60
23 changed files with 2142 additions and 2095 deletions

View File

@@ -2,7 +2,7 @@
#
# Makefile for parser
#
# $PostgreSQL: pgsql/src/backend/parser/Makefile,v 1.44 2006/05/27 17:38:45 tgl Exp $
# $PostgreSQL: pgsql/src/backend/parser/Makefile,v 1.45 2007/06/23 22:12:51 tgl Exp $
#
#-------------------------------------------------------------------------
@@ -14,7 +14,7 @@ override CPPFLAGS := -I$(srcdir) $(CPPFLAGS)
OBJS= analyze.o gram.o keywords.o parser.o parse_agg.o parse_clause.o \
parse_expr.o parse_func.o parse_node.o parse_oper.o parse_relation.o \
parse_type.o parse_coerce.o parse_target.o scansup.o
parse_type.o parse_coerce.o parse_target.o parse_utilcmd.o scansup.o
FLEXFLAGS = -CF

View File

@@ -1,20 +1,21 @@
This directory does more than tokenize and parse SQL queries. It also
creates Query structures for the various complex queries that is passed
creates Query structures for the various complex queries that are passed
to the optimizer and then executor.
parser.c things start here
scan.l break query into tokens
scansup.c handle escapes in input
scansup.c handle escapes in input strings
keywords.c turn keywords into specific tokens
gram.y parse the tokens and fill query-type-specific structures
analyze.c handle post-parse processing for each query type
analyze.c top level of parse analysis for optimizable queries
parse_clause.c handle clauses like WHERE, ORDER BY, GROUP BY, ...
parse_coerce.c used for coercing expressions of different types
parse_coerce.c handle coercing expressions to different types
parse_expr.c handle expressions like col, col + 3, x = 3 or x = 4
parse_oper.c handle operations in expressions
parse_oper.c handle operators in expressions
parse_agg.c handle aggregates, like SUM(col1), AVG(col2), ...
parse_func.c handle functions, table.column and column identifiers
parse_node.c create nodes for various structures
parse_target.c handle the result list of the query
parse_relation.c support routines for tables and column handling
parse_type.c support routines for type handling
parse_utilcmd.c parse analysis for utility commands (done at execution time)

File diff suppressed because it is too large Load Diff

View File

@@ -11,7 +11,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.595 2007/06/18 21:40:57 tgl Exp $
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.596 2007/06/23 22:12:51 tgl Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
@@ -33,7 +33,7 @@
* SET SQL_inheritance TO off; SELECT * FROM foo;
* because the entire string is parsed by gram.y before the SET gets
* executed. Anything that depends on the database or changeable state
* should be handled inside parse_analyze() so that it happens at the
* should be handled during parse analysis so that it happens at the
* right time not the wrong time. The handling of SQL_inheritance is
* a good example.
*
@@ -2093,9 +2093,10 @@ ColConstraintElem:
* ConstraintAttr represents constraint attributes, which we parse as if
* they were independent constraint clauses, in order to avoid shift/reduce
* conflicts (since NOT might start either an independent NOT NULL clause
* or an attribute). analyze.c is responsible for attaching the attribute
* information to the preceding "real" constraint node, and for complaining
* if attribute clauses appear in the wrong place or wrong combinations.
* or an attribute). parse_utilcmd.c is responsible for attaching the
* attribute information to the preceding "real" constraint node, and for
* complaining if attribute clauses appear in the wrong place or wrong
* combinations.
*
* See also ConstraintAttributeSpec, which can be used in places where
* there is no parsing conflict.

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/parser/parse_clause.c,v 1.165 2007/04/27 22:05:48 tgl Exp $
* $PostgreSQL: pgsql/src/backend/parser/parse_clause.c,v 1.166 2007/06/23 22:12:51 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -152,8 +152,8 @@ setTargetTable(ParseState *pstate, RangeVar *relation,
* Open target rel and grab suitable lock (which we will hold till end of
* transaction).
*
* analyze.c will eventually do the corresponding heap_close(), but *not*
* release the lock.
* free_parsestate() will eventually do the corresponding
* heap_close(), but *not* release the lock.
*/
pstate->p_target_relation = heap_openrv(relation, RowExclusiveLock);
@@ -193,7 +193,7 @@ setTargetTable(ParseState *pstate, RangeVar *relation,
* Simplify InhOption (yes/no/default) into boolean yes/no.
*
* The reason we do things this way is that we don't want to examine the
* SQL_inheritance option flag until parse_analyze is run. Otherwise,
* SQL_inheritance option flag until parse_analyze() is run. Otherwise,
* we'd do the wrong thing with query strings that intermix SET commands
* with queries.
*/
@@ -417,7 +417,6 @@ transformTableEntry(ParseState *pstate, RangeVar *r)
static RangeTblEntry *
transformRangeSubselect(ParseState *pstate, RangeSubselect *r)
{
List *parsetrees;
Query *query;
RangeTblEntry *rte;
@@ -434,19 +433,12 @@ transformRangeSubselect(ParseState *pstate, RangeSubselect *r)
/*
* Analyze and transform the subquery.
*/
parsetrees = parse_sub_analyze(r->subquery, pstate);
query = parse_sub_analyze(r->subquery, pstate);
/*
* Check that we got something reasonable. Most of these conditions are
* probably impossible given restrictions of the grammar, but check 'em
* anyway.
* Check that we got something reasonable. Many of these conditions are
* impossible given restrictions of the grammar, but check 'em anyway.
*/
if (list_length(parsetrees) != 1)
elog(ERROR, "unexpected parse analysis result for subquery in FROM");
query = (Query *) linitial(parsetrees);
if (query == NULL || !IsA(query, Query))
elog(ERROR, "unexpected parse analysis result for subquery in FROM");
if (query->commandType != CMD_SELECT ||
query->utilityStmt != NULL)
elog(ERROR, "expected SELECT query from subquery in FROM");

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.220 2007/06/11 22:22:42 tgl Exp $
* $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.221 2007/06/23 22:12:51 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1120,19 +1120,15 @@ transformCaseExpr(ParseState *pstate, CaseExpr *c)
static Node *
transformSubLink(ParseState *pstate, SubLink *sublink)
{
List *qtrees;
Query *qtree;
Node *result = (Node *) sublink;
Query *qtree;
/* If we already transformed this node, do nothing */
if (IsA(sublink->subselect, Query))
return result;
pstate->p_hasSubLinks = true;
qtrees = parse_sub_analyze(sublink->subselect, pstate);
if (list_length(qtrees) != 1)
elog(ERROR, "bad query in sub-select");
qtree = (Query *) linitial(qtrees);
qtree = parse_sub_analyze(sublink->subselect, pstate);
if (qtree->commandType != CMD_SELECT ||
qtree->utilityStmt != NULL ||
qtree->intoClause != NULL)

View File

@@ -8,12 +8,13 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/parser/parse_node.c,v 1.97 2007/03/17 00:11:04 tgl Exp $
* $PostgreSQL: pgsql/src/backend/parser/parse_node.c,v 1.98 2007/06/23 22:12:51 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include "access/heapam.h"
#include "catalog/pg_type.h"
#include "mb/pg_wchar.h"
#include "nodes/makefuncs.h"
@@ -27,9 +28,11 @@
#include "utils/varbit.h"
/* make_parsestate()
* Allocate and initialize a new ParseState.
* The CALLER is responsible for freeing the ParseState* returned.
/*
* make_parsestate
* Allocate and initialize a new ParseState.
*
* Caller should eventually release the ParseState via free_parsestate().
*/
ParseState *
make_parsestate(ParseState *parentParseState)
@@ -52,6 +55,30 @@ make_parsestate(ParseState *parentParseState)
return pstate;
}
/*
* free_parsestate
* Release a ParseState and any subsidiary resources.
*/
void
free_parsestate(ParseState *pstate)
{
/*
* Check that we did not produce too many resnos; at the very least we
* cannot allow more than 2^16, since that would exceed the range of a
* AttrNumber. It seems safest to use MaxTupleAttributeNumber.
*/
if (pstate->p_next_resno - 1 > MaxTupleAttributeNumber)
ereport(ERROR,
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("target lists can have at most %d entries",
MaxTupleAttributeNumber)));
if (pstate->p_target_relation != NULL)
heap_close(pstate->p_target_relation, NoLock);
pfree(pstate);
}
/*
* parser_errposition

File diff suppressed because it is too large Load Diff