PostgreSQL Source Code git master
enum.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * enum.c
4 * I/O functions, operators, aggregates etc for enum types
5 *
6 * Copyright (c) 2006-2025, PostgreSQL Global Development Group
7 *
8 *
9 * IDENTIFICATION
10 * src/backend/utils/adt/enum.c
11 *
12 *-------------------------------------------------------------------------
13 */
14#include "postgres.h"
15
16#include "access/genam.h"
17#include "access/htup_details.h"
18#include "access/table.h"
19#include "catalog/pg_enum.h"
20#include "libpq/pqformat.h"
21#include "storage/procarray.h"
22#include "utils/array.h"
23#include "utils/builtins.h"
24#include "utils/fmgroids.h"
25#include "utils/syscache.h"
26#include "utils/typcache.h"
27
28
29static Oid enum_endpoint(Oid enumtypoid, ScanDirection direction);
30static ArrayType *enum_range_internal(Oid enumtypoid, Oid lower, Oid upper);
31
32
33/*
34 * Disallow use of an uncommitted pg_enum tuple.
35 *
36 * We need to make sure that uncommitted enum values don't get into indexes.
37 * If they did, and if we then rolled back the pg_enum addition, we'd have
38 * broken the index because value comparisons will not work reliably without
39 * an underlying pg_enum entry. (Note that removal of the heap entry
40 * containing an enum value is not sufficient to ensure that it doesn't appear
41 * in upper levels of indexes.) To do this we prevent an uncommitted row from
42 * being used for any SQL-level purpose. This is stronger than necessary,
43 * since the value might not be getting inserted into a table or there might
44 * be no index on its column, but it's easy to enforce centrally.
45 *
46 * However, it's okay to allow use of uncommitted values belonging to enum
47 * types that were themselves created in the same transaction, because then
48 * any such index would also be new and would go away altogether on rollback.
49 * We don't implement that fully right now, but we do allow free use of enum
50 * values created during CREATE TYPE AS ENUM, which are surely of the same
51 * lifespan as the enum type. (This case is required by "pg_restore -1".)
52 * Values added by ALTER TYPE ADD VALUE are also allowed if the enum type
53 * is known to have been created earlier in the same transaction. (Note that
54 * we have to track that explicitly; comparing tuple xmins is insufficient,
55 * because the type tuple might have been updated in the current transaction.
56 * Subtransactions also create hazards to be accounted for; currently,
57 * pg_enum.c only handles ADD VALUE at the outermost transaction level.)
58 *
59 * This function needs to be called (directly or indirectly) in any of the
60 * functions below that could return an enum value to SQL operations.
61 */
62static void
64{
65 TransactionId xmin;
66 Form_pg_enum en = (Form_pg_enum) GETSTRUCT(enumval_tup);
67
68 /*
69 * If the row is hinted as committed, it's surely safe. This provides a
70 * fast path for all normal use-cases.
71 */
72 if (HeapTupleHeaderXminCommitted(enumval_tup->t_data))
73 return;
74
75 /*
76 * Usually, a row would get hinted as committed when it's read or loaded
77 * into syscache; but just in case not, let's check the xmin directly.
78 */
79 xmin = HeapTupleHeaderGetXmin(enumval_tup->t_data);
80 if (!TransactionIdIsInProgress(xmin) &&
82 return;
83
84 /*
85 * Check if the enum value is listed as uncommitted. If not, it's safe,
86 * because it can't be shorter-lived than its owning type. (This'd also
87 * be false for values made by other transactions; but the previous tests
88 * should have handled all of those.)
89 */
90 if (!EnumUncommitted(en->oid))
91 return;
92
93 /*
94 * There might well be other tests we could do here to narrow down the
95 * unsafe conditions, but for now just raise an exception.
96 */
98 (errcode(ERRCODE_UNSAFE_NEW_ENUM_VALUE_USAGE),
99 errmsg("unsafe use of new value \"%s\" of enum type %s",
100 NameStr(en->enumlabel),
101 format_type_be(en->enumtypid)),
102 errhint("New enum values must be committed before they can be used.")));
103}
104
105
106/* Basic I/O support */
107
108Datum
110{
111 char *name = PG_GETARG_CSTRING(0);
112 Oid enumtypoid = PG_GETARG_OID(1);
113 Node *escontext = fcinfo->context;
114 Oid enumoid;
115 HeapTuple tup;
116
117 /* must check length to prevent Assert failure within SearchSysCache */
118 if (strlen(name) >= NAMEDATALEN)
119 ereturn(escontext, (Datum) 0,
120 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
121 errmsg("invalid input value for enum %s: \"%s\"",
122 format_type_be(enumtypoid),
123 name)));
124
125 tup = SearchSysCache2(ENUMTYPOIDNAME,
126 ObjectIdGetDatum(enumtypoid),
128 if (!HeapTupleIsValid(tup))
129 ereturn(escontext, (Datum) 0,
130 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
131 errmsg("invalid input value for enum %s: \"%s\"",
132 format_type_be(enumtypoid),
133 name)));
134
135 /*
136 * Check it's safe to use in SQL. Perhaps we should take the trouble to
137 * report "unsafe use" softly; but it's unclear that it's worth the
138 * trouble, or indeed that that is a legitimate bad-input case at all
139 * rather than an implementation shortcoming.
140 */
142
143 /*
144 * This comes from pg_enum.oid and stores system oids in user tables. This
145 * oid must be preserved by binary upgrades.
146 */
147 enumoid = ((Form_pg_enum) GETSTRUCT(tup))->oid;
148
149 ReleaseSysCache(tup);
150
151 PG_RETURN_OID(enumoid);
152}
153
154Datum
156{
157 Oid enumval = PG_GETARG_OID(0);
158 char *result;
159 HeapTuple tup;
160 Form_pg_enum en;
161
162 tup = SearchSysCache1(ENUMOID, ObjectIdGetDatum(enumval));
163 if (!HeapTupleIsValid(tup))
165 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
166 errmsg("invalid internal value for enum: %u",
167 enumval)));
168 en = (Form_pg_enum) GETSTRUCT(tup);
169
170 result = pstrdup(NameStr(en->enumlabel));
171
172 ReleaseSysCache(tup);
173
174 PG_RETURN_CSTRING(result);
175}
176
177/* Binary I/O support */
178Datum
180{
182 Oid enumtypoid = PG_GETARG_OID(1);
183 Oid enumoid;
184 HeapTuple tup;
185 char *name;
186 int nbytes;
187
188 name = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
189
190 /* must check length to prevent Assert failure within SearchSysCache */
191 if (strlen(name) >= NAMEDATALEN)
193 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
194 errmsg("invalid input value for enum %s: \"%s\"",
195 format_type_be(enumtypoid),
196 name)));
197
198 tup = SearchSysCache2(ENUMTYPOIDNAME,
199 ObjectIdGetDatum(enumtypoid),
201 if (!HeapTupleIsValid(tup))
203 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
204 errmsg("invalid input value for enum %s: \"%s\"",
205 format_type_be(enumtypoid),
206 name)));
207
208 /* check it's safe to use in SQL */
210
211 enumoid = ((Form_pg_enum) GETSTRUCT(tup))->oid;
212
213 ReleaseSysCache(tup);
214
215 pfree(name);
216
217 PG_RETURN_OID(enumoid);
218}
219
220Datum
222{
223 Oid enumval = PG_GETARG_OID(0);
225 HeapTuple tup;
226 Form_pg_enum en;
227
228 tup = SearchSysCache1(ENUMOID, ObjectIdGetDatum(enumval));
229 if (!HeapTupleIsValid(tup))
231 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
232 errmsg("invalid internal value for enum: %u",
233 enumval)));
234 en = (Form_pg_enum) GETSTRUCT(tup);
235
237 pq_sendtext(&buf, NameStr(en->enumlabel), strlen(NameStr(en->enumlabel)));
238
239 ReleaseSysCache(tup);
240
242}
243
244/* Comparison functions and related */
245
246/*
247 * enum_cmp_internal is the common engine for all the visible comparison
248 * functions, except for enum_eq and enum_ne which can just check for OID
249 * equality directly.
250 */
251static int
253{
254 TypeCacheEntry *tcache;
255
256 /*
257 * We don't need the typcache except in the hopefully-uncommon case that
258 * one or both Oids are odd. This means that cursory testing of code that
259 * fails to pass flinfo to an enum comparison function might not disclose
260 * the oversight. To make such errors more obvious, Assert that we have a
261 * place to cache even when we take a fast-path exit.
262 */
263 Assert(fcinfo->flinfo != NULL);
264
265 /* Equal OIDs are equal no matter what */
266 if (arg1 == arg2)
267 return 0;
268
269 /* Fast path: even-numbered Oids are known to compare correctly */
270 if ((arg1 & 1) == 0 && (arg2 & 1) == 0)
271 {
272 if (arg1 < arg2)
273 return -1;
274 else
275 return 1;
276 }
277
278 /* Locate the typcache entry for the enum type */
279 tcache = (TypeCacheEntry *) fcinfo->flinfo->fn_extra;
280 if (tcache == NULL)
281 {
282 HeapTuple enum_tup;
283 Form_pg_enum en;
284 Oid typeoid;
285
286 /* Get the OID of the enum type containing arg1 */
287 enum_tup = SearchSysCache1(ENUMOID, ObjectIdGetDatum(arg1));
288 if (!HeapTupleIsValid(enum_tup))
290 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
291 errmsg("invalid internal value for enum: %u",
292 arg1)));
293 en = (Form_pg_enum) GETSTRUCT(enum_tup);
294 typeoid = en->enumtypid;
295 ReleaseSysCache(enum_tup);
296 /* Now locate and remember the typcache entry */
297 tcache = lookup_type_cache(typeoid, 0);
298 fcinfo->flinfo->fn_extra = tcache;
299 }
300
301 /* The remaining comparison logic is in typcache.c */
302 return compare_values_of_enum(tcache, arg1, arg2);
303}
304
305Datum
307{
308 Oid a = PG_GETARG_OID(0);
309 Oid b = PG_GETARG_OID(1);
310
311 PG_RETURN_BOOL(enum_cmp_internal(a, b, fcinfo) < 0);
312}
313
314Datum
316{
317 Oid a = PG_GETARG_OID(0);
318 Oid b = PG_GETARG_OID(1);
319
320 PG_RETURN_BOOL(enum_cmp_internal(a, b, fcinfo) <= 0);
321}
322
323Datum
325{
326 Oid a = PG_GETARG_OID(0);
327 Oid b = PG_GETARG_OID(1);
328
329 PG_RETURN_BOOL(a == b);
330}
331
332Datum
334{
335 Oid a = PG_GETARG_OID(0);
336 Oid b = PG_GETARG_OID(1);
337
338 PG_RETURN_BOOL(a != b);
339}
340
341Datum
343{
344 Oid a = PG_GETARG_OID(0);
345 Oid b = PG_GETARG_OID(1);
346
347 PG_RETURN_BOOL(enum_cmp_internal(a, b, fcinfo) >= 0);
348}
349
350Datum
352{
353 Oid a = PG_GETARG_OID(0);
354 Oid b = PG_GETARG_OID(1);
355
356 PG_RETURN_BOOL(enum_cmp_internal(a, b, fcinfo) > 0);
357}
358
359Datum
361{
362 Oid a = PG_GETARG_OID(0);
363 Oid b = PG_GETARG_OID(1);
364
365 PG_RETURN_OID(enum_cmp_internal(a, b, fcinfo) < 0 ? a : b);
366}
367
368Datum
370{
371 Oid a = PG_GETARG_OID(0);
372 Oid b = PG_GETARG_OID(1);
373
374 PG_RETURN_OID(enum_cmp_internal(a, b, fcinfo) > 0 ? a : b);
375}
376
377Datum
379{
380 Oid a = PG_GETARG_OID(0);
381 Oid b = PG_GETARG_OID(1);
382
384}
385
386/* Enum programming support functions */
387
388/*
389 * enum_endpoint: common code for enum_first/enum_last
390 */
391static Oid
392enum_endpoint(Oid enumtypoid, ScanDirection direction)
393{
394 Relation enum_rel;
395 Relation enum_idx;
396 SysScanDesc enum_scan;
397 HeapTuple enum_tuple;
398 ScanKeyData skey;
399 Oid minmax;
400
401 /*
402 * Find the first/last enum member using pg_enum_typid_sortorder_index.
403 * Note we must not use the syscache. See comments for RenumberEnumType
404 * in catalog/pg_enum.c for more info.
405 */
406 ScanKeyInit(&skey,
407 Anum_pg_enum_enumtypid,
408 BTEqualStrategyNumber, F_OIDEQ,
409 ObjectIdGetDatum(enumtypoid));
410
411 enum_rel = table_open(EnumRelationId, AccessShareLock);
412 enum_idx = index_open(EnumTypIdSortOrderIndexId, AccessShareLock);
413 enum_scan = systable_beginscan_ordered(enum_rel, enum_idx, NULL,
414 1, &skey);
415
416 enum_tuple = systable_getnext_ordered(enum_scan, direction);
417 if (HeapTupleIsValid(enum_tuple))
418 {
419 /* check it's safe to use in SQL */
420 check_safe_enum_use(enum_tuple);
421 minmax = ((Form_pg_enum) GETSTRUCT(enum_tuple))->oid;
422 }
423 else
424 {
425 /* should only happen with an empty enum */
426 minmax = InvalidOid;
427 }
428
429 systable_endscan_ordered(enum_scan);
430 index_close(enum_idx, AccessShareLock);
431 table_close(enum_rel, AccessShareLock);
432
433 return minmax;
434}
435
436Datum
438{
439 Oid enumtypoid;
440 Oid min;
441
442 /*
443 * We rely on being able to get the specific enum type from the calling
444 * expression tree. Notice that the actual value of the argument isn't
445 * examined at all; in particular it might be NULL.
446 */
447 enumtypoid = get_fn_expr_argtype(fcinfo->flinfo, 0);
448 if (enumtypoid == InvalidOid)
450 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
451 errmsg("could not determine actual enum type")));
452
453 /* Get the OID using the index */
454 min = enum_endpoint(enumtypoid, ForwardScanDirection);
455
456 if (!OidIsValid(min))
458 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
459 errmsg("enum %s contains no values",
460 format_type_be(enumtypoid))));
461
462 PG_RETURN_OID(min);
463}
464
465Datum
467{
468 Oid enumtypoid;
469 Oid max;
470
471 /*
472 * We rely on being able to get the specific enum type from the calling
473 * expression tree. Notice that the actual value of the argument isn't
474 * examined at all; in particular it might be NULL.
475 */
476 enumtypoid = get_fn_expr_argtype(fcinfo->flinfo, 0);
477 if (enumtypoid == InvalidOid)
479 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
480 errmsg("could not determine actual enum type")));
481
482 /* Get the OID using the index */
483 max = enum_endpoint(enumtypoid, BackwardScanDirection);
484
485 if (!OidIsValid(max))
487 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
488 errmsg("enum %s contains no values",
489 format_type_be(enumtypoid))));
490
491 PG_RETURN_OID(max);
492}
493
494/* 2-argument variant of enum_range */
495Datum
497{
498 Oid lower;
499 Oid upper;
500 Oid enumtypoid;
501
502 if (PG_ARGISNULL(0))
504 else
505 lower = PG_GETARG_OID(0);
506 if (PG_ARGISNULL(1))
508 else
509 upper = PG_GETARG_OID(1);
510
511 /*
512 * We rely on being able to get the specific enum type from the calling
513 * expression tree. The generic type mechanism should have ensured that
514 * both are of the same type.
515 */
516 enumtypoid = get_fn_expr_argtype(fcinfo->flinfo, 0);
517 if (enumtypoid == InvalidOid)
519 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
520 errmsg("could not determine actual enum type")));
521
523}
524
525/* 1-argument variant of enum_range */
526Datum
528{
529 Oid enumtypoid;
530
531 /*
532 * We rely on being able to get the specific enum type from the calling
533 * expression tree. Notice that the actual value of the argument isn't
534 * examined at all; in particular it might be NULL.
535 */
536 enumtypoid = get_fn_expr_argtype(fcinfo->flinfo, 0);
537 if (enumtypoid == InvalidOid)
539 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
540 errmsg("could not determine actual enum type")));
541
544}
545
546static ArrayType *
548{
549 ArrayType *result;
550 Relation enum_rel;
551 Relation enum_idx;
552 SysScanDesc enum_scan;
553 HeapTuple enum_tuple;
554 ScanKeyData skey;
555 Datum *elems;
556 int max,
557 cnt;
558 bool left_found;
559
560 /*
561 * Scan the enum members in order using pg_enum_typid_sortorder_index.
562 * Note we must not use the syscache. See comments for RenumberEnumType
563 * in catalog/pg_enum.c for more info.
564 */
565 ScanKeyInit(&skey,
566 Anum_pg_enum_enumtypid,
567 BTEqualStrategyNumber, F_OIDEQ,
568 ObjectIdGetDatum(enumtypoid));
569
570 enum_rel = table_open(EnumRelationId, AccessShareLock);
571 enum_idx = index_open(EnumTypIdSortOrderIndexId, AccessShareLock);
572 enum_scan = systable_beginscan_ordered(enum_rel, enum_idx, NULL, 1, &skey);
573
574 max = 64;
575 elems = (Datum *) palloc(max * sizeof(Datum));
576 cnt = 0;
577 left_found = !OidIsValid(lower);
578
579 while (HeapTupleIsValid(enum_tuple = systable_getnext_ordered(enum_scan, ForwardScanDirection)))
580 {
581 Oid enum_oid = ((Form_pg_enum) GETSTRUCT(enum_tuple))->oid;
582
583 if (!left_found && lower == enum_oid)
584 left_found = true;
585
586 if (left_found)
587 {
588 /* check it's safe to use in SQL */
589 check_safe_enum_use(enum_tuple);
590
591 if (cnt >= max)
592 {
593 max *= 2;
594 elems = (Datum *) repalloc(elems, max * sizeof(Datum));
595 }
596
597 elems[cnt++] = ObjectIdGetDatum(enum_oid);
598 }
599
600 if (OidIsValid(upper) && upper == enum_oid)
601 break;
602 }
603
604 systable_endscan_ordered(enum_scan);
605 index_close(enum_idx, AccessShareLock);
606 table_close(enum_rel, AccessShareLock);
607
608 /* and build the result array */
609 /* note this hardwires some details about the representation of Oid */
610 result = construct_array(elems, cnt, enumtypoid,
611 sizeof(Oid), true, TYPALIGN_INT);
612
613 pfree(elems);
614
615 return result;
616}
#define PG_RETURN_ARRAYTYPE_P(x)
Definition: array.h:265
ArrayType * construct_array(Datum *elems, int nelems, Oid elmtype, int elmlen, bool elmbyval, char elmalign)
Definition: arrayfuncs.c:3361
#define NameStr(name)
Definition: c.h:703
#define Assert(condition)
Definition: c.h:815
uint32 TransactionId
Definition: c.h:609
#define OidIsValid(objectId)
Definition: c.h:732
int errhint(const char *fmt,...)
Definition: elog.c:1317
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ereturn(context, dummy_value,...)
Definition: elog.h:277
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
Datum enum_range_all(PG_FUNCTION_ARGS)
Definition: enum.c:527
Datum enum_last(PG_FUNCTION_ARGS)
Definition: enum.c:466
static void check_safe_enum_use(HeapTuple enumval_tup)
Definition: enum.c:63
Datum enum_gt(PG_FUNCTION_ARGS)
Definition: enum.c:351
Datum enum_first(PG_FUNCTION_ARGS)
Definition: enum.c:437
static Oid enum_endpoint(Oid enumtypoid, ScanDirection direction)
Definition: enum.c:392
Datum enum_smaller(PG_FUNCTION_ARGS)
Definition: enum.c:360
Datum enum_lt(PG_FUNCTION_ARGS)
Definition: enum.c:306
Datum enum_cmp(PG_FUNCTION_ARGS)
Definition: enum.c:378
Datum enum_eq(PG_FUNCTION_ARGS)
Definition: enum.c:324
Datum enum_range_bounds(PG_FUNCTION_ARGS)
Definition: enum.c:496
Datum enum_send(PG_FUNCTION_ARGS)
Definition: enum.c:221
static ArrayType * enum_range_internal(Oid enumtypoid, Oid lower, Oid upper)
Definition: enum.c:547
Datum enum_ge(PG_FUNCTION_ARGS)
Definition: enum.c:342
Datum enum_in(PG_FUNCTION_ARGS)
Definition: enum.c:109
Datum enum_recv(PG_FUNCTION_ARGS)
Definition: enum.c:179
static int enum_cmp_internal(Oid arg1, Oid arg2, FunctionCallInfo fcinfo)
Definition: enum.c:252
Datum enum_out(PG_FUNCTION_ARGS)
Definition: enum.c:155
Datum enum_larger(PG_FUNCTION_ARGS)
Definition: enum.c:369
Datum enum_le(PG_FUNCTION_ARGS)
Definition: enum.c:315
Datum enum_ne(PG_FUNCTION_ARGS)
Definition: enum.c:333
Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
Definition: fmgr.c:1910
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
#define PG_RETURN_BYTEA_P(x)
Definition: fmgr.h:371
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:276
#define PG_RETURN_CSTRING(x)
Definition: fmgr.h:362
#define PG_ARGISNULL(n)
Definition: fmgr.h:209
#define PG_GETARG_CSTRING(n)
Definition: fmgr.h:277
#define PG_RETURN_INT32(x)
Definition: fmgr.h:354
#define PG_RETURN_OID(x)
Definition: fmgr.h:360
#define PG_FUNCTION_ARGS
Definition: fmgr.h:193
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:359
char * format_type_be(Oid type_oid)
Definition: format_type.c:343
SysScanDesc systable_beginscan_ordered(Relation heapRelation, Relation indexRelation, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:653
void systable_endscan_ordered(SysScanDesc sysscan)
Definition: genam.c:760
HeapTuple systable_getnext_ordered(SysScanDesc sysscan, ScanDirection direction)
Definition: genam.c:735
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
static TransactionId HeapTupleHeaderGetXmin(const HeapTupleHeaderData *tup)
Definition: htup_details.h:324
static void * GETSTRUCT(const HeapTupleData *tuple)
Definition: htup_details.h:728
static bool HeapTupleHeaderXminCommitted(const HeapTupleHeaderData *tup)
Definition: htup_details.h:337
void index_close(Relation relation, LOCKMODE lockmode)
Definition: indexam.c:177
Relation index_open(Oid relationId, LOCKMODE lockmode)
Definition: indexam.c:133
int b
Definition: isn.c:69
int a
Definition: isn.c:68
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:76
#define AccessShareLock
Definition: lockdefs.h:36
char * pstrdup(const char *in)
Definition: mcxt.c:1696
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1541
void pfree(void *pointer)
Definition: mcxt.c:1521
void * palloc(Size size)
Definition: mcxt.c:1317
Datum lower(PG_FUNCTION_ARGS)
Definition: oracle_compat.c:49
Datum upper(PG_FUNCTION_ARGS)
Definition: oracle_compat.c:80
#define NAMEDATALEN
bool EnumUncommitted(Oid enum_id)
Definition: pg_enum.c:708
FormData_pg_enum * Form_pg_enum
Definition: pg_enum.h:44
static char * buf
Definition: pg_test_fsync.c:72
uintptr_t Datum
Definition: postgres.h:69
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:257
static Datum CStringGetDatum(const char *X)
Definition: postgres.h:355
#define InvalidOid
Definition: postgres_ext.h:37
unsigned int Oid
Definition: postgres_ext.h:32
void pq_sendtext(StringInfo buf, const char *str, int slen)
Definition: pqformat.c:172
char * pq_getmsgtext(StringInfo msg, int rawbytes, int *nbytes)
Definition: pqformat.c:546
void pq_begintypsend(StringInfo buf)
Definition: pqformat.c:326
bytea * pq_endtypsend(StringInfo buf)
Definition: pqformat.c:346
bool TransactionIdIsInProgress(TransactionId xid)
Definition: procarray.c:1402
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
ScanDirection
Definition: sdir.h:25
@ BackwardScanDirection
Definition: sdir.h:26
@ ForwardScanDirection
Definition: sdir.h:28
#define BTEqualStrategyNumber
Definition: stratnum.h:31
StringInfoData * StringInfo
Definition: stringinfo.h:54
void * fn_extra
Definition: fmgr.h:64
FmgrInfo * flinfo
Definition: fmgr.h:87
HeapTupleHeader t_data
Definition: htup.h:68
Definition: nodes.h:129
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:269
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:221
HeapTuple SearchSysCache2(int cacheId, Datum key1, Datum key2)
Definition: syscache.c:232
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:40
bool TransactionIdDidCommit(TransactionId transactionId)
Definition: transam.c:126
int compare_values_of_enum(TypeCacheEntry *tcache, Oid arg1, Oid arg2)
Definition: typcache.c:2650
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:386
const char * name