mirror of
https://github.com/postgres/postgres.git
synced 2025-11-10 17:42:29 +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:
@@ -5,7 +5,7 @@
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
QueryTreeList *
|
||||
List *
|
||||
parse_analyze(List *pl, ParseState *parentParseState)
|
||||
{
|
||||
QueryTreeList *result;
|
||||
List *result = NIL;
|
||||
ParseState *pstate;
|
||||
Query *parsetree;
|
||||
int i = 0;
|
||||
|
||||
result = malloc(sizeof(QueryTreeList));
|
||||
result->len = length(pl);
|
||||
result->qtrees = (Query **) malloc(result->len * sizeof(Query *));
|
||||
|
||||
while (pl != NIL)
|
||||
{
|
||||
@@ -78,35 +73,25 @@ parse_analyze(List *pl, ParseState *parentParseState)
|
||||
if (pstate->p_target_relation != NULL)
|
||||
heap_close(pstate->p_target_relation);
|
||||
|
||||
if (extras_before != NIL)
|
||||
while (extras_before != NIL)
|
||||
{
|
||||
result->len += length(extras_before);
|
||||
result->qtrees = (Query **) realloc(result->qtrees, result->len * sizeof(Query *));
|
||||
while (extras_before != NIL)
|
||||
{
|
||||
result->qtrees[i++] = transformStmt(pstate, lfirst(extras_before));
|
||||
if (pstate->p_target_relation != NULL)
|
||||
heap_close(pstate->p_target_relation);
|
||||
extras_before = lnext(extras_before);
|
||||
}
|
||||
result = lappend(result,
|
||||
transformStmt(pstate, lfirst(extras_before)));
|
||||
if (pstate->p_target_relation != NULL)
|
||||
heap_close(pstate->p_target_relation);
|
||||
extras_before = lnext(extras_before);
|
||||
}
|
||||
extras_before = NIL;
|
||||
|
||||
result->qtrees[i++] = parsetree;
|
||||
result = lappend(result, parsetree);
|
||||
|
||||
if (extras_after != NIL)
|
||||
while (extras_after != NIL)
|
||||
{
|
||||
result->len += length(extras_after);
|
||||
result->qtrees = (Query **) realloc(result->qtrees, result->len * sizeof(Query *));
|
||||
while (extras_after != NIL)
|
||||
{
|
||||
result->qtrees[i++] = transformStmt(pstate, lfirst(extras_after));
|
||||
if (pstate->p_target_relation != NULL)
|
||||
heap_close(pstate->p_target_relation);
|
||||
extras_after = lnext(extras_after);
|
||||
}
|
||||
result = lappend(result,
|
||||
transformStmt(pstate, lfirst(extras_after)));
|
||||
if (pstate->p_target_relation != NULL)
|
||||
heap_close(pstate->p_target_relation);
|
||||
extras_after = lnext(extras_after);
|
||||
}
|
||||
extras_after = NIL;
|
||||
|
||||
pl = lnext(pl);
|
||||
pfree(pstate);
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* 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)
|
||||
{
|
||||
List *union_list = NIL;
|
||||
QueryTreeList *qlist;
|
||||
int i;
|
||||
List *qlist,
|
||||
*qlist_item;
|
||||
|
||||
if (unionClause)
|
||||
{
|
||||
/* recursion */
|
||||
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 *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");
|
||||
|
||||
foreach(next_target, qlist->qtrees[i]->targetList)
|
||||
foreach(next_target, query->targetList)
|
||||
{
|
||||
Oid itype;
|
||||
Oid otype;
|
||||
@@ -819,7 +820,7 @@ transformUnionClause(List *unionClause, List *targetlist)
|
||||
}
|
||||
prev_target = lnext(prev_target);
|
||||
}
|
||||
union_list = lappend(union_list, qlist->qtrees[i]);
|
||||
union_list = lappend(union_list, query);
|
||||
}
|
||||
return union_list;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* 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:
|
||||
{
|
||||
SubLink *sublink = (SubLink *) expr;
|
||||
QueryTreeList *qtree;
|
||||
List *qtrees;
|
||||
Query *qtree;
|
||||
List *llist;
|
||||
|
||||
pstate->p_hasSubLinks = true;
|
||||
qtree = parse_analyze(lcons(sublink->subselect, NIL), pstate);
|
||||
if (qtree->len != 1 ||
|
||||
qtree->qtrees[0]->commandType != CMD_SELECT ||
|
||||
qtree->qtrees[0]->resultRelation != 0)
|
||||
qtrees = parse_analyze(lcons(sublink->subselect, NIL), pstate);
|
||||
if (length(qtrees) != 1)
|
||||
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)
|
||||
{
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
*
|
||||
*
|
||||
* 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/parser.h"
|
||||
|
||||
#if defined(FLEX_SCANNER)
|
||||
extern void DeleteBuffer(void);
|
||||
#endif /* FLEX_SCANNER */
|
||||
|
||||
char *parseString; /* the char* which holds the string to be
|
||||
* parsed */
|
||||
List *parsetree = NIL;
|
||||
List *parsetree; /* result of parsing is left here */
|
||||
|
||||
#ifdef SETS_FIXED
|
||||
static void fixupsets();
|
||||
static void define_sets();
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
QueryTreeList *queryList;
|
||||
List *queryList;
|
||||
int yyresult;
|
||||
|
||||
#if defined(FLEX_SCANNER)
|
||||
extern void DeleteBuffer(void);
|
||||
|
||||
#endif /* FLEX_SCANNER */
|
||||
|
||||
init_io();
|
||||
|
||||
parseString = pstrdup(str);
|
||||
parsetree = NIL; /* in case parser forgets to set it */
|
||||
|
||||
parser_init(typev, nargs);
|
||||
yyresult = yyparse();
|
||||
@@ -59,7 +57,7 @@ parser(char *str, Oid *typev, int nargs)
|
||||
clearerr(stdin);
|
||||
|
||||
if (yyresult) /* error */
|
||||
return (QueryTreeList *) NULL;
|
||||
return (List *) NULL;
|
||||
|
||||
queryList = parse_analyze(parsetree, NULL);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user