-
Notifications
You must be signed in to change notification settings - Fork 2
/
pgsp_import.c
149 lines (128 loc) · 4.09 KB
/
pgsp_import.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/*-------------------------------------------------------------------------
*
* pspg_import.c: Import of some PostgreSQL private fuctions.
*
* This program is open source, licensed under the PostgreSQL license.
* For license terms, see the LICENSE file.
*
* Copyright (c) 2008-2023, PostgreSQL Global Development Group
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include "optimizer/optimizer.h"
#include "include/pgsp_import.h"
/*
* pgsp_ScanQueryForLocks: recursively scan one Query for AcquirePlannerLocks.
*/
void
pgsp_ScanQueryForLocks(Query *parsetree, bool acquire)
{
ListCell *lc;
/* Shouldn't get called on utility commands */
Assert(parsetree->commandType != CMD_UTILITY);
/*
* First, process RTEs of the current query level.
*/
foreach(lc, parsetree->rtable)
{
RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
switch (rte->rtekind)
{
case RTE_RELATION:
/* Acquire or release the appropriate type of lock */
if (acquire)
LockRelationOid(rte->relid, rte->rellockmode);
else
UnlockRelationOid(rte->relid, rte->rellockmode);
break;
case RTE_SUBQUERY:
/* Recurse into subquery-in-FROM */
pgsp_ScanQueryForLocks(rte->subquery, acquire);
break;
default:
/* ignore other types of RTEs */
break;
}
}
/* Recurse into subquery-in-WITH */
foreach(lc, parsetree->cteList)
{
CommonTableExpr *cte = lfirst_node(CommonTableExpr, lc);
pgsp_ScanQueryForLocks(castNode(Query, cte->ctequery), acquire);
}
/*
* Recurse into sublink subqueries, too. But we already did the ones in
* the rtable and cteList.
*/
if (parsetree->hasSubLinks)
{
query_tree_walker(parsetree, pgsp_ScanQueryWalker,
(void *) &acquire,
QTW_IGNORE_RC_SUBQUERIES);
}
}
/*
* Walker to find sublink subqueries for ScanQueryForLocks
*/
bool
pgsp_ScanQueryWalker(Node *node, bool *acquire)
{
if (node == NULL)
return false;
if (IsA(node, SubLink))
{
SubLink *sub = (SubLink *) node;
/* Do what we came for */
pgsp_ScanQueryForLocks(castNode(Query, sub->subselect), *acquire);
/* Fall through to process lefthand args of SubLink */
}
/*
* Do NOT recurse into Query nodes, because ScanQueryForLocks already
* processed subselects of subselects for us.
*/
return expression_tree_walker(node, pgsp_ScanQueryWalker,
(void *) acquire);
}
/*
* cached_plan_cost: calculate estimated cost of a plan
*
* If include_planner is true, also include the estimated cost of constructing
* the plan. (We must factor that into the cost of using a custom plan, but
* we don't count it for a generic plan.)
*/
double
pgsp_cached_plan_cost(PlannedStmt *plannedstmt, bool include_planner)
{
double result = 0;
if (plannedstmt->commandType == CMD_UTILITY)
return result; /* Ignore utility statements */
result += plannedstmt->planTree->total_cost;
if (include_planner)
{
/*
* Currently we use a very crude estimate of planning effort based
* on the number of relations in the finished plan's rangetable.
* Join planning effort actually scales much worse than linearly
* in the number of relations --- but only until the join collapse
* limits kick in. Also, while inheritance child relations surely
* add to planning effort, they don't make the join situation
* worse. So the actual shape of the planning cost curve versus
* number of relations isn't all that obvious. It will take
* considerable work to arrive at a less crude estimate, and for
* now it's not clear that's worth doing.
*
* The other big difficulty here is that we don't have any very
* good model of how planning cost compares to execution costs.
* The current multiplier of 1000 * cpu_operator_cost is probably
* on the low side, but we'll try this for awhile before making a
* more aggressive correction.
*
* If we ever do write a more complicated estimator, it should
* probably live in src/backend/optimizer/ not here.
*/
int nrelations = list_length(plannedstmt->rtable);
result += 1000.0 * cpu_operator_cost * (nrelations + 1);
}
return result;
}