|
3 | 3 | #include"utils/typcache.h" |
4 | 4 | #include"utils/array.h" |
5 | 5 | #include"access/nbtree.h" |
| 6 | +#include"access/xact.h" |
| 7 | +#include"catalog/pg_type.h" |
| 8 | +#include"executor/spi.h" |
6 | 9 |
|
7 | 10 |
|
8 | 11 | /* declarations */ |
9 | 12 | PG_FUNCTION_INFO_V1(on_partitions_created ); |
10 | 13 | PG_FUNCTION_INFO_V1(on_partitions_updated ); |
11 | 14 | PG_FUNCTION_INFO_V1(on_partitions_removed ); |
12 | 15 | PG_FUNCTION_INFO_V1(find_range_partition ); |
| 16 | +PG_FUNCTION_INFO_V1(find_or_create_range_partition); |
13 | 17 | PG_FUNCTION_INFO_V1(get_range_by_idx ); |
14 | 18 | PG_FUNCTION_INFO_V1(get_partition_range ); |
15 | 19 |
|
@@ -70,8 +74,52 @@ on_partitions_removed(PG_FUNCTION_ARGS) |
70 | 74 | /* |
71 | 75 | * Returns partition oid for specified parent relid and value |
72 | 76 | */ |
| 77 | +// Datum |
| 78 | +// find_range_partition(PG_FUNCTION_ARGS) |
| 79 | +// { |
| 80 | +// intrelid = DatumGetInt32(PG_GETARG_DATUM(0)); |
| 81 | +// Datumvalue = PG_GETARG_DATUM(1); |
| 82 | +// Oidvalue_type = get_fn_expr_argtype(fcinfo->flinfo, 1); |
| 83 | +// intpos; |
| 84 | +// boolfound; |
| 85 | +// RangeRelation*rangerel; |
| 86 | +// RangeEntry*ranges; |
| 87 | +// TypeCacheEntry*tce; |
| 88 | +// PartRelationInfo *prel; |
| 89 | +// Oid cmp_proc_oid; |
| 90 | +// FmgrInfo cmp_func; |
| 91 | + |
| 92 | +// tce = lookup_type_cache(value_type, |
| 93 | +// TYPECACHE_EQ_OPR | TYPECACHE_LT_OPR | TYPECACHE_GT_OPR | |
| 94 | +// TYPECACHE_CMP_PROC | TYPECACHE_CMP_PROC_FINFO); |
| 95 | + |
| 96 | +// prel = (PartRelationInfo *) |
| 97 | +// hash_search(relations, (const void *) &relid, HASH_FIND, NULL); |
| 98 | + |
| 99 | +// cmp_proc_oid = get_opfamily_proc(tce->btree_opf, |
| 100 | +// value_type, |
| 101 | +// prel->atttype, |
| 102 | +// BTORDER_PROC); |
| 103 | +// fmgr_info(cmp_proc_oid, &cmp_func); |
| 104 | + |
| 105 | +// rangerel = (RangeRelation *) |
| 106 | +// hash_search(range_restrictions, (const void *) &relid, HASH_FIND, NULL); |
| 107 | + |
| 108 | +// if (!rangerel) |
| 109 | +// PG_RETURN_NULL(); |
| 110 | + |
| 111 | +// ranges = dsm_array_get_pointer(&rangerel->ranges); |
| 112 | +// pos = range_binary_search(rangerel, &cmp_func, value, &found); |
| 113 | + |
| 114 | +// if (found) |
| 115 | +// PG_RETURN_OID(ranges[pos].child_oid); |
| 116 | + |
| 117 | +// PG_RETURN_NULL(); |
| 118 | +// } |
| 119 | + |
73 | 120 | Datum |
74 | 121 | find_range_partition(PG_FUNCTION_ARGS) |
| 122 | +// find_or_create_range_partition(PG_FUNCTION_ARGS) |
75 | 123 | { |
76 | 124 | intrelid=DatumGetInt32(PG_GETARG_DATUM(0)); |
77 | 125 | Datumvalue=PG_GETARG_DATUM(1); |
@@ -101,14 +149,67 @@ find_range_partition(PG_FUNCTION_ARGS) |
101 | 149 | rangerel= (RangeRelation*) |
102 | 150 | hash_search(range_restrictions, (constvoid*)&relid,HASH_FIND,NULL); |
103 | 151 |
|
104 | | -if (!rangerel) |
| 152 | +if (!rangerel||rangerel->ranges.length==0) |
105 | 153 | PG_RETURN_NULL(); |
106 | 154 |
|
107 | 155 | ranges=dsm_array_get_pointer(&rangerel->ranges); |
108 | 156 | pos=range_binary_search(rangerel,&cmp_func,value,&found); |
109 | 157 |
|
| 158 | +/* |
| 159 | + * If found then just return oid. Else create new partitions |
| 160 | + */ |
110 | 161 | if (found) |
111 | 162 | PG_RETURN_OID(ranges[pos].child_oid); |
| 163 | +else |
| 164 | +{ |
| 165 | +intret; |
| 166 | +Datumvals[4]; |
| 167 | +Oidoids[]= {OIDOID,value_type,value_type,value_type}; |
| 168 | +boolnulls[]= {false, false, false, false}; |
| 169 | +RangeEntry*re=&ranges[rangerel->ranges.length-1]; |
| 170 | +intcmp_upper=FunctionCall2(&cmp_func,value,ranges[rangerel->ranges.length-1].max); |
| 171 | +intcmp_lower=FunctionCall2(&cmp_func,value,ranges[0].min); |
| 172 | + |
| 173 | +if (cmp_upper>0) |
| 174 | +re=&ranges[rangerel->ranges.length-1]; |
| 175 | +elseif (cmp_lower<0) |
| 176 | +re=&ranges[0]; |
| 177 | + |
| 178 | +vals[0]=ObjectIdGetDatum(relid); |
| 179 | +vals[1]=re->min; |
| 180 | +vals[2]=re->max; |
| 181 | +vals[3]=value; |
| 182 | + |
| 183 | +LWLockAcquire(load_config_lock,LW_EXCLUSIVE); |
| 184 | + |
| 185 | +/* create new partitions */ |
| 186 | +SPI_connect(); |
| 187 | +ret=SPI_execute_with_args("select append_partitions_on_demand_internal($1, $2, $3, $4)", |
| 188 | +4,oids,vals,nulls, false,0); |
| 189 | +if (ret>0) |
| 190 | +{ |
| 191 | +free_dsm_array(&rangerel->ranges); |
| 192 | +free_dsm_array(&prel->children); |
| 193 | +load_check_constraints(relid); |
| 194 | +} |
| 195 | +else |
| 196 | +{ |
| 197 | +elog(WARNING,"Attempt to create new partitions failed"); |
| 198 | +} |
| 199 | + |
| 200 | +/* update relation info */ |
| 201 | +SPI_finish(); |
| 202 | + |
| 203 | +LWLockRelease(load_config_lock); |
| 204 | + |
| 205 | +/* repeat binary search */ |
| 206 | +ranges=dsm_array_get_pointer(&rangerel->ranges); |
| 207 | +pos=range_binary_search(rangerel,&cmp_func,value,&found); |
| 208 | +if (found) |
| 209 | +{ |
| 210 | +PG_RETURN_OID(ranges[pos].child_oid); |
| 211 | +} |
| 212 | +} |
112 | 213 |
|
113 | 214 | PG_RETURN_NULL(); |
114 | 215 | } |
|