22
22
#include "utils/array.h"
23
23
24
24
25
+ static char * * deconstruct_text_array (Datum arr , int * num_elems );
26
+
27
+
25
28
/* Function declarations */
26
29
27
30
PG_FUNCTION_INFO_V1 ( create_hash_partitions_internal );
@@ -32,112 +35,85 @@ PG_FUNCTION_INFO_V1( get_hash_part_idx );
32
35
PG_FUNCTION_INFO_V1 ( build_hash_condition );
33
36
34
37
35
- static char * * deconstruct_text_array (Datum arr , int * num_elems );
36
-
37
-
38
38
/*
39
39
* Create HASH partitions implementation (written in C).
40
40
*/
41
41
Datum
42
42
create_hash_partitions_internal (PG_FUNCTION_ARGS )
43
43
{
44
- Oid parent_relid = PG_GETARG_OID (0 );
45
- Datum partitioned_col_name = PG_GETARG_DATUM (1 );
46
- Oid partitioned_col_type ;
47
- uint32 part_count = PG_GETARG_INT32 (2 ),
48
- i ;
49
-
50
- /* Partitions names and tablespaces */
51
- char * * names = NULL ,
52
- * * tablespaces = NULL ;
53
- int names_size = 0 ,
54
- tablespaces_size = 0 ;
55
- RangeVar * * rangevars = NULL ;
44
+ /* Free allocated arrays */
45
+ #define DeepFreeArray (arr , arr_len ) \
46
+ do { \
47
+ int arr_elem; \
48
+ if (!arr) break; \
49
+ for (arr_elem = 0; arr_elem < arr_len; arr_elem++) \
50
+ pfree(arr[arr_elem]); \
51
+ pfree(arr); \
52
+ } while (0)
53
+
54
+ Oid parent_relid = PG_GETARG_OID (0 );
55
+ const char * partitioned_col_name = TextDatumGetCString (PG_GETARG_DATUM (1 ));
56
+ Oid partitioned_col_type ;
57
+ uint32 part_count = PG_GETARG_INT32 (2 ),
58
+ i ;
59
+
60
+ /* Partition names and tablespaces */
61
+ char * * relnames = NULL ,
62
+ * * tablespaces = NULL ;
63
+ int relnames_size = 0 ,
64
+ tablespaces_size = 0 ;
65
+ RangeVar * * rangevars = NULL ;
56
66
57
67
/* Check that there's no partitions yet */
58
68
if (get_pathman_relation_info (parent_relid ))
59
69
elog (ERROR , "cannot add new HASH partitions" );
60
70
61
71
partitioned_col_type = get_attribute_type (parent_relid ,
62
- TextDatumGetCString ( partitioned_col_name ) ,
72
+ partitioned_col_name ,
63
73
false);
64
74
65
- /* Get partition names and tablespaces */
75
+ /* Extract partition names */
66
76
if (!PG_ARGISNULL (3 ))
67
- names = deconstruct_text_array (PG_GETARG_DATUM (3 ), & names_size );
77
+ relnames = deconstruct_text_array (PG_GETARG_DATUM (3 ), & relnames_size );
68
78
79
+ /* Extract partition tablespaces */
69
80
if (!PG_ARGISNULL (4 ))
70
81
tablespaces = deconstruct_text_array (PG_GETARG_DATUM (4 ), & tablespaces_size );
71
82
83
+ /* If both arrays are present, check that their lengths are equal */
84
+ if (relnames && tablespaces && relnames_size != tablespaces_size )
85
+ elog (ERROR , "sizes of arrays 'relnames' and 'tablespaces' are different" );
86
+
72
87
/* Convert partition names into RangeVars */
73
- if (names_size > 0 )
88
+ if (relnames )
74
89
{
75
- rangevars = palloc (sizeof (RangeVar ) * names_size );
76
- for (i = 0 ; i < names_size ; i ++ )
90
+ rangevars = palloc (sizeof (RangeVar ) * relnames_size );
91
+ for (i = 0 ; i < relnames_size ; i ++ )
77
92
{
78
- List * nl = stringToQualifiedNameList (names [i ]);
93
+ List * nl = stringToQualifiedNameList (relnames [i ]);
79
94
80
95
rangevars [i ] = makeRangeVarFromNameList (nl );
81
96
}
82
97
}
83
98
99
+ /* Finally create HASH partitions */
84
100
for (i = 0 ; i < part_count ; i ++ )
85
101
{
86
- RangeVar * rel = rangevars != NULL ? rangevars [i ] : NULL ;
87
- char * tablespace = tablespaces != NULL ? tablespaces [i ] : NULL ;
102
+ RangeVar * partition_rv = rangevars ? rangevars [i ] : NULL ;
103
+ char * tablespace = tablespaces ? tablespaces [i ] : NULL ;
88
104
89
105
/* Create a partition (copy FKs, invoke callbacks etc) */
90
106
create_single_hash_partition_internal (parent_relid , i , part_count ,
91
107
partitioned_col_type ,
92
- rel , tablespace );
108
+ partition_rv , tablespace );
93
109
}
94
110
95
- PG_RETURN_VOID ();
96
- }
97
-
98
- /*
99
- * Convert Datum into cstring array
100
- */
101
- static char * *
102
- deconstruct_text_array (Datum arr , int * num_elems )
103
- {
104
- ArrayType * arrayval ;
105
- int16 elemlen ;
106
- bool elembyval ;
107
- char elemalign ;
108
- Datum * elem_values ;
109
- bool * elem_nulls ;
110
- int16 i ;
111
-
112
- arrayval = DatumGetArrayTypeP (arr );
113
-
114
- Assert (ARR_ELEMTYPE (arrayval ) == TEXTOID );
115
-
116
- get_typlenbyvalalign (ARR_ELEMTYPE (arrayval ),
117
- & elemlen , & elembyval , & elemalign );
118
- deconstruct_array (arrayval ,
119
- ARR_ELEMTYPE (arrayval ),
120
- elemlen , elembyval , elemalign ,
121
- & elem_values , & elem_nulls , num_elems );
122
-
123
- /* If there are actual values then convert them into cstrings */
124
- if (num_elems > 0 )
125
- {
126
- char * * strings = palloc (sizeof (char * ) * * num_elems );
127
-
128
- for (i = 0 ; i < * num_elems ; i ++ )
129
- {
130
- if (elem_nulls [i ])
131
- elog (ERROR ,
132
- "Partition name and tablespace arrays cannot contain nulls" );
133
-
134
- strings [i ] = TextDatumGetCString (elem_values [i ]);
135
- }
136
-
137
- return strings ;
138
- }
111
+ /* Free arrays */
112
+ DeepFreeArray (relnames , relnames_size );
113
+ DeepFreeArray (tablespaces , tablespaces_size );
114
+ DeepFreeArray (rangevars , relnames_size );
139
115
140
- return NULL ;
116
+ PG_RETURN_VOID () ;
141
117
}
142
118
143
119
/*
@@ -201,3 +177,53 @@ build_hash_condition(PG_FUNCTION_ARGS)
201
177
202
178
PG_RETURN_TEXT_P (cstring_to_text (result ));
203
179
}
180
+
181
+
182
+ /*
183
+ * ------------------
184
+ * Helper functions
185
+ * ------------------
186
+ */
187
+
188
+ /* Convert Datum into CSTRING array */
189
+ static char * *
190
+ deconstruct_text_array (Datum arr , int * num_elems )
191
+ {
192
+ ArrayType * arrayval ;
193
+ int16 elemlen ;
194
+ bool elembyval ;
195
+ char elemalign ;
196
+ Datum * elem_values ;
197
+ bool * elem_nulls ;
198
+ int16 i ;
199
+
200
+ arrayval = DatumGetArrayTypeP (arr );
201
+
202
+ Assert (ARR_ELEMTYPE (arrayval ) == TEXTOID );
203
+
204
+ get_typlenbyvalalign (ARR_ELEMTYPE (arrayval ),
205
+ & elemlen , & elembyval , & elemalign );
206
+ deconstruct_array (arrayval ,
207
+ ARR_ELEMTYPE (arrayval ),
208
+ elemlen , elembyval , elemalign ,
209
+ & elem_values , & elem_nulls , num_elems );
210
+
211
+ /* If there are actual values then convert them into CSTRINGs */
212
+ if (num_elems > 0 )
213
+ {
214
+ char * * strings = palloc (sizeof (char * ) * * num_elems );
215
+
216
+ for (i = 0 ; i < * num_elems ; i ++ )
217
+ {
218
+ if (elem_nulls [i ])
219
+ elog (ERROR , "partition name and tablespace arrays "
220
+ "may not contain nulls" );
221
+
222
+ strings [i ] = TextDatumGetCString (elem_values [i ]);
223
+ }
224
+
225
+ return strings ;
226
+ }
227
+
228
+ return NULL ;
229
+ }
0 commit comments