21
21
*--------------------------------------------------------------------------------------------------
22
22
*/
23
23
24
-
25
24
#include "postgres.h"
26
25
27
26
#include "utils/builtins.h"
32
31
static HTAB * yb_enum_label_assignment_map = NULL ;
33
32
static bool yb_enum_label_assignment_exists = false;
34
33
35
- static HTAB * yb_sequence_oid_assignment_map = NULL ;
34
+ static HTAB * yb_oid_assignment_map = NULL ;
35
+ static bool yb_type_oid_assignment_exists = false;
36
36
static bool yb_sequence_oid_assignment_exists = false;
37
37
38
38
/*
@@ -66,12 +66,6 @@ YbClearEnumLabelMap(void)
66
66
static void
67
67
YbCreateEnumLabelMapKey (Oid enum_oid , const char * label , char * key_buffer )
68
68
{
69
- /*
70
- * For now ignore enum OID field. See YbLookupOidAssignmentForEnumLabel
71
- * for why.
72
- */
73
- enum_oid = 42 ;
74
-
75
69
int written_bytes = snprintf (key_buffer ,
76
70
YB_ENUM_LABEL_ASSIGNMENT_MAP_KEY_SIZE , "%u.%s" ,
77
71
enum_oid , label );
@@ -114,74 +108,78 @@ YbLookupOidForEnumLabel(Oid enum_oid, const char *label)
114
108
return InvalidOid ;
115
109
}
116
110
111
+ #define YB_OID_KIND_TYPE "type"
112
+ #define YB_OID_KIND_SEQUENCE "sequence"
113
+
117
114
/*
118
- * yb_sequence_oid_assignment_map key format is <schema>.<name>\0
115
+ * yb_oid_assignment_map key format is <oid_kind>.<schema>.<name>\0
116
+ * <oid_kind>\0 is guaranteed to fit in 20 characters.
119
117
* <identifier>\0 is guaranteed to fit in NAMEDATALEN characters.
120
118
*/
121
- #define YB_SEQUENCE_OID_ASSIGNMENT_MAP_KEY_SIZE ( NAMEDATALEN + NAMEDATALEN)
119
+ #define YB_OID_ASSIGNMENT_MAP_KEY_SIZE (20 + NAMEDATALEN + NAMEDATALEN)
122
120
123
- typedef struct YbSequenceOidAssignmentMapEntry {
124
- /* encodes schema, name */
125
- char key [YB_SEQUENCE_OID_ASSIGNMENT_MAP_KEY_SIZE ];
121
+ typedef struct YbOidAssignmentMapEntry {
122
+ /* encodes oid_kind, schema, name */
123
+ char key [YB_OID_ASSIGNMENT_MAP_KEY_SIZE ];
126
124
Oid oid ;
127
- } YbSequenceOidAssignmentMapEntry ;
125
+ } YbOidAssignmentMapEntry ;
128
126
129
127
static void
130
- YbClearSequenceOidMap (void )
128
+ YbClearOidMap (void )
131
129
{
132
130
HASHCTL ctl ;
133
131
134
- if (yb_sequence_oid_assignment_map != NULL )
135
- hash_destroy (yb_sequence_oid_assignment_map );
132
+ if (yb_oid_assignment_map != NULL )
133
+ hash_destroy (yb_oid_assignment_map );
136
134
memset (& ctl , 0 , sizeof (ctl ));
137
- ctl .keysize = YB_SEQUENCE_OID_ASSIGNMENT_MAP_KEY_SIZE ;
138
- ctl .entrysize = sizeof (YbSequenceOidAssignmentMapEntry );
139
- yb_sequence_oid_assignment_map = hash_create ("YB sequence OIDs map" ,
140
- /* initial size */ 20 , & ctl ,
141
- HASH_ELEM | HASH_STRINGS );
135
+ ctl .keysize = YB_OID_ASSIGNMENT_MAP_KEY_SIZE ;
136
+ ctl .entrysize = sizeof (YbOidAssignmentMapEntry );
137
+ yb_oid_assignment_map = hash_create ("YB OIDs map" ,
138
+ /* initial size */ 20 , & ctl ,
139
+ HASH_ELEM | HASH_STRINGS );
142
140
}
143
141
144
142
static void
145
- YbCreateSequenceOidMapKey (const char * schema , const char * name , char * key_buffer )
143
+ YbCreateOidMapKey (const char * oid_kind , const char * schema , const char * name ,
144
+ char * key_buffer )
146
145
{
147
- int written_bytes = snprintf (key_buffer ,
148
- YB_SEQUENCE_OID_ASSIGNMENT_MAP_KEY_SIZE ,
149
- "%s.%s" , schema , name );
150
- if (written_bytes >= YB_SEQUENCE_OID_ASSIGNMENT_MAP_KEY_SIZE )
146
+ int written_bytes = snprintf (key_buffer , YB_OID_ASSIGNMENT_MAP_KEY_SIZE ,
147
+ "%s.%s.%s" , oid_kind , schema , name );
148
+ if (written_bytes >= YB_OID_ASSIGNMENT_MAP_KEY_SIZE )
151
149
elog (ERROR ,
152
150
"unexpectedly large schema/name in OID assignment (schema '%s', "
153
151
"name '%s')" ,
154
152
schema , name );
155
153
}
156
154
157
155
static void
158
- YbInsertSequenceOid (const char * schema , const char * name , Oid sequence_oid )
156
+ YbInsertOid (const char * oid_kind , const char * schema , const char * name , Oid oid )
159
157
{
160
- char key [YB_SEQUENCE_OID_ASSIGNMENT_MAP_KEY_SIZE ];
161
- YbCreateSequenceOidMapKey ( schema , name , key );
158
+ char key [YB_OID_ASSIGNMENT_MAP_KEY_SIZE ];
159
+ YbCreateOidMapKey ( oid_kind , schema , name , key );
162
160
163
161
bool found ;
164
- YbSequenceOidAssignmentMapEntry * entry =
165
- hash_search (yb_sequence_oid_assignment_map , key , HASH_ENTER , & found );
162
+ YbOidAssignmentMapEntry * entry =
163
+ hash_search (yb_oid_assignment_map , key , HASH_ENTER , & found );
166
164
if (!found )
167
- entry -> oid = sequence_oid ;
168
- else if (entry -> oid != sequence_oid )
165
+ entry -> oid = oid ;
166
+ else if (entry -> oid != oid )
169
167
elog (ERROR ,
170
- "attempt to provide multiple OIDs for sequence %s.%s: %u vs "
168
+ "attempt to provide multiple OIDs for %s %s.%s: %u vs "
171
169
"%u" ,
172
- schema , name , entry -> oid , sequence_oid );
170
+ oid_kind , schema , name , entry -> oid , oid );
173
171
}
174
172
175
173
/* Returns InvalidOid on not found. */
176
174
static Oid
177
- YbLookupOidForSequence ( const char * schema , const char * name )
175
+ YbLookupOid ( const char * oid_kind , const char * schema , const char * name )
178
176
{
179
- char key [YB_SEQUENCE_OID_ASSIGNMENT_MAP_KEY_SIZE ];
180
- YbCreateSequenceOidMapKey ( schema , name , key );
177
+ char key [YB_OID_ASSIGNMENT_MAP_KEY_SIZE ];
178
+ YbCreateOidMapKey ( oid_kind , schema , name , key );
181
179
182
180
bool found ;
183
- YbSequenceOidAssignmentMapEntry * entry =
184
- hash_search (yb_sequence_oid_assignment_map , key , HASH_FIND , & found );
181
+ YbOidAssignmentMapEntry * entry =
182
+ hash_search (yb_oid_assignment_map , key , HASH_FIND , & found );
185
183
if (found )
186
184
return entry -> oid ;
187
185
return InvalidOid ;
@@ -201,6 +199,76 @@ YbGetOidFromText(const text *input)
201
199
return result ;
202
200
}
203
201
202
+ static void
203
+ YbExtractEnumLabelMap (text * json_text , char * map_key , bool * found )
204
+ {
205
+ text * map_json = json_get_value (json_text , map_key );
206
+ if (!map_json )
207
+ {
208
+ * found = false;
209
+ return ;
210
+ }
211
+ * found = true;
212
+
213
+ int length = get_json_array_length (map_json );
214
+ for (int i = 0 ; i < length ; i ++ )
215
+ {
216
+ text * label_info_entry = get_json_array_element (map_json , i );
217
+ char * label = text_to_cstring (json_get_denormalized_value (label_info_entry ,
218
+ "label" ));
219
+ text * label_oid_text = json_get_value (label_info_entry ,
220
+ "label_oid" );
221
+ text * enum_oid_text = json_get_value (label_info_entry ,
222
+ "enum_oid" );
223
+
224
+ Oid label_oid = YbGetOidFromText (label_oid_text );
225
+ Oid enum_oid = YbGetOidFromText (enum_oid_text );
226
+ if (label_oid == InvalidOid || enum_oid == InvalidOid )
227
+ {
228
+ elog (ERROR ,
229
+ "invalid JSON passed to "
230
+ "yb_xcluster_set_next_oid_assignments: '%s'" ,
231
+ text_to_cstring (json_text ));
232
+ }
233
+
234
+ YbInsertEnumLabel (enum_oid , label , label_oid );
235
+ }
236
+ }
237
+
238
+ static void
239
+ YbExtractNameToOidMap (text * json_text , char * map_key , const char * oid_kind ,
240
+ bool * found )
241
+ {
242
+ text * map_json = json_get_value (json_text , map_key );
243
+ if (!map_json )
244
+ {
245
+ * found = false;
246
+ return ;
247
+ }
248
+ * found = true;
249
+
250
+ int length = get_json_array_length (map_json );
251
+ for (int i = 0 ; i < length ; i ++ )
252
+ {
253
+ text * type_info_entry = get_json_array_element (map_json , i );
254
+ char * schema = text_to_cstring (json_get_denormalized_value (type_info_entry ,
255
+ "schema" ));
256
+ char * name = text_to_cstring (json_get_denormalized_value (type_info_entry ,
257
+ "name" ));
258
+ text * oid_text = json_get_value (type_info_entry , "oid" );
259
+ Oid oid = YbGetOidFromText (oid_text );
260
+ if (oid == InvalidOid )
261
+ {
262
+ elog (ERROR ,
263
+ "invalid JSON passed to "
264
+ "yb_xcluster_set_next_oid_assignments: '%s'" ,
265
+ text_to_cstring (json_text ));
266
+ }
267
+
268
+ YbInsertOid (oid_kind , schema , name , oid );
269
+ }
270
+ }
271
+
204
272
PG_FUNCTION_INFO_V1 (yb_xcluster_set_next_oid_assignments );
205
273
206
274
/*
@@ -231,6 +299,24 @@ PG_FUNCTION_INFO_V1(yb_xcluster_set_next_oid_assignments);
231
299
*
232
300
* Example:
233
301
* SELECT pg_catalog.yb_xcluster_set_next_oid_assignments(
302
+ * '{"type_info":[' ||
303
+ * '{"schema":"public","name":"my_range","oid":16406}' ||
304
+ * ']}');
305
+ *
306
+ * This indicates that the type named my_range in schema public should
307
+ * be assigned the OID 16406.
308
+ *
309
+ * The type_info key is optional; if it is present then all types created
310
+ * directly via CREATE TYPE until the assignment is changed are expected to be
311
+ * covered by the assignment. In the example this means that if the DDL
312
+ * attempts to create a range not_my_range then an error will occur. It is
313
+ * not an error if the DDL does not create all the types mentioned in the
314
+ * assignment. Multi-ranges are not covered here as they are not directly
315
+ * created via CREATE TYPE.
316
+ *
317
+ *
318
+ * Example:
319
+ * SELECT pg_catalog.yb_xcluster_set_next_oid_assignments(
234
320
* '{"sequence_info":[' ||
235
321
* '{"schema":"public","name":"my_sequence","oid":16406}' ||
236
322
* ']}');
@@ -263,62 +349,14 @@ yb_xcluster_set_next_oid_assignments(PG_FUNCTION_ARGS)
263
349
text * json_text = PG_GETARG_TEXT_P (0 );
264
350
265
351
YbClearEnumLabelMap ();
266
- yb_enum_label_assignment_exists = false;
267
- text * enum_label_info = json_get_value (json_text , "enum_label_info" );
268
- if (enum_label_info != NULL )
269
- {
270
- yb_enum_label_assignment_exists = true;
271
- int length = get_json_array_length (enum_label_info );
272
- for (int i = 0 ; i < length ; i ++ )
273
- {
274
- text * label_info_entry = get_json_array_element (enum_label_info , i );
275
- char * label = text_to_cstring (json_get_denormalized_value (label_info_entry , "label" ));
276
- text * label_oid_text = json_get_value (label_info_entry ,
277
- "label_oid" );
278
- text * enum_oid_text = json_get_value (label_info_entry ,
279
- "enum_oid" );
280
-
281
- Oid label_oid = YbGetOidFromText (label_oid_text );
282
- Oid enum_oid = YbGetOidFromText (enum_oid_text );
283
- if (label_oid == InvalidOid || enum_oid == InvalidOid )
284
- {
285
- elog (ERROR ,
286
- "corrupted JSON passed to "
287
- "yb_xcluster_set_next_oid_assignments: '%s'" ,
288
- text_to_cstring (json_text ));
289
- }
290
-
291
- YbInsertEnumLabel (enum_oid , label , label_oid );
292
- }
293
- }
352
+ YbExtractEnumLabelMap (json_text , "enum_label_info" ,
353
+ & yb_enum_label_assignment_exists );
294
354
295
- YbClearSequenceOidMap ();
296
- yb_sequence_oid_assignment_exists = false;
297
- text * sequence_info = json_get_value (json_text , "sequence_info" );
298
- if (sequence_info != NULL )
299
- {
300
- yb_sequence_oid_assignment_exists = true;
301
- int length = get_json_array_length (sequence_info );
302
- for (int i = 0 ; i < length ; i ++ )
303
- {
304
- text * sequence_info_entry = get_json_array_element (sequence_info , i );
305
- char * schema = text_to_cstring (json_get_denormalized_value (sequence_info_entry ,
306
- "schema" ));
307
- char * name = text_to_cstring (json_get_denormalized_value (sequence_info_entry ,
308
- "name" ));
309
- text * oid_text = json_get_value (sequence_info_entry , "oid" );
310
- Oid sequence_oid = YbGetOidFromText (oid_text );
311
- if (sequence_oid == InvalidOid )
312
- {
313
- elog (ERROR ,
314
- "corrupted JSON passed to "
315
- "yb_xcluster_set_next_oid_assignments: '%s'" ,
316
- text_to_cstring (json_text ));
317
- }
318
-
319
- YbInsertSequenceOid (schema , name , sequence_oid );
320
- }
321
- }
355
+ YbClearOidMap ();
356
+ YbExtractNameToOidMap (json_text , "type_info" , YB_OID_KIND_TYPE ,
357
+ & yb_type_oid_assignment_exists );
358
+ YbExtractNameToOidMap (json_text , "sequence_info" , YB_OID_KIND_SEQUENCE ,
359
+ & yb_sequence_oid_assignment_exists );
322
360
323
361
PG_RETURN_VOID ();
324
362
}
@@ -332,24 +370,29 @@ YbUsingEnumLabelOidAssignment(void)
332
370
Oid
333
371
YbLookupOidAssignmentForEnumLabel (Oid enum_oid , const char * label )
334
372
{
335
- /*----------
336
- * Currently we do not ensure that enums have the same *pg_type*
337
- * OIDs. We will fix that later, but in the meantime we take
338
- * advantage of the fact that we currently never have a
339
- * replicating DDL that refers to two different enums to ignore
340
- * the actual enum OID field when comparing labels.
341
- *
342
- * See YbCreateEnumLabelMapKey for the temporary code to ignore the enum
343
- * OID field.
344
- *----------
345
- */
346
373
Oid label_oid = YbLookupOidForEnumLabel (enum_oid , label );
347
374
if (label_oid == InvalidOid )
348
375
elog (ERROR , "no OID assignment for enum label %u.%s in OID assignment" ,
349
376
enum_oid , label );
350
377
return label_oid ;
351
378
}
352
379
380
+ bool
381
+ YbUsingTypeOidAssignment (void )
382
+ {
383
+ return yb_type_oid_assignment_exists ;
384
+ }
385
+
386
+ Oid
387
+ YbLookupOidAssignmentForType (const char * schema , const char * name )
388
+ {
389
+ Oid type_oid = YbLookupOid (YB_OID_KIND_TYPE , schema , name );
390
+ if (type_oid == InvalidOid )
391
+ elog (ERROR , "no OID assignment for type %s.%s in OID assignment" ,
392
+ schema , name );
393
+ return type_oid ;
394
+ }
395
+
353
396
bool
354
397
YbUsingSequenceOidAssignment (void )
355
398
{
@@ -359,7 +402,7 @@ YbUsingSequenceOidAssignment(void)
359
402
Oid
360
403
YbLookupOidAssignmentForSequence (const char * schema , const char * name )
361
404
{
362
- Oid sequence_oid = YbLookupOidForSequence ( schema , name );
405
+ Oid sequence_oid = YbLookupOid ( YB_OID_KIND_SEQUENCE , schema , name );
363
406
if (sequence_oid == InvalidOid )
364
407
elog (ERROR , "no OID assignment for sequence %s.%s in OID assignment" ,
365
408
schema , name );
0 commit comments