mirror of
https://github.com/postgres/postgres.git
synced 2025-06-14 18:42:34 +03:00
Rip out QueryTreeList structure, root and branch. Querytree
lists are now plain old garden-variety Lists, allocated with palloc, rather than specialized expansible-array data allocated with malloc. This substantially simplifies their handling and eliminates several sources of memory leakage. Several basic types of erroneous queries (syntax error, attempt to insert a duplicate key into a unique index) now demonstrably leak zero bytes per query.
This commit is contained in:
@ -3758,7 +3758,7 @@ $\ldots$/src/backend/tcop/postgres.c}.
|
|||||||
List *
|
List *
|
||||||
pg_parse_and_plan(char *query_string, Oid *typev,
|
pg_parse_and_plan(char *query_string, Oid *typev,
|
||||||
int nargs,
|
int nargs,
|
||||||
QueryTreeList **queryListP,
|
List **queryListP,
|
||||||
CommandDest dest)
|
CommandDest dest)
|
||||||
{
|
{
|
||||||
.
|
.
|
||||||
@ -4032,7 +4032,7 @@ instead.
|
|||||||
|
|
||||||
if(IsA(tree, SelectStmt))
|
if(IsA(tree, SelectStmt))
|
||||||
{
|
{
|
||||||
QueryTreeList *qtree;
|
List *qtrees;
|
||||||
|
|
||||||
/* If we get to the tree given in first_select
|
/* If we get to the tree given in first_select
|
||||||
* return parsetree instead of performing
|
* return parsetree instead of performing
|
||||||
@ -4044,9 +4044,8 @@ instead.
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* transform the unprocessed Query nodes */
|
/* transform the unprocessed Query nodes */
|
||||||
qtree =
|
qtrees = parse_analyze(lcons(tree, NIL), NULL);
|
||||||
parse_analyze(lcons(tree, NIL), NULL);
|
result = (Node *) lfirst(qtrees);
|
||||||
result = (Node *)qtree->qtrees[0];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(IsA(tree,Expr))
|
if(IsA(tree,Expr))
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.79 1999/05/10 04:02:03 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.80 1999/05/13 07:28:26 tgl Exp $
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* INTERFACE ROUTINES
|
* INTERFACE ROUTINES
|
||||||
@ -1498,9 +1498,9 @@ StoreAttrDefault(Relation rel, AttrDefault *attrdef)
|
|||||||
char str[MAX_PARSE_BUFFER];
|
char str[MAX_PARSE_BUFFER];
|
||||||
char cast[2 * NAMEDATALEN] = {0};
|
char cast[2 * NAMEDATALEN] = {0};
|
||||||
Form_pg_attribute atp = rel->rd_att->attrs[attrdef->adnum - 1];
|
Form_pg_attribute atp = rel->rd_att->attrs[attrdef->adnum - 1];
|
||||||
QueryTreeList *queryTree_list;
|
List *queryTree_list;
|
||||||
Query *query;
|
|
||||||
List *planTree_list;
|
List *planTree_list;
|
||||||
|
Query *query;
|
||||||
TargetEntry *te;
|
TargetEntry *te;
|
||||||
Resdom *resdom;
|
Resdom *resdom;
|
||||||
Node *expr;
|
Node *expr;
|
||||||
@ -1522,9 +1522,10 @@ start:;
|
|||||||
"select %s%s from \"%.*s\"", attrdef->adsrc, cast,
|
"select %s%s from \"%.*s\"", attrdef->adsrc, cast,
|
||||||
NAMEDATALEN, rel->rd_rel->relname.data);
|
NAMEDATALEN, rel->rd_rel->relname.data);
|
||||||
setheapoverride(true);
|
setheapoverride(true);
|
||||||
planTree_list = (List *) pg_parse_and_plan(str, NULL, 0, &queryTree_list, None, FALSE);
|
planTree_list = pg_parse_and_plan(str, NULL, 0,
|
||||||
|
&queryTree_list, None, FALSE);
|
||||||
setheapoverride(false);
|
setheapoverride(false);
|
||||||
query = (Query *) (queryTree_list->qtrees[0]);
|
query = (Query *) lfirst(queryTree_list);
|
||||||
|
|
||||||
if (length(query->rtable) > 1 ||
|
if (length(query->rtable) > 1 ||
|
||||||
flatten_tlist(query->targetList) != NIL)
|
flatten_tlist(query->targetList) != NIL)
|
||||||
@ -1582,9 +1583,9 @@ static void
|
|||||||
StoreRelCheck(Relation rel, ConstrCheck *check)
|
StoreRelCheck(Relation rel, ConstrCheck *check)
|
||||||
{
|
{
|
||||||
char str[MAX_PARSE_BUFFER];
|
char str[MAX_PARSE_BUFFER];
|
||||||
QueryTreeList *queryTree_list;
|
List *queryTree_list;
|
||||||
Query *query;
|
|
||||||
List *planTree_list;
|
List *planTree_list;
|
||||||
|
Query *query;
|
||||||
Plan *plan;
|
Plan *plan;
|
||||||
List *qual;
|
List *qual;
|
||||||
char *ccbin;
|
char *ccbin;
|
||||||
@ -1603,9 +1604,10 @@ StoreRelCheck(Relation rel, ConstrCheck *check)
|
|||||||
"select 1 from \"%.*s\" where %s",
|
"select 1 from \"%.*s\" where %s",
|
||||||
NAMEDATALEN, rel->rd_rel->relname.data, check->ccsrc);
|
NAMEDATALEN, rel->rd_rel->relname.data, check->ccsrc);
|
||||||
setheapoverride(true);
|
setheapoverride(true);
|
||||||
planTree_list = (List *) pg_parse_and_plan(str, NULL, 0, &queryTree_list, None, FALSE);
|
planTree_list = pg_parse_and_plan(str, NULL, 0,
|
||||||
|
&queryTree_list, None, FALSE);
|
||||||
setheapoverride(false);
|
setheapoverride(false);
|
||||||
query = (Query *) (queryTree_list->qtrees[0]);
|
query = (Query *) lfirst(queryTree_list);
|
||||||
|
|
||||||
if (length(query->rtable) > 1)
|
if (length(query->rtable) > 1)
|
||||||
elog(ERROR, "Only relation '%.*s' can be referenced",
|
elog(ERROR, "Only relation '%.*s' can be referenced",
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.27 1999/04/18 02:57:22 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.28 1999/05/13 07:28:27 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -67,7 +67,7 @@ ProcedureCreate(char *procedureName,
|
|||||||
Oid languageObjectId;
|
Oid languageObjectId;
|
||||||
Oid typeObjectId;
|
Oid typeObjectId;
|
||||||
List *x;
|
List *x;
|
||||||
QueryTreeList *querytree_list;
|
List *querytree_list;
|
||||||
List *plan_list;
|
List *plan_list;
|
||||||
Oid typev[8];
|
Oid typev[8];
|
||||||
Oid relid;
|
Oid relid;
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.24 1999/02/13 23:15:20 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.25 1999/05/13 07:28:29 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -97,26 +97,23 @@ init_execution_state(FunctionCachePtr fcache,
|
|||||||
execution_state *newes;
|
execution_state *newes;
|
||||||
execution_state *nextes;
|
execution_state *nextes;
|
||||||
execution_state *preves;
|
execution_state *preves;
|
||||||
QueryTreeList *queryTree_list;
|
List *queryTree_list,
|
||||||
int i;
|
*planTree_list,
|
||||||
List *planTree_list;
|
*qtl_item;
|
||||||
int nargs;
|
int nargs = fcache->nargs;
|
||||||
|
|
||||||
nargs = fcache->nargs;
|
|
||||||
|
|
||||||
newes = (execution_state *) palloc(sizeof(execution_state));
|
newes = (execution_state *) palloc(sizeof(execution_state));
|
||||||
nextes = newes;
|
nextes = newes;
|
||||||
preves = (execution_state *) NULL;
|
preves = (execution_state *) NULL;
|
||||||
|
|
||||||
|
planTree_list = pg_parse_and_plan(fcache->src, fcache->argOidVect,
|
||||||
|
nargs, &queryTree_list, None, FALSE);
|
||||||
|
|
||||||
planTree_list = (List *)
|
foreach (qtl_item, queryTree_list)
|
||||||
pg_parse_and_plan(fcache->src, fcache->argOidVect, nargs, &queryTree_list, None, FALSE);
|
|
||||||
|
|
||||||
for (i = 0; i < queryTree_list->len; i++)
|
|
||||||
{
|
{
|
||||||
EState *estate;
|
Query *queryTree = lfirst(qtl_item);
|
||||||
Query *queryTree = (Query *) (queryTree_list->qtrees[i]);
|
|
||||||
Plan *planTree = lfirst(planTree_list);
|
Plan *planTree = lfirst(planTree_list);
|
||||||
|
EState *estate;
|
||||||
|
|
||||||
if (!nextes)
|
if (!nextes)
|
||||||
nextes = (execution_state *) palloc(sizeof(execution_state));
|
nextes = (execution_state *) palloc(sizeof(execution_state));
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
* spi.c
|
* spi.c
|
||||||
* Server Programming Interface
|
* Server Programming Interface
|
||||||
*
|
*
|
||||||
* $Id: spi.c,v 1.36 1999/03/30 01:37:23 momjian Exp $
|
* $Id: spi.c,v 1.37 1999/05/13 07:28:30 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -602,18 +602,18 @@ spi_printtup(HeapTuple tuple, TupleDesc tupdesc, DestReceiver* self)
|
|||||||
static int
|
static int
|
||||||
_SPI_execute(char *src, int tcount, _SPI_plan *plan)
|
_SPI_execute(char *src, int tcount, _SPI_plan *plan)
|
||||||
{
|
{
|
||||||
QueryTreeList *queryTree_list;
|
List *queryTree_list;
|
||||||
List *planTree_list;
|
List *planTree_list;
|
||||||
|
List *queryTree_list_item;
|
||||||
List *ptlist;
|
List *ptlist;
|
||||||
QueryDesc *qdesc;
|
QueryDesc *qdesc;
|
||||||
Query *queryTree;
|
Query *queryTree;
|
||||||
Plan *planTree;
|
Plan *planTree;
|
||||||
EState *state;
|
EState *state;
|
||||||
int qlen;
|
|
||||||
int nargs = 0;
|
int nargs = 0;
|
||||||
Oid *argtypes = NULL;
|
Oid *argtypes = NULL;
|
||||||
int res;
|
int res = 0;
|
||||||
int i;
|
bool islastquery;
|
||||||
|
|
||||||
/* Increment CommandCounter to see changes made by now */
|
/* Increment CommandCounter to see changes made by now */
|
||||||
CommandCounterIncrement();
|
CommandCounterIncrement();
|
||||||
@ -628,18 +628,17 @@ _SPI_execute(char *src, int tcount, _SPI_plan *plan)
|
|||||||
nargs = plan->nargs;
|
nargs = plan->nargs;
|
||||||
argtypes = plan->argtypes;
|
argtypes = plan->argtypes;
|
||||||
}
|
}
|
||||||
ptlist = planTree_list = (List *)
|
ptlist = planTree_list =
|
||||||
pg_parse_and_plan(src, argtypes, nargs, &queryTree_list, None, FALSE);
|
pg_parse_and_plan(src, argtypes, nargs, &queryTree_list, None, FALSE);
|
||||||
|
|
||||||
_SPI_current->qtlist = queryTree_list;
|
_SPI_current->qtlist = queryTree_list;
|
||||||
|
|
||||||
qlen = queryTree_list->len;
|
foreach (queryTree_list_item, queryTree_list)
|
||||||
for (i = 0;; i++)
|
|
||||||
{
|
{
|
||||||
queryTree = (Query *) (queryTree_list->qtrees[i]);
|
queryTree = (Query *) lfirst(queryTree_list_item);
|
||||||
planTree = lfirst(planTree_list);
|
planTree = lfirst(planTree_list);
|
||||||
|
|
||||||
planTree_list = lnext(planTree_list);
|
planTree_list = lnext(planTree_list);
|
||||||
|
islastquery = (planTree_list == NIL); /* assume lists are same len */
|
||||||
|
|
||||||
if (queryTree->commandType == CMD_UTILITY)
|
if (queryTree->commandType == CMD_UTILITY)
|
||||||
{
|
{
|
||||||
@ -659,32 +658,32 @@ _SPI_execute(char *src, int tcount, _SPI_plan *plan)
|
|||||||
if (plan == NULL)
|
if (plan == NULL)
|
||||||
{
|
{
|
||||||
ProcessUtility(queryTree->utilityStmt, None);
|
ProcessUtility(queryTree->utilityStmt, None);
|
||||||
if (i < qlen - 1)
|
if (! islastquery)
|
||||||
CommandCounterIncrement();
|
CommandCounterIncrement();
|
||||||
else
|
else
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
else if (i >= qlen - 1)
|
else if (islastquery)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (plan == NULL)
|
else if (plan == NULL)
|
||||||
{
|
{
|
||||||
qdesc = CreateQueryDesc(queryTree, planTree,
|
qdesc = CreateQueryDesc(queryTree, planTree,
|
||||||
(i < qlen - 1) ? None : SPI);
|
islastquery ? SPI : None);
|
||||||
state = CreateExecutorState();
|
state = CreateExecutorState();
|
||||||
res = _SPI_pquery(qdesc, state, (i < qlen - 1) ? 0 : tcount);
|
res = _SPI_pquery(qdesc, state, islastquery ? tcount : 0);
|
||||||
if (res < 0 || i >= qlen - 1)
|
if (res < 0 || islastquery)
|
||||||
return res;
|
return res;
|
||||||
CommandCounterIncrement();
|
CommandCounterIncrement();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
qdesc = CreateQueryDesc(queryTree, planTree,
|
qdesc = CreateQueryDesc(queryTree, planTree,
|
||||||
(i < qlen - 1) ? None : SPI);
|
islastquery ? SPI : None);
|
||||||
res = _SPI_pquery(qdesc, NULL, (i < qlen - 1) ? 0 : tcount);
|
res = _SPI_pquery(qdesc, NULL, islastquery ? tcount : 0);
|
||||||
if (res < 0)
|
if (res < 0)
|
||||||
return res;
|
return res;
|
||||||
if (i >= qlen - 1)
|
if (islastquery)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -693,23 +692,22 @@ _SPI_execute(char *src, int tcount, _SPI_plan *plan)
|
|||||||
plan->ptlist = ptlist;
|
plan->ptlist = ptlist;
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
_SPI_execute_plan(_SPI_plan *plan, Datum *Values, char *Nulls, int tcount)
|
_SPI_execute_plan(_SPI_plan *plan, Datum *Values, char *Nulls, int tcount)
|
||||||
{
|
{
|
||||||
QueryTreeList *queryTree_list = plan->qtlist;
|
List *queryTree_list = plan->qtlist;
|
||||||
List *planTree_list = plan->ptlist;
|
List *planTree_list = plan->ptlist;
|
||||||
|
List *queryTree_list_item;
|
||||||
QueryDesc *qdesc;
|
QueryDesc *qdesc;
|
||||||
Query *queryTree;
|
Query *queryTree;
|
||||||
Plan *planTree;
|
Plan *planTree;
|
||||||
EState *state;
|
EState *state;
|
||||||
int nargs = plan->nargs;
|
int nargs = plan->nargs;
|
||||||
int qlen = queryTree_list->len;
|
int res = 0;
|
||||||
int res;
|
bool islastquery;
|
||||||
int i,
|
int k;
|
||||||
k;
|
|
||||||
|
|
||||||
/* Increment CommandCounter to see changes made by now */
|
/* Increment CommandCounter to see changes made by now */
|
||||||
CommandCounterIncrement();
|
CommandCounterIncrement();
|
||||||
@ -719,17 +717,17 @@ _SPI_execute_plan(_SPI_plan *plan, Datum *Values, char *Nulls, int tcount)
|
|||||||
_SPI_current->tuptable = NULL;
|
_SPI_current->tuptable = NULL;
|
||||||
_SPI_current->qtlist = NULL;
|
_SPI_current->qtlist = NULL;
|
||||||
|
|
||||||
for (i = 0;; i++)
|
foreach (queryTree_list_item, queryTree_list)
|
||||||
{
|
{
|
||||||
queryTree = (Query *) (queryTree_list->qtrees[i]);
|
queryTree = (Query *) lfirst(queryTree_list_item);
|
||||||
planTree = lfirst(planTree_list);
|
planTree = lfirst(planTree_list);
|
||||||
|
|
||||||
planTree_list = lnext(planTree_list);
|
planTree_list = lnext(planTree_list);
|
||||||
|
islastquery = (planTree_list == NIL); /* assume lists are same len */
|
||||||
|
|
||||||
if (queryTree->commandType == CMD_UTILITY)
|
if (queryTree->commandType == CMD_UTILITY)
|
||||||
{
|
{
|
||||||
ProcessUtility(queryTree->utilityStmt, None);
|
ProcessUtility(queryTree->utilityStmt, None);
|
||||||
if (i < qlen - 1)
|
if (! islastquery)
|
||||||
CommandCounterIncrement();
|
CommandCounterIncrement();
|
||||||
else
|
else
|
||||||
return SPI_OK_UTILITY;
|
return SPI_OK_UTILITY;
|
||||||
@ -737,7 +735,7 @@ _SPI_execute_plan(_SPI_plan *plan, Datum *Values, char *Nulls, int tcount)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
qdesc = CreateQueryDesc(queryTree, planTree,
|
qdesc = CreateQueryDesc(queryTree, planTree,
|
||||||
(i < qlen - 1) ? None : SPI);
|
islastquery ? SPI : None);
|
||||||
state = CreateExecutorState();
|
state = CreateExecutorState();
|
||||||
if (nargs > 0)
|
if (nargs > 0)
|
||||||
{
|
{
|
||||||
@ -756,15 +754,14 @@ _SPI_execute_plan(_SPI_plan *plan, Datum *Values, char *Nulls, int tcount)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
state->es_param_list_info = NULL;
|
state->es_param_list_info = NULL;
|
||||||
res = _SPI_pquery(qdesc, state, (i < qlen - 1) ? 0 : tcount);
|
res = _SPI_pquery(qdesc, state, islastquery ? tcount : 0);
|
||||||
if (res < 0 || i >= qlen - 1)
|
if (res < 0 || islastquery)
|
||||||
return res;
|
return res;
|
||||||
CommandCounterIncrement();
|
CommandCounterIncrement();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -955,12 +952,7 @@ _SPI_end_call(bool procmem)
|
|||||||
*/
|
*/
|
||||||
_SPI_curid--;
|
_SPI_curid--;
|
||||||
|
|
||||||
if (_SPI_current->qtlist) /* free _SPI_plan allocations */
|
|
||||||
{
|
|
||||||
free(_SPI_current->qtlist->qtrees);
|
|
||||||
free(_SPI_current->qtlist);
|
|
||||||
_SPI_current->qtlist = NULL;
|
_SPI_current->qtlist = NULL;
|
||||||
}
|
|
||||||
|
|
||||||
if (procmem) /* switch to the procedure memory context */
|
if (procmem) /* switch to the procedure memory context */
|
||||||
{ /* but free Executor memory before */
|
{ /* but free Executor memory before */
|
||||||
@ -1000,7 +992,6 @@ _SPI_copy_plan(_SPI_plan *plan, int location)
|
|||||||
{
|
{
|
||||||
_SPI_plan *newplan;
|
_SPI_plan *newplan;
|
||||||
MemoryContext oldcxt = NULL;
|
MemoryContext oldcxt = NULL;
|
||||||
int i;
|
|
||||||
|
|
||||||
if (location == _SPI_CPLAN_PROCXT)
|
if (location == _SPI_CPLAN_PROCXT)
|
||||||
oldcxt = MemoryContextSwitchTo((MemoryContext)
|
oldcxt = MemoryContextSwitchTo((MemoryContext)
|
||||||
@ -1009,14 +1000,7 @@ _SPI_copy_plan(_SPI_plan *plan, int location)
|
|||||||
oldcxt = MemoryContextSwitchTo(TopMemoryContext);
|
oldcxt = MemoryContextSwitchTo(TopMemoryContext);
|
||||||
|
|
||||||
newplan = (_SPI_plan *) palloc(sizeof(_SPI_plan));
|
newplan = (_SPI_plan *) palloc(sizeof(_SPI_plan));
|
||||||
newplan->qtlist = (QueryTreeList *) palloc(sizeof(QueryTreeList));
|
newplan->qtlist = (List *) copyObject(plan->qtlist);
|
||||||
newplan->qtlist->len = plan->qtlist->len;
|
|
||||||
newplan->qtlist->qtrees = (Query **) palloc(plan->qtlist->len *
|
|
||||||
sizeof(Query *));
|
|
||||||
for (i = 0; i < plan->qtlist->len; i++)
|
|
||||||
newplan->qtlist->qtrees[i] = (Query *)
|
|
||||||
copyObject(plan->qtlist->qtrees[i]);
|
|
||||||
|
|
||||||
newplan->ptlist = (List *) copyObject(plan->ptlist);
|
newplan->ptlist = (List *) copyObject(plan->ptlist);
|
||||||
newplan->nargs = plan->nargs;
|
newplan->nargs = plan->nargs;
|
||||||
if (plan->nargs > 0)
|
if (plan->nargs > 0)
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.51 1999/05/12 15:01:37 wieck Exp $
|
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.52 1999/05/13 07:28:32 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -671,7 +671,7 @@ make_sortplan(List *tlist, List *sortcls, Plan *plannode)
|
|||||||
* XXX Why is this function in this module?
|
* XXX Why is this function in this module?
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
pg_checkretval(Oid rettype, QueryTreeList *queryTreeList)
|
pg_checkretval(Oid rettype, List *queryTreeList)
|
||||||
{
|
{
|
||||||
Query *parse;
|
Query *parse;
|
||||||
List *tlist;
|
List *tlist;
|
||||||
@ -686,7 +686,7 @@ pg_checkretval(Oid rettype, QueryTreeList *queryTreeList)
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* find the final query */
|
/* find the final query */
|
||||||
parse = queryTreeList->qtrees[queryTreeList->len - 1];
|
parse = (Query *) nth(length(queryTreeList)-1, queryTreeList);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* test 1: if the last query is a utility invocation, then there had
|
* test 1: if the last query is a utility invocation, then there had
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 1994, Regents of the University of California
|
* Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: analyze.c,v 1.102 1999/05/12 07:17:18 thomas Exp $
|
* $Id: analyze.c,v 1.103 1999/05/13 07:28:34 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -59,17 +59,12 @@ List *extras_after = NIL;
|
|||||||
* all transformed to Query while the rest stays the same.
|
* all transformed to Query while the rest stays the same.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
QueryTreeList *
|
List *
|
||||||
parse_analyze(List *pl, ParseState *parentParseState)
|
parse_analyze(List *pl, ParseState *parentParseState)
|
||||||
{
|
{
|
||||||
QueryTreeList *result;
|
List *result = NIL;
|
||||||
ParseState *pstate;
|
ParseState *pstate;
|
||||||
Query *parsetree;
|
Query *parsetree;
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
result = malloc(sizeof(QueryTreeList));
|
|
||||||
result->len = length(pl);
|
|
||||||
result->qtrees = (Query **) malloc(result->len * sizeof(Query *));
|
|
||||||
|
|
||||||
while (pl != NIL)
|
while (pl != NIL)
|
||||||
{
|
{
|
||||||
@ -78,35 +73,25 @@ parse_analyze(List *pl, ParseState *parentParseState)
|
|||||||
if (pstate->p_target_relation != NULL)
|
if (pstate->p_target_relation != NULL)
|
||||||
heap_close(pstate->p_target_relation);
|
heap_close(pstate->p_target_relation);
|
||||||
|
|
||||||
if (extras_before != NIL)
|
|
||||||
{
|
|
||||||
result->len += length(extras_before);
|
|
||||||
result->qtrees = (Query **) realloc(result->qtrees, result->len * sizeof(Query *));
|
|
||||||
while (extras_before != NIL)
|
while (extras_before != NIL)
|
||||||
{
|
{
|
||||||
result->qtrees[i++] = transformStmt(pstate, lfirst(extras_before));
|
result = lappend(result,
|
||||||
|
transformStmt(pstate, lfirst(extras_before)));
|
||||||
if (pstate->p_target_relation != NULL)
|
if (pstate->p_target_relation != NULL)
|
||||||
heap_close(pstate->p_target_relation);
|
heap_close(pstate->p_target_relation);
|
||||||
extras_before = lnext(extras_before);
|
extras_before = lnext(extras_before);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
extras_before = NIL;
|
|
||||||
|
|
||||||
result->qtrees[i++] = parsetree;
|
result = lappend(result, parsetree);
|
||||||
|
|
||||||
if (extras_after != NIL)
|
|
||||||
{
|
|
||||||
result->len += length(extras_after);
|
|
||||||
result->qtrees = (Query **) realloc(result->qtrees, result->len * sizeof(Query *));
|
|
||||||
while (extras_after != NIL)
|
while (extras_after != NIL)
|
||||||
{
|
{
|
||||||
result->qtrees[i++] = transformStmt(pstate, lfirst(extras_after));
|
result = lappend(result,
|
||||||
|
transformStmt(pstate, lfirst(extras_after)));
|
||||||
if (pstate->p_target_relation != NULL)
|
if (pstate->p_target_relation != NULL)
|
||||||
heap_close(pstate->p_target_relation);
|
heap_close(pstate->p_target_relation);
|
||||||
extras_after = lnext(extras_after);
|
extras_after = lnext(extras_after);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
extras_after = NIL;
|
|
||||||
|
|
||||||
pl = lnext(pl);
|
pl = lnext(pl);
|
||||||
pfree(pstate);
|
pfree(pstate);
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.30 1999/05/12 15:01:50 wieck Exp $
|
* $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.31 1999/05/13 07:28:36 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -752,23 +752,24 @@ List *
|
|||||||
transformUnionClause(List *unionClause, List *targetlist)
|
transformUnionClause(List *unionClause, List *targetlist)
|
||||||
{
|
{
|
||||||
List *union_list = NIL;
|
List *union_list = NIL;
|
||||||
QueryTreeList *qlist;
|
List *qlist,
|
||||||
int i;
|
*qlist_item;
|
||||||
|
|
||||||
if (unionClause)
|
if (unionClause)
|
||||||
{
|
{
|
||||||
/* recursion */
|
/* recursion */
|
||||||
qlist = parse_analyze(unionClause, NULL);
|
qlist = parse_analyze(unionClause, NULL);
|
||||||
|
|
||||||
for (i = 0; i < qlist->len; i++)
|
foreach (qlist_item, qlist)
|
||||||
{
|
{
|
||||||
|
Query *query = (Query *) lfirst(qlist_item);
|
||||||
List *prev_target = targetlist;
|
List *prev_target = targetlist;
|
||||||
List *next_target;
|
List *next_target;
|
||||||
|
|
||||||
if (length(targetlist) != length(qlist->qtrees[i]->targetList))
|
if (length(targetlist) != length(query->targetList))
|
||||||
elog(ERROR, "Each UNION clause must have the same number of columns");
|
elog(ERROR, "Each UNION clause must have the same number of columns");
|
||||||
|
|
||||||
foreach(next_target, qlist->qtrees[i]->targetList)
|
foreach(next_target, query->targetList)
|
||||||
{
|
{
|
||||||
Oid itype;
|
Oid itype;
|
||||||
Oid otype;
|
Oid otype;
|
||||||
@ -819,7 +820,7 @@ transformUnionClause(List *unionClause, List *targetlist)
|
|||||||
}
|
}
|
||||||
prev_target = lnext(prev_target);
|
prev_target = lnext(prev_target);
|
||||||
}
|
}
|
||||||
union_list = lappend(union_list, qlist->qtrees[i]);
|
union_list = lappend(union_list, query);
|
||||||
}
|
}
|
||||||
return union_list;
|
return union_list;
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.44 1999/05/12 07:14:24 thomas Exp $
|
* $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.45 1999/05/13 07:28:38 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -274,16 +274,19 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
|
|||||||
case T_SubLink:
|
case T_SubLink:
|
||||||
{
|
{
|
||||||
SubLink *sublink = (SubLink *) expr;
|
SubLink *sublink = (SubLink *) expr;
|
||||||
QueryTreeList *qtree;
|
List *qtrees;
|
||||||
|
Query *qtree;
|
||||||
List *llist;
|
List *llist;
|
||||||
|
|
||||||
pstate->p_hasSubLinks = true;
|
pstate->p_hasSubLinks = true;
|
||||||
qtree = parse_analyze(lcons(sublink->subselect, NIL), pstate);
|
qtrees = parse_analyze(lcons(sublink->subselect, NIL), pstate);
|
||||||
if (qtree->len != 1 ||
|
if (length(qtrees) != 1)
|
||||||
qtree->qtrees[0]->commandType != CMD_SELECT ||
|
|
||||||
qtree->qtrees[0]->resultRelation != 0)
|
|
||||||
elog(ERROR, "parser: bad query in subselect");
|
elog(ERROR, "parser: bad query in subselect");
|
||||||
sublink->subselect = (Node *) qtree->qtrees[0];
|
qtree = (Query *) lfirst(qtrees);
|
||||||
|
if (qtree->commandType != CMD_SELECT ||
|
||||||
|
qtree->resultRelation != 0)
|
||||||
|
elog(ERROR, "parser: bad query in subselect");
|
||||||
|
sublink->subselect = (Node *) qtree;
|
||||||
|
|
||||||
if (sublink->subLinkType != EXISTS_SUBLINK)
|
if (sublink->subLinkType != EXISTS_SUBLINK)
|
||||||
{
|
{
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/parser/parser.c,v 1.37 1999/02/13 23:17:10 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/parser/parser.c,v 1.38 1999/05/13 07:28:39 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -20,34 +20,32 @@
|
|||||||
#include "parser/parse_node.h"
|
#include "parser/parse_node.h"
|
||||||
#include "parser/parser.h"
|
#include "parser/parser.h"
|
||||||
|
|
||||||
|
#if defined(FLEX_SCANNER)
|
||||||
|
extern void DeleteBuffer(void);
|
||||||
|
#endif /* FLEX_SCANNER */
|
||||||
|
|
||||||
char *parseString; /* the char* which holds the string to be
|
char *parseString; /* the char* which holds the string to be
|
||||||
* parsed */
|
* parsed */
|
||||||
List *parsetree = NIL;
|
List *parsetree; /* result of parsing is left here */
|
||||||
|
|
||||||
#ifdef SETS_FIXED
|
#ifdef SETS_FIXED
|
||||||
static void fixupsets();
|
static void fixupsets();
|
||||||
static void define_sets();
|
static void define_sets();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* parser-- returns a list of parse trees
|
* parser-- returns a list of parse trees
|
||||||
*
|
|
||||||
* CALLER is responsible for free'ing the list returned
|
|
||||||
*/
|
*/
|
||||||
QueryTreeList *
|
List *
|
||||||
parser(char *str, Oid *typev, int nargs)
|
parser(char *str, Oid *typev, int nargs)
|
||||||
{
|
{
|
||||||
QueryTreeList *queryList;
|
List *queryList;
|
||||||
int yyresult;
|
int yyresult;
|
||||||
|
|
||||||
#if defined(FLEX_SCANNER)
|
|
||||||
extern void DeleteBuffer(void);
|
|
||||||
|
|
||||||
#endif /* FLEX_SCANNER */
|
|
||||||
|
|
||||||
init_io();
|
init_io();
|
||||||
|
|
||||||
parseString = pstrdup(str);
|
parseString = pstrdup(str);
|
||||||
|
parsetree = NIL; /* in case parser forgets to set it */
|
||||||
|
|
||||||
parser_init(typev, nargs);
|
parser_init(typev, nargs);
|
||||||
yyresult = yyparse();
|
yyresult = yyparse();
|
||||||
@ -59,7 +57,7 @@ parser(char *str, Oid *typev, int nargs)
|
|||||||
clearerr(stdin);
|
clearerr(stdin);
|
||||||
|
|
||||||
if (yyresult) /* error */
|
if (yyresult) /* error */
|
||||||
return (QueryTreeList *) NULL;
|
return (List *) NULL;
|
||||||
|
|
||||||
queryList = parse_analyze(parsetree, NULL);
|
queryList = parse_analyze(parsetree, NULL);
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.40 1999/05/12 17:04:47 wieck Exp $
|
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.41 1999/05/13 07:28:41 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -3107,25 +3107,25 @@ void create_list(Node *ptr, List **intersect_list)
|
|||||||
* instead. */
|
* instead. */
|
||||||
Node *intersect_tree_analyze(Node *tree, Node *first_select, Node *parsetree)
|
Node *intersect_tree_analyze(Node *tree, Node *first_select, Node *parsetree)
|
||||||
{
|
{
|
||||||
Node *result = (Node *)NIL;
|
Node *result = (Node *) NIL;
|
||||||
List *arg;
|
List *arg;
|
||||||
|
|
||||||
if(IsA(tree, SelectStmt))
|
if (IsA(tree, SelectStmt))
|
||||||
{
|
{
|
||||||
QueryTreeList *qtree;
|
|
||||||
|
|
||||||
/* If we get to the tree given in first_select return
|
/* If we get to the tree given in first_select return
|
||||||
* parsetree instead of performing parse_analyze() */
|
* parsetree instead of performing parse_analyze() */
|
||||||
if(tree == first_select){
|
if (tree == first_select)
|
||||||
|
{
|
||||||
result = parsetree;
|
result = parsetree;
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
/* transform the 'raw' nodes to 'cooked' Query nodes */
|
/* transform the 'raw' nodes to 'cooked' Query nodes */
|
||||||
qtree = parse_analyze(lcons(tree, NIL), NULL);
|
List *qtree = parse_analyze(lcons(tree, NIL), NULL);
|
||||||
result = (Node *)qtree->qtrees[0];
|
result = (Node *) lfirst(qtree);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
if(IsA(tree,Expr))
|
if(IsA(tree,Expr))
|
||||||
{
|
{
|
||||||
/* Call recursively for every argument of the node */
|
/* Call recursively for every argument of the node */
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.112 1999/05/11 09:06:31 wieck Exp $
|
* $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.113 1999/05/13 07:28:46 tgl Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* this is the "main" module of the postgres backend and
|
* this is the "main" module of the postgres backend and
|
||||||
@ -389,19 +389,17 @@ List *
|
|||||||
pg_parse_and_plan(char *query_string, /* string to execute */
|
pg_parse_and_plan(char *query_string, /* string to execute */
|
||||||
Oid *typev, /* argument types */
|
Oid *typev, /* argument types */
|
||||||
int nargs, /* number of arguments */
|
int nargs, /* number of arguments */
|
||||||
QueryTreeList **queryListP, /* pointer to the parse
|
List **queryListP, /* returned pointer to the parse trees */
|
||||||
* trees */
|
|
||||||
CommandDest dest, /* where results should go */
|
CommandDest dest, /* where results should go */
|
||||||
bool aclOverride)
|
bool aclOverride)
|
||||||
{
|
{
|
||||||
QueryTreeList *querytree_list;
|
List *querytree_list = NIL;
|
||||||
int i;
|
|
||||||
List *plan_list = NIL;
|
List *plan_list = NIL;
|
||||||
Plan *plan;
|
List *querytree_list_item;
|
||||||
int j;
|
|
||||||
QueryTreeList *new_list;
|
|
||||||
List *rewritten = NIL;
|
|
||||||
Query *querytree;
|
Query *querytree;
|
||||||
|
Plan *plan;
|
||||||
|
List *new_list;
|
||||||
|
List *rewritten;
|
||||||
|
|
||||||
if (DebugPrintQuery)
|
if (DebugPrintQuery)
|
||||||
{
|
{
|
||||||
@ -461,22 +459,17 @@ pg_parse_and_plan(char *query_string, /* string to execute */
|
|||||||
ShowUsage();
|
ShowUsage();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* new_list holds the rewritten queries */
|
|
||||||
new_list = (QueryTreeList *) malloc(sizeof(QueryTreeList));
|
|
||||||
new_list->len = querytree_list->len;
|
|
||||||
new_list->qtrees = (Query **) malloc(new_list->len * sizeof(Query *));
|
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
* (2) rewrite the queries, as necessary
|
* (2) rewrite the queries, as necessary
|
||||||
*
|
*
|
||||||
* j counts queries output into new_list; the number of rewritten
|
* rewritten queries are collected in new_list. Note there may be
|
||||||
* queries can be different from the original number.
|
* more or fewer than in the original list.
|
||||||
* ----------------
|
* ----------------
|
||||||
*/
|
*/
|
||||||
j = 0;
|
new_list = NIL;
|
||||||
for (i = 0; i < querytree_list->len; i++)
|
foreach (querytree_list_item, querytree_list)
|
||||||
{
|
{
|
||||||
querytree = querytree_list->qtrees[i];
|
querytree = (Query *) lfirst(querytree_list_item);
|
||||||
|
|
||||||
if (DebugPrintParse || DebugPPrintParse)
|
if (DebugPrintParse || DebugPPrintParse)
|
||||||
{
|
{
|
||||||
@ -489,45 +482,18 @@ pg_parse_and_plan(char *query_string, /* string to execute */
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* don't rewrite utilites, just dump 'em into new_list */
|
|
||||||
if (querytree->commandType == CMD_UTILITY)
|
if (querytree->commandType == CMD_UTILITY)
|
||||||
{
|
{
|
||||||
new_list->qtrees[j++] = querytree;
|
/* don't rewrite utilities, just dump 'em into new_list */
|
||||||
continue;
|
new_list = lappend(new_list, querytree);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* rewrite regular queries */
|
|
||||||
rewritten = QueryRewrite(querytree);
|
|
||||||
|
|
||||||
if (rewritten != NIL)
|
|
||||||
{
|
|
||||||
int len,
|
|
||||||
k;
|
|
||||||
|
|
||||||
len = length(rewritten);
|
|
||||||
if (len == 1)
|
|
||||||
new_list->qtrees[j++] = (Query *) lfirst(rewritten);
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* rewritten queries are longer than original query */
|
/* rewrite regular queries */
|
||||||
/* grow the new_list to accommodate */
|
rewritten = QueryRewrite(querytree);
|
||||||
new_list->len += len - 1; /* - 1 because originally
|
new_list = nconc(new_list, rewritten);
|
||||||
* we allocated one space
|
|
||||||
* for the query */
|
|
||||||
new_list->qtrees = realloc(new_list->qtrees,
|
|
||||||
new_list->len * sizeof(Query *));
|
|
||||||
for (k = 0; k < len; k++)
|
|
||||||
new_list->qtrees[j++] = (Query *) nth(k, rewritten);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Update new_list with correct final length */
|
|
||||||
new_list->len = j;
|
|
||||||
|
|
||||||
/* we're done with the original lists, free it */
|
|
||||||
free(querytree_list->qtrees);
|
|
||||||
free(querytree_list);
|
|
||||||
|
|
||||||
querytree_list = new_list;
|
querytree_list = new_list;
|
||||||
|
|
||||||
@ -536,18 +502,18 @@ pg_parse_and_plan(char *query_string, /* string to execute */
|
|||||||
*/
|
*/
|
||||||
if (aclOverride)
|
if (aclOverride)
|
||||||
{
|
{
|
||||||
for (i = 0; i < querytree_list->len; i++)
|
foreach (querytree_list_item, querytree_list)
|
||||||
{
|
{
|
||||||
RangeTblEntry *rte;
|
|
||||||
List *l;
|
List *l;
|
||||||
|
|
||||||
querytree = querytree_list->qtrees[i];
|
querytree = (Query *) lfirst(querytree_list_item);
|
||||||
|
|
||||||
if (querytree->commandType == CMD_UTILITY)
|
if (querytree->commandType == CMD_UTILITY)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
foreach(l, querytree->rtable)
|
foreach(l, querytree->rtable)
|
||||||
{
|
{
|
||||||
rte = (RangeTblEntry *) lfirst(l);
|
RangeTblEntry *rte = (RangeTblEntry *) lfirst(l);
|
||||||
|
|
||||||
rte->skipAcl = TRUE;
|
rte->skipAcl = TRUE;
|
||||||
}
|
}
|
||||||
@ -559,24 +525,26 @@ pg_parse_and_plan(char *query_string, /* string to execute */
|
|||||||
if (DebugPPrintRewrittenParsetree) {
|
if (DebugPPrintRewrittenParsetree) {
|
||||||
TPRINTF(TRACE_PRETTY_REWRITTEN, "after rewriting:");
|
TPRINTF(TRACE_PRETTY_REWRITTEN, "after rewriting:");
|
||||||
|
|
||||||
for (i = 0; i < querytree_list->len; i++)
|
foreach (querytree_list_item, querytree_list)
|
||||||
{
|
{
|
||||||
nodeDisplay(querytree_list->qtrees[i]);
|
querytree = (Query *) lfirst(querytree_list_item);
|
||||||
|
nodeDisplay(querytree);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
TPRINTF(TRACE_REWRITTEN, "after rewriting:");
|
TPRINTF(TRACE_REWRITTEN, "after rewriting:");
|
||||||
|
|
||||||
for (i = 0; i < querytree_list->len; i++)
|
foreach (querytree_list_item, querytree_list)
|
||||||
{
|
{
|
||||||
printf("\n%s\n\n", nodeToString(querytree_list->qtrees[i]));
|
querytree = (Query *) lfirst(querytree_list_item);
|
||||||
|
printf("\n%s\n\n", nodeToString(querytree));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < querytree_list->len; i++)
|
foreach (querytree_list_item, querytree_list)
|
||||||
{
|
{
|
||||||
querytree = querytree_list->qtrees[i];
|
querytree = (Query *) lfirst(querytree_list_item);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For each query that isn't a utility invocation, generate a
|
* For each query that isn't a utility invocation, generate a
|
||||||
@ -600,11 +568,9 @@ pg_parse_and_plan(char *query_string, /* string to execute */
|
|||||||
elog(NOTICE, "(transaction aborted): %s",
|
elog(NOTICE, "(transaction aborted): %s",
|
||||||
"queries ignored until END");
|
"queries ignored until END");
|
||||||
|
|
||||||
free(querytree_list->qtrees);
|
|
||||||
free(querytree_list);
|
|
||||||
if (queryListP)
|
if (queryListP)
|
||||||
*queryListP = (QueryTreeList *) NULL;
|
*queryListP = NIL;
|
||||||
return (List *) NULL;
|
return NIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ShowPlannerStats)
|
if (ShowPlannerStats)
|
||||||
@ -638,8 +604,6 @@ pg_parse_and_plan(char *query_string, /* string to execute */
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#ifdef FUNC_UTIL_PATCH
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the command is an utility append a null plan. This is needed
|
* If the command is an utility append a null plan. This is needed
|
||||||
* to keep the plan_list aligned with the querytree_list or the
|
* to keep the plan_list aligned with the querytree_list or the
|
||||||
@ -647,18 +611,6 @@ pg_parse_and_plan(char *query_string, /* string to execute */
|
|||||||
*/
|
*/
|
||||||
else
|
else
|
||||||
plan_list = lappend(plan_list, NULL);
|
plan_list = lappend(plan_list, NULL);
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ----------
|
|
||||||
* Check if the rewriting had thrown away everything
|
|
||||||
* ----------
|
|
||||||
*/
|
|
||||||
if (querytree_list->len == 0)
|
|
||||||
{
|
|
||||||
free(querytree_list->qtrees);
|
|
||||||
free(querytree_list);
|
|
||||||
querytree_list = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (queryListP)
|
if (queryListP)
|
||||||
@ -702,36 +654,39 @@ pg_exec_query_dest(char *query_string, /* string to execute */
|
|||||||
bool aclOverride) /* to give utility commands power
|
bool aclOverride) /* to give utility commands power
|
||||||
* of superusers */
|
* of superusers */
|
||||||
{
|
{
|
||||||
|
List *querytree_list;
|
||||||
List *plan_list;
|
List *plan_list;
|
||||||
Plan *plan;
|
|
||||||
Query *querytree;
|
Query *querytree;
|
||||||
int i,
|
Plan *plan;
|
||||||
j;
|
int j;
|
||||||
QueryTreeList *querytree_list;
|
|
||||||
|
|
||||||
/* plan the queries */
|
/* plan the queries */
|
||||||
plan_list = pg_parse_and_plan(query_string, NULL, 0, &querytree_list, dest, aclOverride);
|
plan_list = pg_parse_and_plan(query_string, NULL, 0,
|
||||||
|
&querytree_list, dest, aclOverride);
|
||||||
|
|
||||||
|
/* if we got a cancel signal whilst planning, quit */
|
||||||
if (QueryCancel)
|
if (QueryCancel)
|
||||||
CancelQuery();
|
CancelQuery();
|
||||||
|
|
||||||
/* pg_parse_and_plan could have failed */
|
/* OK, do it to it! */
|
||||||
if (querytree_list == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (i = 0; i < querytree_list->len; i++)
|
/* NOTE: we do not use "foreach" here because we want to be sure
|
||||||
{
|
* the list pointers have been advanced before the query is executed.
|
||||||
querytree = querytree_list->qtrees[i];
|
* We need to do that because VACUUM has a nasty little habit of doing
|
||||||
|
* CommitTransactionCommand at startup, and that will release the
|
||||||
#ifdef FUNC_UTIL_PATCH
|
* memory holding our parse/plan lists :-(. This needs a better
|
||||||
|
* solution --- currently, the code will crash if someone submits
|
||||||
/*
|
* "vacuum; something-else" in a single query string. But memory
|
||||||
* Advance on the plan_list in every case. Now the plan_list has
|
* allocation needs redesigned anyway, so this will have to do for now.
|
||||||
* the same length of the querytree_list. DZ - 30-8-1996
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
while (querytree_list)
|
||||||
|
{
|
||||||
|
querytree = (Query *) lfirst(querytree_list);
|
||||||
|
querytree_list = lnext(querytree_list);
|
||||||
plan = (Plan *) lfirst(plan_list);
|
plan = (Plan *) lfirst(plan_list);
|
||||||
plan_list = lnext(plan_list);
|
plan_list = lnext(plan_list);
|
||||||
#endif
|
|
||||||
if (querytree->commandType == CMD_UTILITY)
|
if (querytree->commandType == CMD_UTILITY)
|
||||||
{
|
{
|
||||||
/* ----------------
|
/* ----------------
|
||||||
@ -747,19 +702,9 @@ pg_exec_query_dest(char *query_string, /* string to execute */
|
|||||||
TPRINTF(TRACE_VERBOSE, "ProcessUtility");
|
TPRINTF(TRACE_VERBOSE, "ProcessUtility");
|
||||||
|
|
||||||
ProcessUtility(querytree->utilityStmt, dest);
|
ProcessUtility(querytree->utilityStmt, dest);
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#ifndef FUNC_UTIL_PATCH
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Moved before the if. DZ - 30-8-1996
|
|
||||||
*/
|
|
||||||
plan = (Plan *) lfirst(plan_list);
|
|
||||||
plan_list = lnext(plan_list);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef INDEXSCAN_PATCH
|
#ifdef INDEXSCAN_PATCH
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -810,12 +755,8 @@ pg_exec_query_dest(char *query_string, /* string to execute */
|
|||||||
* visible to subsequent ones.
|
* visible to subsequent ones.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (querytree_list)
|
|
||||||
CommandCounterIncrement();
|
CommandCounterIncrement();
|
||||||
}
|
}
|
||||||
|
|
||||||
free(querytree_list->qtrees);
|
|
||||||
free(querytree_list);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --------------------------------
|
/* --------------------------------
|
||||||
@ -1544,7 +1485,7 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
|
|||||||
if (!IsUnderPostmaster)
|
if (!IsUnderPostmaster)
|
||||||
{
|
{
|
||||||
puts("\nPOSTGRES backend interactive interface ");
|
puts("\nPOSTGRES backend interactive interface ");
|
||||||
puts("$Revision: 1.112 $ $Date: 1999/05/11 09:06:31 $\n");
|
puts("$Revision: 1.113 $ $Date: 1999/05/13 07:28:46 $\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
* spi.c
|
* spi.c
|
||||||
* Server Programming Interface private declarations
|
* Server Programming Interface private declarations
|
||||||
*
|
*
|
||||||
* $Header: /cvsroot/pgsql/src/include/executor/spi_priv.h,v 1.2 1999/02/13 23:21:29 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/include/executor/spi_priv.h,v 1.3 1999/05/13 07:28:58 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
QueryTreeList *qtlist; /* malloced */
|
List *qtlist;
|
||||||
uint32 processed; /* by Executor */
|
uint32 processed; /* by Executor */
|
||||||
SPITupleTable *tuptable;
|
SPITupleTable *tuptable;
|
||||||
Portal portal; /* portal per procedure */
|
Portal portal; /* portal per procedure */
|
||||||
@ -25,7 +25,7 @@ typedef struct
|
|||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
QueryTreeList *qtlist;
|
List *qtlist;
|
||||||
List *ptlist;
|
List *ptlist;
|
||||||
int nargs;
|
int nargs;
|
||||||
Oid *argtypes;
|
Oid *argtypes;
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 1994, Regents of the University of California
|
* Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: planner.h,v 1.10 1999/02/13 23:21:51 momjian Exp $
|
* $Id: planner.h,v 1.11 1999/05/13 07:29:11 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -22,6 +22,6 @@
|
|||||||
|
|
||||||
extern Plan *planner(Query *parse);
|
extern Plan *planner(Query *parse);
|
||||||
extern Plan *union_planner(Query *parse);
|
extern Plan *union_planner(Query *parse);
|
||||||
extern void pg_checkretval(Oid rettype, QueryTreeList *querytree_list);
|
extern void pg_checkretval(Oid rettype, List *querytree_list);
|
||||||
|
|
||||||
#endif /* PLANNER_H */
|
#endif /* PLANNER_H */
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 1994, Regents of the University of California
|
* Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: analyze.h,v 1.5 1999/01/18 00:10:11 momjian Exp $
|
* $Id: analyze.h,v 1.6 1999/05/13 07:29:17 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
#include <parser/parse_node.h>
|
#include <parser/parse_node.h>
|
||||||
|
|
||||||
extern QueryTreeList *parse_analyze(List *pl, ParseState *parentParseState);
|
extern List *parse_analyze(List *pl, ParseState *parentParseState);
|
||||||
/***S*I***/
|
/***S*I***/
|
||||||
extern void create_select_list(Node *ptr, List **select_list, bool *unionall_present);
|
extern void create_select_list(Node *ptr, List **select_list, bool *unionall_present);
|
||||||
extern Node *A_Expr_to_Expr(Node *ptr, bool *intersect_present);
|
extern Node *A_Expr_to_Expr(Node *ptr, bool *intersect_present);
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 1994, Regents of the University of California
|
* Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: parse_node.h,v 1.11 1998/09/01 04:37:35 momjian Exp $
|
* $Id: parse_node.h,v 1.12 1999/05/13 07:29:19 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -19,12 +19,6 @@
|
|||||||
#include <parser/parse_type.h>
|
#include <parser/parse_type.h>
|
||||||
#include <utils/rel.h>
|
#include <utils/rel.h>
|
||||||
|
|
||||||
typedef struct QueryTreeList
|
|
||||||
{
|
|
||||||
int len; /* number of queries */
|
|
||||||
Query **qtrees;
|
|
||||||
} QueryTreeList;
|
|
||||||
|
|
||||||
/* state information used during parse analysis */
|
/* state information used during parse analysis */
|
||||||
typedef struct ParseState
|
typedef struct ParseState
|
||||||
{
|
{
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 1994, Regents of the University of California
|
* Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: parser.h,v 1.4 1998/09/01 04:37:42 momjian Exp $
|
* $Id: parser.h,v 1.5 1999/05/13 07:29:20 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -15,6 +15,6 @@
|
|||||||
|
|
||||||
#include <parser/parse_node.h>
|
#include <parser/parse_node.h>
|
||||||
|
|
||||||
extern QueryTreeList *parser(char *str, Oid *typev, int nargs);
|
extern List *parser(char *str, Oid *typev, int nargs);
|
||||||
|
|
||||||
#endif /* PARSER_H */
|
#endif /* PARSER_H */
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 1994, Regents of the University of California
|
* Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: tcopprot.h,v 1.18 1999/04/20 02:19:55 tgl Exp $
|
* $Id: tcopprot.h,v 1.19 1999/05/13 07:29:22 tgl Exp $
|
||||||
*
|
*
|
||||||
* OLD COMMENTS
|
* OLD COMMENTS
|
||||||
* This file was created so that other c files could get the two
|
* This file was created so that other c files could get the two
|
||||||
@ -41,7 +41,7 @@ extern bool InError;
|
|||||||
|
|
||||||
#ifndef BOOTSTRAP_INCLUDE
|
#ifndef BOOTSTRAP_INCLUDE
|
||||||
extern List *pg_parse_and_plan(char *query_string, Oid *typev, int nargs,
|
extern List *pg_parse_and_plan(char *query_string, Oid *typev, int nargs,
|
||||||
QueryTreeList **queryListP, CommandDest dest,
|
List **queryListP, CommandDest dest,
|
||||||
bool aclOverride);
|
bool aclOverride);
|
||||||
extern void pg_exec_query(char *query_string);
|
extern void pg_exec_query(char *query_string);
|
||||||
extern void pg_exec_query_acl_override(char *query_string);
|
extern void pg_exec_query_acl_override(char *query_string);
|
||||||
|
Reference in New Issue
Block a user