~vcs-imports/mammoth-replicator/trunk

« back to all changes in this revision

Viewing changes to src/backend/utils/cache/lsyscache.c

  • Committer: alvherre
  • Date: 2005-12-16 21:24:52 UTC
  • Revision ID: svn-v4:db760fc0-0f08-0410-9d63-cc6633f64896:trunk:1
Initial import of the REL8_0_3 sources from the Pgsql CVS repository.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*-------------------------------------------------------------------------
 
2
 *
 
3
 * lsyscache.c
 
4
 *        Convenience routines for common queries in the system catalog cache.
 
5
 *
 
6
 * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
 
7
 * Portions Copyright (c) 1994, Regents of the University of California
 
8
 *
 
9
 * IDENTIFICATION
 
10
 *        $PostgreSQL: pgsql/src/backend/utils/cache/lsyscache.c,v 1.119 2004-12-31 22:01:25 pgsql Exp $
 
11
 *
 
12
 * NOTES
 
13
 *        Eventually, the index information should go through here, too.
 
14
 *-------------------------------------------------------------------------
 
15
 */
 
16
#include "postgres.h"
 
17
#include "miscadmin.h"
 
18
 
 
19
#include "access/hash.h"
 
20
#include "access/tupmacs.h"
 
21
#include "catalog/pg_amop.h"
 
22
#include "catalog/pg_amproc.h"
 
23
#include "catalog/pg_namespace.h"
 
24
#include "catalog/pg_opclass.h"
 
25
#include "catalog/pg_operator.h"
 
26
#include "catalog/pg_proc.h"
 
27
#include "catalog/pg_shadow.h"
 
28
#include "catalog/pg_statistic.h"
 
29
#include "catalog/pg_type.h"
 
30
#include "nodes/makefuncs.h"
 
31
#include "utils/array.h"
 
32
#include "utils/builtins.h"
 
33
#include "utils/catcache.h"
 
34
#include "utils/datum.h"
 
35
#include "utils/lsyscache.h"
 
36
#include "utils/syscache.h"
 
37
 
 
38
 
 
39
/*                              ---------- AMOP CACHES ----------                                                */
 
40
 
 
41
/*
 
42
 * op_in_opclass
 
43
 *
 
44
 *              Return t iff operator 'opno' is in operator class 'opclass'.
 
45
 */
 
46
bool
 
47
op_in_opclass(Oid opno, Oid opclass)
 
48
{
 
49
        return SearchSysCacheExists(AMOPOPID,
 
50
                                                                ObjectIdGetDatum(opno),
 
51
                                                                ObjectIdGetDatum(opclass),
 
52
                                                                0, 0);
 
53
}
 
54
 
 
55
/*
 
56
 * get_op_opclass_properties
 
57
 *
 
58
 *              Get the operator's strategy number, subtype, and recheck (lossy) flag
 
59
 *              within the specified opclass.
 
60
 *
 
61
 * Caller should already have verified that opno is a member of opclass,
 
62
 * therefore we raise an error if the tuple is not found.
 
63
 */
 
64
void
 
65
get_op_opclass_properties(Oid opno, Oid opclass,
 
66
                                                  int *strategy, Oid *subtype, bool *recheck)
 
67
{
 
68
        HeapTuple       tp;
 
69
        Form_pg_amop amop_tup;
 
70
 
 
71
        tp = SearchSysCache(AMOPOPID,
 
72
                                                ObjectIdGetDatum(opno),
 
73
                                                ObjectIdGetDatum(opclass),
 
74
                                                0, 0);
 
75
        if (!HeapTupleIsValid(tp))
 
76
                elog(ERROR, "operator %u is not a member of opclass %u",
 
77
                         opno, opclass);
 
78
        amop_tup = (Form_pg_amop) GETSTRUCT(tp);
 
79
        *strategy = amop_tup->amopstrategy;
 
80
        *subtype = amop_tup->amopsubtype;
 
81
        *recheck = amop_tup->amopreqcheck;
 
82
        ReleaseSysCache(tp);
 
83
}
 
84
 
 
85
/*
 
86
 * get_opclass_member
 
87
 *              Get the OID of the operator that implements the specified strategy
 
88
 *              with the specified subtype for the specified opclass.
 
89
 *
 
90
 * Returns InvalidOid if there is no pg_amop entry for the given keys.
 
91
 */
 
92
Oid
 
93
get_opclass_member(Oid opclass, Oid subtype, int16 strategy)
 
94
{
 
95
        HeapTuple       tp;
 
96
        Form_pg_amop amop_tup;
 
97
        Oid                     result;
 
98
 
 
99
        tp = SearchSysCache(AMOPSTRATEGY,
 
100
                                                ObjectIdGetDatum(opclass),
 
101
                                                ObjectIdGetDatum(subtype),
 
102
                                                Int16GetDatum(strategy),
 
103
                                                0);
 
104
        if (!HeapTupleIsValid(tp))
 
105
                return InvalidOid;
 
106
        amop_tup = (Form_pg_amop) GETSTRUCT(tp);
 
107
        result = amop_tup->amopopr;
 
108
        ReleaseSysCache(tp);
 
109
        return result;
 
110
}
 
111
 
 
112
/*
 
113
 * get_op_hash_function
 
114
 *              Get the OID of the datatype-specific hash function associated with
 
115
 *              a hashable equality operator.
 
116
 *
 
117
 * Returns InvalidOid if no hash function can be found.  (This indicates
 
118
 * that the operator should not have been marked oprcanhash.)
 
119
 */
 
120
Oid
 
121
get_op_hash_function(Oid opno)
 
122
{
 
123
        CatCList   *catlist;
 
124
        int                     i;
 
125
        Oid                     opclass = InvalidOid;
 
126
 
 
127
        /*
 
128
         * Search pg_amop to see if the target operator is registered as the
 
129
         * "=" operator of any hash opclass.  If the operator is registered in
 
130
         * multiple opclasses, assume we can use the associated hash function
 
131
         * from any one.
 
132
         */
 
133
        catlist = SearchSysCacheList(AMOPOPID, 1,
 
134
                                                                 ObjectIdGetDatum(opno),
 
135
                                                                 0, 0, 0);
 
136
 
 
137
        for (i = 0; i < catlist->n_members; i++)
 
138
        {
 
139
                HeapTuple       tuple = &catlist->members[i]->tuple;
 
140
                Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
 
141
 
 
142
                if (aform->amopstrategy == HTEqualStrategyNumber &&
 
143
                        opclass_is_hash(aform->amopclaid))
 
144
                {
 
145
                        opclass = aform->amopclaid;
 
146
                        break;
 
147
                }
 
148
        }
 
149
 
 
150
        ReleaseSysCacheList(catlist);
 
151
 
 
152
        if (OidIsValid(opclass))
 
153
        {
 
154
                /* Found a suitable opclass, get its default hash support function */
 
155
                return get_opclass_proc(opclass, InvalidOid, HASHPROC);
 
156
        }
 
157
 
 
158
        /* Didn't find a match... */
 
159
        return InvalidOid;
 
160
}
 
161
 
 
162
 
 
163
/*                              ---------- AMPROC CACHES ----------                                              */
 
164
 
 
165
/*
 
166
 * get_opclass_proc
 
167
 *              Get the OID of the specified support function
 
168
 *              for the specified opclass and subtype.
 
169
 *
 
170
 * Returns InvalidOid if there is no pg_amproc entry for the given keys.
 
171
 */
 
172
Oid
 
173
get_opclass_proc(Oid opclass, Oid subtype, int16 procnum)
 
174
{
 
175
        HeapTuple       tp;
 
176
        Form_pg_amproc amproc_tup;
 
177
        RegProcedure result;
 
178
 
 
179
        tp = SearchSysCache(AMPROCNUM,
 
180
                                                ObjectIdGetDatum(opclass),
 
181
                                                ObjectIdGetDatum(subtype),
 
182
                                                Int16GetDatum(procnum),
 
183
                                                0);
 
184
        if (!HeapTupleIsValid(tp))
 
185
                return InvalidOid;
 
186
        amproc_tup = (Form_pg_amproc) GETSTRUCT(tp);
 
187
        result = amproc_tup->amproc;
 
188
        ReleaseSysCache(tp);
 
189
        return result;
 
190
}
 
191
 
 
192
 
 
193
/*                              ---------- ATTRIBUTE CACHES ----------                                   */
 
194
 
 
195
/*
 
196
 * get_attname
 
197
 *              Given the relation id and the attribute number,
 
198
 *              return the "attname" field from the attribute relation.
 
199
 *
 
200
 * Note: returns a palloc'd copy of the string, or NULL if no such attribute.
 
201
 */
 
202
char *
 
203
get_attname(Oid relid, AttrNumber attnum)
 
204
{
 
205
        HeapTuple       tp;
 
206
 
 
207
        tp = SearchSysCache(ATTNUM,
 
208
                                                ObjectIdGetDatum(relid),
 
209
                                                Int16GetDatum(attnum),
 
210
                                                0, 0);
 
211
        if (HeapTupleIsValid(tp))
 
212
        {
 
213
                Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
 
214
                char       *result;
 
215
 
 
216
                result = pstrdup(NameStr(att_tup->attname));
 
217
                ReleaseSysCache(tp);
 
218
                return result;
 
219
        }
 
220
        else
 
221
                return NULL;
 
222
}
 
223
 
 
224
/*
 
225
 * get_relid_attribute_name
 
226
 *
 
227
 * Same as above routine get_attname(), except that error
 
228
 * is handled by elog() instead of returning NULL.
 
229
 */
 
230
char *
 
231
get_relid_attribute_name(Oid relid, AttrNumber attnum)
 
232
{
 
233
        char       *attname;
 
234
 
 
235
        attname = get_attname(relid, attnum);
 
236
        if (attname == NULL)
 
237
                elog(ERROR, "cache lookup failed for attribute %d of relation %u",
 
238
                         attnum, relid);
 
239
        return attname;
 
240
}
 
241
 
 
242
/*
 
243
 * get_attnum
 
244
 *
 
245
 *              Given the relation id and the attribute name,
 
246
 *              return the "attnum" field from the attribute relation.
 
247
 *
 
248
 *              Returns InvalidAttrNumber if the attr doesn't exist (or is dropped).
 
249
 */
 
250
AttrNumber
 
251
get_attnum(Oid relid, const char *attname)
 
252
{
 
253
        HeapTuple       tp;
 
254
 
 
255
        tp = SearchSysCacheAttName(relid, attname);
 
256
        if (HeapTupleIsValid(tp))
 
257
        {
 
258
                Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
 
259
                AttrNumber      result;
 
260
 
 
261
                result = att_tup->attnum;
 
262
                ReleaseSysCache(tp);
 
263
                return result;
 
264
        }
 
265
        else
 
266
                return InvalidAttrNumber;
 
267
}
 
268
 
 
269
/*
 
270
 * get_atttype
 
271
 *
 
272
 *              Given the relation OID and the attribute number with the relation,
 
273
 *              return the attribute type OID.
 
274
 */
 
275
Oid
 
276
get_atttype(Oid relid, AttrNumber attnum)
 
277
{
 
278
        HeapTuple       tp;
 
279
 
 
280
        tp = SearchSysCache(ATTNUM,
 
281
                                                ObjectIdGetDatum(relid),
 
282
                                                Int16GetDatum(attnum),
 
283
                                                0, 0);
 
284
        if (HeapTupleIsValid(tp))
 
285
        {
 
286
                Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
 
287
                Oid                     result;
 
288
 
 
289
                result = att_tup->atttypid;
 
290
                ReleaseSysCache(tp);
 
291
                return result;
 
292
        }
 
293
        else
 
294
                return InvalidOid;
 
295
}
 
296
 
 
297
/*
 
298
 * get_atttypmod
 
299
 *
 
300
 *              Given the relation id and the attribute number,
 
301
 *              return the "atttypmod" field from the attribute relation.
 
302
 */
 
303
int32
 
304
get_atttypmod(Oid relid, AttrNumber attnum)
 
305
{
 
306
        HeapTuple       tp;
 
307
 
 
308
        tp = SearchSysCache(ATTNUM,
 
309
                                                ObjectIdGetDatum(relid),
 
310
                                                Int16GetDatum(attnum),
 
311
                                                0, 0);
 
312
        if (HeapTupleIsValid(tp))
 
313
        {
 
314
                Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
 
315
                int32           result;
 
316
 
 
317
                result = att_tup->atttypmod;
 
318
                ReleaseSysCache(tp);
 
319
                return result;
 
320
        }
 
321
        else
 
322
                return -1;
 
323
}
 
324
 
 
325
/*
 
326
 * get_atttypetypmod
 
327
 *
 
328
 *              A two-fer: given the relation id and the attribute number,
 
329
 *              fetch both type OID and atttypmod in a single cache lookup.
 
330
 *
 
331
 * Unlike the otherwise-similar get_atttype/get_atttypmod, this routine
 
332
 * raises an error if it can't obtain the information.
 
333
 */
 
334
void
 
335
get_atttypetypmod(Oid relid, AttrNumber attnum,
 
336
                                  Oid *typid, int32 *typmod)
 
337
{
 
338
        HeapTuple       tp;
 
339
        Form_pg_attribute att_tup;
 
340
 
 
341
        tp = SearchSysCache(ATTNUM,
 
342
                                                ObjectIdGetDatum(relid),
 
343
                                                Int16GetDatum(attnum),
 
344
                                                0, 0);
 
345
        if (!HeapTupleIsValid(tp))
 
346
                elog(ERROR, "cache lookup failed for attribute %d of relation %u",
 
347
                         attnum, relid);
 
348
        att_tup = (Form_pg_attribute) GETSTRUCT(tp);
 
349
 
 
350
        *typid = att_tup->atttypid;
 
351
        *typmod = att_tup->atttypmod;
 
352
        ReleaseSysCache(tp);
 
353
}
 
354
 
 
355
/*                              ---------- INDEX CACHE ----------                                                */
 
356
 
 
357
/*              watch this space...
 
358
 */
 
359
 
 
360
/*                              ---------- OPCLASS CACHE ----------                                              */
 
361
 
 
362
/*
 
363
 * opclass_is_btree
 
364
 *
 
365
 *              Returns TRUE iff the specified opclass is associated with the
 
366
 *              btree index access method.
 
367
 */
 
368
bool
 
369
opclass_is_btree(Oid opclass)
 
370
{
 
371
        HeapTuple       tp;
 
372
        Form_pg_opclass cla_tup;
 
373
        bool            result;
 
374
 
 
375
        tp = SearchSysCache(CLAOID,
 
376
                                                ObjectIdGetDatum(opclass),
 
377
                                                0, 0, 0);
 
378
        if (!HeapTupleIsValid(tp))
 
379
                elog(ERROR, "cache lookup failed for opclass %u", opclass);
 
380
        cla_tup = (Form_pg_opclass) GETSTRUCT(tp);
 
381
 
 
382
        result = (cla_tup->opcamid == BTREE_AM_OID);
 
383
        ReleaseSysCache(tp);
 
384
        return result;
 
385
}
 
386
 
 
387
/*
 
388
 * opclass_is_hash
 
389
 *
 
390
 *              Returns TRUE iff the specified opclass is associated with the
 
391
 *              hash index access method.
 
392
 */
 
393
bool
 
394
opclass_is_hash(Oid opclass)
 
395
{
 
396
        HeapTuple       tp;
 
397
        Form_pg_opclass cla_tup;
 
398
        bool            result;
 
399
 
 
400
        tp = SearchSysCache(CLAOID,
 
401
                                                ObjectIdGetDatum(opclass),
 
402
                                                0, 0, 0);
 
403
        if (!HeapTupleIsValid(tp))
 
404
                elog(ERROR, "cache lookup failed for opclass %u", opclass);
 
405
        cla_tup = (Form_pg_opclass) GETSTRUCT(tp);
 
406
 
 
407
        result = (cla_tup->opcamid == HASH_AM_OID);
 
408
        ReleaseSysCache(tp);
 
409
        return result;
 
410
}
 
411
 
 
412
/*                              ---------- OPERATOR CACHE ----------                                     */
 
413
 
 
414
/*
 
415
 * get_opcode
 
416
 *
 
417
 *              Returns the regproc id of the routine used to implement an
 
418
 *              operator given the operator oid.
 
419
 */
 
420
RegProcedure
 
421
get_opcode(Oid opno)
 
422
{
 
423
        HeapTuple       tp;
 
424
 
 
425
        tp = SearchSysCache(OPEROID,
 
426
                                                ObjectIdGetDatum(opno),
 
427
                                                0, 0, 0);
 
428
        if (HeapTupleIsValid(tp))
 
429
        {
 
430
                Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
 
431
                RegProcedure result;
 
432
 
 
433
                result = optup->oprcode;
 
434
                ReleaseSysCache(tp);
 
435
                return result;
 
436
        }
 
437
        else
 
438
                return (RegProcedure) InvalidOid;
 
439
}
 
440
 
 
441
/*
 
442
 * get_opname
 
443
 *        returns the name of the operator with the given opno
 
444
 *
 
445
 * Note: returns a palloc'd copy of the string, or NULL if no such operator.
 
446
 */
 
447
char *
 
448
get_opname(Oid opno)
 
449
{
 
450
        HeapTuple       tp;
 
451
 
 
452
        tp = SearchSysCache(OPEROID,
 
453
                                                ObjectIdGetDatum(opno),
 
454
                                                0, 0, 0);
 
455
        if (HeapTupleIsValid(tp))
 
456
        {
 
457
                Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
 
458
                char       *result;
 
459
 
 
460
                result = pstrdup(NameStr(optup->oprname));
 
461
                ReleaseSysCache(tp);
 
462
                return result;
 
463
        }
 
464
        else
 
465
                return NULL;
 
466
}
 
467
 
 
468
/*
 
469
 * op_input_types
 
470
 *
 
471
 *              Returns the left and right input datatypes for an operator
 
472
 *              (InvalidOid if not relevant).
 
473
 */
 
474
void
 
475
op_input_types(Oid opno, Oid *lefttype, Oid *righttype)
 
476
{
 
477
        HeapTuple       tp;
 
478
        Form_pg_operator optup;
 
479
 
 
480
        tp = SearchSysCache(OPEROID,
 
481
                                                ObjectIdGetDatum(opno),
 
482
                                                0, 0, 0);
 
483
        if (!HeapTupleIsValid(tp))      /* shouldn't happen */
 
484
                elog(ERROR, "cache lookup failed for operator %u", opno);
 
485
        optup = (Form_pg_operator) GETSTRUCT(tp);
 
486
        *lefttype = optup->oprleft;
 
487
        *righttype = optup->oprright;
 
488
        ReleaseSysCache(tp);
 
489
}
 
490
 
 
491
/*
 
492
 * op_mergejoinable
 
493
 *
 
494
 *              Returns the left and right sort operators corresponding to a
 
495
 *              mergejoinable operator, or false if the operator is not mergejoinable.
 
496
 */
 
497
bool
 
498
op_mergejoinable(Oid opno, Oid *leftOp, Oid *rightOp)
 
499
{
 
500
        HeapTuple       tp;
 
501
        bool            result = false;
 
502
 
 
503
        tp = SearchSysCache(OPEROID,
 
504
                                                ObjectIdGetDatum(opno),
 
505
                                                0, 0, 0);
 
506
        if (HeapTupleIsValid(tp))
 
507
        {
 
508
                Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
 
509
 
 
510
                if (optup->oprlsortop &&
 
511
                        optup->oprrsortop)
 
512
                {
 
513
                        *leftOp = optup->oprlsortop;
 
514
                        *rightOp = optup->oprrsortop;
 
515
                        result = true;
 
516
                }
 
517
                ReleaseSysCache(tp);
 
518
        }
 
519
        return result;
 
520
}
 
521
 
 
522
/*
 
523
 * op_mergejoin_crossops
 
524
 *
 
525
 *              Returns the cross-type comparison operators (ltype "<" rtype and
 
526
 *              ltype ">" rtype) for an operator previously determined to be
 
527
 *              mergejoinable.  Optionally, fetches the regproc ids of these
 
528
 *              operators, as well as their operator OIDs.
 
529
 */
 
530
void
 
531
op_mergejoin_crossops(Oid opno, Oid *ltop, Oid *gtop,
 
532
                                          RegProcedure *ltproc, RegProcedure *gtproc)
 
533
{
 
534
        HeapTuple       tp;
 
535
        Form_pg_operator optup;
 
536
 
 
537
        /*
 
538
         * Get the declared comparison operators of the operator.
 
539
         */
 
540
        tp = SearchSysCache(OPEROID,
 
541
                                                ObjectIdGetDatum(opno),
 
542
                                                0, 0, 0);
 
543
        if (!HeapTupleIsValid(tp))      /* shouldn't happen */
 
544
                elog(ERROR, "cache lookup failed for operator %u", opno);
 
545
        optup = (Form_pg_operator) GETSTRUCT(tp);
 
546
        *ltop = optup->oprltcmpop;
 
547
        *gtop = optup->oprgtcmpop;
 
548
        ReleaseSysCache(tp);
 
549
 
 
550
        /* Check < op provided */
 
551
        if (!OidIsValid(*ltop))
 
552
                elog(ERROR, "mergejoin operator %u has no matching < operator",
 
553
                         opno);
 
554
        if (ltproc)
 
555
                *ltproc = get_opcode(*ltop);
 
556
 
 
557
        /* Check > op provided */
 
558
        if (!OidIsValid(*gtop))
 
559
                elog(ERROR, "mergejoin operator %u has no matching > operator",
 
560
                         opno);
 
561
        if (gtproc)
 
562
                *gtproc = get_opcode(*gtop);
 
563
}
 
564
 
 
565
/*
 
566
 * op_hashjoinable
 
567
 *
 
568
 * Returns true if the operator is hashjoinable.
 
569
 */
 
570
bool
 
571
op_hashjoinable(Oid opno)
 
572
{
 
573
        HeapTuple       tp;
 
574
        bool            result = false;
 
575
 
 
576
        tp = SearchSysCache(OPEROID,
 
577
                                                ObjectIdGetDatum(opno),
 
578
                                                0, 0, 0);
 
579
        if (HeapTupleIsValid(tp))
 
580
        {
 
581
                Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
 
582
 
 
583
                result = optup->oprcanhash;
 
584
                ReleaseSysCache(tp);
 
585
        }
 
586
        return result;
 
587
}
 
588
 
 
589
/*
 
590
 * op_strict
 
591
 *
 
592
 * Get the proisstrict flag for the operator's underlying function.
 
593
 */
 
594
bool
 
595
op_strict(Oid opno)
 
596
{
 
597
        RegProcedure funcid = get_opcode(opno);
 
598
 
 
599
        if (funcid == (RegProcedure) InvalidOid)
 
600
                elog(ERROR, "operator %u does not exist", opno);
 
601
 
 
602
        return func_strict((Oid) funcid);
 
603
}
 
604
 
 
605
/*
 
606
 * op_volatile
 
607
 *
 
608
 * Get the provolatile flag for the operator's underlying function.
 
609
 */
 
610
char
 
611
op_volatile(Oid opno)
 
612
{
 
613
        RegProcedure funcid = get_opcode(opno);
 
614
 
 
615
        if (funcid == (RegProcedure) InvalidOid)
 
616
                elog(ERROR, "operator %u does not exist", opno);
 
617
 
 
618
        return func_volatile((Oid) funcid);
 
619
}
 
620
 
 
621
/*
 
622
 * get_commutator
 
623
 *
 
624
 *              Returns the corresponding commutator of an operator.
 
625
 */
 
626
Oid
 
627
get_commutator(Oid opno)
 
628
{
 
629
        HeapTuple       tp;
 
630
 
 
631
        tp = SearchSysCache(OPEROID,
 
632
                                                ObjectIdGetDatum(opno),
 
633
                                                0, 0, 0);
 
634
        if (HeapTupleIsValid(tp))
 
635
        {
 
636
                Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
 
637
                Oid                     result;
 
638
 
 
639
                result = optup->oprcom;
 
640
                ReleaseSysCache(tp);
 
641
                return result;
 
642
        }
 
643
        else
 
644
                return InvalidOid;
 
645
}
 
646
 
 
647
/*
 
648
 * get_negator
 
649
 *
 
650
 *              Returns the corresponding negator of an operator.
 
651
 */
 
652
Oid
 
653
get_negator(Oid opno)
 
654
{
 
655
        HeapTuple       tp;
 
656
 
 
657
        tp = SearchSysCache(OPEROID,
 
658
                                                ObjectIdGetDatum(opno),
 
659
                                                0, 0, 0);
 
660
        if (HeapTupleIsValid(tp))
 
661
        {
 
662
                Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
 
663
                Oid                     result;
 
664
 
 
665
                result = optup->oprnegate;
 
666
                ReleaseSysCache(tp);
 
667
                return result;
 
668
        }
 
669
        else
 
670
                return InvalidOid;
 
671
}
 
672
 
 
673
/*
 
674
 * get_oprrest
 
675
 *
 
676
 *              Returns procedure id for computing selectivity of an operator.
 
677
 */
 
678
RegProcedure
 
679
get_oprrest(Oid opno)
 
680
{
 
681
        HeapTuple       tp;
 
682
 
 
683
        tp = SearchSysCache(OPEROID,
 
684
                                                ObjectIdGetDatum(opno),
 
685
                                                0, 0, 0);
 
686
        if (HeapTupleIsValid(tp))
 
687
        {
 
688
                Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
 
689
                RegProcedure result;
 
690
 
 
691
                result = optup->oprrest;
 
692
                ReleaseSysCache(tp);
 
693
                return result;
 
694
        }
 
695
        else
 
696
                return (RegProcedure) InvalidOid;
 
697
}
 
698
 
 
699
/*
 
700
 * get_oprjoin
 
701
 *
 
702
 *              Returns procedure id for computing selectivity of a join.
 
703
 */
 
704
RegProcedure
 
705
get_oprjoin(Oid opno)
 
706
{
 
707
        HeapTuple       tp;
 
708
 
 
709
        tp = SearchSysCache(OPEROID,
 
710
                                                ObjectIdGetDatum(opno),
 
711
                                                0, 0, 0);
 
712
        if (HeapTupleIsValid(tp))
 
713
        {
 
714
                Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp);
 
715
                RegProcedure result;
 
716
 
 
717
                result = optup->oprjoin;
 
718
                ReleaseSysCache(tp);
 
719
                return result;
 
720
        }
 
721
        else
 
722
                return (RegProcedure) InvalidOid;
 
723
}
 
724
 
 
725
/*                              ---------- FUNCTION CACHE ----------                                     */
 
726
 
 
727
/*
 
728
 * get_func_name
 
729
 *        returns the name of the function with the given funcid
 
730
 *
 
731
 * Note: returns a palloc'd copy of the string, or NULL if no such function.
 
732
 */
 
733
char *
 
734
get_func_name(Oid funcid)
 
735
{
 
736
        HeapTuple       tp;
 
737
 
 
738
        tp = SearchSysCache(PROCOID,
 
739
                                                ObjectIdGetDatum(funcid),
 
740
                                                0, 0, 0);
 
741
        if (HeapTupleIsValid(tp))
 
742
        {
 
743
                Form_pg_proc functup = (Form_pg_proc) GETSTRUCT(tp);
 
744
                char       *result;
 
745
 
 
746
                result = pstrdup(NameStr(functup->proname));
 
747
                ReleaseSysCache(tp);
 
748
                return result;
 
749
        }
 
750
        else
 
751
                return NULL;
 
752
}
 
753
 
 
754
/*
 
755
 * get_func_rettype
 
756
 *              Given procedure id, return the function's result type.
 
757
 */
 
758
Oid
 
759
get_func_rettype(Oid funcid)
 
760
{
 
761
        HeapTuple       tp;
 
762
        Oid                     result;
 
763
 
 
764
        tp = SearchSysCache(PROCOID,
 
765
                                                ObjectIdGetDatum(funcid),
 
766
                                                0, 0, 0);
 
767
        if (!HeapTupleIsValid(tp))
 
768
                elog(ERROR, "cache lookup failed for function %u", funcid);
 
769
 
 
770
        result = ((Form_pg_proc) GETSTRUCT(tp))->prorettype;
 
771
        ReleaseSysCache(tp);
 
772
        return result;
 
773
}
 
774
 
 
775
/*
 
776
 * get_func_signature
 
777
 *              Given procedure id, return the function's argument and result types.
 
778
 *              (The return value is the result type.)
 
779
 *
 
780
 * argtypes must point to a vector of size FUNC_MAX_ARGS.
 
781
 */
 
782
Oid
 
783
get_func_signature(Oid funcid, Oid *argtypes, int *nargs)
 
784
{
 
785
        HeapTuple       tp;
 
786
        Form_pg_proc procstruct;
 
787
        Oid                     result;
 
788
 
 
789
        tp = SearchSysCache(PROCOID,
 
790
                                                ObjectIdGetDatum(funcid),
 
791
                                                0, 0, 0);
 
792
        if (!HeapTupleIsValid(tp))
 
793
                elog(ERROR, "cache lookup failed for function %u", funcid);
 
794
 
 
795
        procstruct = (Form_pg_proc) GETSTRUCT(tp);
 
796
 
 
797
        result = procstruct->prorettype;
 
798
        memcpy(argtypes, procstruct->proargtypes, FUNC_MAX_ARGS * sizeof(Oid));
 
799
        *nargs = (int) procstruct->pronargs;
 
800
 
 
801
        ReleaseSysCache(tp);
 
802
        return result;
 
803
}
 
804
 
 
805
/*
 
806
 * get_func_retset
 
807
 *              Given procedure id, return the function's proretset flag.
 
808
 */
 
809
bool
 
810
get_func_retset(Oid funcid)
 
811
{
 
812
        HeapTuple       tp;
 
813
        bool            result;
 
814
 
 
815
        tp = SearchSysCache(PROCOID,
 
816
                                                ObjectIdGetDatum(funcid),
 
817
                                                0, 0, 0);
 
818
        if (!HeapTupleIsValid(tp))
 
819
                elog(ERROR, "cache lookup failed for function %u", funcid);
 
820
 
 
821
        result = ((Form_pg_proc) GETSTRUCT(tp))->proretset;
 
822
        ReleaseSysCache(tp);
 
823
        return result;
 
824
}
 
825
 
 
826
/*
 
827
 * func_strict
 
828
 *              Given procedure id, return the function's proisstrict flag.
 
829
 */
 
830
bool
 
831
func_strict(Oid funcid)
 
832
{
 
833
        HeapTuple       tp;
 
834
        bool            result;
 
835
 
 
836
        tp = SearchSysCache(PROCOID,
 
837
                                                ObjectIdGetDatum(funcid),
 
838
                                                0, 0, 0);
 
839
        if (!HeapTupleIsValid(tp))
 
840
                elog(ERROR, "cache lookup failed for function %u", funcid);
 
841
 
 
842
        result = ((Form_pg_proc) GETSTRUCT(tp))->proisstrict;
 
843
        ReleaseSysCache(tp);
 
844
        return result;
 
845
}
 
846
 
 
847
/*
 
848
 * func_volatile
 
849
 *              Given procedure id, return the function's provolatile flag.
 
850
 */
 
851
char
 
852
func_volatile(Oid funcid)
 
853
{
 
854
        HeapTuple       tp;
 
855
        char            result;
 
856
 
 
857
        tp = SearchSysCache(PROCOID,
 
858
                                                ObjectIdGetDatum(funcid),
 
859
                                                0, 0, 0);
 
860
        if (!HeapTupleIsValid(tp))
 
861
                elog(ERROR, "cache lookup failed for function %u", funcid);
 
862
 
 
863
        result = ((Form_pg_proc) GETSTRUCT(tp))->provolatile;
 
864
        ReleaseSysCache(tp);
 
865
        return result;
 
866
}
 
867
 
 
868
/*                              ---------- RELATION CACHE ----------                                     */
 
869
 
 
870
/*
 
871
 * get_relname_relid
 
872
 *              Given name and namespace of a relation, look up the OID.
 
873
 *
 
874
 * Returns InvalidOid if there is no such relation.
 
875
 */
 
876
Oid
 
877
get_relname_relid(const char *relname, Oid relnamespace)
 
878
{
 
879
        return GetSysCacheOid(RELNAMENSP,
 
880
                                                  PointerGetDatum(relname),
 
881
                                                  ObjectIdGetDatum(relnamespace),
 
882
                                                  0, 0);
 
883
}
 
884
 
 
885
/*
 
886
 * get_system_catalog_relid
 
887
 *              Get the OID of a system catalog identified by name.
 
888
 */
 
889
Oid
 
890
get_system_catalog_relid(const char *catname)
 
891
{
 
892
        Oid                     relid;
 
893
 
 
894
        relid = GetSysCacheOid(RELNAMENSP,
 
895
                                                   PointerGetDatum(catname),
 
896
                                                   ObjectIdGetDatum(PG_CATALOG_NAMESPACE),
 
897
                                                   0, 0);
 
898
        if (!OidIsValid(relid))
 
899
                elog(ERROR, "cache lookup failed for system relation %s", catname);
 
900
 
 
901
        return relid;
 
902
}
 
903
 
 
904
#ifdef NOT_USED
 
905
/*
 
906
 * get_relnatts
 
907
 *
 
908
 *              Returns the number of attributes for a given relation.
 
909
 */
 
910
int
 
911
get_relnatts(Oid relid)
 
912
{
 
913
        HeapTuple       tp;
 
914
 
 
915
        tp = SearchSysCache(RELOID,
 
916
                                                ObjectIdGetDatum(relid),
 
917
                                                0, 0, 0);
 
918
        if (HeapTupleIsValid(tp))
 
919
        {
 
920
                Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
 
921
                int                     result;
 
922
 
 
923
                result = reltup->relnatts;
 
924
                ReleaseSysCache(tp);
 
925
                return result;
 
926
        }
 
927
        else
 
928
                return InvalidAttrNumber;
 
929
}
 
930
#endif
 
931
 
 
932
/*
 
933
 * get_rel_name
 
934
 *              Returns the name of a given relation.
 
935
 *
 
936
 * Returns a palloc'd copy of the string, or NULL if no such relation.
 
937
 *
 
938
 * NOTE: since relation name is not unique, be wary of code that uses this
 
939
 * for anything except preparing error messages.
 
940
 */
 
941
char *
 
942
get_rel_name(Oid relid)
 
943
{
 
944
        HeapTuple       tp;
 
945
 
 
946
        tp = SearchSysCache(RELOID,
 
947
                                                ObjectIdGetDatum(relid),
 
948
                                                0, 0, 0);
 
949
        if (HeapTupleIsValid(tp))
 
950
        {
 
951
                Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
 
952
                char       *result;
 
953
 
 
954
                result = pstrdup(NameStr(reltup->relname));
 
955
                ReleaseSysCache(tp);
 
956
                return result;
 
957
        }
 
958
        else
 
959
                return NULL;
 
960
}
 
961
 
 
962
/*
 
963
 * get_rel_namespace
 
964
 *
 
965
 *              Returns the pg_namespace OID associated with a given relation.
 
966
 */
 
967
Oid
 
968
get_rel_namespace(Oid relid)
 
969
{
 
970
        HeapTuple       tp;
 
971
 
 
972
        tp = SearchSysCache(RELOID,
 
973
                                                ObjectIdGetDatum(relid),
 
974
                                                0, 0, 0);
 
975
        if (HeapTupleIsValid(tp))
 
976
        {
 
977
                Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
 
978
                Oid                     result;
 
979
 
 
980
                result = reltup->relnamespace;
 
981
                ReleaseSysCache(tp);
 
982
                return result;
 
983
        }
 
984
        else
 
985
                return InvalidOid;
 
986
}
 
987
 
 
988
/*
 
989
 * get_rel_type_id
 
990
 *
 
991
 *              Returns the pg_type OID associated with a given relation.
 
992
 *
 
993
 * Note: not all pg_class entries have associated pg_type OIDs; so be
 
994
 * careful to check for InvalidOid result.
 
995
 */
 
996
Oid
 
997
get_rel_type_id(Oid relid)
 
998
{
 
999
        HeapTuple       tp;
 
1000
 
 
1001
        tp = SearchSysCache(RELOID,
 
1002
                                                ObjectIdGetDatum(relid),
 
1003
                                                0, 0, 0);
 
1004
        if (HeapTupleIsValid(tp))
 
1005
        {
 
1006
                Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
 
1007
                Oid                     result;
 
1008
 
 
1009
                result = reltup->reltype;
 
1010
                ReleaseSysCache(tp);
 
1011
                return result;
 
1012
        }
 
1013
        else
 
1014
                return InvalidOid;
 
1015
}
 
1016
 
 
1017
/*
 
1018
 * get_rel_relkind
 
1019
 *
 
1020
 *              Returns the relkind associated with a given relation.
 
1021
 */
 
1022
char
 
1023
get_rel_relkind(Oid relid)
 
1024
{
 
1025
        HeapTuple       tp;
 
1026
 
 
1027
        tp = SearchSysCache(RELOID,
 
1028
                                                ObjectIdGetDatum(relid),
 
1029
                                                0, 0, 0);
 
1030
        if (HeapTupleIsValid(tp))
 
1031
        {
 
1032
                Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp);
 
1033
                char            result;
 
1034
 
 
1035
                result = reltup->relkind;
 
1036
                ReleaseSysCache(tp);
 
1037
                return result;
 
1038
        }
 
1039
        else
 
1040
                return '\0';
 
1041
}
 
1042
 
 
1043
 
 
1044
/*                              ---------- TYPE CACHE ----------                                                 */
 
1045
 
 
1046
/*
 
1047
 * get_typisdefined
 
1048
 *
 
1049
 *              Given the type OID, determine whether the type is defined
 
1050
 *              (if not, it's only a shell).
 
1051
 */
 
1052
bool
 
1053
get_typisdefined(Oid typid)
 
1054
{
 
1055
        HeapTuple       tp;
 
1056
 
 
1057
        tp = SearchSysCache(TYPEOID,
 
1058
                                                ObjectIdGetDatum(typid),
 
1059
                                                0, 0, 0);
 
1060
        if (HeapTupleIsValid(tp))
 
1061
        {
 
1062
                Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
 
1063
                bool            result;
 
1064
 
 
1065
                result = typtup->typisdefined;
 
1066
                ReleaseSysCache(tp);
 
1067
                return result;
 
1068
        }
 
1069
        else
 
1070
                return false;
 
1071
}
 
1072
 
 
1073
/*
 
1074
 * get_typlen
 
1075
 *
 
1076
 *              Given the type OID, return the length of the type.
 
1077
 */
 
1078
int16
 
1079
get_typlen(Oid typid)
 
1080
{
 
1081
        HeapTuple       tp;
 
1082
 
 
1083
        tp = SearchSysCache(TYPEOID,
 
1084
                                                ObjectIdGetDatum(typid),
 
1085
                                                0, 0, 0);
 
1086
        if (HeapTupleIsValid(tp))
 
1087
        {
 
1088
                Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
 
1089
                int16           result;
 
1090
 
 
1091
                result = typtup->typlen;
 
1092
                ReleaseSysCache(tp);
 
1093
                return result;
 
1094
        }
 
1095
        else
 
1096
                return 0;
 
1097
}
 
1098
 
 
1099
/*
 
1100
 * get_typbyval
 
1101
 *
 
1102
 *              Given the type OID, determine whether the type is returned by value or
 
1103
 *              not.  Returns true if by value, false if by reference.
 
1104
 */
 
1105
bool
 
1106
get_typbyval(Oid typid)
 
1107
{
 
1108
        HeapTuple       tp;
 
1109
 
 
1110
        tp = SearchSysCache(TYPEOID,
 
1111
                                                ObjectIdGetDatum(typid),
 
1112
                                                0, 0, 0);
 
1113
        if (HeapTupleIsValid(tp))
 
1114
        {
 
1115
                Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
 
1116
                bool            result;
 
1117
 
 
1118
                result = typtup->typbyval;
 
1119
                ReleaseSysCache(tp);
 
1120
                return result;
 
1121
        }
 
1122
        else
 
1123
                return false;
 
1124
}
 
1125
 
 
1126
/*
 
1127
 * get_typlenbyval
 
1128
 *
 
1129
 *              A two-fer: given the type OID, return both typlen and typbyval.
 
1130
 *
 
1131
 *              Since both pieces of info are needed to know how to copy a Datum,
 
1132
 *              many places need both.  Might as well get them with one cache lookup
 
1133
 *              instead of two.  Also, this routine raises an error instead of
 
1134
 *              returning a bogus value when given a bad type OID.
 
1135
 */
 
1136
void
 
1137
get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
 
1138
{
 
1139
        HeapTuple       tp;
 
1140
        Form_pg_type typtup;
 
1141
 
 
1142
        tp = SearchSysCache(TYPEOID,
 
1143
                                                ObjectIdGetDatum(typid),
 
1144
                                                0, 0, 0);
 
1145
        if (!HeapTupleIsValid(tp))
 
1146
                elog(ERROR, "cache lookup failed for type %u", typid);
 
1147
        typtup = (Form_pg_type) GETSTRUCT(tp);
 
1148
        *typlen = typtup->typlen;
 
1149
        *typbyval = typtup->typbyval;
 
1150
        ReleaseSysCache(tp);
 
1151
}
 
1152
 
 
1153
/*
 
1154
 * get_typlenbyvalalign
 
1155
 *
 
1156
 *              A three-fer: given the type OID, return typlen, typbyval, typalign.
 
1157
 */
 
1158
void
 
1159
get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval,
 
1160
                                         char *typalign)
 
1161
{
 
1162
        HeapTuple       tp;
 
1163
        Form_pg_type typtup;
 
1164
 
 
1165
        tp = SearchSysCache(TYPEOID,
 
1166
                                                ObjectIdGetDatum(typid),
 
1167
                                                0, 0, 0);
 
1168
        if (!HeapTupleIsValid(tp))
 
1169
                elog(ERROR, "cache lookup failed for type %u", typid);
 
1170
        typtup = (Form_pg_type) GETSTRUCT(tp);
 
1171
        *typlen = typtup->typlen;
 
1172
        *typbyval = typtup->typbyval;
 
1173
        *typalign = typtup->typalign;
 
1174
        ReleaseSysCache(tp);
 
1175
}
 
1176
 
 
1177
/*
 
1178
 * getTypeIOParam
 
1179
 *              Given a pg_type row, select the type OID to pass to I/O functions
 
1180
 *
 
1181
 * Formerly, all I/O functions were passed pg_type.typelem as their second
 
1182
 * parameter, but we now have a more complex rule about what to pass.
 
1183
 * This knowledge is intended to be centralized here --- direct references
 
1184
 * to typelem elsewhere in the code are wrong, if they are associated with
 
1185
 * I/O calls and not with actual subscripting operations!  (But see
 
1186
 * bootstrap.c, which can't conveniently use this routine.)
 
1187
 */
 
1188
Oid
 
1189
getTypeIOParam(HeapTuple typeTuple)
 
1190
{
 
1191
        Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTuple);
 
1192
 
 
1193
        /*
 
1194
         * Composite types get their own OID as parameter; array types get
 
1195
         * their typelem as parameter; everybody else gets zero.
 
1196
         */
 
1197
        if (typeStruct->typtype == 'c')
 
1198
                return HeapTupleGetOid(typeTuple);
 
1199
        else
 
1200
                return typeStruct->typelem;
 
1201
}
 
1202
 
 
1203
/*
 
1204
 * get_type_io_data
 
1205
 *
 
1206
 *              A six-fer:      given the type OID, return typlen, typbyval, typalign,
 
1207
 *                                      typdelim, typioparam, and IO function OID. The IO function
 
1208
 *                                      returned is controlled by IOFuncSelector
 
1209
 */
 
1210
void
 
1211
get_type_io_data(Oid typid,
 
1212
                                 IOFuncSelector which_func,
 
1213
                                 int16 *typlen,
 
1214
                                 bool *typbyval,
 
1215
                                 char *typalign,
 
1216
                                 char *typdelim,
 
1217
                                 Oid *typioparam,
 
1218
                                 Oid *func)
 
1219
{
 
1220
        HeapTuple       typeTuple;
 
1221
        Form_pg_type typeStruct;
 
1222
 
 
1223
        typeTuple = SearchSysCache(TYPEOID,
 
1224
                                                           ObjectIdGetDatum(typid),
 
1225
                                                           0, 0, 0);
 
1226
        if (!HeapTupleIsValid(typeTuple))
 
1227
                elog(ERROR, "cache lookup failed for type %u", typid);
 
1228
        typeStruct = (Form_pg_type) GETSTRUCT(typeTuple);
 
1229
 
 
1230
        *typlen = typeStruct->typlen;
 
1231
        *typbyval = typeStruct->typbyval;
 
1232
        *typalign = typeStruct->typalign;
 
1233
        *typdelim = typeStruct->typdelim;
 
1234
        *typioparam = getTypeIOParam(typeTuple);
 
1235
        switch (which_func)
 
1236
        {
 
1237
                case IOFunc_input:
 
1238
                        *func = typeStruct->typinput;
 
1239
                        break;
 
1240
                case IOFunc_output:
 
1241
                        *func = typeStruct->typoutput;
 
1242
                        break;
 
1243
                case IOFunc_receive:
 
1244
                        *func = typeStruct->typreceive;
 
1245
                        break;
 
1246
                case IOFunc_send:
 
1247
                        *func = typeStruct->typsend;
 
1248
                        break;
 
1249
        }
 
1250
        ReleaseSysCache(typeTuple);
 
1251
}
 
1252
 
 
1253
#ifdef NOT_USED
 
1254
char
 
1255
get_typalign(Oid typid)
 
1256
{
 
1257
        HeapTuple       tp;
 
1258
 
 
1259
        tp = SearchSysCache(TYPEOID,
 
1260
                                                ObjectIdGetDatum(typid),
 
1261
                                                0, 0, 0);
 
1262
        if (HeapTupleIsValid(tp))
 
1263
        {
 
1264
                Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
 
1265
                char            result;
 
1266
 
 
1267
                result = typtup->typalign;
 
1268
                ReleaseSysCache(tp);
 
1269
                return result;
 
1270
        }
 
1271
        else
 
1272
                return 'i';
 
1273
}
 
1274
#endif
 
1275
 
 
1276
char
 
1277
get_typstorage(Oid typid)
 
1278
{
 
1279
        HeapTuple       tp;
 
1280
 
 
1281
        tp = SearchSysCache(TYPEOID,
 
1282
                                                ObjectIdGetDatum(typid),
 
1283
                                                0, 0, 0);
 
1284
        if (HeapTupleIsValid(tp))
 
1285
        {
 
1286
                Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
 
1287
                char            result;
 
1288
 
 
1289
                result = typtup->typstorage;
 
1290
                ReleaseSysCache(tp);
 
1291
                return result;
 
1292
        }
 
1293
        else
 
1294
                return 'p';
 
1295
}
 
1296
 
 
1297
/*
 
1298
 * get_typtypmod
 
1299
 *
 
1300
 *              Given the type OID, return the typtypmod field (domain's typmod
 
1301
 *              for base type)
 
1302
 */
 
1303
int32
 
1304
get_typtypmod(Oid typid)
 
1305
{
 
1306
        HeapTuple       tp;
 
1307
 
 
1308
        tp = SearchSysCache(TYPEOID,
 
1309
                                                ObjectIdGetDatum(typid),
 
1310
                                                0, 0, 0);
 
1311
        if (HeapTupleIsValid(tp))
 
1312
        {
 
1313
                Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
 
1314
                int32           result;
 
1315
 
 
1316
                result = typtup->typtypmod;
 
1317
                ReleaseSysCache(tp);
 
1318
                return result;
 
1319
        }
 
1320
        else
 
1321
                return -1;
 
1322
}
 
1323
 
 
1324
/*
 
1325
 * get_typdefault
 
1326
 *        Given a type OID, return the type's default value, if any.
 
1327
 *
 
1328
 *        The result is a palloc'd expression node tree, or NULL if there
 
1329
 *        is no defined default for the datatype.
 
1330
 *
 
1331
 * NB: caller should be prepared to coerce result to correct datatype;
 
1332
 * the returned expression tree might produce something of the wrong type.
 
1333
 */
 
1334
Node *
 
1335
get_typdefault(Oid typid)
 
1336
{
 
1337
        HeapTuple       typeTuple;
 
1338
        Form_pg_type type;
 
1339
        Datum           datum;
 
1340
        bool            isNull;
 
1341
        Node       *expr;
 
1342
 
 
1343
        typeTuple = SearchSysCache(TYPEOID,
 
1344
                                                           ObjectIdGetDatum(typid),
 
1345
                                                           0, 0, 0);
 
1346
        if (!HeapTupleIsValid(typeTuple))
 
1347
                elog(ERROR, "cache lookup failed for type %u", typid);
 
1348
        type = (Form_pg_type) GETSTRUCT(typeTuple);
 
1349
 
 
1350
        /*
 
1351
         * typdefault and typdefaultbin are potentially null, so don't try to
 
1352
         * access 'em as struct fields. Must do it the hard way with
 
1353
         * SysCacheGetAttr.
 
1354
         */
 
1355
        datum = SysCacheGetAttr(TYPEOID,
 
1356
                                                        typeTuple,
 
1357
                                                        Anum_pg_type_typdefaultbin,
 
1358
                                                        &isNull);
 
1359
 
 
1360
        if (!isNull)
 
1361
        {
 
1362
                /* We have an expression default */
 
1363
                expr = stringToNode(DatumGetCString(DirectFunctionCall1(textout,
 
1364
                                                                                                                                datum)));
 
1365
        }
 
1366
        else
 
1367
        {
 
1368
                /* Perhaps we have a plain literal default */
 
1369
                datum = SysCacheGetAttr(TYPEOID,
 
1370
                                                                typeTuple,
 
1371
                                                                Anum_pg_type_typdefault,
 
1372
                                                                &isNull);
 
1373
 
 
1374
                if (!isNull)
 
1375
                {
 
1376
                        char       *strDefaultVal;
 
1377
 
 
1378
                        /* Convert text datum to C string */
 
1379
                        strDefaultVal = DatumGetCString(DirectFunctionCall1(textout,
 
1380
                                                                                                                                datum));
 
1381
                        /* Convert C string to a value of the given type */
 
1382
                        datum = OidFunctionCall3(type->typinput,
 
1383
                                                                         CStringGetDatum(strDefaultVal),
 
1384
                                                         ObjectIdGetDatum(getTypeIOParam(typeTuple)),
 
1385
                                                                         Int32GetDatum(-1));
 
1386
                        /* Build a Const node containing the value */
 
1387
                        expr = (Node *) makeConst(typid,
 
1388
                                                                          type->typlen,
 
1389
                                                                          datum,
 
1390
                                                                          false,
 
1391
                                                                          type->typbyval);
 
1392
                        pfree(strDefaultVal);
 
1393
                }
 
1394
                else
 
1395
                {
 
1396
                        /* No default */
 
1397
                        expr = NULL;
 
1398
                }
 
1399
        }
 
1400
 
 
1401
        ReleaseSysCache(typeTuple);
 
1402
 
 
1403
        return expr;
 
1404
}
 
1405
 
 
1406
/*
 
1407
 * getBaseType
 
1408
 *              If the given type is a domain, return its base type;
 
1409
 *              otherwise return the type's own OID.
 
1410
 */
 
1411
Oid
 
1412
getBaseType(Oid typid)
 
1413
{
 
1414
        /*
 
1415
         * We loop to find the bottom base type in a stack of domains.
 
1416
         */
 
1417
        for (;;)
 
1418
        {
 
1419
                HeapTuple       tup;
 
1420
                Form_pg_type typTup;
 
1421
 
 
1422
                tup = SearchSysCache(TYPEOID,
 
1423
                                                         ObjectIdGetDatum(typid),
 
1424
                                                         0, 0, 0);
 
1425
                if (!HeapTupleIsValid(tup))
 
1426
                        elog(ERROR, "cache lookup failed for type %u", typid);
 
1427
                typTup = (Form_pg_type) GETSTRUCT(tup);
 
1428
                if (typTup->typtype != 'd')
 
1429
                {
 
1430
                        /* Not a domain, so done */
 
1431
                        ReleaseSysCache(tup);
 
1432
                        break;
 
1433
                }
 
1434
 
 
1435
                typid = typTup->typbasetype;
 
1436
                ReleaseSysCache(tup);
 
1437
        }
 
1438
 
 
1439
        return typid;
 
1440
}
 
1441
 
 
1442
/*
 
1443
 * get_typavgwidth
 
1444
 *
 
1445
 *        Given a type OID and a typmod value (pass -1 if typmod is unknown),
 
1446
 *        estimate the average width of values of the type.  This is used by
 
1447
 *        the planner, which doesn't require absolutely correct results;
 
1448
 *        it's OK (and expected) to guess if we don't know for sure.
 
1449
 */
 
1450
int32
 
1451
get_typavgwidth(Oid typid, int32 typmod)
 
1452
{
 
1453
        int                     typlen = get_typlen(typid);
 
1454
        int32           maxwidth;
 
1455
 
 
1456
        /*
 
1457
         * Easy if it's a fixed-width type
 
1458
         */
 
1459
        if (typlen > 0)
 
1460
                return typlen;
 
1461
 
 
1462
        /*
 
1463
         * type_maximum_size knows the encoding of typmod for some datatypes;
 
1464
         * don't duplicate that knowledge here.
 
1465
         */
 
1466
        maxwidth = type_maximum_size(typid, typmod);
 
1467
        if (maxwidth > 0)
 
1468
        {
 
1469
                /*
 
1470
                 * For BPCHAR, the max width is also the only width.  Otherwise we
 
1471
                 * need to guess about the typical data width given the max. A
 
1472
                 * sliding scale for percentage of max width seems reasonable.
 
1473
                 */
 
1474
                if (typid == BPCHAROID)
 
1475
                        return maxwidth;
 
1476
                if (maxwidth <= 32)
 
1477
                        return maxwidth;        /* assume full width */
 
1478
                if (maxwidth < 1000)
 
1479
                        return 32 + (maxwidth - 32) / 2;        /* assume 50% */
 
1480
 
 
1481
                /*
 
1482
                 * Beyond 1000, assume we're looking at something like
 
1483
                 * "varchar(10000)" where the limit isn't actually reached often,
 
1484
                 * and use a fixed estimate.
 
1485
                 */
 
1486
                return 32 + (1000 - 32) / 2;
 
1487
        }
 
1488
 
 
1489
        /*
 
1490
         * Ooops, we have no idea ... wild guess time.
 
1491
         */
 
1492
        return 32;
 
1493
}
 
1494
 
 
1495
/*
 
1496
 * get_typtype
 
1497
 *
 
1498
 *              Given the type OID, find if it is a basic type, a complex type, etc.
 
1499
 *              It returns the null char if the cache lookup fails...
 
1500
 */
 
1501
char
 
1502
get_typtype(Oid typid)
 
1503
{
 
1504
        HeapTuple       tp;
 
1505
 
 
1506
        tp = SearchSysCache(TYPEOID,
 
1507
                                                ObjectIdGetDatum(typid),
 
1508
                                                0, 0, 0);
 
1509
        if (HeapTupleIsValid(tp))
 
1510
        {
 
1511
                Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
 
1512
                char            result;
 
1513
 
 
1514
                result = typtup->typtype;
 
1515
                ReleaseSysCache(tp);
 
1516
                return result;
 
1517
        }
 
1518
        else
 
1519
                return '\0';
 
1520
}
 
1521
 
 
1522
/*
 
1523
 * get_type_func_class
 
1524
 *
 
1525
 *              Given the type OID, obtain its TYPEFUNC classification.
 
1526
 *
 
1527
 * This is intended to centralize a bunch of formerly ad-hoc code for
 
1528
 * classifying types.  The categories used here are useful for deciding
 
1529
 * how to handle functions returning the datatype.
 
1530
 */
 
1531
TypeFuncClass
 
1532
get_type_func_class(Oid typid)
 
1533
{
 
1534
        switch (get_typtype(typid))
 
1535
        {
 
1536
                case 'c':
 
1537
                        return TYPEFUNC_COMPOSITE;
 
1538
                case 'b':
 
1539
                case 'd':
 
1540
                        return TYPEFUNC_SCALAR;
 
1541
                case 'p':
 
1542
                        if (typid == RECORDOID)
 
1543
                                return TYPEFUNC_RECORD;
 
1544
                        /*
 
1545
                         * We treat VOID and CSTRING as legitimate scalar datatypes,
 
1546
                         * mostly for the convenience of the JDBC driver (which wants
 
1547
                         * to be able to do "SELECT * FROM foo()" for all legitimately
 
1548
                         * user-callable functions).
 
1549
                         */
 
1550
                        if (typid == VOIDOID || typid == CSTRINGOID)
 
1551
                                return TYPEFUNC_SCALAR;
 
1552
                        return TYPEFUNC_OTHER;
 
1553
        }
 
1554
        /* shouldn't get here, probably */
 
1555
        return TYPEFUNC_OTHER;
 
1556
}
 
1557
 
 
1558
/*
 
1559
 * get_typ_typrelid
 
1560
 *
 
1561
 *              Given the type OID, get the typrelid (InvalidOid if not a complex
 
1562
 *              type).
 
1563
 */
 
1564
Oid
 
1565
get_typ_typrelid(Oid typid)
 
1566
{
 
1567
        HeapTuple       tp;
 
1568
 
 
1569
        tp = SearchSysCache(TYPEOID,
 
1570
                                                ObjectIdGetDatum(typid),
 
1571
                                                0, 0, 0);
 
1572
        if (HeapTupleIsValid(tp))
 
1573
        {
 
1574
                Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
 
1575
                Oid                     result;
 
1576
 
 
1577
                result = typtup->typrelid;
 
1578
                ReleaseSysCache(tp);
 
1579
                return result;
 
1580
        }
 
1581
        else
 
1582
                return InvalidOid;
 
1583
}
 
1584
 
 
1585
/*
 
1586
 * get_element_type
 
1587
 *
 
1588
 *              Given the type OID, get the typelem (InvalidOid if not an array type).
 
1589
 *
 
1590
 * NB: this only considers varlena arrays to be true arrays; InvalidOid is
 
1591
 * returned if the input is a fixed-length array type.
 
1592
 */
 
1593
Oid
 
1594
get_element_type(Oid typid)
 
1595
{
 
1596
        HeapTuple       tp;
 
1597
 
 
1598
        tp = SearchSysCache(TYPEOID,
 
1599
                                                ObjectIdGetDatum(typid),
 
1600
                                                0, 0, 0);
 
1601
        if (HeapTupleIsValid(tp))
 
1602
        {
 
1603
                Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
 
1604
                Oid                     result;
 
1605
 
 
1606
                if (typtup->typlen == -1)
 
1607
                        result = typtup->typelem;
 
1608
                else
 
1609
                        result = InvalidOid;
 
1610
                ReleaseSysCache(tp);
 
1611
                return result;
 
1612
        }
 
1613
        else
 
1614
                return InvalidOid;
 
1615
}
 
1616
 
 
1617
/*
 
1618
 * get_array_type
 
1619
 *
 
1620
 *              Given the type OID, get the corresponding array type.
 
1621
 *              Returns InvalidOid if no array type can be found.
 
1622
 *
 
1623
 * NB: this only considers varlena arrays to be true arrays.
 
1624
 */
 
1625
Oid
 
1626
get_array_type(Oid typid)
 
1627
{
 
1628
        HeapTuple       tp;
 
1629
 
 
1630
        tp = SearchSysCache(TYPEOID,
 
1631
                                                ObjectIdGetDatum(typid),
 
1632
                                                0, 0, 0);
 
1633
        if (HeapTupleIsValid(tp))
 
1634
        {
 
1635
                Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
 
1636
                char       *array_typename;
 
1637
                Oid                     namespaceId;
 
1638
 
 
1639
                array_typename = makeArrayTypeName(NameStr(typtup->typname));
 
1640
                namespaceId = typtup->typnamespace;
 
1641
                ReleaseSysCache(tp);
 
1642
 
 
1643
                tp = SearchSysCache(TYPENAMENSP,
 
1644
                                                        PointerGetDatum(array_typename),
 
1645
                                                        ObjectIdGetDatum(namespaceId),
 
1646
                                                        0, 0);
 
1647
 
 
1648
                pfree(array_typename);
 
1649
 
 
1650
                if (HeapTupleIsValid(tp))
 
1651
                {
 
1652
                        Oid                     result;
 
1653
 
 
1654
                        typtup = (Form_pg_type) GETSTRUCT(tp);
 
1655
                        if (typtup->typlen == -1 && typtup->typelem == typid)
 
1656
                                result = HeapTupleGetOid(tp);
 
1657
                        else
 
1658
                                result = InvalidOid;
 
1659
                        ReleaseSysCache(tp);
 
1660
                        return result;
 
1661
                }
 
1662
        }
 
1663
        return InvalidOid;
 
1664
}
 
1665
 
 
1666
/*
 
1667
 * getTypeInputInfo
 
1668
 *
 
1669
 *              Get info needed for converting values of a type to internal form
 
1670
 */
 
1671
void
 
1672
getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)
 
1673
{
 
1674
        HeapTuple       typeTuple;
 
1675
        Form_pg_type pt;
 
1676
 
 
1677
        typeTuple = SearchSysCache(TYPEOID,
 
1678
                                                           ObjectIdGetDatum(type),
 
1679
                                                           0, 0, 0);
 
1680
        if (!HeapTupleIsValid(typeTuple))
 
1681
                elog(ERROR, "cache lookup failed for type %u", type);
 
1682
        pt = (Form_pg_type) GETSTRUCT(typeTuple);
 
1683
 
 
1684
        if (!pt->typisdefined)
 
1685
                ereport(ERROR,
 
1686
                                (errcode(ERRCODE_UNDEFINED_OBJECT),
 
1687
                                 errmsg("type %s is only a shell",
 
1688
                                                format_type_be(type))));
 
1689
        if (!OidIsValid(pt->typinput))
 
1690
                ereport(ERROR,
 
1691
                                (errcode(ERRCODE_UNDEFINED_FUNCTION),
 
1692
                                 errmsg("no input function available for type %s",
 
1693
                                                format_type_be(type))));
 
1694
 
 
1695
        *typInput = pt->typinput;
 
1696
        *typIOParam = getTypeIOParam(typeTuple);
 
1697
 
 
1698
        ReleaseSysCache(typeTuple);
 
1699
}
 
1700
 
 
1701
/*
 
1702
 * getTypeOutputInfo
 
1703
 *
 
1704
 *              Get info needed for printing values of a type
 
1705
 */
 
1706
void
 
1707
getTypeOutputInfo(Oid type, Oid *typOutput, Oid *typIOParam,
 
1708
                                  bool *typIsVarlena)
 
1709
{
 
1710
        HeapTuple       typeTuple;
 
1711
        Form_pg_type pt;
 
1712
 
 
1713
        typeTuple = SearchSysCache(TYPEOID,
 
1714
                                                           ObjectIdGetDatum(type),
 
1715
                                                           0, 0, 0);
 
1716
        if (!HeapTupleIsValid(typeTuple))
 
1717
                elog(ERROR, "cache lookup failed for type %u", type);
 
1718
        pt = (Form_pg_type) GETSTRUCT(typeTuple);
 
1719
 
 
1720
        if (!pt->typisdefined)
 
1721
                ereport(ERROR,
 
1722
                                (errcode(ERRCODE_UNDEFINED_OBJECT),
 
1723
                                 errmsg("type %s is only a shell",
 
1724
                                                format_type_be(type))));
 
1725
        if (!OidIsValid(pt->typoutput))
 
1726
                ereport(ERROR,
 
1727
                                (errcode(ERRCODE_UNDEFINED_FUNCTION),
 
1728
                                 errmsg("no output function available for type %s",
 
1729
                                                format_type_be(type))));
 
1730
 
 
1731
        *typOutput = pt->typoutput;
 
1732
        *typIOParam = getTypeIOParam(typeTuple);
 
1733
        *typIsVarlena = (!pt->typbyval) && (pt->typlen == -1);
 
1734
 
 
1735
        ReleaseSysCache(typeTuple);
 
1736
}
 
1737
 
 
1738
/*
 
1739
 * getTypeBinaryInputInfo
 
1740
 *
 
1741
 *              Get info needed for binary input of values of a type
 
1742
 */
 
1743
void
 
1744
getTypeBinaryInputInfo(Oid type, Oid *typReceive, Oid *typIOParam)
 
1745
{
 
1746
        HeapTuple       typeTuple;
 
1747
        Form_pg_type pt;
 
1748
 
 
1749
        typeTuple = SearchSysCache(TYPEOID,
 
1750
                                                           ObjectIdGetDatum(type),
 
1751
                                                           0, 0, 0);
 
1752
        if (!HeapTupleIsValid(typeTuple))
 
1753
                elog(ERROR, "cache lookup failed for type %u", type);
 
1754
        pt = (Form_pg_type) GETSTRUCT(typeTuple);
 
1755
 
 
1756
        if (!pt->typisdefined)
 
1757
                ereport(ERROR,
 
1758
                                (errcode(ERRCODE_UNDEFINED_OBJECT),
 
1759
                                 errmsg("type %s is only a shell",
 
1760
                                                format_type_be(type))));
 
1761
        if (!OidIsValid(pt->typreceive))
 
1762
                ereport(ERROR,
 
1763
                                (errcode(ERRCODE_UNDEFINED_FUNCTION),
 
1764
                                 errmsg("no binary input function available for type %s",
 
1765
                                                format_type_be(type))));
 
1766
 
 
1767
        *typReceive = pt->typreceive;
 
1768
        *typIOParam = getTypeIOParam(typeTuple);
 
1769
 
 
1770
        ReleaseSysCache(typeTuple);
 
1771
}
 
1772
 
 
1773
/*
 
1774
 * getTypeBinaryOutputInfo
 
1775
 *
 
1776
 *              Get info needed for binary output of values of a type
 
1777
 */
 
1778
void
 
1779
getTypeBinaryOutputInfo(Oid type, Oid *typSend, Oid *typIOParam,
 
1780
                                                bool *typIsVarlena)
 
1781
{
 
1782
        HeapTuple       typeTuple;
 
1783
        Form_pg_type pt;
 
1784
 
 
1785
        typeTuple = SearchSysCache(TYPEOID,
 
1786
                                                           ObjectIdGetDatum(type),
 
1787
                                                           0, 0, 0);
 
1788
        if (!HeapTupleIsValid(typeTuple))
 
1789
                elog(ERROR, "cache lookup failed for type %u", type);
 
1790
        pt = (Form_pg_type) GETSTRUCT(typeTuple);
 
1791
 
 
1792
        if (!pt->typisdefined)
 
1793
                ereport(ERROR,
 
1794
                                (errcode(ERRCODE_UNDEFINED_OBJECT),
 
1795
                                 errmsg("type %s is only a shell",
 
1796
                                                format_type_be(type))));
 
1797
        if (!OidIsValid(pt->typsend))
 
1798
                ereport(ERROR,
 
1799
                                (errcode(ERRCODE_UNDEFINED_FUNCTION),
 
1800
                                 errmsg("no binary output function available for type %s",
 
1801
                                                format_type_be(type))));
 
1802
 
 
1803
        *typSend = pt->typsend;
 
1804
        *typIOParam = getTypeIOParam(typeTuple);
 
1805
        *typIsVarlena = (!pt->typbyval) && (pt->typlen == -1);
 
1806
 
 
1807
        ReleaseSysCache(typeTuple);
 
1808
}
 
1809
 
 
1810
 
 
1811
/*                              ---------- STATISTICS CACHE ----------                                   */
 
1812
 
 
1813
/*
 
1814
 * get_attavgwidth
 
1815
 *
 
1816
 *        Given the table and attribute number of a column, get the average
 
1817
 *        width of entries in the column.  Return zero if no data available.
 
1818
 */
 
1819
int32
 
1820
get_attavgwidth(Oid relid, AttrNumber attnum)
 
1821
{
 
1822
        HeapTuple       tp;
 
1823
 
 
1824
        tp = SearchSysCache(STATRELATT,
 
1825
                                                ObjectIdGetDatum(relid),
 
1826
                                                Int16GetDatum(attnum),
 
1827
                                                0, 0);
 
1828
        if (HeapTupleIsValid(tp))
 
1829
        {
 
1830
                int32           stawidth = ((Form_pg_statistic) GETSTRUCT(tp))->stawidth;
 
1831
 
 
1832
                ReleaseSysCache(tp);
 
1833
                if (stawidth > 0)
 
1834
                        return stawidth;
 
1835
        }
 
1836
        return 0;
 
1837
}
 
1838
 
 
1839
/*
 
1840
 * get_attstatsslot
 
1841
 *
 
1842
 *              Extract the contents of a "slot" of a pg_statistic tuple.
 
1843
 *              Returns TRUE if requested slot type was found, else FALSE.
 
1844
 *
 
1845
 * Unlike other routines in this file, this takes a pointer to an
 
1846
 * already-looked-up tuple in the pg_statistic cache.  We do this since
 
1847
 * most callers will want to extract more than one value from the cache
 
1848
 * entry, and we don't want to repeat the cache lookup unnecessarily.
 
1849
 *
 
1850
 * statstuple: pg_statistics tuple to be examined.
 
1851
 * atttype: type OID of attribute.
 
1852
 * atttypmod: typmod of attribute.
 
1853
 * reqkind: STAKIND code for desired statistics slot kind.
 
1854
 * reqop: STAOP value wanted, or InvalidOid if don't care.
 
1855
 * values, nvalues: if not NULL, the slot's stavalues are extracted.
 
1856
 * numbers, nnumbers: if not NULL, the slot's stanumbers are extracted.
 
1857
 *
 
1858
 * If assigned, values and numbers are set to point to palloc'd arrays.
 
1859
 * If the attribute type is pass-by-reference, the values referenced by
 
1860
 * the values array are themselves palloc'd.  The palloc'd stuff can be
 
1861
 * freed by calling free_attstatsslot.
 
1862
 */
 
1863
bool
 
1864
get_attstatsslot(HeapTuple statstuple,
 
1865
                                 Oid atttype, int32 atttypmod,
 
1866
                                 int reqkind, Oid reqop,
 
1867
                                 Datum **values, int *nvalues,
 
1868
                                 float4 **numbers, int *nnumbers)
 
1869
{
 
1870
        Form_pg_statistic stats = (Form_pg_statistic) GETSTRUCT(statstuple);
 
1871
        int                     i,
 
1872
                                j;
 
1873
        Datum           val;
 
1874
        bool            isnull;
 
1875
        ArrayType  *statarray;
 
1876
        int                     narrayelem;
 
1877
        HeapTuple       typeTuple;
 
1878
        Form_pg_type typeForm;
 
1879
 
 
1880
        for (i = 0; i < STATISTIC_NUM_SLOTS; i++)
 
1881
        {
 
1882
                if ((&stats->stakind1)[i] == reqkind &&
 
1883
                        (reqop == InvalidOid || (&stats->staop1)[i] == reqop))
 
1884
                        break;
 
1885
        }
 
1886
        if (i >= STATISTIC_NUM_SLOTS)
 
1887
                return false;                   /* not there */
 
1888
 
 
1889
        if (values)
 
1890
        {
 
1891
                val = SysCacheGetAttr(STATRELATT, statstuple,
 
1892
                                                          Anum_pg_statistic_stavalues1 + i,
 
1893
                                                          &isnull);
 
1894
                if (isnull)
 
1895
                        elog(ERROR, "stavalues is null");
 
1896
                statarray = DatumGetArrayTypeP(val);
 
1897
 
 
1898
                /* Need to get info about the array element type */
 
1899
                typeTuple = SearchSysCache(TYPEOID,
 
1900
                                                                   ObjectIdGetDatum(atttype),
 
1901
                                                                   0, 0, 0);
 
1902
                if (!HeapTupleIsValid(typeTuple))
 
1903
                        elog(ERROR, "cache lookup failed for type %u", atttype);
 
1904
                typeForm = (Form_pg_type) GETSTRUCT(typeTuple);
 
1905
 
 
1906
                /* Deconstruct array into Datum elements */
 
1907
                deconstruct_array(statarray,
 
1908
                                                  atttype,
 
1909
                                                  typeForm->typlen,
 
1910
                                                  typeForm->typbyval,
 
1911
                                                  typeForm->typalign,
 
1912
                                                  values, nvalues);
 
1913
 
 
1914
                /*
 
1915
                 * If the element type is pass-by-reference, we now have a bunch
 
1916
                 * of Datums that are pointers into the syscache value.  Copy them
 
1917
                 * to avoid problems if syscache decides to drop the entry.
 
1918
                 */
 
1919
                if (!typeForm->typbyval)
 
1920
                {
 
1921
                        for (j = 0; j < *nvalues; j++)
 
1922
                        {
 
1923
                                (*values)[j] = datumCopy((*values)[j],
 
1924
                                                                                 typeForm->typbyval,
 
1925
                                                                                 typeForm->typlen);
 
1926
                        }
 
1927
                }
 
1928
 
 
1929
                ReleaseSysCache(typeTuple);
 
1930
 
 
1931
                /*
 
1932
                 * Free statarray if it's a detoasted copy.
 
1933
                 */
 
1934
                if ((Pointer) statarray != DatumGetPointer(val))
 
1935
                        pfree(statarray);
 
1936
        }
 
1937
 
 
1938
        if (numbers)
 
1939
        {
 
1940
                val = SysCacheGetAttr(STATRELATT, statstuple,
 
1941
                                                          Anum_pg_statistic_stanumbers1 + i,
 
1942
                                                          &isnull);
 
1943
                if (isnull)
 
1944
                        elog(ERROR, "stanumbers is null");
 
1945
                statarray = DatumGetArrayTypeP(val);
 
1946
 
 
1947
                /*
 
1948
                 * We expect the array to be a 1-D float4 array; verify that. We
 
1949
                 * don't need to use deconstruct_array() since the array data is
 
1950
                 * just going to look like a C array of float4 values.
 
1951
                 */
 
1952
                narrayelem = ARR_DIMS(statarray)[0];
 
1953
                if (ARR_NDIM(statarray) != 1 || narrayelem <= 0 ||
 
1954
                        ARR_ELEMTYPE(statarray) != FLOAT4OID)
 
1955
                        elog(ERROR, "stanumbers is not a 1-D float4 array");
 
1956
                *numbers = (float4 *) palloc(narrayelem * sizeof(float4));
 
1957
                memcpy(*numbers, ARR_DATA_PTR(statarray), narrayelem * sizeof(float4));
 
1958
                *nnumbers = narrayelem;
 
1959
 
 
1960
                /*
 
1961
                 * Free statarray if it's a detoasted copy.
 
1962
                 */
 
1963
                if ((Pointer) statarray != DatumGetPointer(val))
 
1964
                        pfree(statarray);
 
1965
        }
 
1966
 
 
1967
        return true;
 
1968
}
 
1969
 
 
1970
void
 
1971
free_attstatsslot(Oid atttype,
 
1972
                                  Datum *values, int nvalues,
 
1973
                                  float4 *numbers, int nnumbers)
 
1974
{
 
1975
        if (values)
 
1976
        {
 
1977
                if (!get_typbyval(atttype))
 
1978
                {
 
1979
                        int                     i;
 
1980
 
 
1981
                        for (i = 0; i < nvalues; i++)
 
1982
                                pfree(DatumGetPointer(values[i]));
 
1983
                }
 
1984
                pfree(values);
 
1985
        }
 
1986
        if (numbers)
 
1987
                pfree(numbers);
 
1988
}
 
1989
 
 
1990
/*                              ---------- PG_NAMESPACE CACHE ----------                                 */
 
1991
 
 
1992
/*
 
1993
 * get_namespace_name
 
1994
 *              Returns the name of a given namespace
 
1995
 *
 
1996
 * Returns a palloc'd copy of the string, or NULL if no such namespace.
 
1997
 */
 
1998
char *
 
1999
get_namespace_name(Oid nspid)
 
2000
{
 
2001
        HeapTuple       tp;
 
2002
 
 
2003
        tp = SearchSysCache(NAMESPACEOID,
 
2004
                                                ObjectIdGetDatum(nspid),
 
2005
                                                0, 0, 0);
 
2006
        if (HeapTupleIsValid(tp))
 
2007
        {
 
2008
                Form_pg_namespace nsptup = (Form_pg_namespace) GETSTRUCT(tp);
 
2009
                char       *result;
 
2010
 
 
2011
                result = pstrdup(NameStr(nsptup->nspname));
 
2012
                ReleaseSysCache(tp);
 
2013
                return result;
 
2014
        }
 
2015
        else
 
2016
                return NULL;
 
2017
}
 
2018
 
 
2019
/*                              ---------- PG_SHADOW CACHE ----------                                    */
 
2020
 
 
2021
/*
 
2022
 * get_usesysid
 
2023
 *
 
2024
 *        Given a user name, look up the user's sysid.
 
2025
 *        Raises an error if no such user (rather than returning zero,
 
2026
 *        which might possibly be a valid usesysid).
 
2027
 *
 
2028
 * Note: the type of usesysid is currently int4, but may change to Oid
 
2029
 * someday.  It'd be reasonable to return zero on failure if we were
 
2030
 * using Oid ...
 
2031
 */
 
2032
AclId
 
2033
get_usesysid(const char *username)
 
2034
{
 
2035
        int32           result;
 
2036
        HeapTuple       userTup;
 
2037
 
 
2038
        userTup = SearchSysCache(SHADOWNAME,
 
2039
                                                         PointerGetDatum(username),
 
2040
                                                         0, 0, 0);
 
2041
        if (!HeapTupleIsValid(userTup))
 
2042
                ereport(ERROR,
 
2043
                                (errcode(ERRCODE_UNDEFINED_OBJECT),
 
2044
                                 errmsg("user \"%s\" does not exist", username)));
 
2045
 
 
2046
        result = ((Form_pg_shadow) GETSTRUCT(userTup))->usesysid;
 
2047
 
 
2048
        ReleaseSysCache(userTup);
 
2049
 
 
2050
        return result;
 
2051
}