Skip to content

Commit 507a0a2

Browse files
committed
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.
1 parent f806421 commit 507a0a2

File tree

18 files changed

+192
-288
lines changed

18 files changed

+192
-288
lines changed

doc/src/sgml/arch-dev.sgml

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3758,7 +3758,7 @@ $\ldots$/src/backend/tcop/postgres.c}.
37583758
List *
37593759
pg_parse_and_plan(char *query_string, Oid *typev,
37603760
int nargs,
3761-
QueryTreeList **queryListP,
3761+
List **queryListP,
37623762
CommandDest dest)
37633763
{
37643764
.
@@ -4032,7 +4032,7 @@ instead.
40324032

40334033
if(IsA(tree, SelectStmt))
40344034
{
4035-
QueryTreeList *qtree;
4035+
List *qtrees;
40364036

40374037
/* If we get to the tree given in first_select
40384038
* return parsetree instead of performing
@@ -4044,9 +4044,8 @@ instead.
40444044
else
40454045
{
40464046
/* transform the unprocessed Query nodes */
4047-
qtree =
4048-
parse_analyze(lcons(tree, NIL), NULL);
4049-
result = (Node *)qtree->qtrees[0];
4047+
qtrees = parse_analyze(lcons(tree, NIL), NULL);
4048+
result = (Node *) lfirst(qtrees);
40504049
}
40514050
}
40524051
if(IsA(tree,Expr))

src/backend/catalog/heap.c

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.79 1999/05/10 04:02:03 momjian Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.80 1999/05/13 07:28:26 tgl Exp $
1111
*
1212
*
1313
* INTERFACE ROUTINES
@@ -1498,9 +1498,9 @@ StoreAttrDefault(Relation rel, AttrDefault *attrdef)
14981498
char str[MAX_PARSE_BUFFER];
14991499
char cast[2 * NAMEDATALEN] = {0};
15001500
Form_pg_attribute atp = rel->rd_att->attrs[attrdef->adnum - 1];
1501-
QueryTreeList *queryTree_list;
1502-
Query *query;
1501+
List *queryTree_list;
15031502
List *planTree_list;
1503+
Query *query;
15041504
TargetEntry *te;
15051505
Resdom *resdom;
15061506
Node *expr;
@@ -1522,9 +1522,10 @@ start:;
15221522
"select %s%s from \"%.*s\"", attrdef->adsrc, cast,
15231523
NAMEDATALEN, rel->rd_rel->relname.data);
15241524
setheapoverride(true);
1525-
planTree_list = (List *) pg_parse_and_plan(str, NULL, 0, &queryTree_list, None, FALSE);
1525+
planTree_list = pg_parse_and_plan(str, NULL, 0,
1526+
&queryTree_list, None, FALSE);
15261527
setheapoverride(false);
1527-
query = (Query *) (queryTree_list->qtrees[0]);
1528+
query = (Query *) lfirst(queryTree_list);
15281529

15291530
if (length(query->rtable) > 1 ||
15301531
flatten_tlist(query->targetList) != NIL)
@@ -1582,9 +1583,9 @@ static void
15821583
StoreRelCheck(Relation rel, ConstrCheck *check)
15831584
{
15841585
char str[MAX_PARSE_BUFFER];
1585-
QueryTreeList *queryTree_list;
1586-
Query *query;
1586+
List *queryTree_list;
15871587
List *planTree_list;
1588+
Query *query;
15881589
Plan *plan;
15891590
List *qual;
15901591
char *ccbin;
@@ -1603,9 +1604,10 @@ StoreRelCheck(Relation rel, ConstrCheck *check)
16031604
"select 1 from \"%.*s\" where %s",
16041605
NAMEDATALEN, rel->rd_rel->relname.data, check->ccsrc);
16051606
setheapoverride(true);
1606-
planTree_list = (List *) pg_parse_and_plan(str, NULL, 0, &queryTree_list, None, FALSE);
1607+
planTree_list = pg_parse_and_plan(str, NULL, 0,
1608+
&queryTree_list, None, FALSE);
16071609
setheapoverride(false);
1608-
query = (Query *) (queryTree_list->qtrees[0]);
1610+
query = (Query *) lfirst(queryTree_list);
16091611

16101612
if (length(query->rtable) > 1)
16111613
elog(ERROR, "Only relation '%.*s' can be referenced",

src/backend/catalog/pg_proc.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.27 1999/04/18 02:57:22 tgl Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.28 1999/05/13 07:28:27 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -67,7 +67,7 @@ ProcedureCreate(char *procedureName,
6767
Oid languageObjectId;
6868
Oid typeObjectId;
6969
List *x;
70-
QueryTreeList *querytree_list;
70+
List *querytree_list;
7171
List *plan_list;
7272
Oid typev[8];
7373
Oid relid;

src/backend/executor/functions.c

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.24 1999/02/13 23:15:20 momjian Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.25 1999/05/13 07:28:29 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -97,26 +97,23 @@ init_execution_state(FunctionCachePtr fcache,
9797
execution_state *newes;
9898
execution_state *nextes;
9999
execution_state *preves;
100-
QueryTreeList *queryTree_list;
101-
int i;
102-
List *planTree_list;
103-
int nargs;
104-
105-
nargs = fcache->nargs;
100+
List *queryTree_list,
101+
*planTree_list,
102+
*qtl_item;
103+
int nargs = fcache->nargs;
106104

107105
newes = (execution_state *) palloc(sizeof(execution_state));
108106
nextes = newes;
109107
preves = (execution_state *) NULL;
110108

109+
planTree_list = pg_parse_and_plan(fcache->src, fcache->argOidVect,
110+
nargs, &queryTree_list, None, FALSE);
111111

112-
planTree_list = (List *)
113-
pg_parse_and_plan(fcache->src, fcache->argOidVect, nargs, &queryTree_list, None, FALSE);
114-
115-
for (i = 0; i < queryTree_list->len; i++)
112+
foreach (qtl_item, queryTree_list)
116113
{
117-
EState *estate;
118-
Query *queryTree = (Query *) (queryTree_list->qtrees[i]);
114+
Query *queryTree = lfirst(qtl_item);
119115
Plan *planTree = lfirst(planTree_list);
116+
EState *estate;
120117

121118
if (!nextes)
122119
nextes = (execution_state *) palloc(sizeof(execution_state));

src/backend/executor/spi.c

Lines changed: 31 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* spi.c
44
* Server Programming Interface
55
*
6-
* $Id: spi.c,v 1.36 1999/03/30 01:37:23 momjian Exp $
6+
* $Id: spi.c,v 1.37 1999/05/13 07:28:30 tgl Exp $
77
*
88
*-------------------------------------------------------------------------
99
*/
@@ -602,18 +602,18 @@ spi_printtup(HeapTuple tuple, TupleDesc tupdesc, DestReceiver* self)
602602
static int
603603
_SPI_execute(char *src, int tcount, _SPI_plan *plan)
604604
{
605-
QueryTreeList *queryTree_list;
605+
List *queryTree_list;
606606
List *planTree_list;
607+
List *queryTree_list_item;
607608
List *ptlist;
608609
QueryDesc *qdesc;
609610
Query *queryTree;
610611
Plan *planTree;
611612
EState *state;
612-
int qlen;
613613
int nargs = 0;
614614
Oid *argtypes = NULL;
615-
int res;
616-
int i;
615+
int res = 0;
616+
bool islastquery;
617617

618618
/* Increment CommandCounter to see changes made by now */
619619
CommandCounterIncrement();
@@ -628,18 +628,17 @@ _SPI_execute(char *src, int tcount, _SPI_plan *plan)
628628
nargs = plan->nargs;
629629
argtypes = plan->argtypes;
630630
}
631-
ptlist = planTree_list = (List *)
631+
ptlist = planTree_list =
632632
pg_parse_and_plan(src, argtypes, nargs, &queryTree_list, None, FALSE);
633633

634634
_SPI_current->qtlist = queryTree_list;
635635

636-
qlen = queryTree_list->len;
637-
for (i = 0;; i++)
636+
foreach (queryTree_list_item, queryTree_list)
638637
{
639-
queryTree = (Query *) (queryTree_list->qtrees[i]);
638+
queryTree = (Query *) lfirst(queryTree_list_item);
640639
planTree = lfirst(planTree_list);
641-
642640
planTree_list = lnext(planTree_list);
641+
islastquery = (planTree_list == NIL); /* assume lists are same len */
643642

644643
if (queryTree->commandType == CMD_UTILITY)
645644
{
@@ -659,32 +658,32 @@ _SPI_execute(char *src, int tcount, _SPI_plan *plan)
659658
if (plan == NULL)
660659
{
661660
ProcessUtility(queryTree->utilityStmt, None);
662-
if (i < qlen - 1)
661+
if (! islastquery)
663662
CommandCounterIncrement();
664663
else
665664
return res;
666665
}
667-
else if (i >= qlen - 1)
666+
else if (islastquery)
668667
break;
669668
}
670669
else if (plan == NULL)
671670
{
672671
qdesc = CreateQueryDesc(queryTree, planTree,
673-
(i < qlen - 1) ? None : SPI);
672+
islastquery ? SPI : None);
674673
state = CreateExecutorState();
675-
res = _SPI_pquery(qdesc, state, (i < qlen - 1) ? 0 : tcount);
676-
if (res < 0 || i >= qlen - 1)
674+
res = _SPI_pquery(qdesc, state, islastquery ? tcount : 0);
675+
if (res < 0 || islastquery)
677676
return res;
678677
CommandCounterIncrement();
679678
}
680679
else
681680
{
682681
qdesc = CreateQueryDesc(queryTree, planTree,
683-
(i < qlen - 1) ? None : SPI);
684-
res = _SPI_pquery(qdesc, NULL, (i < qlen - 1) ? 0 : tcount);
682+
islastquery ? SPI : None);
683+
res = _SPI_pquery(qdesc, NULL, islastquery ? tcount : 0);
685684
if (res < 0)
686685
return res;
687-
if (i >= qlen - 1)
686+
if (islastquery)
688687
break;
689688
}
690689
}
@@ -693,23 +692,22 @@ _SPI_execute(char *src, int tcount, _SPI_plan *plan)
693692
plan->ptlist = ptlist;
694693

695694
return res;
696-
697695
}
698696

699697
static int
700698
_SPI_execute_plan(_SPI_plan *plan, Datum *Values, char *Nulls, int tcount)
701699
{
702-
QueryTreeList *queryTree_list = plan->qtlist;
700+
List *queryTree_list = plan->qtlist;
703701
List *planTree_list = plan->ptlist;
702+
List *queryTree_list_item;
704703
QueryDesc *qdesc;
705704
Query *queryTree;
706705
Plan *planTree;
707706
EState *state;
708707
int nargs = plan->nargs;
709-
int qlen = queryTree_list->len;
710-
int res;
711-
int i,
712-
k;
708+
int res = 0;
709+
bool islastquery;
710+
int k;
713711

714712
/* Increment CommandCounter to see changes made by now */
715713
CommandCounterIncrement();
@@ -719,25 +717,25 @@ _SPI_execute_plan(_SPI_plan *plan, Datum *Values, char *Nulls, int tcount)
719717
_SPI_current->tuptable = NULL;
720718
_SPI_current->qtlist = NULL;
721719

722-
for (i = 0;; i++)
720+
foreach (queryTree_list_item, queryTree_list)
723721
{
724-
queryTree = (Query *) (queryTree_list->qtrees[i]);
722+
queryTree = (Query *) lfirst(queryTree_list_item);
725723
planTree = lfirst(planTree_list);
726-
727724
planTree_list = lnext(planTree_list);
725+
islastquery = (planTree_list == NIL); /* assume lists are same len */
728726

729727
if (queryTree->commandType == CMD_UTILITY)
730728
{
731729
ProcessUtility(queryTree->utilityStmt, None);
732-
if (i < qlen - 1)
730+
if (! islastquery)
733731
CommandCounterIncrement();
734732
else
735733
return SPI_OK_UTILITY;
736734
}
737735
else
738736
{
739737
qdesc = CreateQueryDesc(queryTree, planTree,
740-
(i < qlen - 1) ? None : SPI);
738+
islastquery ? SPI : None);
741739
state = CreateExecutorState();
742740
if (nargs > 0)
743741
{
@@ -756,15 +754,14 @@ _SPI_execute_plan(_SPI_plan *plan, Datum *Values, char *Nulls, int tcount)
756754
}
757755
else
758756
state->es_param_list_info = NULL;
759-
res = _SPI_pquery(qdesc, state, (i < qlen - 1) ? 0 : tcount);
760-
if (res < 0 || i >= qlen - 1)
757+
res = _SPI_pquery(qdesc, state, islastquery ? tcount : 0);
758+
if (res < 0 || islastquery)
761759
return res;
762760
CommandCounterIncrement();
763761
}
764762
}
765763

766764
return res;
767-
768765
}
769766

770767
static int
@@ -955,12 +952,7 @@ _SPI_end_call(bool procmem)
955952
*/
956953
_SPI_curid--;
957954

958-
if (_SPI_current->qtlist) /* free _SPI_plan allocations */
959-
{
960-
free(_SPI_current->qtlist->qtrees);
961-
free(_SPI_current->qtlist);
962-
_SPI_current->qtlist = NULL;
963-
}
955+
_SPI_current->qtlist = NULL;
964956

965957
if (procmem) /* switch to the procedure memory context */
966958
{ /* but free Executor memory before */
@@ -1000,7 +992,6 @@ _SPI_copy_plan(_SPI_plan *plan, int location)
1000992
{
1001993
_SPI_plan *newplan;
1002994
MemoryContext oldcxt = NULL;
1003-
int i;
1004995

1005996
if (location == _SPI_CPLAN_PROCXT)
1006997
oldcxt = MemoryContextSwitchTo((MemoryContext)
@@ -1009,14 +1000,7 @@ _SPI_copy_plan(_SPI_plan *plan, int location)
10091000
oldcxt = MemoryContextSwitchTo(TopMemoryContext);
10101001

10111002
newplan = (_SPI_plan *) palloc(sizeof(_SPI_plan));
1012-
newplan->qtlist = (QueryTreeList *) palloc(sizeof(QueryTreeList));
1013-
newplan->qtlist->len = plan->qtlist->len;
1014-
newplan->qtlist->qtrees = (Query **) palloc(plan->qtlist->len *
1015-
sizeof(Query *));
1016-
for (i = 0; i < plan->qtlist->len; i++)
1017-
newplan->qtlist->qtrees[i] = (Query *)
1018-
copyObject(plan->qtlist->qtrees[i]);
1019-
1003+
newplan->qtlist = (List *) copyObject(plan->qtlist);
10201004
newplan->ptlist = (List *) copyObject(plan->ptlist);
10211005
newplan->nargs = plan->nargs;
10221006
if (plan->nargs > 0)

src/backend/optimizer/plan/planner.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.51 1999/05/12 15:01:37 wieck Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.52 1999/05/13 07:28:32 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -671,7 +671,7 @@ make_sortplan(List *tlist, List *sortcls, Plan *plannode)
671671
* XXX Why is this function in this module?
672672
*/
673673
void
674-
pg_checkretval(Oid rettype, QueryTreeList *queryTreeList)
674+
pg_checkretval(Oid rettype, List *queryTreeList)
675675
{
676676
Query *parse;
677677
List *tlist;
@@ -686,7 +686,7 @@ pg_checkretval(Oid rettype, QueryTreeList *queryTreeList)
686686
int i;
687687

688688
/* find the final query */
689-
parse = queryTreeList->qtrees[queryTreeList->len - 1];
689+
parse = (Query *) nth(length(queryTreeList)-1, queryTreeList);
690690

691691
/*
692692
* test 1: if the last query is a utility invocation, then there had

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy