mirror of
https://github.com/postgres/postgres.git
synced 2025-04-21 12:05:57 +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:
parent
ec0bb02db8
commit
46379d6e60
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/commands/indexcmds.c,v 1.159 2007/06/03 17:06:16 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/commands/indexcmds.c,v 1.160 2007/06/23 22:12:50 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -367,7 +367,7 @@ DefineIndex(RangeVar *heapRelation,
|
|||||||
/*
|
/*
|
||||||
* This shouldn't happen during CREATE TABLE, but can happen
|
* This shouldn't happen during CREATE TABLE, but can happen
|
||||||
* during ALTER TABLE. Keep message in sync with
|
* during ALTER TABLE. Keep message in sync with
|
||||||
* transformIndexConstraints() in parser/analyze.c.
|
* transformIndexConstraints() in parser/parse_utilcmd.c.
|
||||||
*/
|
*/
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_UNDEFINED_COLUMN),
|
(errcode(ERRCODE_UNDEFINED_COLUMN),
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
* Copyright (c) 2002-2007, PostgreSQL Global Development Group
|
* Copyright (c) 2002-2007, PostgreSQL Global Development Group
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/commands/prepare.c,v 1.76 2007/05/25 17:54:25 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/commands/prepare.c,v 1.77 2007/06/23 22:12:50 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -55,7 +55,6 @@ PrepareQuery(PrepareStmt *stmt, const char *queryString)
|
|||||||
{
|
{
|
||||||
Oid *argtypes = NULL;
|
Oid *argtypes = NULL;
|
||||||
int nargs;
|
int nargs;
|
||||||
List *queries;
|
|
||||||
Query *query;
|
Query *query;
|
||||||
List *query_list,
|
List *query_list,
|
||||||
*plan_list;
|
*plan_list;
|
||||||
@ -105,7 +104,7 @@ PrepareQuery(PrepareStmt *stmt, const char *queryString)
|
|||||||
* Because parse analysis scribbles on the raw querytree, we must make
|
* Because parse analysis scribbles on the raw querytree, we must make
|
||||||
* a copy to ensure we have a pristine raw tree to cache. FIXME someday.
|
* a copy to ensure we have a pristine raw tree to cache. FIXME someday.
|
||||||
*/
|
*/
|
||||||
queries = parse_analyze_varparams((Node *) copyObject(stmt->query),
|
query = parse_analyze_varparams((Node *) copyObject(stmt->query),
|
||||||
queryString,
|
queryString,
|
||||||
&argtypes, &nargs);
|
&argtypes, &nargs);
|
||||||
|
|
||||||
@ -124,15 +123,8 @@ PrepareQuery(PrepareStmt *stmt, const char *queryString)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Shouldn't get any extra statements, since grammar only allows
|
* grammar only allows OptimizableStmt, so this check should be redundant
|
||||||
* OptimizableStmt
|
|
||||||
*/
|
*/
|
||||||
if (list_length(queries) != 1)
|
|
||||||
elog(ERROR, "unexpected extra stuff in prepared statement");
|
|
||||||
|
|
||||||
query = (Query *) linitial(queries);
|
|
||||||
Assert(IsA(query, Query));
|
|
||||||
|
|
||||||
switch (query->commandType)
|
switch (query->commandType)
|
||||||
{
|
{
|
||||||
case CMD_SELECT:
|
case CMD_SELECT:
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/commands/schemacmds.c,v 1.45 2007/03/23 19:53:51 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/commands/schemacmds.c,v 1.46 2007/06/23 22:12:50 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -24,7 +24,7 @@
|
|||||||
#include "commands/dbcommands.h"
|
#include "commands/dbcommands.h"
|
||||||
#include "commands/schemacmds.h"
|
#include "commands/schemacmds.h"
|
||||||
#include "miscadmin.h"
|
#include "miscadmin.h"
|
||||||
#include "parser/analyze.h"
|
#include "parser/parse_utilcmd.h"
|
||||||
#include "tcop/utility.h"
|
#include "tcop/utility.h"
|
||||||
#include "utils/acl.h"
|
#include "utils/acl.h"
|
||||||
#include "utils/builtins.h"
|
#include "utils/builtins.h"
|
||||||
@ -111,31 +111,24 @@ CreateSchemaCommand(CreateSchemaStmt *stmt, const char *queryString)
|
|||||||
/*
|
/*
|
||||||
* Examine the list of commands embedded in the CREATE SCHEMA command, and
|
* Examine the list of commands embedded in the CREATE SCHEMA command, and
|
||||||
* reorganize them into a sequentially executable order with no forward
|
* reorganize them into a sequentially executable order with no forward
|
||||||
* references. Note that the result is still a list of raw parsetrees in
|
* references. Note that the result is still a list of raw parsetrees
|
||||||
* need of parse analysis --- we cannot, in general, run analyze.c on one
|
* --- we cannot, in general, run parse analysis on one statement until
|
||||||
* statement until we have actually executed the prior ones.
|
* we have actually executed the prior ones.
|
||||||
*/
|
*/
|
||||||
parsetree_list = analyzeCreateSchemaStmt(stmt);
|
parsetree_list = transformCreateSchemaStmt(stmt);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Analyze and execute each command contained in the CREATE SCHEMA
|
* Execute each command contained in the CREATE SCHEMA. Since the
|
||||||
|
* grammar allows only utility commands in CREATE SCHEMA, there is
|
||||||
|
* no need to pass them through parse_analyze() or the rewriter;
|
||||||
|
* we can just hand them straight to ProcessUtility.
|
||||||
*/
|
*/
|
||||||
foreach(parsetree_item, parsetree_list)
|
foreach(parsetree_item, parsetree_list)
|
||||||
{
|
{
|
||||||
Node *parsetree = (Node *) lfirst(parsetree_item);
|
Node *stmt = (Node *) lfirst(parsetree_item);
|
||||||
List *querytree_list;
|
|
||||||
ListCell *querytree_item;
|
|
||||||
|
|
||||||
querytree_list = parse_analyze(parsetree, queryString, NULL, 0);
|
|
||||||
|
|
||||||
foreach(querytree_item, querytree_list)
|
|
||||||
{
|
|
||||||
Query *querytree = (Query *) lfirst(querytree_item);
|
|
||||||
|
|
||||||
/* schemas should contain only utility stmts */
|
|
||||||
Assert(querytree->commandType == CMD_UTILITY);
|
|
||||||
/* do this step */
|
/* do this step */
|
||||||
ProcessUtility(querytree->utilityStmt,
|
ProcessUtility(stmt,
|
||||||
queryString,
|
queryString,
|
||||||
NULL,
|
NULL,
|
||||||
false, /* not top level */
|
false, /* not top level */
|
||||||
@ -144,7 +137,6 @@ CreateSchemaCommand(CreateSchemaStmt *stmt, const char *queryString)
|
|||||||
/* make sure later steps can see the object created here */
|
/* make sure later steps can see the object created here */
|
||||||
CommandCounterIncrement();
|
CommandCounterIncrement();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Reset search path to normal state */
|
/* Reset search path to normal state */
|
||||||
PopOverrideSearchPath();
|
PopOverrideSearchPath();
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.227 2007/06/03 22:16:03 petere Exp $
|
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.228 2007/06/23 22:12:50 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -44,7 +44,6 @@
|
|||||||
#include "optimizer/clauses.h"
|
#include "optimizer/clauses.h"
|
||||||
#include "optimizer/plancat.h"
|
#include "optimizer/plancat.h"
|
||||||
#include "optimizer/prep.h"
|
#include "optimizer/prep.h"
|
||||||
#include "parser/analyze.h"
|
|
||||||
#include "parser/gramparse.h"
|
#include "parser/gramparse.h"
|
||||||
#include "parser/parse_clause.h"
|
#include "parser/parse_clause.h"
|
||||||
#include "parser/parse_coerce.h"
|
#include "parser/parse_coerce.h"
|
||||||
@ -52,6 +51,7 @@
|
|||||||
#include "parser/parse_oper.h"
|
#include "parser/parse_oper.h"
|
||||||
#include "parser/parse_relation.h"
|
#include "parser/parse_relation.h"
|
||||||
#include "parser/parse_type.h"
|
#include "parser/parse_type.h"
|
||||||
|
#include "parser/parse_utilcmd.h"
|
||||||
#include "parser/parser.h"
|
#include "parser/parser.h"
|
||||||
#include "rewrite/rewriteDefine.h"
|
#include "rewrite/rewriteDefine.h"
|
||||||
#include "rewrite/rewriteHandler.h"
|
#include "rewrite/rewriteHandler.h"
|
||||||
@ -394,7 +394,7 @@ DefineRelation(CreateStmt *stmt, char relkind)
|
|||||||
add_nonduplicate_constraint(cdef, check, &ncheck);
|
add_nonduplicate_constraint(cdef, check, &ncheck);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* analyze.c might have passed some precooked constraints too,
|
* parse_utilcmd.c might have passed some precooked constraints too,
|
||||||
* due to LIKE tab INCLUDING CONSTRAINTS
|
* due to LIKE tab INCLUDING CONSTRAINTS
|
||||||
*/
|
*/
|
||||||
foreach(listptr, stmt->constraints)
|
foreach(listptr, stmt->constraints)
|
||||||
@ -2922,7 +2922,7 @@ find_composite_type_dependencies(Oid typeOid,
|
|||||||
*
|
*
|
||||||
* Adds an additional attribute to a relation making the assumption that
|
* Adds an additional attribute to a relation making the assumption that
|
||||||
* CHECK, NOT NULL, and FOREIGN KEY constraints will be removed from the
|
* CHECK, NOT NULL, and FOREIGN KEY constraints will be removed from the
|
||||||
* AT_AddColumn AlterTableCmd by analyze.c and added as independent
|
* AT_AddColumn AlterTableCmd by parse_utilcmd.c and added as independent
|
||||||
* AlterTableCmd's.
|
* AlterTableCmd's.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
@ -3745,9 +3745,9 @@ ATExecDropColumn(Relation rel, const char *colName,
|
|||||||
/*
|
/*
|
||||||
* ALTER TABLE ADD INDEX
|
* ALTER TABLE ADD INDEX
|
||||||
*
|
*
|
||||||
* There is no such command in the grammar, but the parser converts UNIQUE
|
* There is no such command in the grammar, but parse_utilcmd.c converts
|
||||||
* and PRIMARY KEY constraints into AT_AddIndex subcommands. This lets us
|
* UNIQUE and PRIMARY KEY constraints into AT_AddIndex subcommands. This lets
|
||||||
* schedule creation of the index at the appropriate time during ALTER.
|
* us schedule creation of the index at the appropriate time during ALTER.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
ATExecAddIndex(AlteredTableInfo *tab, Relation rel,
|
ATExecAddIndex(AlteredTableInfo *tab, Relation rel,
|
||||||
@ -3766,13 +3766,8 @@ ATExecAddIndex(AlteredTableInfo *tab, Relation rel,
|
|||||||
/* suppress notices when rebuilding existing index */
|
/* suppress notices when rebuilding existing index */
|
||||||
quiet = is_rebuild;
|
quiet = is_rebuild;
|
||||||
|
|
||||||
/*
|
/* The IndexStmt has already been through transformIndexStmt */
|
||||||
* Run parse analysis. We don't have convenient access to the query text
|
|
||||||
* here, but it's probably not worth worrying about.
|
|
||||||
*/
|
|
||||||
stmt = analyzeIndexStmt(stmt, NULL);
|
|
||||||
|
|
||||||
/* ... and do it */
|
|
||||||
DefineIndex(stmt->relation, /* relation */
|
DefineIndex(stmt->relation, /* relation */
|
||||||
stmt->idxname, /* index name */
|
stmt->idxname, /* index name */
|
||||||
InvalidOid, /* no predefined OID */
|
InvalidOid, /* no predefined OID */
|
||||||
@ -3806,7 +3801,7 @@ ATExecAddConstraint(AlteredTableInfo *tab, Relation rel, Node *newConstraint)
|
|||||||
/*
|
/*
|
||||||
* Currently, we only expect to see CONSTR_CHECK nodes
|
* Currently, we only expect to see CONSTR_CHECK nodes
|
||||||
* arriving here (see the preprocessing done in
|
* arriving here (see the preprocessing done in
|
||||||
* parser/analyze.c). Use a switch anyway to make it easier
|
* parse_utilcmd.c). Use a switch anyway to make it easier
|
||||||
* to add more code later.
|
* to add more code later.
|
||||||
*/
|
*/
|
||||||
switch (constr->contype)
|
switch (constr->contype)
|
||||||
@ -5239,17 +5234,27 @@ ATPostAlterTypeParse(char *cmd, List **wqueue)
|
|||||||
ListCell *list_item;
|
ListCell *list_item;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We expect that we only have to do raw parsing and parse analysis, not
|
* We expect that we will get only ALTER TABLE and CREATE INDEX statements.
|
||||||
* any rule rewriting, since these will all be utility statements.
|
* Hence, there is no need to pass them through parse_analyze() or the
|
||||||
|
* rewriter, but instead we need to pass them through parse_utilcmd.c
|
||||||
|
* to make them ready for execution.
|
||||||
*/
|
*/
|
||||||
raw_parsetree_list = raw_parser(cmd);
|
raw_parsetree_list = raw_parser(cmd);
|
||||||
querytree_list = NIL;
|
querytree_list = NIL;
|
||||||
foreach(list_item, raw_parsetree_list)
|
foreach(list_item, raw_parsetree_list)
|
||||||
{
|
{
|
||||||
Node *parsetree = (Node *) lfirst(list_item);
|
Node *stmt = (Node *) lfirst(list_item);
|
||||||
|
|
||||||
|
if (IsA(stmt, IndexStmt))
|
||||||
|
querytree_list = lappend(querytree_list,
|
||||||
|
transformIndexStmt((IndexStmt *) stmt,
|
||||||
|
cmd));
|
||||||
|
else if (IsA(stmt, AlterTableStmt))
|
||||||
querytree_list = list_concat(querytree_list,
|
querytree_list = list_concat(querytree_list,
|
||||||
parse_analyze(parsetree, cmd, NULL, 0));
|
transformAlterTableStmt((AlterTableStmt *) stmt,
|
||||||
|
cmd));
|
||||||
|
else
|
||||||
|
querytree_list = lappend(querytree_list, stmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -5258,17 +5263,15 @@ ATPostAlterTypeParse(char *cmd, List **wqueue)
|
|||||||
*/
|
*/
|
||||||
foreach(list_item, querytree_list)
|
foreach(list_item, querytree_list)
|
||||||
{
|
{
|
||||||
Query *query = (Query *) lfirst(list_item);
|
Node *stm = (Node *) lfirst(list_item);
|
||||||
Relation rel;
|
Relation rel;
|
||||||
AlteredTableInfo *tab;
|
AlteredTableInfo *tab;
|
||||||
|
|
||||||
Assert(IsA(query, Query));
|
switch (nodeTag(stm))
|
||||||
Assert(query->commandType == CMD_UTILITY);
|
|
||||||
switch (nodeTag(query->utilityStmt))
|
|
||||||
{
|
{
|
||||||
case T_IndexStmt:
|
case T_IndexStmt:
|
||||||
{
|
{
|
||||||
IndexStmt *stmt = (IndexStmt *) query->utilityStmt;
|
IndexStmt *stmt = (IndexStmt *) stm;
|
||||||
AlterTableCmd *newcmd;
|
AlterTableCmd *newcmd;
|
||||||
|
|
||||||
rel = relation_openrv(stmt->relation, AccessExclusiveLock);
|
rel = relation_openrv(stmt->relation, AccessExclusiveLock);
|
||||||
@ -5283,7 +5286,7 @@ ATPostAlterTypeParse(char *cmd, List **wqueue)
|
|||||||
}
|
}
|
||||||
case T_AlterTableStmt:
|
case T_AlterTableStmt:
|
||||||
{
|
{
|
||||||
AlterTableStmt *stmt = (AlterTableStmt *) query->utilityStmt;
|
AlterTableStmt *stmt = (AlterTableStmt *) stm;
|
||||||
ListCell *lcmd;
|
ListCell *lcmd;
|
||||||
|
|
||||||
rel = relation_openrv(stmt->relation, AccessExclusiveLock);
|
rel = relation_openrv(stmt->relation, AccessExclusiveLock);
|
||||||
@ -5313,7 +5316,7 @@ ATPostAlterTypeParse(char *cmd, List **wqueue)
|
|||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
elog(ERROR, "unexpected statement type: %d",
|
elog(ERROR, "unexpected statement type: %d",
|
||||||
(int) nodeTag(query->utilityStmt));
|
(int) nodeTag(stm));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/commands/view.c,v 1.100 2007/03/13 00:33:40 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/commands/view.c,v 1.101 2007/06/23 22:12:50 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -351,7 +351,6 @@ UpdateRangeTableOfViewParse(Oid viewOid, Query *viewParse)
|
|||||||
void
|
void
|
||||||
DefineView(ViewStmt *stmt, const char *queryString)
|
DefineView(ViewStmt *stmt, const char *queryString)
|
||||||
{
|
{
|
||||||
List *stmts;
|
|
||||||
Query *viewParse;
|
Query *viewParse;
|
||||||
Oid viewOid;
|
Oid viewOid;
|
||||||
RangeVar *view;
|
RangeVar *view;
|
||||||
@ -363,15 +362,12 @@ DefineView(ViewStmt *stmt, const char *queryString)
|
|||||||
* Since parse analysis scribbles on its input, copy the raw parse tree;
|
* Since parse analysis scribbles on its input, copy the raw parse tree;
|
||||||
* this ensures we don't corrupt a prepared statement, for example.
|
* this ensures we don't corrupt a prepared statement, for example.
|
||||||
*/
|
*/
|
||||||
stmts = parse_analyze((Node *) copyObject(stmt->query),
|
viewParse = parse_analyze((Node *) copyObject(stmt->query),
|
||||||
queryString, NULL, 0);
|
queryString, NULL, 0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The grammar should ensure that the result is a single SELECT Query.
|
* The grammar should ensure that the result is a single SELECT Query.
|
||||||
*/
|
*/
|
||||||
if (list_length(stmts) != 1)
|
|
||||||
elog(ERROR, "unexpected parse analysis result");
|
|
||||||
viewParse = (Query *) linitial(stmts);
|
|
||||||
if (!IsA(viewParse, Query) ||
|
if (!IsA(viewParse, Query) ||
|
||||||
viewParse->commandType != CMD_SELECT)
|
viewParse->commandType != CMD_SELECT)
|
||||||
elog(ERROR, "unexpected parse analysis result");
|
elog(ERROR, "unexpected parse analysis result");
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/nodes/makefuncs.c,v 1.55 2007/03/17 00:11:03 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/nodes/makefuncs.c,v 1.56 2007/06/23 22:12:50 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -134,6 +134,20 @@ flatCopyTargetEntry(TargetEntry *src_tle)
|
|||||||
return tle;
|
return tle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* makeFromExpr -
|
||||||
|
* creates a FromExpr node
|
||||||
|
*/
|
||||||
|
FromExpr *
|
||||||
|
makeFromExpr(List *fromlist, Node *quals)
|
||||||
|
{
|
||||||
|
FromExpr *f = makeNode(FromExpr);
|
||||||
|
|
||||||
|
f->fromlist = fromlist;
|
||||||
|
f->quals = quals;
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* makeConst -
|
* makeConst -
|
||||||
* creates a Const node
|
* creates a Const node
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.246 2007/06/11 01:16:23 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.247 2007/06/23 22:12:50 tgl Exp $
|
||||||
*
|
*
|
||||||
* HISTORY
|
* HISTORY
|
||||||
* AUTHOR DATE MAJOR EVENT
|
* AUTHOR DATE MAJOR EVENT
|
||||||
@ -2910,7 +2910,6 @@ inline_function(Oid funcid, Oid result_type, List *args,
|
|||||||
MemoryContext mycxt;
|
MemoryContext mycxt;
|
||||||
ErrorContextCallback sqlerrcontext;
|
ErrorContextCallback sqlerrcontext;
|
||||||
List *raw_parsetree_list;
|
List *raw_parsetree_list;
|
||||||
List *querytree_list;
|
|
||||||
Query *querytree;
|
Query *querytree;
|
||||||
Node *newexpr;
|
Node *newexpr;
|
||||||
int *usecounts;
|
int *usecounts;
|
||||||
@ -2986,14 +2985,9 @@ inline_function(Oid funcid, Oid result_type, List *args,
|
|||||||
if (list_length(raw_parsetree_list) != 1)
|
if (list_length(raw_parsetree_list) != 1)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
querytree_list = parse_analyze(linitial(raw_parsetree_list), src,
|
querytree = parse_analyze(linitial(raw_parsetree_list), src,
|
||||||
argtypes, funcform->pronargs);
|
argtypes, funcform->pronargs);
|
||||||
|
|
||||||
if (list_length(querytree_list) != 1)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
querytree = (Query *) linitial(querytree_list);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The single command must be a simple "SELECT expression".
|
* The single command must be a simple "SELECT expression".
|
||||||
*/
|
*/
|
||||||
@ -3025,7 +3019,7 @@ inline_function(Oid funcid, Oid result_type, List *args,
|
|||||||
* no rewriting was needed; that's probably not important, but let's be
|
* no rewriting was needed; that's probably not important, but let's be
|
||||||
* careful.
|
* careful.
|
||||||
*/
|
*/
|
||||||
if (check_sql_fn_retval(funcid, result_type, querytree_list, NULL))
|
if (check_sql_fn_retval(funcid, result_type, list_make1(querytree), NULL))
|
||||||
goto fail; /* reject whole-tuple-result cases */
|
goto fail; /* reject whole-tuple-result cases */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
#
|
#
|
||||||
# Makefile for parser
|
# 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 \
|
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_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
|
FLEXFLAGS = -CF
|
||||||
|
|
||||||
|
@ -1,20 +1,21 @@
|
|||||||
This directory does more than tokenize and parse SQL queries. It also
|
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.
|
to the optimizer and then executor.
|
||||||
|
|
||||||
parser.c things start here
|
parser.c things start here
|
||||||
scan.l break query into tokens
|
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
|
keywords.c turn keywords into specific tokens
|
||||||
gram.y parse the tokens and fill query-type-specific structures
|
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_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_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_agg.c handle aggregates, like SUM(col1), AVG(col2), ...
|
||||||
parse_func.c handle functions, table.column and column identifiers
|
parse_func.c handle functions, table.column and column identifiers
|
||||||
parse_node.c create nodes for various structures
|
parse_node.c create nodes for various structures
|
||||||
parse_target.c handle the result list of the query
|
parse_target.c handle the result list of the query
|
||||||
parse_relation.c support routines for tables and column handling
|
parse_relation.c support routines for tables and column handling
|
||||||
parse_type.c support routines for type 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
@ -11,7 +11,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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
|
* HISTORY
|
||||||
* AUTHOR DATE MAJOR EVENT
|
* AUTHOR DATE MAJOR EVENT
|
||||||
@ -33,7 +33,7 @@
|
|||||||
* SET SQL_inheritance TO off; SELECT * FROM foo;
|
* SET SQL_inheritance TO off; SELECT * FROM foo;
|
||||||
* because the entire string is parsed by gram.y before the SET gets
|
* because the entire string is parsed by gram.y before the SET gets
|
||||||
* executed. Anything that depends on the database or changeable state
|
* 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
|
* right time not the wrong time. The handling of SQL_inheritance is
|
||||||
* a good example.
|
* a good example.
|
||||||
*
|
*
|
||||||
@ -2093,9 +2093,10 @@ ColConstraintElem:
|
|||||||
* ConstraintAttr represents constraint attributes, which we parse as if
|
* ConstraintAttr represents constraint attributes, which we parse as if
|
||||||
* they were independent constraint clauses, in order to avoid shift/reduce
|
* they were independent constraint clauses, in order to avoid shift/reduce
|
||||||
* conflicts (since NOT might start either an independent NOT NULL clause
|
* conflicts (since NOT might start either an independent NOT NULL clause
|
||||||
* or an attribute). analyze.c is responsible for attaching the attribute
|
* or an attribute). parse_utilcmd.c is responsible for attaching the
|
||||||
* information to the preceding "real" constraint node, and for complaining
|
* attribute information to the preceding "real" constraint node, and for
|
||||||
* if attribute clauses appear in the wrong place or wrong combinations.
|
* complaining if attribute clauses appear in the wrong place or wrong
|
||||||
|
* combinations.
|
||||||
*
|
*
|
||||||
* See also ConstraintAttributeSpec, which can be used in places where
|
* See also ConstraintAttributeSpec, which can be used in places where
|
||||||
* there is no parsing conflict.
|
* there is no parsing conflict.
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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
|
* Open target rel and grab suitable lock (which we will hold till end of
|
||||||
* transaction).
|
* transaction).
|
||||||
*
|
*
|
||||||
* analyze.c will eventually do the corresponding heap_close(), but *not*
|
* free_parsestate() will eventually do the corresponding
|
||||||
* release the lock.
|
* heap_close(), but *not* release the lock.
|
||||||
*/
|
*/
|
||||||
pstate->p_target_relation = heap_openrv(relation, RowExclusiveLock);
|
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.
|
* 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
|
* 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
|
* we'd do the wrong thing with query strings that intermix SET commands
|
||||||
* with queries.
|
* with queries.
|
||||||
*/
|
*/
|
||||||
@ -417,7 +417,6 @@ transformTableEntry(ParseState *pstate, RangeVar *r)
|
|||||||
static RangeTblEntry *
|
static RangeTblEntry *
|
||||||
transformRangeSubselect(ParseState *pstate, RangeSubselect *r)
|
transformRangeSubselect(ParseState *pstate, RangeSubselect *r)
|
||||||
{
|
{
|
||||||
List *parsetrees;
|
|
||||||
Query *query;
|
Query *query;
|
||||||
RangeTblEntry *rte;
|
RangeTblEntry *rte;
|
||||||
|
|
||||||
@ -434,19 +433,12 @@ transformRangeSubselect(ParseState *pstate, RangeSubselect *r)
|
|||||||
/*
|
/*
|
||||||
* Analyze and transform the subquery.
|
* 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
|
* Check that we got something reasonable. Many of these conditions are
|
||||||
* probably impossible given restrictions of the grammar, but check 'em
|
* impossible given restrictions of the grammar, but check 'em anyway.
|
||||||
* 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 ||
|
if (query->commandType != CMD_SELECT ||
|
||||||
query->utilityStmt != NULL)
|
query->utilityStmt != NULL)
|
||||||
elog(ERROR, "expected SELECT query from subquery in FROM");
|
elog(ERROR, "expected SELECT query from subquery in FROM");
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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 *
|
static Node *
|
||||||
transformSubLink(ParseState *pstate, SubLink *sublink)
|
transformSubLink(ParseState *pstate, SubLink *sublink)
|
||||||
{
|
{
|
||||||
List *qtrees;
|
|
||||||
Query *qtree;
|
|
||||||
Node *result = (Node *) sublink;
|
Node *result = (Node *) sublink;
|
||||||
|
Query *qtree;
|
||||||
|
|
||||||
/* If we already transformed this node, do nothing */
|
/* If we already transformed this node, do nothing */
|
||||||
if (IsA(sublink->subselect, Query))
|
if (IsA(sublink->subselect, Query))
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
pstate->p_hasSubLinks = true;
|
pstate->p_hasSubLinks = true;
|
||||||
qtrees = parse_sub_analyze(sublink->subselect, pstate);
|
qtree = parse_sub_analyze(sublink->subselect, pstate);
|
||||||
if (list_length(qtrees) != 1)
|
|
||||||
elog(ERROR, "bad query in sub-select");
|
|
||||||
qtree = (Query *) linitial(qtrees);
|
|
||||||
if (qtree->commandType != CMD_SELECT ||
|
if (qtree->commandType != CMD_SELECT ||
|
||||||
qtree->utilityStmt != NULL ||
|
qtree->utilityStmt != NULL ||
|
||||||
qtree->intoClause != NULL)
|
qtree->intoClause != NULL)
|
||||||
|
@ -8,12 +8,13 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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 "postgres.h"
|
||||||
|
|
||||||
|
#include "access/heapam.h"
|
||||||
#include "catalog/pg_type.h"
|
#include "catalog/pg_type.h"
|
||||||
#include "mb/pg_wchar.h"
|
#include "mb/pg_wchar.h"
|
||||||
#include "nodes/makefuncs.h"
|
#include "nodes/makefuncs.h"
|
||||||
@ -27,9 +28,11 @@
|
|||||||
#include "utils/varbit.h"
|
#include "utils/varbit.h"
|
||||||
|
|
||||||
|
|
||||||
/* make_parsestate()
|
/*
|
||||||
|
* make_parsestate
|
||||||
* Allocate and initialize a new ParseState.
|
* Allocate and initialize a new ParseState.
|
||||||
* The CALLER is responsible for freeing the ParseState* returned.
|
*
|
||||||
|
* Caller should eventually release the ParseState via free_parsestate().
|
||||||
*/
|
*/
|
||||||
ParseState *
|
ParseState *
|
||||||
make_parsestate(ParseState *parentParseState)
|
make_parsestate(ParseState *parentParseState)
|
||||||
@ -52,6 +55,30 @@ make_parsestate(ParseState *parentParseState)
|
|||||||
return pstate;
|
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
|
* parser_errposition
|
||||||
|
1800
src/backend/parser/parse_utilcmd.c
Normal file
1800
src/backend/parser/parse_utilcmd.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/rewrite/rewriteDefine.c,v 1.120 2007/04/27 22:05:48 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/rewrite/rewriteDefine.c,v 1.121 2007/06/23 22:12:51 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -20,8 +20,8 @@
|
|||||||
#include "catalog/pg_rewrite.h"
|
#include "catalog/pg_rewrite.h"
|
||||||
#include "miscadmin.h"
|
#include "miscadmin.h"
|
||||||
#include "optimizer/clauses.h"
|
#include "optimizer/clauses.h"
|
||||||
#include "parser/analyze.h"
|
|
||||||
#include "parser/parse_expr.h"
|
#include "parser/parse_expr.h"
|
||||||
|
#include "parser/parse_utilcmd.h"
|
||||||
#include "rewrite/rewriteDefine.h"
|
#include "rewrite/rewriteDefine.h"
|
||||||
#include "rewrite/rewriteManip.h"
|
#include "rewrite/rewriteManip.h"
|
||||||
#include "rewrite/rewriteSupport.h"
|
#include "rewrite/rewriteSupport.h"
|
||||||
@ -191,7 +191,7 @@ DefineRule(RuleStmt *stmt, const char *queryString)
|
|||||||
Node *whereClause;
|
Node *whereClause;
|
||||||
|
|
||||||
/* Parse analysis ... */
|
/* Parse analysis ... */
|
||||||
analyzeRuleStmt(stmt, queryString, &actions, &whereClause);
|
transformRuleStmt(stmt, queryString, &actions, &whereClause);
|
||||||
|
|
||||||
/* ... and execution */
|
/* ... and execution */
|
||||||
DefineQueryRewrite(stmt->rulename,
|
DefineQueryRewrite(stmt->rulename,
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.533 2007/04/30 16:37:08 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.534 2007/06/23 22:12:52 tgl Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* this is the "main" module of the postgres backend and
|
* this is the "main" module of the postgres backend and
|
||||||
@ -165,7 +165,7 @@ static int UseNewLine = 0; /* Use EOF as query delimiters */
|
|||||||
static int InteractiveBackend(StringInfo inBuf);
|
static int InteractiveBackend(StringInfo inBuf);
|
||||||
static int SocketBackend(StringInfo inBuf);
|
static int SocketBackend(StringInfo inBuf);
|
||||||
static int ReadCommand(StringInfo inBuf);
|
static int ReadCommand(StringInfo inBuf);
|
||||||
static List *pg_rewrite_queries(List *querytree_list);
|
static List *pg_rewrite_query(Query *query);
|
||||||
static bool check_log_statement(List *stmt_list);
|
static bool check_log_statement(List *stmt_list);
|
||||||
static int errdetail_execute(List *raw_parsetree_list);
|
static int errdetail_execute(List *raw_parsetree_list);
|
||||||
static int errdetail_params(ParamListInfo params);
|
static int errdetail_params(ParamListInfo params);
|
||||||
@ -567,6 +567,7 @@ List *
|
|||||||
pg_analyze_and_rewrite(Node *parsetree, const char *query_string,
|
pg_analyze_and_rewrite(Node *parsetree, const char *query_string,
|
||||||
Oid *paramTypes, int numParams)
|
Oid *paramTypes, int numParams)
|
||||||
{
|
{
|
||||||
|
Query *query;
|
||||||
List *querytree_list;
|
List *querytree_list;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -575,8 +576,7 @@ pg_analyze_and_rewrite(Node *parsetree, const char *query_string,
|
|||||||
if (log_parser_stats)
|
if (log_parser_stats)
|
||||||
ResetUsage();
|
ResetUsage();
|
||||||
|
|
||||||
querytree_list = parse_analyze(parsetree, query_string,
|
query = parse_analyze(parsetree, query_string, paramTypes, numParams);
|
||||||
paramTypes, numParams);
|
|
||||||
|
|
||||||
if (log_parser_stats)
|
if (log_parser_stats)
|
||||||
ShowUsage("PARSE ANALYSIS STATISTICS");
|
ShowUsage("PARSE ANALYSIS STATISTICS");
|
||||||
@ -584,68 +584,55 @@ pg_analyze_and_rewrite(Node *parsetree, const char *query_string,
|
|||||||
/*
|
/*
|
||||||
* (2) Rewrite the queries, as necessary
|
* (2) Rewrite the queries, as necessary
|
||||||
*/
|
*/
|
||||||
querytree_list = pg_rewrite_queries(querytree_list);
|
querytree_list = pg_rewrite_query(query);
|
||||||
|
|
||||||
return querytree_list;
|
return querytree_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Perform rewriting of a list of queries produced by parse analysis.
|
* Perform rewriting of a query produced by parse analysis.
|
||||||
*
|
*
|
||||||
* Note: queries must just have come from the parser, because we do not do
|
* Note: query must just have come from the parser, because we do not do
|
||||||
* AcquireRewriteLocks() on them.
|
* AcquireRewriteLocks() on it.
|
||||||
*/
|
*/
|
||||||
static List *
|
static List *
|
||||||
pg_rewrite_queries(List *querytree_list)
|
pg_rewrite_query(Query *query)
|
||||||
{
|
{
|
||||||
List *new_list = NIL;
|
List *querytree_list;
|
||||||
ListCell *list_item;
|
|
||||||
|
|
||||||
if (log_parser_stats)
|
if (log_parser_stats)
|
||||||
ResetUsage();
|
ResetUsage();
|
||||||
|
|
||||||
/*
|
|
||||||
* rewritten queries are collected in new_list. Note there may be more or
|
|
||||||
* fewer than in the original list.
|
|
||||||
*/
|
|
||||||
foreach(list_item, querytree_list)
|
|
||||||
{
|
|
||||||
Query *querytree = (Query *) lfirst(list_item);
|
|
||||||
|
|
||||||
if (Debug_print_parse)
|
if (Debug_print_parse)
|
||||||
elog_node_display(DEBUG1, "parse tree", querytree,
|
elog_node_display(DEBUG1, "parse tree", query,
|
||||||
Debug_pretty_print);
|
Debug_pretty_print);
|
||||||
|
|
||||||
if (querytree->commandType == CMD_UTILITY)
|
if (query->commandType == CMD_UTILITY)
|
||||||
{
|
{
|
||||||
/* don't rewrite utilities, just dump 'em into new_list */
|
/* don't rewrite utilities, just dump 'em into result list */
|
||||||
new_list = lappend(new_list, querytree);
|
querytree_list = list_make1(query);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* rewrite regular queries */
|
/* rewrite regular queries */
|
||||||
List *rewritten = QueryRewrite(querytree);
|
querytree_list = QueryRewrite(query);
|
||||||
|
|
||||||
new_list = list_concat(new_list, rewritten);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
querytree_list = new_list;
|
|
||||||
|
|
||||||
if (log_parser_stats)
|
if (log_parser_stats)
|
||||||
ShowUsage("REWRITER STATISTICS");
|
ShowUsage("REWRITER STATISTICS");
|
||||||
|
|
||||||
#ifdef COPY_PARSE_PLAN_TREES
|
#ifdef COPY_PARSE_PLAN_TREES
|
||||||
|
/* Optional debugging check: pass querytree output through copyObject() */
|
||||||
|
{
|
||||||
|
List *new_list;
|
||||||
|
|
||||||
/*
|
|
||||||
* Optional debugging check: pass querytree output through copyObject()
|
|
||||||
*/
|
|
||||||
new_list = (List *) copyObject(querytree_list);
|
new_list = (List *) copyObject(querytree_list);
|
||||||
/* This checks both copyObject() and the equal() routines... */
|
/* This checks both copyObject() and the equal() routines... */
|
||||||
if (!equal(new_list, querytree_list))
|
if (!equal(new_list, querytree_list))
|
||||||
elog(WARNING, "copyObject() failed to produce an equal parse tree");
|
elog(WARNING, "copyObject() failed to produce equal parse tree");
|
||||||
else
|
else
|
||||||
querytree_list = new_list;
|
querytree_list = new_list;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (Debug_print_rewritten)
|
if (Debug_print_rewritten)
|
||||||
@ -1139,6 +1126,7 @@ exec_parse_message(const char *query_string, /* string to execute */
|
|||||||
|
|
||||||
if (parsetree_list != NIL)
|
if (parsetree_list != NIL)
|
||||||
{
|
{
|
||||||
|
Query *query;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
raw_parse_tree = (Node *) linitial(parsetree_list);
|
raw_parse_tree = (Node *) linitial(parsetree_list);
|
||||||
@ -1175,7 +1163,7 @@ exec_parse_message(const char *query_string, /* string to execute */
|
|||||||
if (log_parser_stats)
|
if (log_parser_stats)
|
||||||
ResetUsage();
|
ResetUsage();
|
||||||
|
|
||||||
querytree_list = parse_analyze_varparams(copyObject(raw_parse_tree),
|
query = parse_analyze_varparams(copyObject(raw_parse_tree),
|
||||||
query_string,
|
query_string,
|
||||||
¶mTypes,
|
¶mTypes,
|
||||||
&numParams);
|
&numParams);
|
||||||
@ -1197,7 +1185,7 @@ exec_parse_message(const char *query_string, /* string to execute */
|
|||||||
if (log_parser_stats)
|
if (log_parser_stats)
|
||||||
ShowUsage("PARSE ANALYSIS STATISTICS");
|
ShowUsage("PARSE ANALYSIS STATISTICS");
|
||||||
|
|
||||||
querytree_list = pg_rewrite_queries(querytree_list);
|
querytree_list = pg_rewrite_query(query);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If this is the unnamed statement and it has parameters, defer query
|
* If this is the unnamed statement and it has parameters, defer query
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.280 2007/05/30 20:12:01 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.281 2007/06/23 22:12:52 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -45,7 +45,7 @@
|
|||||||
#include "commands/vacuum.h"
|
#include "commands/vacuum.h"
|
||||||
#include "commands/view.h"
|
#include "commands/view.h"
|
||||||
#include "miscadmin.h"
|
#include "miscadmin.h"
|
||||||
#include "parser/analyze.h"
|
#include "parser/parse_utilcmd.h"
|
||||||
#include "postmaster/bgwriter.h"
|
#include "postmaster/bgwriter.h"
|
||||||
#include "rewrite/rewriteDefine.h"
|
#include "rewrite/rewriteDefine.h"
|
||||||
#include "rewrite/rewriteRemove.h"
|
#include "rewrite/rewriteRemove.h"
|
||||||
@ -544,18 +544,48 @@ ProcessUtility(Node *parsetree,
|
|||||||
|
|
||||||
case T_CreateStmt:
|
case T_CreateStmt:
|
||||||
{
|
{
|
||||||
|
List *stmts;
|
||||||
|
ListCell *l;
|
||||||
Oid relOid;
|
Oid relOid;
|
||||||
|
|
||||||
relOid = DefineRelation((CreateStmt *) parsetree,
|
/* Run parse analysis ... */
|
||||||
|
stmts = transformCreateStmt((CreateStmt *) parsetree,
|
||||||
|
queryString);
|
||||||
|
|
||||||
|
/* ... and do it */
|
||||||
|
foreach(l, stmts)
|
||||||
|
{
|
||||||
|
Node *stmt = (Node *) lfirst(l);
|
||||||
|
|
||||||
|
if (IsA(stmt, CreateStmt))
|
||||||
|
{
|
||||||
|
/* Create the table itself */
|
||||||
|
relOid = DefineRelation((CreateStmt *) stmt,
|
||||||
RELKIND_RELATION);
|
RELKIND_RELATION);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Let AlterTableCreateToastTable decide if this one needs a
|
* Let AlterTableCreateToastTable decide if this one
|
||||||
* secondary relation too.
|
* needs a secondary relation too.
|
||||||
*/
|
*/
|
||||||
CommandCounterIncrement();
|
CommandCounterIncrement();
|
||||||
AlterTableCreateToastTable(relOid);
|
AlterTableCreateToastTable(relOid);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Recurse for anything else */
|
||||||
|
ProcessUtility(stmt,
|
||||||
|
queryString,
|
||||||
|
params,
|
||||||
|
false,
|
||||||
|
None_Receiver,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Need CCI between commands */
|
||||||
|
if (lnext(l) != NULL)
|
||||||
|
CommandCounterIncrement();
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_CreateTableSpaceStmt:
|
case T_CreateTableSpaceStmt:
|
||||||
@ -693,7 +723,40 @@ ProcessUtility(Node *parsetree,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case T_AlterTableStmt:
|
case T_AlterTableStmt:
|
||||||
AlterTable((AlterTableStmt *) parsetree);
|
{
|
||||||
|
List *stmts;
|
||||||
|
ListCell *l;
|
||||||
|
|
||||||
|
/* Run parse analysis ... */
|
||||||
|
stmts = transformAlterTableStmt((AlterTableStmt *) parsetree,
|
||||||
|
queryString);
|
||||||
|
|
||||||
|
/* ... and do it */
|
||||||
|
foreach(l, stmts)
|
||||||
|
{
|
||||||
|
Node *stmt = (Node *) lfirst(l);
|
||||||
|
|
||||||
|
if (IsA(stmt, AlterTableStmt))
|
||||||
|
{
|
||||||
|
/* Do the table alteration proper */
|
||||||
|
AlterTable((AlterTableStmt *) stmt);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Recurse for anything else */
|
||||||
|
ProcessUtility(stmt,
|
||||||
|
queryString,
|
||||||
|
params,
|
||||||
|
false,
|
||||||
|
None_Receiver,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Need CCI between commands */
|
||||||
|
if (lnext(l) != NULL)
|
||||||
|
CommandCounterIncrement();
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_AlterDomainStmt:
|
case T_AlterDomainStmt:
|
||||||
@ -812,7 +875,7 @@ ProcessUtility(Node *parsetree,
|
|||||||
CheckRelationOwnership(stmt->relation, true);
|
CheckRelationOwnership(stmt->relation, true);
|
||||||
|
|
||||||
/* Run parse analysis ... */
|
/* Run parse analysis ... */
|
||||||
stmt = analyzeIndexStmt(stmt, queryString);
|
stmt = transformIndexStmt(stmt, queryString);
|
||||||
|
|
||||||
/* ... and do it */
|
/* ... and do it */
|
||||||
DefineIndex(stmt->relation, /* relation */
|
DefineIndex(stmt->relation, /* relation */
|
||||||
@ -1605,7 +1668,7 @@ CreateCommandTag(Node *parsetree)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* We might be supporting ALTER INDEX here, so set the
|
* We might be supporting ALTER INDEX here, so set the
|
||||||
* completion table appropriately. Catch all other
|
* completion tag appropriately. Catch all other
|
||||||
* possibilities with ALTER TABLE
|
* possibilities with ALTER TABLE
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/nodes/makefuncs.h,v 1.58 2007/03/17 00:11:05 tgl Exp $
|
* $PostgreSQL: pgsql/src/include/nodes/makefuncs.h,v 1.59 2007/06/23 22:12:52 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -36,6 +36,8 @@ extern TargetEntry *makeTargetEntry(Expr *expr,
|
|||||||
|
|
||||||
extern TargetEntry *flatCopyTargetEntry(TargetEntry *src_tle);
|
extern TargetEntry *flatCopyTargetEntry(TargetEntry *src_tle);
|
||||||
|
|
||||||
|
extern FromExpr *makeFromExpr(List *fromlist, Node *quals);
|
||||||
|
|
||||||
extern Const *makeConst(Oid consttype,
|
extern Const *makeConst(Oid consttype,
|
||||||
int32 consttypmod,
|
int32 consttypmod,
|
||||||
int constlen,
|
int constlen,
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.348 2007/04/27 22:05:49 tgl Exp $
|
* $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.349 2007/06/23 22:12:52 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -21,7 +21,7 @@
|
|||||||
typedef enum QuerySource
|
typedef enum QuerySource
|
||||||
{
|
{
|
||||||
QSRC_ORIGINAL, /* original parsetree (explicit query) */
|
QSRC_ORIGINAL, /* original parsetree (explicit query) */
|
||||||
QSRC_PARSER, /* added by parse analysis */
|
QSRC_PARSER, /* added by parse analysis (now unused) */
|
||||||
QSRC_INSTEAD_RULE, /* added by unconditional INSTEAD rule */
|
QSRC_INSTEAD_RULE, /* added by unconditional INSTEAD rule */
|
||||||
QSRC_QUAL_INSTEAD_RULE, /* added by conditional INSTEAD rule */
|
QSRC_QUAL_INSTEAD_RULE, /* added by conditional INSTEAD rule */
|
||||||
QSRC_NON_INSTEAD_RULE /* added by non-INSTEAD rule */
|
QSRC_NON_INSTEAD_RULE /* added by non-INSTEAD rule */
|
||||||
@ -799,10 +799,12 @@ typedef struct SetOperationStmt
|
|||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* Other Statements (no optimizations required)
|
* Other Statements (no optimizations required)
|
||||||
*
|
*
|
||||||
* Some of them require a little bit of transformation (which is also
|
* These are not touched by parser/analyze.c except to put them into
|
||||||
* done by transformStmt). The whole structure is then passed on to
|
* the utilityStmt field of a Query. This is eventually passed to
|
||||||
* ProcessUtility (by-passing the optimization step) as the utilityStmt
|
* ProcessUtility (by-passing rewriting and planning). Some of the
|
||||||
* field in Query.
|
* statements do need attention from parse analysis, and this is
|
||||||
|
* done by routines in parser/parse_utilcmd.c after ProcessUtility
|
||||||
|
* receives the command for execution.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -886,7 +888,7 @@ typedef enum AlterTableType
|
|||||||
AT_ReAddIndex, /* internal to commands/tablecmds.c */
|
AT_ReAddIndex, /* internal to commands/tablecmds.c */
|
||||||
AT_AddConstraint, /* add constraint */
|
AT_AddConstraint, /* add constraint */
|
||||||
AT_ProcessedConstraint, /* pre-processed add constraint (local in
|
AT_ProcessedConstraint, /* pre-processed add constraint (local in
|
||||||
* parser/analyze.c) */
|
* parser/parse_utilcmd.c) */
|
||||||
AT_DropConstraint, /* drop constraint */
|
AT_DropConstraint, /* drop constraint */
|
||||||
AT_DropConstraintQuietly, /* drop constraint, no error/warning (local in
|
AT_DropConstraintQuietly, /* drop constraint, no error/warning (local in
|
||||||
* commands/tablecmds.c) */
|
* commands/tablecmds.c) */
|
||||||
@ -1083,7 +1085,7 @@ typedef struct CreateStmt
|
|||||||
* relation). We should never have both in the same node!
|
* relation). We should never have both in the same node!
|
||||||
*
|
*
|
||||||
* Constraint attributes (DEFERRABLE etc) are initially represented as
|
* Constraint attributes (DEFERRABLE etc) are initially represented as
|
||||||
* separate Constraint nodes for simplicity of parsing. analyze.c makes
|
* separate Constraint nodes for simplicity of parsing. parse_utilcmd.c makes
|
||||||
* a pass through the constraints list to attach the info to the appropriate
|
* a pass through the constraints list to attach the info to the appropriate
|
||||||
* FkConstraint node (and, perhaps, someday to other kinds of constraints).
|
* FkConstraint node (and, perhaps, someday to other kinds of constraints).
|
||||||
* ----------
|
* ----------
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
/*-------------------------------------------------------------------------
|
/*-------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* analyze.h
|
* analyze.h
|
||||||
|
* parse analysis for optimizable statements
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/parser/analyze.h,v 1.36 2007/03/13 00:33:43 tgl Exp $
|
* $PostgreSQL: pgsql/src/include/parser/analyze.h,v 1.37 2007/06/23 22:12:52 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -16,16 +17,14 @@
|
|||||||
#include "parser/parse_node.h"
|
#include "parser/parse_node.h"
|
||||||
|
|
||||||
|
|
||||||
extern List *parse_analyze(Node *parseTree, const char *sourceText,
|
extern Query *parse_analyze(Node *parseTree, const char *sourceText,
|
||||||
Oid *paramTypes, int numParams);
|
Oid *paramTypes, int numParams);
|
||||||
extern List *parse_analyze_varparams(Node *parseTree, const char *sourceText,
|
extern Query *parse_analyze_varparams(Node *parseTree, const char *sourceText,
|
||||||
Oid **paramTypes, int *numParams);
|
Oid **paramTypes, int *numParams);
|
||||||
extern List *parse_sub_analyze(Node *parseTree, ParseState *parentParseState);
|
|
||||||
|
|
||||||
extern IndexStmt *analyzeIndexStmt(IndexStmt *stmt, const char *queryString);
|
extern Query *parse_sub_analyze(Node *parseTree, ParseState *parentParseState);
|
||||||
extern void analyzeRuleStmt(RuleStmt *stmt, const char *queryString,
|
extern Query *transformStmt(ParseState *pstate, Node *parseTree);
|
||||||
List **actions, Node **whereClause);
|
|
||||||
extern List *analyzeCreateSchemaStmt(CreateSchemaStmt *stmt);
|
|
||||||
extern void CheckSelectLocking(Query *qry);
|
extern void CheckSelectLocking(Query *qry);
|
||||||
extern void applyLockingClause(Query *qry, Index rtindex,
|
extern void applyLockingClause(Query *qry, Index rtindex,
|
||||||
bool forUpdate, bool noWait);
|
bool forUpdate, bool noWait);
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/parser/parse_node.h,v 1.51 2007/01/05 22:19:57 momjian Exp $
|
* $PostgreSQL: pgsql/src/include/parser/parse_node.h,v 1.52 2007/06/23 22:12:52 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -83,6 +83,7 @@ typedef struct ParseState
|
|||||||
} ParseState;
|
} ParseState;
|
||||||
|
|
||||||
extern ParseState *make_parsestate(ParseState *parentParseState);
|
extern ParseState *make_parsestate(ParseState *parentParseState);
|
||||||
|
extern void free_parsestate(ParseState *pstate);
|
||||||
extern int parser_errposition(ParseState *pstate, int location);
|
extern int parser_errposition(ParseState *pstate, int location);
|
||||||
|
|
||||||
extern Var *make_var(ParseState *pstate, RangeTblEntry *rte, int attrno);
|
extern Var *make_var(ParseState *pstate, RangeTblEntry *rte, int attrno);
|
||||||
|
28
src/include/parser/parse_utilcmd.h
Normal file
28
src/include/parser/parse_utilcmd.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* parse_utilcmd.h
|
||||||
|
* parse analysis for utility commands
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
|
||||||
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
|
*
|
||||||
|
* $PostgreSQL: pgsql/src/include/parser/parse_utilcmd.h,v 1.1 2007/06/23 22:12:52 tgl Exp $
|
||||||
|
*
|
||||||
|
*-------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
#ifndef PARSE_UTILCMD_H
|
||||||
|
#define PARSE_UTILCMD_H
|
||||||
|
|
||||||
|
#include "parser/parse_node.h"
|
||||||
|
|
||||||
|
|
||||||
|
extern List *transformCreateStmt(CreateStmt *stmt, const char *queryString);
|
||||||
|
extern List *transformAlterTableStmt(AlterTableStmt *stmt,
|
||||||
|
const char *queryString);
|
||||||
|
extern IndexStmt *transformIndexStmt(IndexStmt *stmt, const char *queryString);
|
||||||
|
extern void transformRuleStmt(RuleStmt *stmt, const char *queryString,
|
||||||
|
List **actions, Node **whereClause);
|
||||||
|
extern List *transformCreateSchemaStmt(CreateSchemaStmt *stmt);
|
||||||
|
|
||||||
|
#endif /* PARSE_UTILCMD_H */
|
Loading…
x
Reference in New Issue
Block a user