Skip to content

Commit 5d319bd

Browse files
committed
pathman: RANGE partitioning
1 parent c723654 commit 5d319bd

File tree

7 files changed

+998
-299
lines changed

7 files changed

+998
-299
lines changed

contrib/pathman/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# contrib/pathman/Makefile
22

33
MODULE_big = pathman
4-
OBJS = pathman.o $(WIN32RES)
4+
OBJS = init.o pathman.o $(WIN32RES)
55

66
EXTENSION = pathman
77
DATA = pathman--0.1.sql

contrib/pathman/init.c

Lines changed: 288 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,288 @@
1+
#include "pathman.h"
2+
#include "executor/spi.h"
3+
#include "catalog/pg_type.h"
4+
5+
HTAB *relations = NULL;
6+
HTAB *hash_restrictions = NULL;
7+
HTAB *range_restrictions = NULL;
8+
bool initialization_needed = true;
9+
10+
/*
11+
* Initialize hashtables
12+
*/
13+
void
14+
init(void)
15+
{
16+
initialization_needed = false;
17+
load_part_relations_hashtable();
18+
// load_hash_restrictions_hashtable();
19+
// load_range_restrictions_hashtable();
20+
}
21+
22+
void
23+
load_part_relations_hashtable()
24+
{
25+
PartRelationInfo *prinfo;
26+
int ret;
27+
int i;
28+
int proc;
29+
bool isnull;
30+
List *part_oids = NIL;
31+
ListCell *lc;
32+
33+
SPI_connect();
34+
ret = SPI_exec("SELECT pg_class.relfilenode, pg_attribute.attnum, pg_pathman_rels.parttype "
35+
"FROM pg_pathman_rels "
36+
"JOIN pg_class ON pg_class.relname = pg_pathman_rels.relname "
37+
"JOIN pg_attribute ON pg_attribute.attname = pg_pathman_rels.attname "
38+
"AND attrelid = pg_class.relfilenode", 0);
39+
proc = SPI_processed;
40+
41+
if (ret > 0 && SPI_tuptable != NULL)
42+
{
43+
TupleDesc tupdesc = SPI_tuptable->tupdesc;
44+
SPITupleTable *tuptable = SPI_tuptable;
45+
46+
for (i=0; i<proc; i++)
47+
{
48+
HeapTuple tuple = tuptable->vals[i];
49+
50+
int oid = DatumGetObjectId(SPI_getbinval(tuple, tupdesc, 1, &isnull));
51+
prinfo = (PartRelationInfo*)hash_search(relations, (const void *)&oid, HASH_ENTER, NULL);
52+
prinfo->oid = oid;
53+
prinfo->attnum = DatumGetInt32(SPI_getbinval(tuple, tupdesc, 2, &isnull));
54+
prinfo->parttype = DatumGetInt32(SPI_getbinval(tuple, tupdesc, 3, &isnull));
55+
56+
part_oids = lappend_int(part_oids, oid);
57+
58+
/* children will be filled in later */
59+
// prinfo->children = NIL;
60+
}
61+
}
62+
63+
/* load children information */
64+
foreach(lc, part_oids)
65+
{
66+
Oid oid = (int) lfirst_int(lc);
67+
68+
prinfo = (PartRelationInfo*)
69+
hash_search(relations, (const void *)&oid, HASH_FIND, NULL);
70+
71+
switch(prinfo->parttype)
72+
{
73+
case PT_RANGE:
74+
load_range_restrictions(oid);
75+
break;
76+
case PT_HASH:
77+
load_hash_restrictions(oid);
78+
break;
79+
}
80+
}
81+
SPI_finish();
82+
}
83+
84+
void
85+
create_part_relations_hashtable()
86+
{
87+
HASHCTL ctl;
88+
89+
memset(&ctl, 0, sizeof(ctl));
90+
ctl.keysize = sizeof(int);
91+
ctl.entrysize = sizeof(PartRelationInfo);
92+
93+
/* already exists, recreate */
94+
if (relations != NULL)
95+
hash_destroy(relations);
96+
97+
relations = ShmemInitHash("Partitioning relation info",
98+
128, 128,
99+
&ctl, HASH_ELEM | HASH_BLOBS);
100+
}
101+
102+
void
103+
load_hash_restrictions(Oid parent_oid)
104+
{
105+
bool found;
106+
PartRelationInfo *prel;
107+
HashRelation *hashrel;
108+
HashRelationKey key;
109+
int ret;
110+
int i;
111+
int proc;
112+
bool isnull;
113+
114+
Datum vals[1];
115+
Oid oids[1] = {INT4OID};
116+
bool nulls[1] = {false};
117+
vals[0] = Int32GetDatum(parent_oid);
118+
119+
prel = (PartRelationInfo*)
120+
hash_search(relations, (const void *) &parent_oid, HASH_FIND, &found);
121+
122+
/* if already loaded then quit */
123+
if (prel->children_count > 0)
124+
return;
125+
126+
ret = SPI_execute_with_args("SELECT p.relfilenode, hr.hash, c.relfilenode "
127+
"FROM pg_pathman_hash_rels hr "
128+
"JOIN pg_class p ON p.relname = hr.parent "
129+
"JOIN pg_class c ON c.relname = hr.child "
130+
"WHERE p.relfilenode = $1",
131+
1, oids, vals, nulls, true, 0);
132+
proc = SPI_processed;
133+
134+
if (ret > 0 && SPI_tuptable != NULL)
135+
{
136+
TupleDesc tupdesc = SPI_tuptable->tupdesc;
137+
SPITupleTable *tuptable = SPI_tuptable;
138+
139+
for (i=0; i<proc; i++)
140+
{
141+
HeapTuple tuple = tuptable->vals[i];
142+
int child_oid = DatumGetObjectId(SPI_getbinval(tuple, tupdesc, 3, &isnull));
143+
144+
key.parent_oid = DatumGetObjectId(SPI_getbinval(tuple, tupdesc, 1, &isnull));
145+
key.hash = DatumGetInt32(SPI_getbinval(tuple, tupdesc, 2, &isnull));
146+
147+
hashrel = (HashRelation *)
148+
hash_search(hash_restrictions, (void *) &key, HASH_ENTER, &found);
149+
hashrel->child_oid = child_oid;
150+
151+
/* appending children to PartRelationInfo */
152+
prel->children[prel->children_count++] = child_oid;
153+
}
154+
}
155+
156+
// SPI_finish();
157+
}
158+
159+
/*
160+
* Create hash restrictions table
161+
*/
162+
void
163+
create_hash_restrictions_hashtable()
164+
{
165+
HASHCTL ctl;
166+
167+
memset(&ctl, 0, sizeof(ctl));
168+
ctl.keysize = sizeof(HashRelationKey);
169+
ctl.entrysize = sizeof(HashRelation);
170+
171+
/* already exists, recreate */
172+
if (hash_restrictions != NULL)
173+
hash_destroy(hash_restrictions);
174+
175+
hash_restrictions = ShmemInitHash("pg_pathman hash restrictions",
176+
1024, 1024,
177+
&ctl, HASH_ELEM | HASH_BLOBS);
178+
}
179+
180+
void
181+
load_range_restrictions(Oid parent_oid)
182+
{
183+
bool found;
184+
PartRelationInfo *prel;
185+
RangeRelation *rangerel;
186+
// HashRelation *hashrel;
187+
// HashRelationKey key;
188+
int ret;
189+
int i;
190+
int proc;
191+
bool arg1_isnull, arg2_isnull;
192+
193+
Datum vals[1];
194+
Oid oids[1] = {INT4OID};
195+
bool nulls[1] = {false};
196+
vals[0] = Int32GetDatum(parent_oid);
197+
198+
prel = (PartRelationInfo*)
199+
hash_search(relations, (const void *) &parent_oid, HASH_FIND, &found);
200+
201+
/* if already loaded then quit */
202+
if (prel->children_count > 0)
203+
return;
204+
205+
// SPI_connect();
206+
ret = SPI_execute_with_args("SELECT p.relfilenode, c.relfilenode, "
207+
"rr.min_int, rr.max_int, rr.min_dt, rr.max_dt "
208+
"FROM pg_pathman_range_rels rr "
209+
"JOIN pg_class p ON p.relname = rr.parent "
210+
"JOIN pg_class c ON c.relname = rr.child "
211+
"WHERE p.relfilenode = $1 "
212+
"ORDER BY rr.parent, rr.min_int, rr.min_dt",
213+
1, oids, vals, nulls, true, 0);
214+
proc = SPI_processed;
215+
216+
if (ret > 0 && SPI_tuptable != NULL)
217+
{
218+
TupleDesc tupdesc = SPI_tuptable->tupdesc;
219+
SPITupleTable *tuptable = SPI_tuptable;
220+
221+
for (i=0; i<proc; i++)
222+
{
223+
Datum min;
224+
Datum max;
225+
RangeEntry re;
226+
HeapTuple tuple = tuptable->vals[i];
227+
228+
// int parent_oid = DatumGetObjectId(SPI_getbinval(tuple, tupdesc, 1, &arg1_isnull));
229+
re.child_oid = DatumGetObjectId(SPI_getbinval(tuple, tupdesc, 2, &arg1_isnull));
230+
231+
rangerel = (RangeRelation *)
232+
hash_search(range_restrictions, (void *) &parent_oid, HASH_ENTER, &found);
233+
234+
/* date */
235+
// switch (prinfo->atttype)
236+
// {
237+
// case AT_INT:
238+
// min = SPI_getbinval(tuple, tupdesc, 3, &isnull);
239+
// max = SPI_getbinval(tuple, tupdesc, 4, &isnull);
240+
// re.min.integer = DatumGetInt32(min);
241+
// re.max.integer = DatumGetInt32(max);
242+
// break;
243+
// case AT_DATE:
244+
// min = SPI_getbinval(tuple, tupdesc, 5, &isnull);
245+
// max = SPI_getbinval(tuple, tupdesc, 6, &isnull);
246+
// re.min.date = DatumGetDateADT(min);
247+
// re.max.date = DatumGetDateADT(max);
248+
// break;
249+
// }
250+
251+
re.min = SPI_getbinval(tuple, tupdesc, 3, &arg1_isnull);
252+
re.max = SPI_getbinval(tuple, tupdesc, 4, &arg2_isnull);
253+
prel->atttype = AT_INT;
254+
255+
if (arg1_isnull || arg2_isnull)
256+
{
257+
re.min = SPI_getbinval(tuple, tupdesc, 5, &arg1_isnull);
258+
re.max = SPI_getbinval(tuple, tupdesc, 6, &arg2_isnull);
259+
prel->atttype = AT_DATE;
260+
261+
if (arg1_isnull || arg2_isnull)
262+
ereport(ERROR, (errmsg("Range relation should be of type either INTEGER or DATE")));
263+
}
264+
rangerel->ranges[rangerel->nranges++] = re;
265+
266+
prel->children[prel->children_count++] = re.child_oid;
267+
}
268+
}
269+
270+
// SPI_finish();
271+
}
272+
273+
/*
274+
* Create range restrictions table
275+
*/
276+
void
277+
create_range_restrictions_hashtable()
278+
{
279+
HASHCTL ctl;
280+
281+
memset(&ctl, 0, sizeof(ctl));
282+
ctl.keysize = sizeof(int);
283+
ctl.entrysize = sizeof(RangeRelation);
284+
285+
range_restrictions = ShmemInitHash("pg_pathman range restrictions",
286+
16, 16,
287+
&ctl, HASH_ELEM | HASH_BLOBS);
288+
}

0 commit comments

Comments
 (0)