Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit de2b9bd

Browse files
committed
WIP: ArrangeAppend-related code
1 parent ef9f5d9 commit de2b9bd

File tree

2 files changed

+252
-0
lines changed

2 files changed

+252
-0
lines changed

arrangeappend.c

Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
#include "postgres.h"
2+
#include "arrangeappend.h"
3+
#include "pickyappend.h"
4+
5+
#include "pathman.h"
6+
7+
#include "optimizer/clauses.h"
8+
#include "optimizer/cost.h"
9+
#include "optimizer/restrictinfo.h"
10+
#include "optimizer/planmain.h"
11+
#include "optimizer/tlist.h"
12+
#include "optimizer/var.h"
13+
14+
#include "lib/binaryheap.h"
15+
16+
17+
bool pg_pathman_enable_arrangeappend = true;
18+
19+
CustomPathMethods arrangeappend_path_methods;
20+
CustomScanMethods arrangeappend_plan_methods;
21+
CustomExecMethods arrangeappend_exec_methods;
22+
23+
24+
/*
25+
* We have one slot for each item in the heap array. We use SlotNumber
26+
* to store slot indexes. This doesn't actually provide any formal
27+
* type-safety, but it makes the code more self-documenting.
28+
*/
29+
typedef int32 SlotNumber;
30+
31+
/*
32+
* Compare the tuples in the two given slots.
33+
*/
34+
static int32
35+
heap_compare_slots(Datum a, Datum b, void *arg)
36+
{
37+
ArrangeAppendState *node = (ArrangeAppendState *) arg;
38+
SlotNumber slot1 = DatumGetInt32(a);
39+
SlotNumber slot2 = DatumGetInt32(b);
40+
41+
TupleTableSlot *s1 = node->ms_slots[slot1];
42+
TupleTableSlot *s2 = node->ms_slots[slot2];
43+
int nkey;
44+
45+
Assert(!TupIsNull(s1));
46+
Assert(!TupIsNull(s2));
47+
48+
for (nkey = 0; nkey < node->ms_nkeys; nkey++)
49+
{
50+
SortSupport sortKey = node->ms_sortkeys + nkey;
51+
AttrNumber attno = sortKey->ssup_attno;
52+
Datum datum1,
53+
datum2;
54+
bool isNull1,
55+
isNull2;
56+
int compare;
57+
58+
datum1 = slot_getattr(s1, attno, &isNull1);
59+
datum2 = slot_getattr(s2, attno, &isNull2);
60+
61+
compare = ApplySortComparator(datum1, isNull1,
62+
datum2, isNull2,
63+
sortKey);
64+
if (compare != 0)
65+
return -compare;
66+
}
67+
return 0;
68+
}
69+
70+
Path *
71+
create_arrangeappend_path(PlannerInfo *root,
72+
AppendPath *inner_append,
73+
ParamPathInfo *param_info,
74+
List *picky_clauses)
75+
{
76+
return create_append_path_common(root, inner_append,
77+
param_info, picky_clauses,
78+
&arrangeappend_path_methods);
79+
}
80+
81+
Plan *
82+
create_arrangeappend_plan(PlannerInfo *root, RelOptInfo *rel,
83+
CustomPath *best_path, List *tlist,
84+
List *clauses, List *custom_plans)
85+
{
86+
return create_append_plan_common(root, rel,
87+
best_path, tlist,
88+
clauses, custom_plans,
89+
&arrangeappend_plan_methods);
90+
}
91+
92+
Node *
93+
arrangeappend_create_scan_state(CustomScan *node)
94+
{
95+
return create_append_scan_state_common(node,
96+
&arrangeappend_exec_methods,
97+
sizeof(ArrangeAppendState));
98+
}
99+
100+
void
101+
arrangeappend_begin(CustomScanState *node, EState *estate, int eflags)
102+
{
103+
ArrangeAppendState *scan_state = (ArrangeAppendState *) node;
104+
105+
begin_append_common(node, estate, eflags);
106+
}
107+
108+
TupleTableSlot *
109+
arrangeappend_exec(CustomScanState *node)
110+
{
111+
ArrangeAppendState *scan_state = (ArrangeAppendState *) node;
112+
113+
while (scan_state->running_idx < scan_state->ncur_plans)
114+
{
115+
ChildScanCommon child = scan_state->cur_plans[scan_state->running_idx];
116+
PlanState *state = child->content.plan_state;
117+
TupleTableSlot *slot = NULL;
118+
bool quals;
119+
120+
for (;;)
121+
{
122+
slot = ExecProcNode(state);
123+
124+
if (TupIsNull(slot))
125+
break;
126+
127+
node->ss.ps.ps_ExprContext->ecxt_scantuple = slot;
128+
quals = ExecQual(scan_state->custom_expr_states,
129+
node->ss.ps.ps_ExprContext, false);
130+
131+
if (quals)
132+
return slot;
133+
}
134+
135+
scan_state->running_idx++;
136+
}
137+
138+
return NULL;
139+
}
140+
141+
void
142+
arrangeappend_end(CustomScanState *node)
143+
{
144+
ArrangeAppendState *scan_state = (ArrangeAppendState *) node;
145+
146+
end_append_common(node);
147+
}
148+
149+
void
150+
arrangeappend_rescan(CustomScanState *node)
151+
{
152+
ArrangeAppendState *scan_state = (ArrangeAppendState *) node;
153+
int nplans = scan_state->picky_base.ncur_plans;
154+
int i;
155+
156+
rescan_append_common(node);
157+
158+
scan_state->ms_slots = (TupleTableSlot **) palloc0(sizeof(TupleTableSlot *) * nplans);
159+
scan_state->ms_heap = binaryheap_allocate(nplans, heap_compare_slots, scan_state);
160+
161+
/*
162+
* initialize sort-key information
163+
*/
164+
scan_state->ms_nkeys = scan_state->numCols;
165+
scan_state->ms_sortkeys = palloc0(sizeof(SortSupportData) * scan_state->numCols);
166+
167+
for (i = 0; i < scan_state->numCols; i++)
168+
{
169+
SortSupport sortKey = scan_state->ms_sortkeys + i;
170+
171+
sortKey->ssup_cxt = CurrentMemoryContext;
172+
sortKey->ssup_collation = scan_state->collations[i];
173+
sortKey->ssup_nulls_first = scan_state->nullsFirst[i];
174+
sortKey->ssup_attno = scan_state->sortColIdx[i];
175+
176+
/*
177+
* It isn't feasible to perform abbreviated key conversion, since
178+
* tuples are pulled into mergestate's binary heap as needed. It
179+
* would likely be counter-productive to convert tuples into an
180+
* abbreviated representation as they're pulled up, so opt out of that
181+
* additional optimization entirely.
182+
*/
183+
sortKey->abbreviate = false;
184+
185+
PrepareSortSupportFromOrderingOp(scan_state->sortOperators[i], sortKey);
186+
}
187+
}
188+
189+
void
190+
pickyppend_explain(CustomScanState *node, List *ancestors, ExplainState *es)
191+
{
192+
ArrangeAppendState *scan_state = (ArrangeAppendState *) node;
193+
194+
explain_append_common(node, scan_state->picky_base.children_table, es);
195+
}

arrangeappend.h

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
#ifndef ARRANGEAPPEND_H
2+
#define ARRANGEAPPEND_H
3+
4+
#include "postgres.h"
5+
#include "pickyappend.h"
6+
#include "pathman.h"
7+
8+
9+
typedef struct
10+
{
11+
CustomPath cpath;
12+
Oid relid; /* relid of the partitioned table */
13+
14+
ChildScanCommon *children; /* all available plans */
15+
int nchildren;
16+
} ArrangeAppendPath;
17+
18+
typedef struct
19+
{
20+
PickyAppendState picky_base;
21+
22+
int numCols; /* number of sort-key columns */
23+
AttrNumber *sortColIdx; /* their indexes in the target list */
24+
Oid *sortOperators; /* OIDs of operators to sort them by */
25+
Oid *collations; /* OIDs of collations */
26+
bool *nullsFirst; /* NULLS FIRST/LAST directions */
27+
28+
int ms_nkeys;
29+
SortSupport ms_sortkeys;
30+
TupleTableSlot **ms_slots;
31+
struct binaryheap *ms_heap;
32+
} ArrangeAppendState;
33+
34+
35+
extern bool pg_pathman_enable_arrangeappend;
36+
37+
extern CustomPathMethods arrangeappend_path_methods;
38+
extern CustomScanMethods arrangeappend_plan_methods;
39+
extern CustomExecMethods arrangeappend_exec_methods;
40+
41+
Plan * create_arrangeappend_plan(PlannerInfo *root, RelOptInfo *rel,
42+
CustomPath *best_path, List *tlist,
43+
List *clauses, List *custom_plans);
44+
45+
Node * arrangeappend_create_scan_state(CustomScan *node);
46+
47+
void arrangeappend_begin(CustomScanState *node, EState *estate, int eflags);
48+
49+
TupleTableSlot * arrangeappend_exec(CustomScanState *node);
50+
51+
void arrangeappend_end(CustomScanState *node);
52+
53+
void arrangeappend_rescan(CustomScanState *node);
54+
55+
void arrangeappend_explain(CustomScanState *node, List *ancestors, ExplainState *es);
56+
57+
#endif

0 commit comments

Comments
 (0)