~ubuntu-branches/ubuntu/hardy/postgresql-8.4/hardy-backports

« back to all changes in this revision

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

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2009-03-20 12:00:13 UTC
  • Revision ID: james.westby@ubuntu.com-20090320120013-hogj7egc5mjncc5g
Tags: upstream-8.4~0cvs20090328
ImportĀ upstreamĀ versionĀ 8.4~0cvs20090328

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*-------------------------------------------------------------------------
 
2
 *
 
3
 * relcache.c
 
4
 *        POSTGRES relation descriptor cache code
 
5
 *
 
6
 * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
 
7
 * Portions Copyright (c) 1994, Regents of the University of California
 
8
 *
 
9
 *
 
10
 * IDENTIFICATION
 
11
 *        $PostgreSQL$
 
12
 *
 
13
 *-------------------------------------------------------------------------
 
14
 */
 
15
/*
 
16
 * INTERFACE ROUTINES
 
17
 *              RelationCacheInitialize                 - initialize relcache (to empty)
 
18
 *              RelationCacheInitializePhase2   - finish initializing relcache
 
19
 *              RelationIdGetRelation                   - get a reldesc by relation id
 
20
 *              RelationClose                                   - close an open relation
 
21
 *
 
22
 * NOTES
 
23
 *              The following code contains many undocumented hacks.  Please be
 
24
 *              careful....
 
25
 */
 
26
#include "postgres.h"
 
27
 
 
28
#include <sys/file.h>
 
29
#include <fcntl.h>
 
30
#include <unistd.h>
 
31
 
 
32
#include "access/genam.h"
 
33
#include "access/heapam.h"
 
34
#include "access/reloptions.h"
 
35
#include "access/sysattr.h"
 
36
#include "access/xact.h"
 
37
#include "catalog/catalog.h"
 
38
#include "catalog/index.h"
 
39
#include "catalog/indexing.h"
 
40
#include "catalog/namespace.h"
 
41
#include "catalog/pg_amop.h"
 
42
#include "catalog/pg_amproc.h"
 
43
#include "catalog/pg_attrdef.h"
 
44
#include "catalog/pg_authid.h"
 
45
#include "catalog/pg_constraint.h"
 
46
#include "catalog/pg_namespace.h"
 
47
#include "catalog/pg_opclass.h"
 
48
#include "catalog/pg_proc.h"
 
49
#include "catalog/pg_rewrite.h"
 
50
#include "catalog/pg_type.h"
 
51
#include "commands/trigger.h"
 
52
#include "miscadmin.h"
 
53
#include "optimizer/clauses.h"
 
54
#include "optimizer/planmain.h"
 
55
#include "optimizer/prep.h"
 
56
#include "optimizer/var.h"
 
57
#include "rewrite/rewriteDefine.h"
 
58
#include "storage/fd.h"
 
59
#include "storage/lmgr.h"
 
60
#include "storage/smgr.h"
 
61
#include "utils/builtins.h"
 
62
#include "utils/fmgroids.h"
 
63
#include "utils/inval.h"
 
64
#include "utils/memutils.h"
 
65
#include "utils/relcache.h"
 
66
#include "utils/resowner.h"
 
67
#include "utils/syscache.h"
 
68
#include "utils/tqual.h"
 
69
#include "utils/typcache.h"
 
70
 
 
71
 
 
72
/*
 
73
 * name of relcache init file, used to speed up backend startup
 
74
 */
 
75
#define RELCACHE_INIT_FILENAME  "pg_internal.init"
 
76
 
 
77
#define RELCACHE_INIT_FILEMAGIC         0x573264        /* version ID value */
 
78
 
 
79
/*
 
80
 *              hardcoded tuple descriptors.  see include/catalog/pg_attribute.h
 
81
 */
 
82
static FormData_pg_attribute Desc_pg_class[Natts_pg_class] = {Schema_pg_class};
 
83
static FormData_pg_attribute Desc_pg_attribute[Natts_pg_attribute] = {Schema_pg_attribute};
 
84
static FormData_pg_attribute Desc_pg_proc[Natts_pg_proc] = {Schema_pg_proc};
 
85
static FormData_pg_attribute Desc_pg_type[Natts_pg_type] = {Schema_pg_type};
 
86
static FormData_pg_attribute Desc_pg_index[Natts_pg_index] = {Schema_pg_index};
 
87
 
 
88
/*
 
89
 *              Hash tables that index the relation cache
 
90
 *
 
91
 *              We used to index the cache by both name and OID, but now there
 
92
 *              is only an index by OID.
 
93
 */
 
94
typedef struct relidcacheent
 
95
{
 
96
        Oid                     reloid;
 
97
        Relation        reldesc;
 
98
} RelIdCacheEnt;
 
99
 
 
100
static HTAB *RelationIdCache;
 
101
 
 
102
/*
 
103
 * This flag is false until we have prepared the critical relcache entries
 
104
 * that are needed to do indexscans on the tables read by relcache building.
 
105
 */
 
106
bool            criticalRelcachesBuilt = false;
 
107
 
 
108
/*
 
109
 * This counter counts relcache inval events received since backend startup
 
110
 * (but only for rels that are actually in cache).      Presently, we use it only
 
111
 * to detect whether data about to be written by write_relcache_init_file()
 
112
 * might already be obsolete.
 
113
 */
 
114
static long relcacheInvalsReceived = 0L;
 
115
 
 
116
/*
 
117
 * This list remembers the OIDs of the relations cached in the relcache
 
118
 * init file.
 
119
 */
 
120
static List *initFileRelationIds = NIL;
 
121
 
 
122
/*
 
123
 * This flag lets us optimize away work in AtEO(Sub)Xact_RelationCache().
 
124
 */
 
125
static bool need_eoxact_work = false;
 
126
 
 
127
 
 
128
/*
 
129
 *              macros to manipulate the lookup hashtables
 
130
 */
 
131
#define RelationCacheInsert(RELATION)   \
 
132
do { \
 
133
        RelIdCacheEnt *idhentry; bool found; \
 
134
        idhentry = (RelIdCacheEnt*)hash_search(RelationIdCache, \
 
135
                                                                                   (void *) &(RELATION->rd_id), \
 
136
                                                                                   HASH_ENTER, \
 
137
                                                                                   &found); \
 
138
        /* used to give notice if found -- now just keep quiet */ \
 
139
        idhentry->reldesc = RELATION; \
 
140
} while(0)
 
141
 
 
142
#define RelationIdCacheLookup(ID, RELATION) \
 
143
do { \
 
144
        RelIdCacheEnt *hentry; \
 
145
        hentry = (RelIdCacheEnt*)hash_search(RelationIdCache, \
 
146
                                                                                 (void *) &(ID), HASH_FIND,NULL); \
 
147
        if (hentry) \
 
148
                RELATION = hentry->reldesc; \
 
149
        else \
 
150
                RELATION = NULL; \
 
151
} while(0)
 
152
 
 
153
#define RelationCacheDelete(RELATION) \
 
154
do { \
 
155
        RelIdCacheEnt *idhentry; \
 
156
        idhentry = (RelIdCacheEnt*)hash_search(RelationIdCache, \
 
157
                                                                                   (void *) &(RELATION->rd_id), \
 
158
                                                                                   HASH_REMOVE, NULL); \
 
159
        if (idhentry == NULL) \
 
160
                elog(WARNING, "trying to delete a rd_id reldesc that does not exist"); \
 
161
} while(0)
 
162
 
 
163
 
 
164
/*
 
165
 * Special cache for opclass-related information
 
166
 *
 
167
 * Note: only default operators and support procs get cached, ie, those with
 
168
 * lefttype = righttype = opcintype.
 
169
 */
 
170
typedef struct opclasscacheent
 
171
{
 
172
        Oid                     opclassoid;             /* lookup key: OID of opclass */
 
173
        bool            valid;                  /* set TRUE after successful fill-in */
 
174
        StrategyNumber numStrats;       /* max # of strategies (from pg_am) */
 
175
        StrategyNumber numSupport;      /* max # of support procs (from pg_am) */
 
176
        Oid                     opcfamily;              /* OID of opclass's family */
 
177
        Oid                     opcintype;              /* OID of opclass's declared input type */
 
178
        Oid                *operatorOids;       /* strategy operators' OIDs */
 
179
        RegProcedure *supportProcs; /* support procs */
 
180
} OpClassCacheEnt;
 
181
 
 
182
static HTAB *OpClassCache = NULL;
 
183
 
 
184
 
 
185
/* non-export function prototypes */
 
186
 
 
187
static void RelationClearRelation(Relation relation, bool rebuild);
 
188
 
 
189
static void RelationReloadIndexInfo(Relation relation);
 
190
static void RelationFlushRelation(Relation relation);
 
191
static bool load_relcache_init_file(void);
 
192
static void write_relcache_init_file(void);
 
193
static void write_item(const void *data, Size len, FILE *fp);
 
194
 
 
195
static void formrdesc(const char *relationName, Oid relationReltype,
 
196
                  bool hasoids, int natts, FormData_pg_attribute *att);
 
197
 
 
198
static HeapTuple ScanPgRelation(Oid targetRelId, bool indexOK);
 
199
static Relation AllocateRelationDesc(Relation relation, Form_pg_class relp);
 
200
static void RelationParseRelOptions(Relation relation, HeapTuple tuple);
 
201
static void RelationBuildTupleDesc(Relation relation);
 
202
static Relation RelationBuildDesc(Oid targetRelId, Relation oldrelation);
 
203
static void RelationInitPhysicalAddr(Relation relation);
 
204
static TupleDesc GetPgClassDescriptor(void);
 
205
static TupleDesc GetPgIndexDescriptor(void);
 
206
static void AttrDefaultFetch(Relation relation);
 
207
static void CheckConstraintFetch(Relation relation);
 
208
static List *insert_ordered_oid(List *list, Oid datum);
 
209
static void IndexSupportInitialize(oidvector *indclass,
 
210
                                           Oid *indexOperator,
 
211
                                           RegProcedure *indexSupport,
 
212
                                           Oid *opFamily,
 
213
                                           Oid *opcInType,
 
214
                                           StrategyNumber maxStrategyNumber,
 
215
                                           StrategyNumber maxSupportNumber,
 
216
                                           AttrNumber maxAttributeNumber);
 
217
static OpClassCacheEnt *LookupOpclassInfo(Oid operatorClassOid,
 
218
                                  StrategyNumber numStrats,
 
219
                                  StrategyNumber numSupport);
 
220
 
 
221
 
 
222
/*
 
223
 *              ScanPgRelation
 
224
 *
 
225
 *              This is used by RelationBuildDesc to find a pg_class
 
226
 *              tuple matching targetRelId.  The caller must hold at least
 
227
 *              AccessShareLock on the target relid to prevent concurrent-update
 
228
 *              scenarios --- else our SnapshotNow scan might fail to find any
 
229
 *              version that it thinks is live.
 
230
 *
 
231
 *              NB: the returned tuple has been copied into palloc'd storage
 
232
 *              and must eventually be freed with heap_freetuple.
 
233
 */
 
234
static HeapTuple
 
235
ScanPgRelation(Oid targetRelId, bool indexOK)
 
236
{
 
237
        HeapTuple       pg_class_tuple;
 
238
        Relation        pg_class_desc;
 
239
        SysScanDesc pg_class_scan;
 
240
        ScanKeyData key[1];
 
241
 
 
242
        /*
 
243
         * form a scan key
 
244
         */
 
245
        ScanKeyInit(&key[0],
 
246
                                ObjectIdAttributeNumber,
 
247
                                BTEqualStrategyNumber, F_OIDEQ,
 
248
                                ObjectIdGetDatum(targetRelId));
 
249
 
 
250
        /*
 
251
         * Open pg_class and fetch a tuple.  Force heap scan if we haven't yet
 
252
         * built the critical relcache entries (this includes initdb and startup
 
253
         * without a pg_internal.init file).  The caller can also force a heap
 
254
         * scan by setting indexOK == false.
 
255
         */
 
256
        pg_class_desc = heap_open(RelationRelationId, AccessShareLock);
 
257
        pg_class_scan = systable_beginscan(pg_class_desc, ClassOidIndexId,
 
258
                                                                           indexOK && criticalRelcachesBuilt,
 
259
                                                                           SnapshotNow,
 
260
                                                                           1, key);
 
261
 
 
262
        pg_class_tuple = systable_getnext(pg_class_scan);
 
263
 
 
264
        /*
 
265
         * Must copy tuple before releasing buffer.
 
266
         */
 
267
        if (HeapTupleIsValid(pg_class_tuple))
 
268
                pg_class_tuple = heap_copytuple(pg_class_tuple);
 
269
 
 
270
        /* all done */
 
271
        systable_endscan(pg_class_scan);
 
272
        heap_close(pg_class_desc, AccessShareLock);
 
273
 
 
274
        return pg_class_tuple;
 
275
}
 
276
 
 
277
/*
 
278
 *              AllocateRelationDesc
 
279
 *
 
280
 *              This is used to allocate memory for a new relation descriptor
 
281
 *              and initialize the rd_rel field.
 
282
 *
 
283
 *              If 'relation' is NULL, allocate a new RelationData object.
 
284
 *              If not, reuse the given object (that path is taken only when
 
285
 *              we have to rebuild a relcache entry during RelationClearRelation).
 
286
 */
 
287
static Relation
 
288
AllocateRelationDesc(Relation relation, Form_pg_class relp)
 
289
{
 
290
        MemoryContext oldcxt;
 
291
        Form_pg_class relationForm;
 
292
 
 
293
        /* Relcache entries must live in CacheMemoryContext */
 
294
        oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
 
295
 
 
296
        /*
 
297
         * allocate space for new relation descriptor, if needed
 
298
         */
 
299
        if (relation == NULL)
 
300
                relation = (Relation) palloc(sizeof(RelationData));
 
301
 
 
302
        /*
 
303
         * clear all fields of reldesc
 
304
         */
 
305
        MemSet(relation, 0, sizeof(RelationData));
 
306
        relation->rd_targblock = InvalidBlockNumber;
 
307
        relation->rd_fsm_nblocks = InvalidBlockNumber;
 
308
        relation->rd_vm_nblocks = InvalidBlockNumber;
 
309
 
 
310
        /* make sure relation is marked as having no open file yet */
 
311
        relation->rd_smgr = NULL;
 
312
 
 
313
        /*
 
314
         * Copy the relation tuple form
 
315
         *
 
316
         * We only allocate space for the fixed fields, ie, CLASS_TUPLE_SIZE. The
 
317
         * variable-length fields (relacl, reloptions) are NOT stored in the
 
318
         * relcache --- there'd be little point in it, since we don't copy the
 
319
         * tuple's nulls bitmap and hence wouldn't know if the values are valid.
 
320
         * Bottom line is that relacl *cannot* be retrieved from the relcache. Get
 
321
         * it from the syscache if you need it.  The same goes for the original
 
322
         * form of reloptions (however, we do store the parsed form of reloptions
 
323
         * in rd_options).
 
324
         */
 
325
        relationForm = (Form_pg_class) palloc(CLASS_TUPLE_SIZE);
 
326
 
 
327
        memcpy(relationForm, relp, CLASS_TUPLE_SIZE);
 
328
 
 
329
        /* initialize relation tuple form */
 
330
        relation->rd_rel = relationForm;
 
331
 
 
332
        /* and allocate attribute tuple form storage */
 
333
        relation->rd_att = CreateTemplateTupleDesc(relationForm->relnatts,
 
334
                                                                                           relationForm->relhasoids);
 
335
        /* which we mark as a reference-counted tupdesc */
 
336
        relation->rd_att->tdrefcount = 1;
 
337
 
 
338
        MemoryContextSwitchTo(oldcxt);
 
339
 
 
340
        return relation;
 
341
}
 
342
 
 
343
/*
 
344
 * RelationParseRelOptions
 
345
 *              Convert pg_class.reloptions into pre-parsed rd_options
 
346
 *
 
347
 * tuple is the real pg_class tuple (not rd_rel!) for relation
 
348
 *
 
349
 * Note: rd_rel and (if an index) rd_am must be valid already
 
350
 */
 
351
static void
 
352
RelationParseRelOptions(Relation relation, HeapTuple tuple)
 
353
{
 
354
        bytea      *options;
 
355
 
 
356
        relation->rd_options = NULL;
 
357
 
 
358
        /* Fall out if relkind should not have options */
 
359
        switch (relation->rd_rel->relkind)
 
360
        {
 
361
                case RELKIND_RELATION:
 
362
                case RELKIND_TOASTVALUE:
 
363
                case RELKIND_UNCATALOGED:
 
364
                case RELKIND_INDEX:
 
365
                        break;
 
366
                default:
 
367
                        return;
 
368
        }
 
369
 
 
370
        /*
 
371
         * Fetch reloptions from tuple; have to use a hardwired descriptor because
 
372
         * we might not have any other for pg_class yet (consider executing this
 
373
         * code for pg_class itself)
 
374
         */
 
375
        options = extractRelOptions(tuple,
 
376
                                                                GetPgClassDescriptor(),
 
377
                                                                relation->rd_rel->relkind == RELKIND_INDEX ?
 
378
                                                                relation->rd_am->amoptions : InvalidOid);
 
379
 
 
380
        /* Copy parsed data into CacheMemoryContext */
 
381
        if (options)
 
382
        {
 
383
                relation->rd_options = MemoryContextAlloc(CacheMemoryContext,
 
384
                                                                                                  VARSIZE(options));
 
385
                memcpy(relation->rd_options, options, VARSIZE(options));
 
386
        }
 
387
}
 
388
 
 
389
/*
 
390
 *              RelationBuildTupleDesc
 
391
 *
 
392
 *              Form the relation's tuple descriptor from information in
 
393
 *              the pg_attribute, pg_attrdef & pg_constraint system catalogs.
 
394
 */
 
395
static void
 
396
RelationBuildTupleDesc(Relation relation)
 
397
{
 
398
        HeapTuple       pg_attribute_tuple;
 
399
        Relation        pg_attribute_desc;
 
400
        SysScanDesc pg_attribute_scan;
 
401
        ScanKeyData skey[2];
 
402
        int                     need;
 
403
        TupleConstr *constr;
 
404
        AttrDefault *attrdef = NULL;
 
405
        int                     ndef = 0;
 
406
 
 
407
        /* copy some fields from pg_class row to rd_att */
 
408
        relation->rd_att->tdtypeid = relation->rd_rel->reltype;
 
409
        relation->rd_att->tdtypmod = -1;        /* unnecessary, but... */
 
410
        relation->rd_att->tdhasoid = relation->rd_rel->relhasoids;
 
411
 
 
412
        constr = (TupleConstr *) MemoryContextAlloc(CacheMemoryContext,
 
413
                                                                                                sizeof(TupleConstr));
 
414
        constr->has_not_null = false;
 
415
 
 
416
        /*
 
417
         * Form a scan key that selects only user attributes (attnum > 0).
 
418
         * (Eliminating system attribute rows at the index level is lots faster
 
419
         * than fetching them.)
 
420
         */
 
421
        ScanKeyInit(&skey[0],
 
422
                                Anum_pg_attribute_attrelid,
 
423
                                BTEqualStrategyNumber, F_OIDEQ,
 
424
                                ObjectIdGetDatum(RelationGetRelid(relation)));
 
425
        ScanKeyInit(&skey[1],
 
426
                                Anum_pg_attribute_attnum,
 
427
                                BTGreaterStrategyNumber, F_INT2GT,
 
428
                                Int16GetDatum(0));
 
429
 
 
430
        /*
 
431
         * Open pg_attribute and begin a scan.  Force heap scan if we haven't yet
 
432
         * built the critical relcache entries (this includes initdb and startup
 
433
         * without a pg_internal.init file).
 
434
         */
 
435
        pg_attribute_desc = heap_open(AttributeRelationId, AccessShareLock);
 
436
        pg_attribute_scan = systable_beginscan(pg_attribute_desc,
 
437
                                                                                   AttributeRelidNumIndexId,
 
438
                                                                                   criticalRelcachesBuilt,
 
439
                                                                                   SnapshotNow,
 
440
                                                                                   2, skey);
 
441
 
 
442
        /*
 
443
         * add attribute data to relation->rd_att
 
444
         */
 
445
        need = relation->rd_rel->relnatts;
 
446
 
 
447
        while (HeapTupleIsValid(pg_attribute_tuple = systable_getnext(pg_attribute_scan)))
 
448
        {
 
449
                Form_pg_attribute attp;
 
450
 
 
451
                attp = (Form_pg_attribute) GETSTRUCT(pg_attribute_tuple);
 
452
 
 
453
                if (attp->attnum <= 0 ||
 
454
                        attp->attnum > relation->rd_rel->relnatts)
 
455
                        elog(ERROR, "invalid attribute number %d for %s",
 
456
                                 attp->attnum, RelationGetRelationName(relation));
 
457
 
 
458
                memcpy(relation->rd_att->attrs[attp->attnum - 1],
 
459
                           attp,
 
460
                           ATTRIBUTE_FIXED_PART_SIZE);
 
461
 
 
462
                /* Update constraint/default info */
 
463
                if (attp->attnotnull)
 
464
                        constr->has_not_null = true;
 
465
 
 
466
                if (attp->atthasdef)
 
467
                {
 
468
                        if (attrdef == NULL)
 
469
                                attrdef = (AttrDefault *)
 
470
                                        MemoryContextAllocZero(CacheMemoryContext,
 
471
                                                                                   relation->rd_rel->relnatts *
 
472
                                                                                   sizeof(AttrDefault));
 
473
                        attrdef[ndef].adnum = attp->attnum;
 
474
                        attrdef[ndef].adbin = NULL;
 
475
                        ndef++;
 
476
                }
 
477
                need--;
 
478
                if (need == 0)
 
479
                        break;
 
480
        }
 
481
 
 
482
        /*
 
483
         * end the scan and close the attribute relation
 
484
         */
 
485
        systable_endscan(pg_attribute_scan);
 
486
        heap_close(pg_attribute_desc, AccessShareLock);
 
487
 
 
488
        if (need != 0)
 
489
                elog(ERROR, "catalog is missing %d attribute(s) for relid %u",
 
490
                         need, RelationGetRelid(relation));
 
491
 
 
492
        /*
 
493
         * The attcacheoff values we read from pg_attribute should all be -1
 
494
         * ("unknown").  Verify this if assert checking is on.  They will be
 
495
         * computed when and if needed during tuple access.
 
496
         */
 
497
#ifdef USE_ASSERT_CHECKING
 
498
        {
 
499
                int                     i;
 
500
 
 
501
                for (i = 0; i < relation->rd_rel->relnatts; i++)
 
502
                        Assert(relation->rd_att->attrs[i]->attcacheoff == -1);
 
503
        }
 
504
#endif
 
505
 
 
506
        /*
 
507
         * However, we can easily set the attcacheoff value for the first
 
508
         * attribute: it must be zero.  This eliminates the need for special cases
 
509
         * for attnum=1 that used to exist in fastgetattr() and index_getattr().
 
510
         */
 
511
        if (relation->rd_rel->relnatts > 0)
 
512
                relation->rd_att->attrs[0]->attcacheoff = 0;
 
513
 
 
514
        /*
 
515
         * Set up constraint/default info
 
516
         */
 
517
        if (constr->has_not_null || ndef > 0 || relation->rd_rel->relchecks)
 
518
        {
 
519
                relation->rd_att->constr = constr;
 
520
 
 
521
                if (ndef > 0)                   /* DEFAULTs */
 
522
                {
 
523
                        if (ndef < relation->rd_rel->relnatts)
 
524
                                constr->defval = (AttrDefault *)
 
525
                                        repalloc(attrdef, ndef * sizeof(AttrDefault));
 
526
                        else
 
527
                                constr->defval = attrdef;
 
528
                        constr->num_defval = ndef;
 
529
                        AttrDefaultFetch(relation);
 
530
                }
 
531
                else
 
532
                        constr->num_defval = 0;
 
533
 
 
534
                if (relation->rd_rel->relchecks > 0)    /* CHECKs */
 
535
                {
 
536
                        constr->num_check = relation->rd_rel->relchecks;
 
537
                        constr->check = (ConstrCheck *)
 
538
                                MemoryContextAllocZero(CacheMemoryContext,
 
539
                                                                        constr->num_check * sizeof(ConstrCheck));
 
540
                        CheckConstraintFetch(relation);
 
541
                }
 
542
                else
 
543
                        constr->num_check = 0;
 
544
        }
 
545
        else
 
546
        {
 
547
                pfree(constr);
 
548
                relation->rd_att->constr = NULL;
 
549
        }
 
550
}
 
551
 
 
552
/*
 
553
 *              RelationBuildRuleLock
 
554
 *
 
555
 *              Form the relation's rewrite rules from information in
 
556
 *              the pg_rewrite system catalog.
 
557
 *
 
558
 * Note: The rule parsetrees are potentially very complex node structures.
 
559
 * To allow these trees to be freed when the relcache entry is flushed,
 
560
 * we make a private memory context to hold the RuleLock information for
 
561
 * each relcache entry that has associated rules.  The context is used
 
562
 * just for rule info, not for any other subsidiary data of the relcache
 
563
 * entry, because that keeps the update logic in RelationClearRelation()
 
564
 * manageable.  The other subsidiary data structures are simple enough
 
565
 * to be easy to free explicitly, anyway.
 
566
 */
 
567
static void
 
568
RelationBuildRuleLock(Relation relation)
 
569
{
 
570
        MemoryContext rulescxt;
 
571
        MemoryContext oldcxt;
 
572
        HeapTuple       rewrite_tuple;
 
573
        Relation        rewrite_desc;
 
574
        TupleDesc       rewrite_tupdesc;
 
575
        SysScanDesc rewrite_scan;
 
576
        ScanKeyData key;
 
577
        RuleLock   *rulelock;
 
578
        int                     numlocks;
 
579
        RewriteRule **rules;
 
580
        int                     maxlocks;
 
581
 
 
582
        /*
 
583
         * Make the private context.  Parameters are set on the assumption that
 
584
         * it'll probably not contain much data.
 
585
         */
 
586
        rulescxt = AllocSetContextCreate(CacheMemoryContext,
 
587
                                                                         RelationGetRelationName(relation),
 
588
                                                                         ALLOCSET_SMALL_MINSIZE,
 
589
                                                                         ALLOCSET_SMALL_INITSIZE,
 
590
                                                                         ALLOCSET_SMALL_MAXSIZE);
 
591
        relation->rd_rulescxt = rulescxt;
 
592
 
 
593
        /*
 
594
         * allocate an array to hold the rewrite rules (the array is extended if
 
595
         * necessary)
 
596
         */
 
597
        maxlocks = 4;
 
598
        rules = (RewriteRule **)
 
599
                MemoryContextAlloc(rulescxt, sizeof(RewriteRule *) * maxlocks);
 
600
        numlocks = 0;
 
601
 
 
602
        /*
 
603
         * form a scan key
 
604
         */
 
605
        ScanKeyInit(&key,
 
606
                                Anum_pg_rewrite_ev_class,
 
607
                                BTEqualStrategyNumber, F_OIDEQ,
 
608
                                ObjectIdGetDatum(RelationGetRelid(relation)));
 
609
 
 
610
        /*
 
611
         * open pg_rewrite and begin a scan
 
612
         *
 
613
         * Note: since we scan the rules using RewriteRelRulenameIndexId, we will
 
614
         * be reading the rules in name order, except possibly during
 
615
         * emergency-recovery operations (ie, IgnoreSystemIndexes). This in turn
 
616
         * ensures that rules will be fired in name order.
 
617
         */
 
618
        rewrite_desc = heap_open(RewriteRelationId, AccessShareLock);
 
619
        rewrite_tupdesc = RelationGetDescr(rewrite_desc);
 
620
        rewrite_scan = systable_beginscan(rewrite_desc,
 
621
                                                                          RewriteRelRulenameIndexId,
 
622
                                                                          true, SnapshotNow,
 
623
                                                                          1, &key);
 
624
 
 
625
        while (HeapTupleIsValid(rewrite_tuple = systable_getnext(rewrite_scan)))
 
626
        {
 
627
                Form_pg_rewrite rewrite_form = (Form_pg_rewrite) GETSTRUCT(rewrite_tuple);
 
628
                bool            isnull;
 
629
                Datum           rule_datum;
 
630
                char       *rule_str;
 
631
                RewriteRule *rule;
 
632
 
 
633
                rule = (RewriteRule *) MemoryContextAlloc(rulescxt,
 
634
                                                                                                  sizeof(RewriteRule));
 
635
 
 
636
                rule->ruleId = HeapTupleGetOid(rewrite_tuple);
 
637
 
 
638
                rule->event = rewrite_form->ev_type - '0';
 
639
                rule->attrno = rewrite_form->ev_attr;
 
640
                rule->enabled = rewrite_form->ev_enabled;
 
641
                rule->isInstead = rewrite_form->is_instead;
 
642
 
 
643
                /*
 
644
                 * Must use heap_getattr to fetch ev_action and ev_qual.  Also, the
 
645
                 * rule strings are often large enough to be toasted.  To avoid
 
646
                 * leaking memory in the caller's context, do the detoasting here so
 
647
                 * we can free the detoasted version.
 
648
                 */
 
649
                rule_datum = heap_getattr(rewrite_tuple,
 
650
                                                                  Anum_pg_rewrite_ev_action,
 
651
                                                                  rewrite_tupdesc,
 
652
                                                                  &isnull);
 
653
                Assert(!isnull);
 
654
                rule_str = TextDatumGetCString(rule_datum);
 
655
                oldcxt = MemoryContextSwitchTo(rulescxt);
 
656
                rule->actions = (List *) stringToNode(rule_str);
 
657
                MemoryContextSwitchTo(oldcxt);
 
658
                pfree(rule_str);
 
659
 
 
660
                rule_datum = heap_getattr(rewrite_tuple,
 
661
                                                                  Anum_pg_rewrite_ev_qual,
 
662
                                                                  rewrite_tupdesc,
 
663
                                                                  &isnull);
 
664
                Assert(!isnull);
 
665
                rule_str = TextDatumGetCString(rule_datum);
 
666
                oldcxt = MemoryContextSwitchTo(rulescxt);
 
667
                rule->qual = (Node *) stringToNode(rule_str);
 
668
                MemoryContextSwitchTo(oldcxt);
 
669
                pfree(rule_str);
 
670
 
 
671
                /*
 
672
                 * We want the rule's table references to be checked as though by the
 
673
                 * table owner, not the user referencing the rule.      Therefore, scan
 
674
                 * through the rule's actions and set the checkAsUser field on all
 
675
                 * rtable entries.      We have to look at the qual as well, in case it
 
676
                 * contains sublinks.
 
677
                 *
 
678
                 * The reason for doing this when the rule is loaded, rather than when
 
679
                 * it is stored, is that otherwise ALTER TABLE OWNER would have to
 
680
                 * grovel through stored rules to update checkAsUser fields. Scanning
 
681
                 * the rule tree during load is relatively cheap (compared to
 
682
                 * constructing it in the first place), so we do it here.
 
683
                 */
 
684
                setRuleCheckAsUser((Node *) rule->actions, relation->rd_rel->relowner);
 
685
                setRuleCheckAsUser(rule->qual, relation->rd_rel->relowner);
 
686
 
 
687
                if (numlocks >= maxlocks)
 
688
                {
 
689
                        maxlocks *= 2;
 
690
                        rules = (RewriteRule **)
 
691
                                repalloc(rules, sizeof(RewriteRule *) * maxlocks);
 
692
                }
 
693
                rules[numlocks++] = rule;
 
694
        }
 
695
 
 
696
        /*
 
697
         * end the scan and close the attribute relation
 
698
         */
 
699
        systable_endscan(rewrite_scan);
 
700
        heap_close(rewrite_desc, AccessShareLock);
 
701
 
 
702
        /*
 
703
         * there might not be any rules (if relhasrules is out-of-date)
 
704
         */
 
705
        if (numlocks == 0)
 
706
        {
 
707
                relation->rd_rules = NULL;
 
708
                relation->rd_rulescxt = NULL;
 
709
                MemoryContextDelete(rulescxt);
 
710
                return;
 
711
        }
 
712
 
 
713
        /*
 
714
         * form a RuleLock and insert into relation
 
715
         */
 
716
        rulelock = (RuleLock *) MemoryContextAlloc(rulescxt, sizeof(RuleLock));
 
717
        rulelock->numLocks = numlocks;
 
718
        rulelock->rules = rules;
 
719
 
 
720
        relation->rd_rules = rulelock;
 
721
}
 
722
 
 
723
/*
 
724
 *              equalRuleLocks
 
725
 *
 
726
 *              Determine whether two RuleLocks are equivalent
 
727
 *
 
728
 *              Probably this should be in the rules code someplace...
 
729
 */
 
730
static bool
 
731
equalRuleLocks(RuleLock *rlock1, RuleLock *rlock2)
 
732
{
 
733
        int                     i;
 
734
 
 
735
        /*
 
736
         * As of 7.3 we assume the rule ordering is repeatable, because
 
737
         * RelationBuildRuleLock should read 'em in a consistent order.  So just
 
738
         * compare corresponding slots.
 
739
         */
 
740
        if (rlock1 != NULL)
 
741
        {
 
742
                if (rlock2 == NULL)
 
743
                        return false;
 
744
                if (rlock1->numLocks != rlock2->numLocks)
 
745
                        return false;
 
746
                for (i = 0; i < rlock1->numLocks; i++)
 
747
                {
 
748
                        RewriteRule *rule1 = rlock1->rules[i];
 
749
                        RewriteRule *rule2 = rlock2->rules[i];
 
750
 
 
751
                        if (rule1->ruleId != rule2->ruleId)
 
752
                                return false;
 
753
                        if (rule1->event != rule2->event)
 
754
                                return false;
 
755
                        if (rule1->attrno != rule2->attrno)
 
756
                                return false;
 
757
                        if (rule1->enabled != rule2->enabled)
 
758
                                return false;
 
759
                        if (rule1->isInstead != rule2->isInstead)
 
760
                                return false;
 
761
                        if (!equal(rule1->qual, rule2->qual))
 
762
                                return false;
 
763
                        if (!equal(rule1->actions, rule2->actions))
 
764
                                return false;
 
765
                }
 
766
        }
 
767
        else if (rlock2 != NULL)
 
768
                return false;
 
769
        return true;
 
770
}
 
771
 
 
772
 
 
773
/*
 
774
 *              RelationBuildDesc
 
775
 *
 
776
 *              Build a relation descriptor --- either a new one, or by
 
777
 *              recycling the given old relation object.  The latter case
 
778
 *              supports rebuilding a relcache entry without invalidating
 
779
 *              pointers to it.  The caller must hold at least
 
780
 *              AccessShareLock on the target relid.
 
781
 *
 
782
 *              Returns NULL if no pg_class row could be found for the given relid
 
783
 *              (suggesting we are trying to access a just-deleted relation).
 
784
 *              Any other error is reported via elog.
 
785
 */
 
786
static Relation
 
787
RelationBuildDesc(Oid targetRelId, Relation oldrelation)
 
788
{
 
789
        Relation        relation;
 
790
        Oid                     relid;
 
791
        HeapTuple       pg_class_tuple;
 
792
        Form_pg_class relp;
 
793
        MemoryContext oldcxt;
 
794
 
 
795
        /*
 
796
         * find the tuple in pg_class corresponding to the given relation id
 
797
         */
 
798
        pg_class_tuple = ScanPgRelation(targetRelId, true);
 
799
 
 
800
        /*
 
801
         * if no such tuple exists, return NULL
 
802
         */
 
803
        if (!HeapTupleIsValid(pg_class_tuple))
 
804
                return NULL;
 
805
 
 
806
        /*
 
807
         * get information from the pg_class_tuple
 
808
         */
 
809
        relid = HeapTupleGetOid(pg_class_tuple);
 
810
        relp = (Form_pg_class) GETSTRUCT(pg_class_tuple);
 
811
 
 
812
        /*
 
813
         * allocate storage for the relation descriptor, and copy pg_class_tuple
 
814
         * to relation->rd_rel.
 
815
         */
 
816
        relation = AllocateRelationDesc(oldrelation, relp);
 
817
 
 
818
        /*
 
819
         * initialize the relation's relation id (relation->rd_id)
 
820
         */
 
821
        RelationGetRelid(relation) = relid;
 
822
 
 
823
        /*
 
824
         * normal relations are not nailed into the cache; nor can a pre-existing
 
825
         * relation be new.  It could be temp though.  (Actually, it could be new
 
826
         * too, but it's okay to forget that fact if forced to flush the entry.)
 
827
         */
 
828
        relation->rd_refcnt = 0;
 
829
        relation->rd_isnailed = false;
 
830
        relation->rd_createSubid = InvalidSubTransactionId;
 
831
        relation->rd_newRelfilenodeSubid = InvalidSubTransactionId;
 
832
        relation->rd_istemp = isTempOrToastNamespace(relation->rd_rel->relnamespace);
 
833
 
 
834
        /*
 
835
         * initialize the tuple descriptor (relation->rd_att).
 
836
         */
 
837
        RelationBuildTupleDesc(relation);
 
838
 
 
839
        /*
 
840
         * Fetch rules and triggers that affect this relation
 
841
         */
 
842
        if (relation->rd_rel->relhasrules)
 
843
                RelationBuildRuleLock(relation);
 
844
        else
 
845
        {
 
846
                relation->rd_rules = NULL;
 
847
                relation->rd_rulescxt = NULL;
 
848
        }
 
849
 
 
850
        if (relation->rd_rel->relhastriggers)
 
851
                RelationBuildTriggers(relation);
 
852
        else
 
853
                relation->trigdesc = NULL;
 
854
 
 
855
        /*
 
856
         * if it's an index, initialize index-related information
 
857
         */
 
858
        if (OidIsValid(relation->rd_rel->relam))
 
859
                RelationInitIndexAccessInfo(relation);
 
860
 
 
861
        /* extract reloptions if any */
 
862
        RelationParseRelOptions(relation, pg_class_tuple);
 
863
 
 
864
        /*
 
865
         * initialize the relation lock manager information
 
866
         */
 
867
        RelationInitLockInfo(relation);         /* see lmgr.c */
 
868
 
 
869
        /*
 
870
         * initialize physical addressing information for the relation
 
871
         */
 
872
        RelationInitPhysicalAddr(relation);
 
873
 
 
874
        /* make sure relation is marked as having no open file yet */
 
875
        relation->rd_smgr = NULL;
 
876
 
 
877
        /*
 
878
         * now we can free the memory allocated for pg_class_tuple
 
879
         */
 
880
        heap_freetuple(pg_class_tuple);
 
881
 
 
882
        /*
 
883
         * Insert newly created relation into relcache hash tables.
 
884
         */
 
885
        oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
 
886
        RelationCacheInsert(relation);
 
887
        MemoryContextSwitchTo(oldcxt);
 
888
 
 
889
        /* It's fully valid */
 
890
        relation->rd_isvalid = true;
 
891
 
 
892
        return relation;
 
893
}
 
894
 
 
895
/*
 
896
 * Initialize the physical addressing info (RelFileNode) for a relcache entry
 
897
 */
 
898
static void
 
899
RelationInitPhysicalAddr(Relation relation)
 
900
{
 
901
        if (relation->rd_rel->reltablespace)
 
902
                relation->rd_node.spcNode = relation->rd_rel->reltablespace;
 
903
        else
 
904
                relation->rd_node.spcNode = MyDatabaseTableSpace;
 
905
        if (relation->rd_rel->relisshared)
 
906
                relation->rd_node.dbNode = InvalidOid;
 
907
        else
 
908
                relation->rd_node.dbNode = MyDatabaseId;
 
909
        relation->rd_node.relNode = relation->rd_rel->relfilenode;
 
910
}
 
911
 
 
912
/*
 
913
 * Initialize index-access-method support data for an index relation
 
914
 */
 
915
void
 
916
RelationInitIndexAccessInfo(Relation relation)
 
917
{
 
918
        HeapTuple       tuple;
 
919
        Form_pg_am      aform;
 
920
        Datum           indclassDatum;
 
921
        Datum           indoptionDatum;
 
922
        bool            isnull;
 
923
        oidvector  *indclass;
 
924
        int2vector *indoption;
 
925
        MemoryContext indexcxt;
 
926
        MemoryContext oldcontext;
 
927
        int                     natts;
 
928
        uint16          amstrategies;
 
929
        uint16          amsupport;
 
930
 
 
931
        /*
 
932
         * Make a copy of the pg_index entry for the index.  Since pg_index
 
933
         * contains variable-length and possibly-null fields, we have to do this
 
934
         * honestly rather than just treating it as a Form_pg_index struct.
 
935
         */
 
936
        tuple = SearchSysCache(INDEXRELID,
 
937
                                                   ObjectIdGetDatum(RelationGetRelid(relation)),
 
938
                                                   0, 0, 0);
 
939
        if (!HeapTupleIsValid(tuple))
 
940
                elog(ERROR, "cache lookup failed for index %u",
 
941
                         RelationGetRelid(relation));
 
942
        oldcontext = MemoryContextSwitchTo(CacheMemoryContext);
 
943
        relation->rd_indextuple = heap_copytuple(tuple);
 
944
        relation->rd_index = (Form_pg_index) GETSTRUCT(relation->rd_indextuple);
 
945
        MemoryContextSwitchTo(oldcontext);
 
946
        ReleaseSysCache(tuple);
 
947
 
 
948
        /*
 
949
         * Make a copy of the pg_am entry for the index's access method
 
950
         */
 
951
        tuple = SearchSysCache(AMOID,
 
952
                                                   ObjectIdGetDatum(relation->rd_rel->relam),
 
953
                                                   0, 0, 0);
 
954
        if (!HeapTupleIsValid(tuple))
 
955
                elog(ERROR, "cache lookup failed for access method %u",
 
956
                         relation->rd_rel->relam);
 
957
        aform = (Form_pg_am) MemoryContextAlloc(CacheMemoryContext, sizeof *aform);
 
958
        memcpy(aform, GETSTRUCT(tuple), sizeof *aform);
 
959
        ReleaseSysCache(tuple);
 
960
        relation->rd_am = aform;
 
961
 
 
962
        natts = relation->rd_rel->relnatts;
 
963
        if (natts != relation->rd_index->indnatts)
 
964
                elog(ERROR, "relnatts disagrees with indnatts for index %u",
 
965
                         RelationGetRelid(relation));
 
966
        amstrategies = aform->amstrategies;
 
967
        amsupport = aform->amsupport;
 
968
 
 
969
        /*
 
970
         * Make the private context to hold index access info.  The reason we need
 
971
         * a context, and not just a couple of pallocs, is so that we won't leak
 
972
         * any subsidiary info attached to fmgr lookup records.
 
973
         *
 
974
         * Context parameters are set on the assumption that it'll probably not
 
975
         * contain much data.
 
976
         */
 
977
        indexcxt = AllocSetContextCreate(CacheMemoryContext,
 
978
                                                                         RelationGetRelationName(relation),
 
979
                                                                         ALLOCSET_SMALL_MINSIZE,
 
980
                                                                         ALLOCSET_SMALL_INITSIZE,
 
981
                                                                         ALLOCSET_SMALL_MAXSIZE);
 
982
        relation->rd_indexcxt = indexcxt;
 
983
 
 
984
        /*
 
985
         * Allocate arrays to hold data
 
986
         */
 
987
        relation->rd_aminfo = (RelationAmInfo *)
 
988
                MemoryContextAllocZero(indexcxt, sizeof(RelationAmInfo));
 
989
 
 
990
        relation->rd_opfamily = (Oid *)
 
991
                MemoryContextAllocZero(indexcxt, natts * sizeof(Oid));
 
992
        relation->rd_opcintype = (Oid *)
 
993
                MemoryContextAllocZero(indexcxt, natts * sizeof(Oid));
 
994
 
 
995
        if (amstrategies > 0)
 
996
                relation->rd_operator = (Oid *)
 
997
                        MemoryContextAllocZero(indexcxt,
 
998
                                                                   natts * amstrategies * sizeof(Oid));
 
999
        else
 
1000
                relation->rd_operator = NULL;
 
1001
 
 
1002
        if (amsupport > 0)
 
1003
        {
 
1004
                int                     nsupport = natts * amsupport;
 
1005
 
 
1006
                relation->rd_support = (RegProcedure *)
 
1007
                        MemoryContextAllocZero(indexcxt, nsupport * sizeof(RegProcedure));
 
1008
                relation->rd_supportinfo = (FmgrInfo *)
 
1009
                        MemoryContextAllocZero(indexcxt, nsupport * sizeof(FmgrInfo));
 
1010
        }
 
1011
        else
 
1012
        {
 
1013
                relation->rd_support = NULL;
 
1014
                relation->rd_supportinfo = NULL;
 
1015
        }
 
1016
 
 
1017
        relation->rd_indoption = (int16 *)
 
1018
                MemoryContextAllocZero(indexcxt, natts * sizeof(int16));
 
1019
 
 
1020
        /*
 
1021
         * indclass cannot be referenced directly through the C struct, because it
 
1022
         * comes after the variable-width indkey field.  Must extract the datum
 
1023
         * the hard way...
 
1024
         */
 
1025
        indclassDatum = fastgetattr(relation->rd_indextuple,
 
1026
                                                                Anum_pg_index_indclass,
 
1027
                                                                GetPgIndexDescriptor(),
 
1028
                                                                &isnull);
 
1029
        Assert(!isnull);
 
1030
        indclass = (oidvector *) DatumGetPointer(indclassDatum);
 
1031
 
 
1032
        /*
 
1033
         * Fill the operator and support procedure OID arrays, as well as the info
 
1034
         * about opfamilies and opclass input types.  (aminfo and supportinfo are
 
1035
         * left as zeroes, and are filled on-the-fly when used)
 
1036
         */
 
1037
        IndexSupportInitialize(indclass,
 
1038
                                                   relation->rd_operator, relation->rd_support,
 
1039
                                                   relation->rd_opfamily, relation->rd_opcintype,
 
1040
                                                   amstrategies, amsupport, natts);
 
1041
 
 
1042
        /*
 
1043
         * Similarly extract indoption and copy it to the cache entry
 
1044
         */
 
1045
        indoptionDatum = fastgetattr(relation->rd_indextuple,
 
1046
                                                                 Anum_pg_index_indoption,
 
1047
                                                                 GetPgIndexDescriptor(),
 
1048
                                                                 &isnull);
 
1049
        Assert(!isnull);
 
1050
        indoption = (int2vector *) DatumGetPointer(indoptionDatum);
 
1051
        memcpy(relation->rd_indoption, indoption->values, natts * sizeof(int16));
 
1052
 
 
1053
        /*
 
1054
         * expressions and predicate cache will be filled later
 
1055
         */
 
1056
        relation->rd_indexprs = NIL;
 
1057
        relation->rd_indpred = NIL;
 
1058
        relation->rd_amcache = NULL;
 
1059
}
 
1060
 
 
1061
/*
 
1062
 * IndexSupportInitialize
 
1063
 *              Initializes an index's cached opclass information,
 
1064
 *              given the index's pg_index.indclass entry.
 
1065
 *
 
1066
 * Data is returned into *indexOperator, *indexSupport, *opFamily, and
 
1067
 * *opcInType, which are arrays allocated by the caller.
 
1068
 *
 
1069
 * The caller also passes maxStrategyNumber, maxSupportNumber, and
 
1070
 * maxAttributeNumber, since these indicate the size of the arrays
 
1071
 * it has allocated --- but in practice these numbers must always match
 
1072
 * those obtainable from the system catalog entries for the index and
 
1073
 * access method.
 
1074
 */
 
1075
static void
 
1076
IndexSupportInitialize(oidvector *indclass,
 
1077
                                           Oid *indexOperator,
 
1078
                                           RegProcedure *indexSupport,
 
1079
                                           Oid *opFamily,
 
1080
                                           Oid *opcInType,
 
1081
                                           StrategyNumber maxStrategyNumber,
 
1082
                                           StrategyNumber maxSupportNumber,
 
1083
                                           AttrNumber maxAttributeNumber)
 
1084
{
 
1085
        int                     attIndex;
 
1086
 
 
1087
        for (attIndex = 0; attIndex < maxAttributeNumber; attIndex++)
 
1088
        {
 
1089
                OpClassCacheEnt *opcentry;
 
1090
 
 
1091
                if (!OidIsValid(indclass->values[attIndex]))
 
1092
                        elog(ERROR, "bogus pg_index tuple");
 
1093
 
 
1094
                /* look up the info for this opclass, using a cache */
 
1095
                opcentry = LookupOpclassInfo(indclass->values[attIndex],
 
1096
                                                                         maxStrategyNumber,
 
1097
                                                                         maxSupportNumber);
 
1098
 
 
1099
                /* copy cached data into relcache entry */
 
1100
                opFamily[attIndex] = opcentry->opcfamily;
 
1101
                opcInType[attIndex] = opcentry->opcintype;
 
1102
                if (maxStrategyNumber > 0)
 
1103
                        memcpy(&indexOperator[attIndex * maxStrategyNumber],
 
1104
                                   opcentry->operatorOids,
 
1105
                                   maxStrategyNumber * sizeof(Oid));
 
1106
                if (maxSupportNumber > 0)
 
1107
                        memcpy(&indexSupport[attIndex * maxSupportNumber],
 
1108
                                   opcentry->supportProcs,
 
1109
                                   maxSupportNumber * sizeof(RegProcedure));
 
1110
        }
 
1111
}
 
1112
 
 
1113
/*
 
1114
 * LookupOpclassInfo
 
1115
 *
 
1116
 * This routine maintains a per-opclass cache of the information needed
 
1117
 * by IndexSupportInitialize().  This is more efficient than relying on
 
1118
 * the catalog cache, because we can load all the info about a particular
 
1119
 * opclass in a single indexscan of pg_amproc or pg_amop.
 
1120
 *
 
1121
 * The information from pg_am about expected range of strategy and support
 
1122
 * numbers is passed in, rather than being looked up, mainly because the
 
1123
 * caller will have it already.
 
1124
 *
 
1125
 * Note there is no provision for flushing the cache.  This is OK at the
 
1126
 * moment because there is no way to ALTER any interesting properties of an
 
1127
 * existing opclass --- all you can do is drop it, which will result in
 
1128
 * a useless but harmless dead entry in the cache.  To support altering
 
1129
 * opclass membership (not the same as opfamily membership!), we'd need to
 
1130
 * be able to flush this cache as well as the contents of relcache entries
 
1131
 * for indexes.
 
1132
 */
 
1133
static OpClassCacheEnt *
 
1134
LookupOpclassInfo(Oid operatorClassOid,
 
1135
                                  StrategyNumber numStrats,
 
1136
                                  StrategyNumber numSupport)
 
1137
{
 
1138
        OpClassCacheEnt *opcentry;
 
1139
        bool            found;
 
1140
        Relation        rel;
 
1141
        SysScanDesc scan;
 
1142
        ScanKeyData skey[3];
 
1143
        HeapTuple       htup;
 
1144
        bool            indexOK;
 
1145
 
 
1146
        if (OpClassCache == NULL)
 
1147
        {
 
1148
                /* First time through: initialize the opclass cache */
 
1149
                HASHCTL         ctl;
 
1150
 
 
1151
                if (!CacheMemoryContext)
 
1152
                        CreateCacheMemoryContext();
 
1153
 
 
1154
                MemSet(&ctl, 0, sizeof(ctl));
 
1155
                ctl.keysize = sizeof(Oid);
 
1156
                ctl.entrysize = sizeof(OpClassCacheEnt);
 
1157
                ctl.hash = oid_hash;
 
1158
                OpClassCache = hash_create("Operator class cache", 64,
 
1159
                                                                   &ctl, HASH_ELEM | HASH_FUNCTION);
 
1160
        }
 
1161
 
 
1162
        opcentry = (OpClassCacheEnt *) hash_search(OpClassCache,
 
1163
                                                                                           (void *) &operatorClassOid,
 
1164
                                                                                           HASH_ENTER, &found);
 
1165
 
 
1166
        if (!found)
 
1167
        {
 
1168
                /* Need to allocate memory for new entry */
 
1169
                opcentry->valid = false;        /* until known OK */
 
1170
                opcentry->numStrats = numStrats;
 
1171
                opcentry->numSupport = numSupport;
 
1172
 
 
1173
                if (numStrats > 0)
 
1174
                        opcentry->operatorOids = (Oid *)
 
1175
                                MemoryContextAllocZero(CacheMemoryContext,
 
1176
                                                                           numStrats * sizeof(Oid));
 
1177
                else
 
1178
                        opcentry->operatorOids = NULL;
 
1179
 
 
1180
                if (numSupport > 0)
 
1181
                        opcentry->supportProcs = (RegProcedure *)
 
1182
                                MemoryContextAllocZero(CacheMemoryContext,
 
1183
                                                                           numSupport * sizeof(RegProcedure));
 
1184
                else
 
1185
                        opcentry->supportProcs = NULL;
 
1186
        }
 
1187
        else
 
1188
        {
 
1189
                Assert(numStrats == opcentry->numStrats);
 
1190
                Assert(numSupport == opcentry->numSupport);
 
1191
        }
 
1192
 
 
1193
        /*
 
1194
         * When testing for cache-flush hazards, we intentionally disable the
 
1195
         * operator class cache and force reloading of the info on each call.
 
1196
         * This is helpful because we want to test the case where a cache flush
 
1197
         * occurs while we are loading the info, and it's very hard to provoke
 
1198
         * that if this happens only once per opclass per backend.
 
1199
         */
 
1200
#if defined(CLOBBER_CACHE_ALWAYS)
 
1201
        opcentry->valid = false;
 
1202
#endif
 
1203
 
 
1204
        if (opcentry->valid)
 
1205
                return opcentry;
 
1206
 
 
1207
        /*
 
1208
         * Need to fill in new entry.
 
1209
         *
 
1210
         * To avoid infinite recursion during startup, force heap scans if we're
 
1211
         * looking up info for the opclasses used by the indexes we would like to
 
1212
         * reference here.
 
1213
         */
 
1214
        indexOK = criticalRelcachesBuilt ||
 
1215
                (operatorClassOid != OID_BTREE_OPS_OID &&
 
1216
                 operatorClassOid != INT2_BTREE_OPS_OID);
 
1217
 
 
1218
        /*
 
1219
         * We have to fetch the pg_opclass row to determine its opfamily and
 
1220
         * opcintype, which are needed to look up the operators and functions.
 
1221
         * It'd be convenient to use the syscache here, but that probably doesn't
 
1222
         * work while bootstrapping.
 
1223
         */
 
1224
        ScanKeyInit(&skey[0],
 
1225
                                ObjectIdAttributeNumber,
 
1226
                                BTEqualStrategyNumber, F_OIDEQ,
 
1227
                                ObjectIdGetDatum(operatorClassOid));
 
1228
        rel = heap_open(OperatorClassRelationId, AccessShareLock);
 
1229
        scan = systable_beginscan(rel, OpclassOidIndexId, indexOK,
 
1230
                                                          SnapshotNow, 1, skey);
 
1231
 
 
1232
        if (HeapTupleIsValid(htup = systable_getnext(scan)))
 
1233
        {
 
1234
                Form_pg_opclass opclassform = (Form_pg_opclass) GETSTRUCT(htup);
 
1235
 
 
1236
                opcentry->opcfamily = opclassform->opcfamily;
 
1237
                opcentry->opcintype = opclassform->opcintype;
 
1238
        }
 
1239
        else
 
1240
                elog(ERROR, "could not find tuple for opclass %u", operatorClassOid);
 
1241
 
 
1242
        systable_endscan(scan);
 
1243
        heap_close(rel, AccessShareLock);
 
1244
 
 
1245
 
 
1246
        /*
 
1247
         * Scan pg_amop to obtain operators for the opclass.  We only fetch the
 
1248
         * default ones (those with lefttype = righttype = opcintype).
 
1249
         */
 
1250
        if (numStrats > 0)
 
1251
        {
 
1252
                ScanKeyInit(&skey[0],
 
1253
                                        Anum_pg_amop_amopfamily,
 
1254
                                        BTEqualStrategyNumber, F_OIDEQ,
 
1255
                                        ObjectIdGetDatum(opcentry->opcfamily));
 
1256
                ScanKeyInit(&skey[1],
 
1257
                                        Anum_pg_amop_amoplefttype,
 
1258
                                        BTEqualStrategyNumber, F_OIDEQ,
 
1259
                                        ObjectIdGetDatum(opcentry->opcintype));
 
1260
                ScanKeyInit(&skey[2],
 
1261
                                        Anum_pg_amop_amoprighttype,
 
1262
                                        BTEqualStrategyNumber, F_OIDEQ,
 
1263
                                        ObjectIdGetDatum(opcentry->opcintype));
 
1264
                rel = heap_open(AccessMethodOperatorRelationId, AccessShareLock);
 
1265
                scan = systable_beginscan(rel, AccessMethodStrategyIndexId, indexOK,
 
1266
                                                                  SnapshotNow, 3, skey);
 
1267
 
 
1268
                while (HeapTupleIsValid(htup = systable_getnext(scan)))
 
1269
                {
 
1270
                        Form_pg_amop amopform = (Form_pg_amop) GETSTRUCT(htup);
 
1271
 
 
1272
                        if (amopform->amopstrategy <= 0 ||
 
1273
                                (StrategyNumber) amopform->amopstrategy > numStrats)
 
1274
                                elog(ERROR, "invalid amopstrategy number %d for opclass %u",
 
1275
                                         amopform->amopstrategy, operatorClassOid);
 
1276
                        opcentry->operatorOids[amopform->amopstrategy - 1] =
 
1277
                                amopform->amopopr;
 
1278
                }
 
1279
 
 
1280
                systable_endscan(scan);
 
1281
                heap_close(rel, AccessShareLock);
 
1282
        }
 
1283
 
 
1284
        /*
 
1285
         * Scan pg_amproc to obtain support procs for the opclass.      We only fetch
 
1286
         * the default ones (those with lefttype = righttype = opcintype).
 
1287
         */
 
1288
        if (numSupport > 0)
 
1289
        {
 
1290
                ScanKeyInit(&skey[0],
 
1291
                                        Anum_pg_amproc_amprocfamily,
 
1292
                                        BTEqualStrategyNumber, F_OIDEQ,
 
1293
                                        ObjectIdGetDatum(opcentry->opcfamily));
 
1294
                ScanKeyInit(&skey[1],
 
1295
                                        Anum_pg_amproc_amproclefttype,
 
1296
                                        BTEqualStrategyNumber, F_OIDEQ,
 
1297
                                        ObjectIdGetDatum(opcentry->opcintype));
 
1298
                ScanKeyInit(&skey[2],
 
1299
                                        Anum_pg_amproc_amprocrighttype,
 
1300
                                        BTEqualStrategyNumber, F_OIDEQ,
 
1301
                                        ObjectIdGetDatum(opcentry->opcintype));
 
1302
                rel = heap_open(AccessMethodProcedureRelationId, AccessShareLock);
 
1303
                scan = systable_beginscan(rel, AccessMethodProcedureIndexId, indexOK,
 
1304
                                                                  SnapshotNow, 3, skey);
 
1305
 
 
1306
                while (HeapTupleIsValid(htup = systable_getnext(scan)))
 
1307
                {
 
1308
                        Form_pg_amproc amprocform = (Form_pg_amproc) GETSTRUCT(htup);
 
1309
 
 
1310
                        if (amprocform->amprocnum <= 0 ||
 
1311
                                (StrategyNumber) amprocform->amprocnum > numSupport)
 
1312
                                elog(ERROR, "invalid amproc number %d for opclass %u",
 
1313
                                         amprocform->amprocnum, operatorClassOid);
 
1314
 
 
1315
                        opcentry->supportProcs[amprocform->amprocnum - 1] =
 
1316
                                amprocform->amproc;
 
1317
                }
 
1318
 
 
1319
                systable_endscan(scan);
 
1320
                heap_close(rel, AccessShareLock);
 
1321
        }
 
1322
 
 
1323
        opcentry->valid = true;
 
1324
        return opcentry;
 
1325
}
 
1326
 
 
1327
 
 
1328
/*
 
1329
 *              formrdesc
 
1330
 *
 
1331
 *              This is a special cut-down version of RelationBuildDesc()
 
1332
 *              used by RelationCacheInitializePhase2() in initializing the relcache.
 
1333
 *              The relation descriptor is built just from the supplied parameters,
 
1334
 *              without actually looking at any system table entries.  We cheat
 
1335
 *              quite a lot since we only need to work for a few basic system
 
1336
 *              catalogs.
 
1337
 *
 
1338
 * formrdesc is currently used for: pg_class, pg_attribute, pg_proc,
 
1339
 * and pg_type (see RelationCacheInitializePhase2).
 
1340
 *
 
1341
 * Note that these catalogs can't have constraints (except attnotnull),
 
1342
 * default values, rules, or triggers, since we don't cope with any of that.
 
1343
 *
 
1344
 * NOTE: we assume we are already switched into CacheMemoryContext.
 
1345
 */
 
1346
static void
 
1347
formrdesc(const char *relationName, Oid relationReltype,
 
1348
                  bool hasoids, int natts, FormData_pg_attribute *att)
 
1349
{
 
1350
        Relation        relation;
 
1351
        int                     i;
 
1352
        bool            has_not_null;
 
1353
 
 
1354
        /*
 
1355
         * allocate new relation desc, clear all fields of reldesc
 
1356
         */
 
1357
        relation = (Relation) palloc0(sizeof(RelationData));
 
1358
        relation->rd_targblock = InvalidBlockNumber;
 
1359
        relation->rd_fsm_nblocks = InvalidBlockNumber;
 
1360
        relation->rd_vm_nblocks = InvalidBlockNumber;
 
1361
 
 
1362
        /* make sure relation is marked as having no open file yet */
 
1363
        relation->rd_smgr = NULL;
 
1364
 
 
1365
        /*
 
1366
         * initialize reference count: 1 because it is nailed in cache
 
1367
         */
 
1368
        relation->rd_refcnt = 1;
 
1369
 
 
1370
        /*
 
1371
         * all entries built with this routine are nailed-in-cache; none are for
 
1372
         * new or temp relations.
 
1373
         */
 
1374
        relation->rd_isnailed = true;
 
1375
        relation->rd_createSubid = InvalidSubTransactionId;
 
1376
        relation->rd_newRelfilenodeSubid = InvalidSubTransactionId;
 
1377
        relation->rd_istemp = false;
 
1378
 
 
1379
        /*
 
1380
         * initialize relation tuple form
 
1381
         *
 
1382
         * The data we insert here is pretty incomplete/bogus, but it'll serve to
 
1383
         * get us launched.  RelationCacheInitializePhase2() will read the real
 
1384
         * data from pg_class and replace what we've done here.
 
1385
         */
 
1386
        relation->rd_rel = (Form_pg_class) palloc0(CLASS_TUPLE_SIZE);
 
1387
 
 
1388
        namestrcpy(&relation->rd_rel->relname, relationName);
 
1389
        relation->rd_rel->relnamespace = PG_CATALOG_NAMESPACE;
 
1390
        relation->rd_rel->reltype = relationReltype;
 
1391
 
 
1392
        /*
 
1393
         * It's important to distinguish between shared and non-shared relations,
 
1394
         * even at bootstrap time, to make sure we know where they are stored.  At
 
1395
         * present, all relations that formrdesc is used for are not shared.
 
1396
         */
 
1397
        relation->rd_rel->relisshared = false;
 
1398
 
 
1399
        relation->rd_rel->relpages = 1;
 
1400
        relation->rd_rel->reltuples = 1;
 
1401
        relation->rd_rel->relkind = RELKIND_RELATION;
 
1402
        relation->rd_rel->relhasoids = hasoids;
 
1403
        relation->rd_rel->relnatts = (int16) natts;
 
1404
 
 
1405
        /*
 
1406
         * initialize attribute tuple form
 
1407
         *
 
1408
         * Unlike the case with the relation tuple, this data had better be right
 
1409
         * because it will never be replaced.  The input values must be correctly
 
1410
         * defined by macros in src/include/catalog/ headers.
 
1411
         */
 
1412
        relation->rd_att = CreateTemplateTupleDesc(natts, hasoids);
 
1413
        relation->rd_att->tdrefcount = 1;       /* mark as refcounted */
 
1414
 
 
1415
        relation->rd_att->tdtypeid = relationReltype;
 
1416
        relation->rd_att->tdtypmod = -1;        /* unnecessary, but... */
 
1417
 
 
1418
        /*
 
1419
         * initialize tuple desc info
 
1420
         */
 
1421
        has_not_null = false;
 
1422
        for (i = 0; i < natts; i++)
 
1423
        {
 
1424
                memcpy(relation->rd_att->attrs[i],
 
1425
                           &att[i],
 
1426
                           ATTRIBUTE_FIXED_PART_SIZE);
 
1427
                has_not_null |= att[i].attnotnull;
 
1428
                /* make sure attcacheoff is valid */
 
1429
                relation->rd_att->attrs[i]->attcacheoff = -1;
 
1430
        }
 
1431
 
 
1432
        /* initialize first attribute's attcacheoff, cf RelationBuildTupleDesc */
 
1433
        relation->rd_att->attrs[0]->attcacheoff = 0;
 
1434
 
 
1435
        /* mark not-null status */
 
1436
        if (has_not_null)
 
1437
        {
 
1438
                TupleConstr *constr = (TupleConstr *) palloc0(sizeof(TupleConstr));
 
1439
 
 
1440
                constr->has_not_null = true;
 
1441
                relation->rd_att->constr = constr;
 
1442
        }
 
1443
 
 
1444
        /*
 
1445
         * initialize relation id from info in att array (my, this is ugly)
 
1446
         */
 
1447
        RelationGetRelid(relation) = relation->rd_att->attrs[0]->attrelid;
 
1448
        relation->rd_rel->relfilenode = RelationGetRelid(relation);
 
1449
 
 
1450
        /*
 
1451
         * initialize the relation lock manager information
 
1452
         */
 
1453
        RelationInitLockInfo(relation);         /* see lmgr.c */
 
1454
 
 
1455
        /*
 
1456
         * initialize physical addressing information for the relation
 
1457
         */
 
1458
        RelationInitPhysicalAddr(relation);
 
1459
 
 
1460
        /*
 
1461
         * initialize the rel-has-index flag, using hardwired knowledge
 
1462
         */
 
1463
        if (IsBootstrapProcessingMode())
 
1464
        {
 
1465
                /* In bootstrap mode, we have no indexes */
 
1466
                relation->rd_rel->relhasindex = false;
 
1467
        }
 
1468
        else
 
1469
        {
 
1470
                /* Otherwise, all the rels formrdesc is used for have indexes */
 
1471
                relation->rd_rel->relhasindex = true;
 
1472
        }
 
1473
 
 
1474
        /*
 
1475
         * add new reldesc to relcache
 
1476
         */
 
1477
        RelationCacheInsert(relation);
 
1478
 
 
1479
        /* It's fully valid */
 
1480
        relation->rd_isvalid = true;
 
1481
}
 
1482
 
 
1483
 
 
1484
/* ----------------------------------------------------------------
 
1485
 *                               Relation Descriptor Lookup Interface
 
1486
 * ----------------------------------------------------------------
 
1487
 */
 
1488
 
 
1489
/*
 
1490
 *              RelationIdGetRelation
 
1491
 *
 
1492
 *              Lookup a reldesc by OID; make one if not already in cache.
 
1493
 *
 
1494
 *              Returns NULL if no pg_class row could be found for the given relid
 
1495
 *              (suggesting we are trying to access a just-deleted relation).
 
1496
 *              Any other error is reported via elog.
 
1497
 *
 
1498
 *              NB: caller should already have at least AccessShareLock on the
 
1499
 *              relation ID, else there are nasty race conditions.
 
1500
 *
 
1501
 *              NB: relation ref count is incremented, or set to 1 if new entry.
 
1502
 *              Caller should eventually decrement count.  (Usually,
 
1503
 *              that happens by calling RelationClose().)
 
1504
 */
 
1505
Relation
 
1506
RelationIdGetRelation(Oid relationId)
 
1507
{
 
1508
        Relation        rd;
 
1509
 
 
1510
        /*
 
1511
         * first try to find reldesc in the cache
 
1512
         */
 
1513
        RelationIdCacheLookup(relationId, rd);
 
1514
 
 
1515
        if (RelationIsValid(rd))
 
1516
        {
 
1517
                RelationIncrementReferenceCount(rd);
 
1518
                /* revalidate nailed index if necessary */
 
1519
                if (!rd->rd_isvalid)
 
1520
                        RelationReloadIndexInfo(rd);
 
1521
                return rd;
 
1522
        }
 
1523
 
 
1524
        /*
 
1525
         * no reldesc in the cache, so have RelationBuildDesc() build one and add
 
1526
         * it.
 
1527
         */
 
1528
        rd = RelationBuildDesc(relationId, NULL);
 
1529
        if (RelationIsValid(rd))
 
1530
                RelationIncrementReferenceCount(rd);
 
1531
        return rd;
 
1532
}
 
1533
 
 
1534
/* ----------------------------------------------------------------
 
1535
 *                              cache invalidation support routines
 
1536
 * ----------------------------------------------------------------
 
1537
 */
 
1538
 
 
1539
/*
 
1540
 * RelationIncrementReferenceCount
 
1541
 *              Increments relation reference count.
 
1542
 *
 
1543
 * Note: bootstrap mode has its own weird ideas about relation refcount
 
1544
 * behavior; we ought to fix it someday, but for now, just disable
 
1545
 * reference count ownership tracking in bootstrap mode.
 
1546
 */
 
1547
void
 
1548
RelationIncrementReferenceCount(Relation rel)
 
1549
{
 
1550
        ResourceOwnerEnlargeRelationRefs(CurrentResourceOwner);
 
1551
        rel->rd_refcnt += 1;
 
1552
        if (!IsBootstrapProcessingMode())
 
1553
                ResourceOwnerRememberRelationRef(CurrentResourceOwner, rel);
 
1554
}
 
1555
 
 
1556
/*
 
1557
 * RelationDecrementReferenceCount
 
1558
 *              Decrements relation reference count.
 
1559
 */
 
1560
void
 
1561
RelationDecrementReferenceCount(Relation rel)
 
1562
{
 
1563
        Assert(rel->rd_refcnt > 0);
 
1564
        rel->rd_refcnt -= 1;
 
1565
        if (!IsBootstrapProcessingMode())
 
1566
                ResourceOwnerForgetRelationRef(CurrentResourceOwner, rel);
 
1567
}
 
1568
 
 
1569
/*
 
1570
 * RelationClose - close an open relation
 
1571
 *
 
1572
 *      Actually, we just decrement the refcount.
 
1573
 *
 
1574
 *      NOTE: if compiled with -DRELCACHE_FORCE_RELEASE then relcache entries
 
1575
 *      will be freed as soon as their refcount goes to zero.  In combination
 
1576
 *      with aset.c's CLOBBER_FREED_MEMORY option, this provides a good test
 
1577
 *      to catch references to already-released relcache entries.  It slows
 
1578
 *      things down quite a bit, however.
 
1579
 */
 
1580
void
 
1581
RelationClose(Relation relation)
 
1582
{
 
1583
        /* Note: no locking manipulations needed */
 
1584
        RelationDecrementReferenceCount(relation);
 
1585
 
 
1586
#ifdef RELCACHE_FORCE_RELEASE
 
1587
        if (RelationHasReferenceCountZero(relation) &&
 
1588
                relation->rd_createSubid == InvalidSubTransactionId &&
 
1589
                relation->rd_newRelfilenodeSubid == InvalidSubTransactionId)
 
1590
                RelationClearRelation(relation, false);
 
1591
#endif
 
1592
}
 
1593
 
 
1594
/*
 
1595
 * RelationReloadIndexInfo - reload minimal information for an open index
 
1596
 *
 
1597
 *      This function is used only for indexes.  A relcache inval on an index
 
1598
 *      can mean that its pg_class or pg_index row changed.  There are only
 
1599
 *      very limited changes that are allowed to an existing index's schema,
 
1600
 *      so we can update the relcache entry without a complete rebuild; which
 
1601
 *      is fortunate because we can't rebuild an index entry that is "nailed"
 
1602
 *      and/or in active use.  We support full replacement of the pg_class row,
 
1603
 *      as well as updates of a few simple fields of the pg_index row.
 
1604
 *
 
1605
 *      We can't necessarily reread the catalog rows right away; we might be
 
1606
 *      in a failed transaction when we receive the SI notification.  If so,
 
1607
 *      RelationClearRelation just marks the entry as invalid by setting
 
1608
 *      rd_isvalid to false.  This routine is called to fix the entry when it
 
1609
 *      is next needed.
 
1610
 *
 
1611
 *      We assume that at the time we are called, we have at least AccessShareLock
 
1612
 *      on the target index.  (Note: in the calls from RelationClearRelation,
 
1613
 *      this is legitimate because we know the rel has positive refcount.)
 
1614
 */
 
1615
static void
 
1616
RelationReloadIndexInfo(Relation relation)
 
1617
{
 
1618
        bool            indexOK;
 
1619
        HeapTuple       pg_class_tuple;
 
1620
        Form_pg_class relp;
 
1621
 
 
1622
        /* Should be called only for invalidated indexes */
 
1623
        Assert(relation->rd_rel->relkind == RELKIND_INDEX &&
 
1624
                   !relation->rd_isvalid);
 
1625
        /* Should be closed at smgr level */
 
1626
        Assert(relation->rd_smgr == NULL);
 
1627
 
 
1628
        /*
 
1629
         * Read the pg_class row
 
1630
         *
 
1631
         * Don't try to use an indexscan of pg_class_oid_index to reload the info
 
1632
         * for pg_class_oid_index ...
 
1633
         */
 
1634
        indexOK = (RelationGetRelid(relation) != ClassOidIndexId);
 
1635
        pg_class_tuple = ScanPgRelation(RelationGetRelid(relation), indexOK);
 
1636
        if (!HeapTupleIsValid(pg_class_tuple))
 
1637
                elog(ERROR, "could not find pg_class tuple for index %u",
 
1638
                         RelationGetRelid(relation));
 
1639
        relp = (Form_pg_class) GETSTRUCT(pg_class_tuple);
 
1640
        memcpy(relation->rd_rel, relp, CLASS_TUPLE_SIZE);
 
1641
        /* Reload reloptions in case they changed */
 
1642
        if (relation->rd_options)
 
1643
                pfree(relation->rd_options);
 
1644
        RelationParseRelOptions(relation, pg_class_tuple);
 
1645
        /* done with pg_class tuple */
 
1646
        heap_freetuple(pg_class_tuple);
 
1647
        /* We must recalculate physical address in case it changed */
 
1648
        RelationInitPhysicalAddr(relation);
 
1649
        /*
 
1650
         * Must reset targblock, fsm_nblocks and vm_nblocks in case rel was
 
1651
         * truncated
 
1652
         */
 
1653
        relation->rd_targblock = InvalidBlockNumber;
 
1654
        relation->rd_fsm_nblocks = InvalidBlockNumber;
 
1655
        relation->rd_vm_nblocks = InvalidBlockNumber;
 
1656
        /* Must free any AM cached data, too */
 
1657
        if (relation->rd_amcache)
 
1658
                pfree(relation->rd_amcache);
 
1659
        relation->rd_amcache = NULL;
 
1660
 
 
1661
        /*
 
1662
         * For a non-system index, there are fields of the pg_index row that are
 
1663
         * allowed to change, so re-read that row and update the relcache entry.
 
1664
         * Most of the info derived from pg_index (such as support function lookup
 
1665
         * info) cannot change, and indeed the whole point of this routine is to
 
1666
         * update the relcache entry without clobbering that data; so wholesale
 
1667
         * replacement is not appropriate.
 
1668
         */
 
1669
        if (!IsSystemRelation(relation))
 
1670
        {
 
1671
                HeapTuple       tuple;
 
1672
                Form_pg_index index;
 
1673
 
 
1674
                tuple = SearchSysCache(INDEXRELID,
 
1675
                                                           ObjectIdGetDatum(RelationGetRelid(relation)),
 
1676
                                                           0, 0, 0);
 
1677
                if (!HeapTupleIsValid(tuple))
 
1678
                        elog(ERROR, "cache lookup failed for index %u",
 
1679
                                 RelationGetRelid(relation));
 
1680
                index = (Form_pg_index) GETSTRUCT(tuple);
 
1681
 
 
1682
                relation->rd_index->indisvalid = index->indisvalid;
 
1683
                relation->rd_index->indcheckxmin = index->indcheckxmin;
 
1684
                relation->rd_index->indisready = index->indisready;
 
1685
                HeapTupleHeaderSetXmin(relation->rd_indextuple->t_data,
 
1686
                                                           HeapTupleHeaderGetXmin(tuple->t_data));
 
1687
 
 
1688
                ReleaseSysCache(tuple);
 
1689
        }
 
1690
 
 
1691
        /* Okay, now it's valid again */
 
1692
        relation->rd_isvalid = true;
 
1693
}
 
1694
 
 
1695
/*
 
1696
 * RelationClearRelation
 
1697
 *
 
1698
 *       Physically blow away a relation cache entry, or reset it and rebuild
 
1699
 *       it from scratch (that is, from catalog entries).  The latter path is
 
1700
 *       usually used when we are notified of a change to an open relation
 
1701
 *       (one with refcount > 0).  However, this routine just does whichever
 
1702
 *       it's told to do; callers must determine which they want.
 
1703
 *
 
1704
 *       NB: when rebuilding, we'd better hold some lock on the relation.
 
1705
 *       In current usages this is presumed true because it has refcnt > 0.
 
1706
 */
 
1707
static void
 
1708
RelationClearRelation(Relation relation, bool rebuild)
 
1709
{
 
1710
        Oid                     old_reltype = relation->rd_rel->reltype;
 
1711
        MemoryContext oldcxt;
 
1712
 
 
1713
        /*
 
1714
         * Make sure smgr and lower levels close the relation's files, if they
 
1715
         * weren't closed already.  If the relation is not getting deleted, the
 
1716
         * next smgr access should reopen the files automatically.      This ensures
 
1717
         * that the low-level file access state is updated after, say, a vacuum
 
1718
         * truncation.
 
1719
         */
 
1720
        RelationCloseSmgr(relation);
 
1721
 
 
1722
        /*
 
1723
         * Never, never ever blow away a nailed-in system relation, because we'd
 
1724
         * be unable to recover.  However, we must reset rd_targblock, in case we
 
1725
         * got called because of a relation cache flush that was triggered by
 
1726
         * VACUUM.
 
1727
         *
 
1728
         * If it's a nailed index, then we need to re-read the pg_class row to see
 
1729
         * if its relfilenode changed.  We can't necessarily do that here, because
 
1730
         * we might be in a failed transaction.  We assume it's okay to do it if
 
1731
         * there are open references to the relcache entry (cf notes for
 
1732
         * AtEOXact_RelationCache).  Otherwise just mark the entry as possibly
 
1733
         * invalid, and it'll be fixed when next opened.
 
1734
         */
 
1735
        if (relation->rd_isnailed)
 
1736
        {
 
1737
                relation->rd_targblock = InvalidBlockNumber;
 
1738
                relation->rd_fsm_nblocks = InvalidBlockNumber;
 
1739
                relation->rd_vm_nblocks = InvalidBlockNumber;
 
1740
                if (relation->rd_rel->relkind == RELKIND_INDEX)
 
1741
                {
 
1742
                        relation->rd_isvalid = false;           /* needs to be revalidated */
 
1743
                        if (relation->rd_refcnt > 1)
 
1744
                                RelationReloadIndexInfo(relation);
 
1745
                }
 
1746
                return;
 
1747
        }
 
1748
 
 
1749
        /*
 
1750
         * Even non-system indexes should not be blown away if they are open and
 
1751
         * have valid index support information.  This avoids problems with active
 
1752
         * use of the index support information.  As with nailed indexes, we
 
1753
         * re-read the pg_class row to handle possible physical relocation of the
 
1754
         * index, and we check for pg_index updates too.
 
1755
         */
 
1756
        if (relation->rd_rel->relkind == RELKIND_INDEX &&
 
1757
                relation->rd_refcnt > 0 &&
 
1758
                relation->rd_indexcxt != NULL)
 
1759
        {
 
1760
                relation->rd_isvalid = false;   /* needs to be revalidated */
 
1761
                RelationReloadIndexInfo(relation);
 
1762
                return;
 
1763
        }
 
1764
 
 
1765
        /*
 
1766
         * Remove relation from hash tables
 
1767
         *
 
1768
         * Note: we might be reinserting it momentarily, but we must not have it
 
1769
         * visible in the hash tables until it's valid again, so don't try to
 
1770
         * optimize this away...
 
1771
         */
 
1772
        oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
 
1773
        RelationCacheDelete(relation);
 
1774
        MemoryContextSwitchTo(oldcxt);
 
1775
 
 
1776
        /* Clear out catcache's entries for this relation */
 
1777
        CatalogCacheFlushRelation(RelationGetRelid(relation));
 
1778
 
 
1779
        /*
 
1780
         * Free all the subsidiary data structures of the relcache entry. We
 
1781
         * cannot free rd_att if we are trying to rebuild the entry, however,
 
1782
         * because pointers to it may be cached in various places. The rule
 
1783
         * manager might also have pointers into the rewrite rules. So to begin
 
1784
         * with, we can only get rid of these fields:
 
1785
         */
 
1786
        FreeTriggerDesc(relation->trigdesc);
 
1787
        if (relation->rd_indextuple)
 
1788
                pfree(relation->rd_indextuple);
 
1789
        if (relation->rd_am)
 
1790
                pfree(relation->rd_am);
 
1791
        if (relation->rd_rel)
 
1792
                pfree(relation->rd_rel);
 
1793
        if (relation->rd_options)
 
1794
                pfree(relation->rd_options);
 
1795
        list_free(relation->rd_indexlist);
 
1796
        bms_free(relation->rd_indexattr);
 
1797
        if (relation->rd_indexcxt)
 
1798
                MemoryContextDelete(relation->rd_indexcxt);
 
1799
 
 
1800
        /*
 
1801
         * If we're really done with the relcache entry, blow it away. But if
 
1802
         * someone is still using it, reconstruct the whole deal without moving
 
1803
         * the physical RelationData record (so that the someone's pointer is
 
1804
         * still valid).
 
1805
         */
 
1806
        if (!rebuild)
 
1807
        {
 
1808
                /* ok to zap remaining substructure */
 
1809
                flush_rowtype_cache(old_reltype);
 
1810
                /* can't use DecrTupleDescRefCount here */
 
1811
                Assert(relation->rd_att->tdrefcount > 0);
 
1812
                if (--relation->rd_att->tdrefcount == 0)
 
1813
                        FreeTupleDesc(relation->rd_att);
 
1814
                if (relation->rd_rulescxt)
 
1815
                        MemoryContextDelete(relation->rd_rulescxt);
 
1816
                pfree(relation);
 
1817
        }
 
1818
        else
 
1819
        {
 
1820
                /*
 
1821
                 * When rebuilding an open relcache entry, must preserve ref count and
 
1822
                 * rd_createSubid/rd_newRelfilenodeSubid state.  Also attempt to
 
1823
                 * preserve the tupledesc and rewrite-rule substructures in place.
 
1824
                 * (Note: the refcount mechanism for tupledescs may eventually ensure
 
1825
                 * that we don't really need to preserve the tupledesc in-place, but
 
1826
                 * for now there are still a lot of places that assume an open rel's
 
1827
                 * tupledesc won't move.)
 
1828
                 *
 
1829
                 * Note that this process does not touch CurrentResourceOwner; which
 
1830
                 * is good because whatever ref counts the entry may have do not
 
1831
                 * necessarily belong to that resource owner.
 
1832
                 */
 
1833
                Oid                     save_relid = RelationGetRelid(relation);
 
1834
                int                     old_refcnt = relation->rd_refcnt;
 
1835
                SubTransactionId old_createSubid = relation->rd_createSubid;
 
1836
                SubTransactionId old_newRelfilenodeSubid = relation->rd_newRelfilenodeSubid;
 
1837
                struct PgStat_TableStatus *old_pgstat_info = relation->pgstat_info;
 
1838
                TupleDesc       old_att = relation->rd_att;
 
1839
                RuleLock   *old_rules = relation->rd_rules;
 
1840
                MemoryContext old_rulescxt = relation->rd_rulescxt;
 
1841
 
 
1842
                if (RelationBuildDesc(save_relid, relation) != relation)
 
1843
                {
 
1844
                        /* Should only get here if relation was deleted */
 
1845
                        flush_rowtype_cache(old_reltype);
 
1846
                        Assert(old_att->tdrefcount > 0);
 
1847
                        if (--old_att->tdrefcount == 0)
 
1848
                                FreeTupleDesc(old_att);
 
1849
                        if (old_rulescxt)
 
1850
                                MemoryContextDelete(old_rulescxt);
 
1851
                        pfree(relation);
 
1852
                        elog(ERROR, "relation %u deleted while still in use", save_relid);
 
1853
                }
 
1854
                relation->rd_refcnt = old_refcnt;
 
1855
                relation->rd_createSubid = old_createSubid;
 
1856
                relation->rd_newRelfilenodeSubid = old_newRelfilenodeSubid;
 
1857
                relation->pgstat_info = old_pgstat_info;
 
1858
 
 
1859
                if (equalTupleDescs(old_att, relation->rd_att))
 
1860
                {
 
1861
                        /* needn't flush typcache here */
 
1862
                        Assert(relation->rd_att->tdrefcount == 1);
 
1863
                        if (--relation->rd_att->tdrefcount == 0)
 
1864
                                FreeTupleDesc(relation->rd_att);
 
1865
                        relation->rd_att = old_att;
 
1866
                }
 
1867
                else
 
1868
                {
 
1869
                        flush_rowtype_cache(old_reltype);
 
1870
                        Assert(old_att->tdrefcount > 0);
 
1871
                        if (--old_att->tdrefcount == 0)
 
1872
                                FreeTupleDesc(old_att);
 
1873
                }
 
1874
                if (equalRuleLocks(old_rules, relation->rd_rules))
 
1875
                {
 
1876
                        if (relation->rd_rulescxt)
 
1877
                                MemoryContextDelete(relation->rd_rulescxt);
 
1878
                        relation->rd_rules = old_rules;
 
1879
                        relation->rd_rulescxt = old_rulescxt;
 
1880
                }
 
1881
                else
 
1882
                {
 
1883
                        if (old_rulescxt)
 
1884
                                MemoryContextDelete(old_rulescxt);
 
1885
                }
 
1886
        }
 
1887
}
 
1888
 
 
1889
/*
 
1890
 * RelationFlushRelation
 
1891
 *
 
1892
 *       Rebuild the relation if it is open (refcount > 0), else blow it away.
 
1893
 */
 
1894
static void
 
1895
RelationFlushRelation(Relation relation)
 
1896
{
 
1897
        bool            rebuild;
 
1898
 
 
1899
        if (relation->rd_createSubid != InvalidSubTransactionId ||
 
1900
                relation->rd_newRelfilenodeSubid != InvalidSubTransactionId)
 
1901
        {
 
1902
                /*
 
1903
                 * New relcache entries are always rebuilt, not flushed; else we'd
 
1904
                 * forget the "new" status of the relation, which is a useful
 
1905
                 * optimization to have.  Ditto for the new-relfilenode status.
 
1906
                 */
 
1907
                rebuild = true;
 
1908
        }
 
1909
        else
 
1910
        {
 
1911
                /*
 
1912
                 * Pre-existing rels can be dropped from the relcache if not open.
 
1913
                 */
 
1914
                rebuild = !RelationHasReferenceCountZero(relation);
 
1915
        }
 
1916
 
 
1917
        RelationClearRelation(relation, rebuild);
 
1918
}
 
1919
 
 
1920
/*
 
1921
 * RelationForgetRelation - unconditionally remove a relcache entry
 
1922
 *
 
1923
 *                 External interface for destroying a relcache entry when we
 
1924
 *                 drop the relation.
 
1925
 */
 
1926
void
 
1927
RelationForgetRelation(Oid rid)
 
1928
{
 
1929
        Relation        relation;
 
1930
 
 
1931
        RelationIdCacheLookup(rid, relation);
 
1932
 
 
1933
        if (!PointerIsValid(relation))
 
1934
                return;                                 /* not in cache, nothing to do */
 
1935
 
 
1936
        if (!RelationHasReferenceCountZero(relation))
 
1937
                elog(ERROR, "relation %u is still open", rid);
 
1938
 
 
1939
        /* Unconditionally destroy the relcache entry */
 
1940
        RelationClearRelation(relation, false);
 
1941
}
 
1942
 
 
1943
/*
 
1944
 *              RelationCacheInvalidateEntry
 
1945
 *
 
1946
 *              This routine is invoked for SI cache flush messages.
 
1947
 *
 
1948
 * Any relcache entry matching the relid must be flushed.  (Note: caller has
 
1949
 * already determined that the relid belongs to our database or is a shared
 
1950
 * relation.)
 
1951
 *
 
1952
 * We used to skip local relations, on the grounds that they could
 
1953
 * not be targets of cross-backend SI update messages; but it seems
 
1954
 * safer to process them, so that our *own* SI update messages will
 
1955
 * have the same effects during CommandCounterIncrement for both
 
1956
 * local and nonlocal relations.
 
1957
 */
 
1958
void
 
1959
RelationCacheInvalidateEntry(Oid relationId)
 
1960
{
 
1961
        Relation        relation;
 
1962
 
 
1963
        RelationIdCacheLookup(relationId, relation);
 
1964
 
 
1965
        if (PointerIsValid(relation))
 
1966
        {
 
1967
                relcacheInvalsReceived++;
 
1968
                RelationFlushRelation(relation);
 
1969
        }
 
1970
}
 
1971
 
 
1972
/*
 
1973
 * RelationCacheInvalidate
 
1974
 *       Blow away cached relation descriptors that have zero reference counts,
 
1975
 *       and rebuild those with positive reference counts.      Also reset the smgr
 
1976
 *       relation cache.
 
1977
 *
 
1978
 *       This is currently used only to recover from SI message buffer overflow,
 
1979
 *       so we do not touch new-in-transaction relations; they cannot be targets
 
1980
 *       of cross-backend SI updates (and our own updates now go through a
 
1981
 *       separate linked list that isn't limited by the SI message buffer size).
 
1982
 *       Likewise, we need not discard new-relfilenode-in-transaction hints,
 
1983
 *       since any invalidation of those would be a local event.
 
1984
 *
 
1985
 *       We do this in two phases: the first pass deletes deletable items, and
 
1986
 *       the second one rebuilds the rebuildable items.  This is essential for
 
1987
 *       safety, because hash_seq_search only copes with concurrent deletion of
 
1988
 *       the element it is currently visiting.  If a second SI overflow were to
 
1989
 *       occur while we are walking the table, resulting in recursive entry to
 
1990
 *       this routine, we could crash because the inner invocation blows away
 
1991
 *       the entry next to be visited by the outer scan.  But this way is OK,
 
1992
 *       because (a) during the first pass we won't process any more SI messages,
 
1993
 *       so hash_seq_search will complete safely; (b) during the second pass we
 
1994
 *       only hold onto pointers to nondeletable entries.
 
1995
 *
 
1996
 *       The two-phase approach also makes it easy to ensure that we process
 
1997
 *       nailed-in-cache indexes before other nondeletable items, and that we
 
1998
 *       process pg_class_oid_index first of all.  In scenarios where a nailed
 
1999
 *       index has been given a new relfilenode, we have to detect that update
 
2000
 *       before the nailed index is used in reloading any other relcache entry.
 
2001
 */
 
2002
void
 
2003
RelationCacheInvalidate(void)
 
2004
{
 
2005
        HASH_SEQ_STATUS status;
 
2006
        RelIdCacheEnt *idhentry;
 
2007
        Relation        relation;
 
2008
        List       *rebuildFirstList = NIL;
 
2009
        List       *rebuildList = NIL;
 
2010
        ListCell   *l;
 
2011
 
 
2012
        /* Phase 1 */
 
2013
        hash_seq_init(&status, RelationIdCache);
 
2014
 
 
2015
        while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
 
2016
        {
 
2017
                relation = idhentry->reldesc;
 
2018
 
 
2019
                /* Must close all smgr references to avoid leaving dangling ptrs */
 
2020
                RelationCloseSmgr(relation);
 
2021
 
 
2022
                /* Ignore new relations, since they are never SI targets */
 
2023
                if (relation->rd_createSubid != InvalidSubTransactionId)
 
2024
                        continue;
 
2025
 
 
2026
                relcacheInvalsReceived++;
 
2027
 
 
2028
                if (RelationHasReferenceCountZero(relation))
 
2029
                {
 
2030
                        /* Delete this entry immediately */
 
2031
                        Assert(!relation->rd_isnailed);
 
2032
                        RelationClearRelation(relation, false);
 
2033
                }
 
2034
                else
 
2035
                {
 
2036
                        /*
 
2037
                         * Add this entry to list of stuff to rebuild in second pass.
 
2038
                         * pg_class_oid_index goes on the front of rebuildFirstList, other
 
2039
                         * nailed indexes on the back, and everything else into
 
2040
                         * rebuildList (in no particular order).
 
2041
                         */
 
2042
                        if (relation->rd_isnailed &&
 
2043
                                relation->rd_rel->relkind == RELKIND_INDEX)
 
2044
                        {
 
2045
                                if (RelationGetRelid(relation) == ClassOidIndexId)
 
2046
                                        rebuildFirstList = lcons(relation, rebuildFirstList);
 
2047
                                else
 
2048
                                        rebuildFirstList = lappend(rebuildFirstList, relation);
 
2049
                        }
 
2050
                        else
 
2051
                                rebuildList = lcons(relation, rebuildList);
 
2052
                }
 
2053
        }
 
2054
 
 
2055
        /*
 
2056
         * Now zap any remaining smgr cache entries.  This must happen before we
 
2057
         * start to rebuild entries, since that may involve catalog fetches which
 
2058
         * will re-open catalog files.
 
2059
         */
 
2060
        smgrcloseall();
 
2061
 
 
2062
        /* Phase 2: rebuild the items found to need rebuild in phase 1 */
 
2063
        foreach(l, rebuildFirstList)
 
2064
        {
 
2065
                relation = (Relation) lfirst(l);
 
2066
                RelationClearRelation(relation, true);
 
2067
        }
 
2068
        list_free(rebuildFirstList);
 
2069
        foreach(l, rebuildList)
 
2070
        {
 
2071
                relation = (Relation) lfirst(l);
 
2072
                RelationClearRelation(relation, true);
 
2073
        }
 
2074
        list_free(rebuildList);
 
2075
}
 
2076
 
 
2077
/*
 
2078
 * AtEOXact_RelationCache
 
2079
 *
 
2080
 *      Clean up the relcache at main-transaction commit or abort.
 
2081
 *
 
2082
 * Note: this must be called *before* processing invalidation messages.
 
2083
 * In the case of abort, we don't want to try to rebuild any invalidated
 
2084
 * cache entries (since we can't safely do database accesses).  Therefore
 
2085
 * we must reset refcnts before handling pending invalidations.
 
2086
 *
 
2087
 * As of PostgreSQL 8.1, relcache refcnts should get released by the
 
2088
 * ResourceOwner mechanism.  This routine just does a debugging
 
2089
 * cross-check that no pins remain.  However, we also need to do special
 
2090
 * cleanup when the current transaction created any relations or made use
 
2091
 * of forced index lists.
 
2092
 */
 
2093
void
 
2094
AtEOXact_RelationCache(bool isCommit)
 
2095
{
 
2096
        HASH_SEQ_STATUS status;
 
2097
        RelIdCacheEnt *idhentry;
 
2098
 
 
2099
        /*
 
2100
         * To speed up transaction exit, we want to avoid scanning the relcache
 
2101
         * unless there is actually something for this routine to do.  Other than
 
2102
         * the debug-only Assert checks, most transactions don't create any work
 
2103
         * for us to do here, so we keep a static flag that gets set if there is
 
2104
         * anything to do.      (Currently, this means either a relation is created in
 
2105
         * the current xact, or one is given a new relfilenode, or an index list
 
2106
         * is forced.)  For simplicity, the flag remains set till end of top-level
 
2107
         * transaction, even though we could clear it at subtransaction end in
 
2108
         * some cases.
 
2109
         */
 
2110
        if (!need_eoxact_work
 
2111
#ifdef USE_ASSERT_CHECKING
 
2112
                && !assert_enabled
 
2113
#endif
 
2114
                )
 
2115
                return;
 
2116
 
 
2117
        hash_seq_init(&status, RelationIdCache);
 
2118
 
 
2119
        while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
 
2120
        {
 
2121
                Relation        relation = idhentry->reldesc;
 
2122
 
 
2123
                /*
 
2124
                 * The relcache entry's ref count should be back to its normal
 
2125
                 * not-in-a-transaction state: 0 unless it's nailed in cache.
 
2126
                 *
 
2127
                 * In bootstrap mode, this is NOT true, so don't check it --- the
 
2128
                 * bootstrap code expects relations to stay open across start/commit
 
2129
                 * transaction calls.  (That seems bogus, but it's not worth fixing.)
 
2130
                 */
 
2131
#ifdef USE_ASSERT_CHECKING
 
2132
                if (!IsBootstrapProcessingMode())
 
2133
                {
 
2134
                        int                     expected_refcnt;
 
2135
 
 
2136
                        expected_refcnt = relation->rd_isnailed ? 1 : 0;
 
2137
                        Assert(relation->rd_refcnt == expected_refcnt);
 
2138
                }
 
2139
#endif
 
2140
 
 
2141
                /*
 
2142
                 * Is it a relation created in the current transaction?
 
2143
                 *
 
2144
                 * During commit, reset the flag to zero, since we are now out of the
 
2145
                 * creating transaction.  During abort, simply delete the relcache
 
2146
                 * entry --- it isn't interesting any longer.  (NOTE: if we have
 
2147
                 * forgotten the new-ness of a new relation due to a forced cache
 
2148
                 * flush, the entry will get deleted anyway by shared-cache-inval
 
2149
                 * processing of the aborted pg_class insertion.)
 
2150
                 */
 
2151
                if (relation->rd_createSubid != InvalidSubTransactionId)
 
2152
                {
 
2153
                        if (isCommit)
 
2154
                                relation->rd_createSubid = InvalidSubTransactionId;
 
2155
                        else
 
2156
                        {
 
2157
                                RelationClearRelation(relation, false);
 
2158
                                continue;
 
2159
                        }
 
2160
                }
 
2161
 
 
2162
                /*
 
2163
                 * Likewise, reset the hint about the relfilenode being new.
 
2164
                 */
 
2165
                relation->rd_newRelfilenodeSubid = InvalidSubTransactionId;
 
2166
 
 
2167
                /*
 
2168
                 * Flush any temporary index list.
 
2169
                 */
 
2170
                if (relation->rd_indexvalid == 2)
 
2171
                {
 
2172
                        list_free(relation->rd_indexlist);
 
2173
                        relation->rd_indexlist = NIL;
 
2174
                        relation->rd_oidindex = InvalidOid;
 
2175
                        relation->rd_indexvalid = 0;
 
2176
                }
 
2177
        }
 
2178
 
 
2179
        /* Once done with the transaction, we can reset need_eoxact_work */
 
2180
        need_eoxact_work = false;
 
2181
}
 
2182
 
 
2183
/*
 
2184
 * AtEOSubXact_RelationCache
 
2185
 *
 
2186
 *      Clean up the relcache at sub-transaction commit or abort.
 
2187
 *
 
2188
 * Note: this must be called *before* processing invalidation messages.
 
2189
 */
 
2190
void
 
2191
AtEOSubXact_RelationCache(bool isCommit, SubTransactionId mySubid,
 
2192
                                                  SubTransactionId parentSubid)
 
2193
{
 
2194
        HASH_SEQ_STATUS status;
 
2195
        RelIdCacheEnt *idhentry;
 
2196
 
 
2197
        /*
 
2198
         * Skip the relcache scan if nothing to do --- see notes for
 
2199
         * AtEOXact_RelationCache.
 
2200
         */
 
2201
        if (!need_eoxact_work)
 
2202
                return;
 
2203
 
 
2204
        hash_seq_init(&status, RelationIdCache);
 
2205
 
 
2206
        while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
 
2207
        {
 
2208
                Relation        relation = idhentry->reldesc;
 
2209
 
 
2210
                /*
 
2211
                 * Is it a relation created in the current subtransaction?
 
2212
                 *
 
2213
                 * During subcommit, mark it as belonging to the parent, instead.
 
2214
                 * During subabort, simply delete the relcache entry.
 
2215
                 */
 
2216
                if (relation->rd_createSubid == mySubid)
 
2217
                {
 
2218
                        if (isCommit)
 
2219
                                relation->rd_createSubid = parentSubid;
 
2220
                        else
 
2221
                        {
 
2222
                                Assert(RelationHasReferenceCountZero(relation));
 
2223
                                RelationClearRelation(relation, false);
 
2224
                                continue;
 
2225
                        }
 
2226
                }
 
2227
 
 
2228
                /*
 
2229
                 * Likewise, update or drop any new-relfilenode-in-subtransaction
 
2230
                 * hint.
 
2231
                 */
 
2232
                if (relation->rd_newRelfilenodeSubid == mySubid)
 
2233
                {
 
2234
                        if (isCommit)
 
2235
                                relation->rd_newRelfilenodeSubid = parentSubid;
 
2236
                        else
 
2237
                                relation->rd_newRelfilenodeSubid = InvalidSubTransactionId;
 
2238
                }
 
2239
 
 
2240
                /*
 
2241
                 * Flush any temporary index list.
 
2242
                 */
 
2243
                if (relation->rd_indexvalid == 2)
 
2244
                {
 
2245
                        list_free(relation->rd_indexlist);
 
2246
                        relation->rd_indexlist = NIL;
 
2247
                        relation->rd_oidindex = InvalidOid;
 
2248
                        relation->rd_indexvalid = 0;
 
2249
                }
 
2250
        }
 
2251
}
 
2252
 
 
2253
/*
 
2254
 * RelationCacheMarkNewRelfilenode
 
2255
 *
 
2256
 *      Mark the rel as having been given a new relfilenode in the current
 
2257
 *      (sub) transaction.      This is a hint that can be used to optimize
 
2258
 *      later operations on the rel in the same transaction.
 
2259
 */
 
2260
void
 
2261
RelationCacheMarkNewRelfilenode(Relation rel)
 
2262
{
 
2263
        /* Mark it... */
 
2264
        rel->rd_newRelfilenodeSubid = GetCurrentSubTransactionId();
 
2265
        /* ... and now we have eoxact cleanup work to do */
 
2266
        need_eoxact_work = true;
 
2267
}
 
2268
 
 
2269
 
 
2270
/*
 
2271
 *              RelationBuildLocalRelation
 
2272
 *                      Build a relcache entry for an about-to-be-created relation,
 
2273
 *                      and enter it into the relcache.
 
2274
 */
 
2275
Relation
 
2276
RelationBuildLocalRelation(const char *relname,
 
2277
                                                   Oid relnamespace,
 
2278
                                                   TupleDesc tupDesc,
 
2279
                                                   Oid relid,
 
2280
                                                   Oid reltablespace,
 
2281
                                                   bool shared_relation)
 
2282
{
 
2283
        Relation        rel;
 
2284
        MemoryContext oldcxt;
 
2285
        int                     natts = tupDesc->natts;
 
2286
        int                     i;
 
2287
        bool            has_not_null;
 
2288
        bool            nailit;
 
2289
 
 
2290
        AssertArg(natts >= 0);
 
2291
 
 
2292
        /*
 
2293
         * check for creation of a rel that must be nailed in cache.
 
2294
         *
 
2295
         * XXX this list had better match RelationCacheInitializePhase2's list.
 
2296
         */
 
2297
        switch (relid)
 
2298
        {
 
2299
                case RelationRelationId:
 
2300
                case AttributeRelationId:
 
2301
                case ProcedureRelationId:
 
2302
                case TypeRelationId:
 
2303
                        nailit = true;
 
2304
                        break;
 
2305
                default:
 
2306
                        nailit = false;
 
2307
                        break;
 
2308
        }
 
2309
 
 
2310
        /*
 
2311
         * check that hardwired list of shared rels matches what's in the
 
2312
         * bootstrap .bki file.  If you get a failure here during initdb, you
 
2313
         * probably need to fix IsSharedRelation() to match whatever you've done
 
2314
         * to the set of shared relations.
 
2315
         */
 
2316
        if (shared_relation != IsSharedRelation(relid))
 
2317
                elog(ERROR, "shared_relation flag for \"%s\" does not match IsSharedRelation(%u)",
 
2318
                         relname, relid);
 
2319
 
 
2320
        /*
 
2321
         * switch to the cache context to create the relcache entry.
 
2322
         */
 
2323
        if (!CacheMemoryContext)
 
2324
                CreateCacheMemoryContext();
 
2325
 
 
2326
        oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
 
2327
 
 
2328
        /*
 
2329
         * allocate a new relation descriptor and fill in basic state fields.
 
2330
         */
 
2331
        rel = (Relation) palloc0(sizeof(RelationData));
 
2332
 
 
2333
        rel->rd_targblock = InvalidBlockNumber;
 
2334
        rel->rd_fsm_nblocks = InvalidBlockNumber;
 
2335
        rel->rd_vm_nblocks = InvalidBlockNumber;
 
2336
 
 
2337
        /* make sure relation is marked as having no open file yet */
 
2338
        rel->rd_smgr = NULL;
 
2339
 
 
2340
        /* mark it nailed if appropriate */
 
2341
        rel->rd_isnailed = nailit;
 
2342
 
 
2343
        rel->rd_refcnt = nailit ? 1 : 0;
 
2344
 
 
2345
        /* it's being created in this transaction */
 
2346
        rel->rd_createSubid = GetCurrentSubTransactionId();
 
2347
        rel->rd_newRelfilenodeSubid = InvalidSubTransactionId;
 
2348
 
 
2349
        /* must flag that we have rels created in this transaction */
 
2350
        need_eoxact_work = true;
 
2351
 
 
2352
        /* is it a temporary relation? */
 
2353
        rel->rd_istemp = isTempOrToastNamespace(relnamespace);
 
2354
 
 
2355
        /*
 
2356
         * create a new tuple descriptor from the one passed in.  We do this
 
2357
         * partly to copy it into the cache context, and partly because the new
 
2358
         * relation can't have any defaults or constraints yet; they have to be
 
2359
         * added in later steps, because they require additions to multiple system
 
2360
         * catalogs.  We can copy attnotnull constraints here, however.
 
2361
         */
 
2362
        rel->rd_att = CreateTupleDescCopy(tupDesc);
 
2363
        rel->rd_att->tdrefcount = 1;    /* mark as refcounted */
 
2364
        has_not_null = false;
 
2365
        for (i = 0; i < natts; i++)
 
2366
        {
 
2367
                rel->rd_att->attrs[i]->attnotnull = tupDesc->attrs[i]->attnotnull;
 
2368
                has_not_null |= tupDesc->attrs[i]->attnotnull;
 
2369
        }
 
2370
 
 
2371
        if (has_not_null)
 
2372
        {
 
2373
                TupleConstr *constr = (TupleConstr *) palloc0(sizeof(TupleConstr));
 
2374
 
 
2375
                constr->has_not_null = true;
 
2376
                rel->rd_att->constr = constr;
 
2377
        }
 
2378
 
 
2379
        /*
 
2380
         * initialize relation tuple form (caller may add/override data later)
 
2381
         */
 
2382
        rel->rd_rel = (Form_pg_class) palloc0(CLASS_TUPLE_SIZE);
 
2383
 
 
2384
        namestrcpy(&rel->rd_rel->relname, relname);
 
2385
        rel->rd_rel->relnamespace = relnamespace;
 
2386
 
 
2387
        rel->rd_rel->relkind = RELKIND_UNCATALOGED;
 
2388
        rel->rd_rel->relhasoids = rel->rd_att->tdhasoid;
 
2389
        rel->rd_rel->relnatts = natts;
 
2390
        rel->rd_rel->reltype = InvalidOid;
 
2391
        /* needed when bootstrapping: */
 
2392
        rel->rd_rel->relowner = BOOTSTRAP_SUPERUSERID;
 
2393
 
 
2394
        /*
 
2395
         * Insert relation physical and logical identifiers (OIDs) into the right
 
2396
         * places.      Note that the physical ID (relfilenode) is initially the same
 
2397
         * as the logical ID (OID).
 
2398
         */
 
2399
        rel->rd_rel->relisshared = shared_relation;
 
2400
 
 
2401
        RelationGetRelid(rel) = relid;
 
2402
 
 
2403
        for (i = 0; i < natts; i++)
 
2404
                rel->rd_att->attrs[i]->attrelid = relid;
 
2405
 
 
2406
        rel->rd_rel->relfilenode = relid;
 
2407
        rel->rd_rel->reltablespace = reltablespace;
 
2408
 
 
2409
        RelationInitLockInfo(rel);      /* see lmgr.c */
 
2410
 
 
2411
        RelationInitPhysicalAddr(rel);
 
2412
 
 
2413
        /*
 
2414
         * Okay to insert into the relcache hash tables.
 
2415
         */
 
2416
        RelationCacheInsert(rel);
 
2417
 
 
2418
        /*
 
2419
         * done building relcache entry.
 
2420
         */
 
2421
        MemoryContextSwitchTo(oldcxt);
 
2422
 
 
2423
        /* It's fully valid */
 
2424
        rel->rd_isvalid = true;
 
2425
 
 
2426
        /*
 
2427
         * Caller expects us to pin the returned entry.
 
2428
         */
 
2429
        RelationIncrementReferenceCount(rel);
 
2430
 
 
2431
        return rel;
 
2432
}
 
2433
 
 
2434
/*
 
2435
 *              RelationCacheInitialize
 
2436
 *
 
2437
 *              This initializes the relation descriptor cache.  At the time
 
2438
 *              that this is invoked, we can't do database access yet (mainly
 
2439
 *              because the transaction subsystem is not up); all we are doing
 
2440
 *              is making an empty cache hashtable.  This must be done before
 
2441
 *              starting the initialization transaction, because otherwise
 
2442
 *              AtEOXact_RelationCache would crash if that transaction aborts
 
2443
 *              before we can get the relcache set up.
 
2444
 */
 
2445
 
 
2446
#define INITRELCACHESIZE                400
 
2447
 
 
2448
void
 
2449
RelationCacheInitialize(void)
 
2450
{
 
2451
        MemoryContext oldcxt;
 
2452
        HASHCTL         ctl;
 
2453
 
 
2454
        /*
 
2455
         * switch to cache memory context
 
2456
         */
 
2457
        if (!CacheMemoryContext)
 
2458
                CreateCacheMemoryContext();
 
2459
 
 
2460
        oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
 
2461
 
 
2462
        /*
 
2463
         * create hashtable that indexes the relcache
 
2464
         */
 
2465
        MemSet(&ctl, 0, sizeof(ctl));
 
2466
        ctl.keysize = sizeof(Oid);
 
2467
        ctl.entrysize = sizeof(RelIdCacheEnt);
 
2468
        ctl.hash = oid_hash;
 
2469
        RelationIdCache = hash_create("Relcache by OID", INITRELCACHESIZE,
 
2470
                                                                  &ctl, HASH_ELEM | HASH_FUNCTION);
 
2471
 
 
2472
        MemoryContextSwitchTo(oldcxt);
 
2473
}
 
2474
 
 
2475
/*
 
2476
 *              RelationCacheInitializePhase2
 
2477
 *
 
2478
 *              This is called as soon as the catcache and transaction system
 
2479
 *              are functional.  At this point we can actually read data from
 
2480
 *              the system catalogs.  We first try to read pre-computed relcache
 
2481
 *              entries from the pg_internal.init file.  If that's missing or
 
2482
 *              broken, make phony entries for the minimum set of nailed-in-cache
 
2483
 *              relations.      Then (unless bootstrapping) make sure we have entries
 
2484
 *              for the critical system indexes.  Once we've done all this, we
 
2485
 *              have enough infrastructure to open any system catalog or use any
 
2486
 *              catcache.  The last step is to rewrite pg_internal.init if needed.
 
2487
 */
 
2488
void
 
2489
RelationCacheInitializePhase2(void)
 
2490
{
 
2491
        HASH_SEQ_STATUS status;
 
2492
        RelIdCacheEnt *idhentry;
 
2493
        MemoryContext oldcxt;
 
2494
        bool            needNewCacheFile = false;
 
2495
 
 
2496
        /*
 
2497
         * switch to cache memory context
 
2498
         */
 
2499
        oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
 
2500
 
 
2501
        /*
 
2502
         * Try to load the relcache cache file.  If unsuccessful, bootstrap the
 
2503
         * cache with pre-made descriptors for the critical "nailed-in" system
 
2504
         * catalogs.
 
2505
         */
 
2506
        if (IsBootstrapProcessingMode() ||
 
2507
                !load_relcache_init_file())
 
2508
        {
 
2509
                needNewCacheFile = true;
 
2510
 
 
2511
                formrdesc("pg_class", PG_CLASS_RELTYPE_OID,
 
2512
                                  true, Natts_pg_class, Desc_pg_class);
 
2513
                formrdesc("pg_attribute", PG_ATTRIBUTE_RELTYPE_OID,
 
2514
                                  false, Natts_pg_attribute, Desc_pg_attribute);
 
2515
                formrdesc("pg_proc", PG_PROC_RELTYPE_OID,
 
2516
                                  true, Natts_pg_proc, Desc_pg_proc);
 
2517
                formrdesc("pg_type", PG_TYPE_RELTYPE_OID,
 
2518
                                  true, Natts_pg_type, Desc_pg_type);
 
2519
 
 
2520
#define NUM_CRITICAL_RELS       4       /* fix if you change list above */
 
2521
        }
 
2522
 
 
2523
        MemoryContextSwitchTo(oldcxt);
 
2524
 
 
2525
        /* In bootstrap mode, the faked-up formrdesc info is all we'll have */
 
2526
        if (IsBootstrapProcessingMode())
 
2527
                return;
 
2528
 
 
2529
        /*
 
2530
         * If we didn't get the critical system indexes loaded into relcache, do
 
2531
         * so now.      These are critical because the catcache and/or opclass cache
 
2532
         * depend on them for fetches done during relcache load.  Thus, we have an
 
2533
         * infinite-recursion problem.  We can break the recursion by doing
 
2534
         * heapscans instead of indexscans at certain key spots. To avoid hobbling
 
2535
         * performance, we only want to do that until we have the critical indexes
 
2536
         * loaded into relcache.  Thus, the flag criticalRelcachesBuilt is used to
 
2537
         * decide whether to do heapscan or indexscan at the key spots, and we set
 
2538
         * it true after we've loaded the critical indexes.
 
2539
         *
 
2540
         * The critical indexes are marked as "nailed in cache", partly to make it
 
2541
         * easy for load_relcache_init_file to count them, but mainly because we
 
2542
         * cannot flush and rebuild them once we've set criticalRelcachesBuilt to
 
2543
         * true.  (NOTE: perhaps it would be possible to reload them by
 
2544
         * temporarily setting criticalRelcachesBuilt to false again.  For now,
 
2545
         * though, we just nail 'em in.)
 
2546
         *
 
2547
         * RewriteRelRulenameIndexId and TriggerRelidNameIndexId are not critical
 
2548
         * in the same way as the others, because the critical catalogs don't
 
2549
         * (currently) have any rules or triggers, and so these indexes can be
 
2550
         * rebuilt without inducing recursion.  However they are used during
 
2551
         * relcache load when a rel does have rules or triggers, so we choose to
 
2552
         * nail them for performance reasons.
 
2553
         */
 
2554
        if (!criticalRelcachesBuilt)
 
2555
        {
 
2556
                Relation        ird;
 
2557
 
 
2558
#define LOAD_CRIT_INDEX(indexoid) \
 
2559
                do { \
 
2560
                        LockRelationOid(indexoid, AccessShareLock); \
 
2561
                        ird = RelationBuildDesc(indexoid, NULL); \
 
2562
                        if (ird == NULL) \
 
2563
                                elog(PANIC, "could not open critical system index %u", \
 
2564
                                         indexoid); \
 
2565
                        ird->rd_isnailed = true; \
 
2566
                        ird->rd_refcnt = 1; \
 
2567
                        UnlockRelationOid(indexoid, AccessShareLock); \
 
2568
                } while (0)
 
2569
 
 
2570
                LOAD_CRIT_INDEX(ClassOidIndexId);
 
2571
                LOAD_CRIT_INDEX(AttributeRelidNumIndexId);
 
2572
                LOAD_CRIT_INDEX(IndexRelidIndexId);
 
2573
                LOAD_CRIT_INDEX(OpclassOidIndexId);
 
2574
                LOAD_CRIT_INDEX(AccessMethodStrategyIndexId);
 
2575
                LOAD_CRIT_INDEX(AccessMethodProcedureIndexId);
 
2576
                LOAD_CRIT_INDEX(OperatorOidIndexId);
 
2577
                LOAD_CRIT_INDEX(RewriteRelRulenameIndexId);
 
2578
                LOAD_CRIT_INDEX(TriggerRelidNameIndexId);
 
2579
 
 
2580
#define NUM_CRITICAL_INDEXES    9               /* fix if you change list above */
 
2581
 
 
2582
                criticalRelcachesBuilt = true;
 
2583
        }
 
2584
 
 
2585
        /*
 
2586
         * Now, scan all the relcache entries and update anything that might be
 
2587
         * wrong in the results from formrdesc or the relcache cache file. If we
 
2588
         * faked up relcache entries using formrdesc, then read the real pg_class
 
2589
         * rows and replace the fake entries with them. Also, if any of the
 
2590
         * relcache entries have rules or triggers, load that info the hard way
 
2591
         * since it isn't recorded in the cache file.
 
2592
         */
 
2593
        hash_seq_init(&status, RelationIdCache);
 
2594
 
 
2595
        while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
 
2596
        {
 
2597
                Relation        relation = idhentry->reldesc;
 
2598
 
 
2599
                /*
 
2600
                 * If it's a faked-up entry, read the real pg_class tuple.
 
2601
                 */
 
2602
                if (needNewCacheFile && relation->rd_isnailed)
 
2603
                {
 
2604
                        HeapTuple       htup;
 
2605
                        Form_pg_class relp;
 
2606
 
 
2607
                        htup = SearchSysCache(RELOID,
 
2608
                                                                ObjectIdGetDatum(RelationGetRelid(relation)),
 
2609
                                                                  0, 0, 0);
 
2610
                        if (!HeapTupleIsValid(htup))
 
2611
                                elog(FATAL, "cache lookup failed for relation %u",
 
2612
                                         RelationGetRelid(relation));
 
2613
                        relp = (Form_pg_class) GETSTRUCT(htup);
 
2614
 
 
2615
                        /*
 
2616
                         * Copy tuple to relation->rd_rel. (See notes in
 
2617
                         * AllocateRelationDesc())
 
2618
                         */
 
2619
                        Assert(relation->rd_rel != NULL);
 
2620
                        memcpy((char *) relation->rd_rel, (char *) relp, CLASS_TUPLE_SIZE);
 
2621
 
 
2622
                        /* Update rd_options while we have the tuple */
 
2623
                        if (relation->rd_options)
 
2624
                                pfree(relation->rd_options);
 
2625
                        RelationParseRelOptions(relation, htup);
 
2626
 
 
2627
                        /*
 
2628
                         * Also update the derived fields in rd_att.
 
2629
                         */
 
2630
                        relation->rd_att->tdtypeid = relp->reltype;
 
2631
                        relation->rd_att->tdtypmod = -1;        /* unnecessary, but... */
 
2632
                        relation->rd_att->tdhasoid = relp->relhasoids;
 
2633
 
 
2634
                        ReleaseSysCache(htup);
 
2635
                }
 
2636
 
 
2637
                /*
 
2638
                 * Fix data that isn't saved in relcache cache file.
 
2639
                 */
 
2640
                if (relation->rd_rel->relhasrules && relation->rd_rules == NULL)
 
2641
                        RelationBuildRuleLock(relation);
 
2642
                if (relation->rd_rel->relhastriggers && relation->trigdesc == NULL)
 
2643
                        RelationBuildTriggers(relation);
 
2644
        }
 
2645
 
 
2646
        /*
 
2647
         * Lastly, write out a new relcache cache file if one is needed.
 
2648
         */
 
2649
        if (needNewCacheFile)
 
2650
        {
 
2651
                /*
 
2652
                 * Force all the catcaches to finish initializing and thereby open the
 
2653
                 * catalogs and indexes they use.  This will preload the relcache with
 
2654
                 * entries for all the most important system catalogs and indexes, so
 
2655
                 * that the init file will be most useful for future backends.
 
2656
                 */
 
2657
                InitCatalogCachePhase2();
 
2658
 
 
2659
                /* now write the file */
 
2660
                write_relcache_init_file();
 
2661
        }
 
2662
}
 
2663
 
 
2664
/*
 
2665
 * GetPgClassDescriptor -- get a predefined tuple descriptor for pg_class
 
2666
 * GetPgIndexDescriptor -- get a predefined tuple descriptor for pg_index
 
2667
 *
 
2668
 * We need this kluge because we have to be able to access non-fixed-width
 
2669
 * fields of pg_class and pg_index before we have the standard catalog caches
 
2670
 * available.  We use predefined data that's set up in just the same way as
 
2671
 * the bootstrapped reldescs used by formrdesc().  The resulting tupdesc is
 
2672
 * not 100% kosher: it does not have the correct rowtype OID in tdtypeid, nor
 
2673
 * does it have a TupleConstr field.  But it's good enough for the purpose of
 
2674
 * extracting fields.
 
2675
 */
 
2676
static TupleDesc
 
2677
BuildHardcodedDescriptor(int natts, Form_pg_attribute attrs, bool hasoids)
 
2678
{
 
2679
        TupleDesc       result;
 
2680
        MemoryContext oldcxt;
 
2681
        int                     i;
 
2682
 
 
2683
        oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
 
2684
 
 
2685
        result = CreateTemplateTupleDesc(natts, hasoids);
 
2686
        result->tdtypeid = RECORDOID;           /* not right, but we don't care */
 
2687
        result->tdtypmod = -1;
 
2688
 
 
2689
        for (i = 0; i < natts; i++)
 
2690
        {
 
2691
                memcpy(result->attrs[i], &attrs[i], ATTRIBUTE_FIXED_PART_SIZE);
 
2692
                /* make sure attcacheoff is valid */
 
2693
                result->attrs[i]->attcacheoff = -1;
 
2694
        }
 
2695
 
 
2696
        /* initialize first attribute's attcacheoff, cf RelationBuildTupleDesc */
 
2697
        result->attrs[0]->attcacheoff = 0;
 
2698
 
 
2699
        /* Note: we don't bother to set up a TupleConstr entry */
 
2700
 
 
2701
        MemoryContextSwitchTo(oldcxt);
 
2702
 
 
2703
        return result;
 
2704
}
 
2705
 
 
2706
static TupleDesc
 
2707
GetPgClassDescriptor(void)
 
2708
{
 
2709
        static TupleDesc pgclassdesc = NULL;
 
2710
 
 
2711
        /* Already done? */
 
2712
        if (pgclassdesc == NULL)
 
2713
                pgclassdesc = BuildHardcodedDescriptor(Natts_pg_class,
 
2714
                                                                                           Desc_pg_class,
 
2715
                                                                                           true);
 
2716
 
 
2717
        return pgclassdesc;
 
2718
}
 
2719
 
 
2720
static TupleDesc
 
2721
GetPgIndexDescriptor(void)
 
2722
{
 
2723
        static TupleDesc pgindexdesc = NULL;
 
2724
 
 
2725
        /* Already done? */
 
2726
        if (pgindexdesc == NULL)
 
2727
                pgindexdesc = BuildHardcodedDescriptor(Natts_pg_index,
 
2728
                                                                                           Desc_pg_index,
 
2729
                                                                                           false);
 
2730
 
 
2731
        return pgindexdesc;
 
2732
}
 
2733
 
 
2734
static void
 
2735
AttrDefaultFetch(Relation relation)
 
2736
{
 
2737
        AttrDefault *attrdef = relation->rd_att->constr->defval;
 
2738
        int                     ndef = relation->rd_att->constr->num_defval;
 
2739
        Relation        adrel;
 
2740
        SysScanDesc adscan;
 
2741
        ScanKeyData skey;
 
2742
        HeapTuple       htup;
 
2743
        Datum           val;
 
2744
        bool            isnull;
 
2745
        int                     found;
 
2746
        int                     i;
 
2747
 
 
2748
        ScanKeyInit(&skey,
 
2749
                                Anum_pg_attrdef_adrelid,
 
2750
                                BTEqualStrategyNumber, F_OIDEQ,
 
2751
                                ObjectIdGetDatum(RelationGetRelid(relation)));
 
2752
 
 
2753
        adrel = heap_open(AttrDefaultRelationId, AccessShareLock);
 
2754
        adscan = systable_beginscan(adrel, AttrDefaultIndexId, true,
 
2755
                                                                SnapshotNow, 1, &skey);
 
2756
        found = 0;
 
2757
 
 
2758
        while (HeapTupleIsValid(htup = systable_getnext(adscan)))
 
2759
        {
 
2760
                Form_pg_attrdef adform = (Form_pg_attrdef) GETSTRUCT(htup);
 
2761
 
 
2762
                for (i = 0; i < ndef; i++)
 
2763
                {
 
2764
                        if (adform->adnum != attrdef[i].adnum)
 
2765
                                continue;
 
2766
                        if (attrdef[i].adbin != NULL)
 
2767
                                elog(WARNING, "multiple attrdef records found for attr %s of rel %s",
 
2768
                                NameStr(relation->rd_att->attrs[adform->adnum - 1]->attname),
 
2769
                                         RelationGetRelationName(relation));
 
2770
                        else
 
2771
                                found++;
 
2772
 
 
2773
                        val = fastgetattr(htup,
 
2774
                                                          Anum_pg_attrdef_adbin,
 
2775
                                                          adrel->rd_att, &isnull);
 
2776
                        if (isnull)
 
2777
                                elog(WARNING, "null adbin for attr %s of rel %s",
 
2778
                                NameStr(relation->rd_att->attrs[adform->adnum - 1]->attname),
 
2779
                                         RelationGetRelationName(relation));
 
2780
                        else
 
2781
                                attrdef[i].adbin = MemoryContextStrdup(CacheMemoryContext,
 
2782
                                                                                                        TextDatumGetCString(val));
 
2783
                        break;
 
2784
                }
 
2785
 
 
2786
                if (i >= ndef)
 
2787
                        elog(WARNING, "unexpected attrdef record found for attr %d of rel %s",
 
2788
                                 adform->adnum, RelationGetRelationName(relation));
 
2789
        }
 
2790
 
 
2791
        systable_endscan(adscan);
 
2792
        heap_close(adrel, AccessShareLock);
 
2793
 
 
2794
        if (found != ndef)
 
2795
                elog(WARNING, "%d attrdef record(s) missing for rel %s",
 
2796
                         ndef - found, RelationGetRelationName(relation));
 
2797
}
 
2798
 
 
2799
static void
 
2800
CheckConstraintFetch(Relation relation)
 
2801
{
 
2802
        ConstrCheck *check = relation->rd_att->constr->check;
 
2803
        int                     ncheck = relation->rd_att->constr->num_check;
 
2804
        Relation        conrel;
 
2805
        SysScanDesc conscan;
 
2806
        ScanKeyData skey[1];
 
2807
        HeapTuple       htup;
 
2808
        Datum           val;
 
2809
        bool            isnull;
 
2810
        int                     found = 0;
 
2811
 
 
2812
        ScanKeyInit(&skey[0],
 
2813
                                Anum_pg_constraint_conrelid,
 
2814
                                BTEqualStrategyNumber, F_OIDEQ,
 
2815
                                ObjectIdGetDatum(RelationGetRelid(relation)));
 
2816
 
 
2817
        conrel = heap_open(ConstraintRelationId, AccessShareLock);
 
2818
        conscan = systable_beginscan(conrel, ConstraintRelidIndexId, true,
 
2819
                                                                 SnapshotNow, 1, skey);
 
2820
 
 
2821
        while (HeapTupleIsValid(htup = systable_getnext(conscan)))
 
2822
        {
 
2823
                Form_pg_constraint conform = (Form_pg_constraint) GETSTRUCT(htup);
 
2824
 
 
2825
                /* We want check constraints only */
 
2826
                if (conform->contype != CONSTRAINT_CHECK)
 
2827
                        continue;
 
2828
 
 
2829
                if (found >= ncheck)
 
2830
                        elog(ERROR, "unexpected constraint record found for rel %s",
 
2831
                                 RelationGetRelationName(relation));
 
2832
 
 
2833
                check[found].ccname = MemoryContextStrdup(CacheMemoryContext,
 
2834
                                                                                                  NameStr(conform->conname));
 
2835
 
 
2836
                /* Grab and test conbin is actually set */
 
2837
                val = fastgetattr(htup,
 
2838
                                                  Anum_pg_constraint_conbin,
 
2839
                                                  conrel->rd_att, &isnull);
 
2840
                if (isnull)
 
2841
                        elog(ERROR, "null conbin for rel %s",
 
2842
                                 RelationGetRelationName(relation));
 
2843
 
 
2844
                check[found].ccbin = MemoryContextStrdup(CacheMemoryContext,
 
2845
                                                                                                 TextDatumGetCString(val));
 
2846
                found++;
 
2847
        }
 
2848
 
 
2849
        systable_endscan(conscan);
 
2850
        heap_close(conrel, AccessShareLock);
 
2851
 
 
2852
        if (found != ncheck)
 
2853
                elog(ERROR, "%d constraint record(s) missing for rel %s",
 
2854
                         ncheck - found, RelationGetRelationName(relation));
 
2855
}
 
2856
 
 
2857
/*
 
2858
 * RelationGetIndexList -- get a list of OIDs of indexes on this relation
 
2859
 *
 
2860
 * The index list is created only if someone requests it.  We scan pg_index
 
2861
 * to find relevant indexes, and add the list to the relcache entry so that
 
2862
 * we won't have to compute it again.  Note that shared cache inval of a
 
2863
 * relcache entry will delete the old list and set rd_indexvalid to 0,
 
2864
 * so that we must recompute the index list on next request.  This handles
 
2865
 * creation or deletion of an index.
 
2866
 *
 
2867
 * The returned list is guaranteed to be sorted in order by OID.  This is
 
2868
 * needed by the executor, since for index types that we obtain exclusive
 
2869
 * locks on when updating the index, all backends must lock the indexes in
 
2870
 * the same order or we will get deadlocks (see ExecOpenIndices()).  Any
 
2871
 * consistent ordering would do, but ordering by OID is easy.
 
2872
 *
 
2873
 * Since shared cache inval causes the relcache's copy of the list to go away,
 
2874
 * we return a copy of the list palloc'd in the caller's context.  The caller
 
2875
 * may list_free() the returned list after scanning it. This is necessary
 
2876
 * since the caller will typically be doing syscache lookups on the relevant
 
2877
 * indexes, and syscache lookup could cause SI messages to be processed!
 
2878
 *
 
2879
 * We also update rd_oidindex, which this module treats as effectively part
 
2880
 * of the index list.  rd_oidindex is valid when rd_indexvalid isn't zero;
 
2881
 * it is the pg_class OID of a unique index on OID when the relation has one,
 
2882
 * and InvalidOid if there is no such index.
 
2883
 */
 
2884
List *
 
2885
RelationGetIndexList(Relation relation)
 
2886
{
 
2887
        Relation        indrel;
 
2888
        SysScanDesc indscan;
 
2889
        ScanKeyData skey;
 
2890
        HeapTuple       htup;
 
2891
        List       *result;
 
2892
        Oid                     oidIndex;
 
2893
        MemoryContext oldcxt;
 
2894
 
 
2895
        /* Quick exit if we already computed the list. */
 
2896
        if (relation->rd_indexvalid != 0)
 
2897
                return list_copy(relation->rd_indexlist);
 
2898
 
 
2899
        /*
 
2900
         * We build the list we intend to return (in the caller's context) while
 
2901
         * doing the scan.      After successfully completing the scan, we copy that
 
2902
         * list into the relcache entry.  This avoids cache-context memory leakage
 
2903
         * if we get some sort of error partway through.
 
2904
         */
 
2905
        result = NIL;
 
2906
        oidIndex = InvalidOid;
 
2907
 
 
2908
        /* Prepare to scan pg_index for entries having indrelid = this rel. */
 
2909
        ScanKeyInit(&skey,
 
2910
                                Anum_pg_index_indrelid,
 
2911
                                BTEqualStrategyNumber, F_OIDEQ,
 
2912
                                ObjectIdGetDatum(RelationGetRelid(relation)));
 
2913
 
 
2914
        indrel = heap_open(IndexRelationId, AccessShareLock);
 
2915
        indscan = systable_beginscan(indrel, IndexIndrelidIndexId, true,
 
2916
                                                                 SnapshotNow, 1, &skey);
 
2917
 
 
2918
        while (HeapTupleIsValid(htup = systable_getnext(indscan)))
 
2919
        {
 
2920
                Form_pg_index index = (Form_pg_index) GETSTRUCT(htup);
 
2921
 
 
2922
                /* Add index's OID to result list in the proper order */
 
2923
                result = insert_ordered_oid(result, index->indexrelid);
 
2924
 
 
2925
                /* Check to see if it is a unique, non-partial btree index on OID */
 
2926
                if (index->indnatts == 1 &&
 
2927
                        index->indisunique &&
 
2928
                        index->indkey.values[0] == ObjectIdAttributeNumber &&
 
2929
                        index->indclass.values[0] == OID_BTREE_OPS_OID &&
 
2930
                        heap_attisnull(htup, Anum_pg_index_indpred))
 
2931
                        oidIndex = index->indexrelid;
 
2932
        }
 
2933
 
 
2934
        systable_endscan(indscan);
 
2935
        heap_close(indrel, AccessShareLock);
 
2936
 
 
2937
        /* Now save a copy of the completed list in the relcache entry. */
 
2938
        oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
 
2939
        relation->rd_indexlist = list_copy(result);
 
2940
        relation->rd_oidindex = oidIndex;
 
2941
        relation->rd_indexvalid = 1;
 
2942
        MemoryContextSwitchTo(oldcxt);
 
2943
 
 
2944
        return result;
 
2945
}
 
2946
 
 
2947
/*
 
2948
 * insert_ordered_oid
 
2949
 *              Insert a new Oid into a sorted list of Oids, preserving ordering
 
2950
 *
 
2951
 * Building the ordered list this way is O(N^2), but with a pretty small
 
2952
 * constant, so for the number of entries we expect it will probably be
 
2953
 * faster than trying to apply qsort().  Most tables don't have very many
 
2954
 * indexes...
 
2955
 */
 
2956
static List *
 
2957
insert_ordered_oid(List *list, Oid datum)
 
2958
{
 
2959
        ListCell   *prev;
 
2960
 
 
2961
        /* Does the datum belong at the front? */
 
2962
        if (list == NIL || datum < linitial_oid(list))
 
2963
                return lcons_oid(datum, list);
 
2964
        /* No, so find the entry it belongs after */
 
2965
        prev = list_head(list);
 
2966
        for (;;)
 
2967
        {
 
2968
                ListCell   *curr = lnext(prev);
 
2969
 
 
2970
                if (curr == NULL || datum < lfirst_oid(curr))
 
2971
                        break;                          /* it belongs after 'prev', before 'curr' */
 
2972
 
 
2973
                prev = curr;
 
2974
        }
 
2975
        /* Insert datum into list after 'prev' */
 
2976
        lappend_cell_oid(list, prev, datum);
 
2977
        return list;
 
2978
}
 
2979
 
 
2980
/*
 
2981
 * RelationSetIndexList -- externally force the index list contents
 
2982
 *
 
2983
 * This is used to temporarily override what we think the set of valid
 
2984
 * indexes is (including the presence or absence of an OID index).
 
2985
 * The forcing will be valid only until transaction commit or abort.
 
2986
 *
 
2987
 * This should only be applied to nailed relations, because in a non-nailed
 
2988
 * relation the hacked index list could be lost at any time due to SI
 
2989
 * messages.  In practice it is only used on pg_class (see REINDEX).
 
2990
 *
 
2991
 * It is up to the caller to make sure the given list is correctly ordered.
 
2992
 *
 
2993
 * We deliberately do not change rd_indexattr here: even when operating
 
2994
 * with a temporary partial index list, HOT-update decisions must be made
 
2995
 * correctly with respect to the full index set.  It is up to the caller
 
2996
 * to ensure that a correct rd_indexattr set has been cached before first
 
2997
 * calling RelationSetIndexList; else a subsequent inquiry might cause a
 
2998
 * wrong rd_indexattr set to get computed and cached.
 
2999
 */
 
3000
void
 
3001
RelationSetIndexList(Relation relation, List *indexIds, Oid oidIndex)
 
3002
{
 
3003
        MemoryContext oldcxt;
 
3004
 
 
3005
        Assert(relation->rd_isnailed);
 
3006
        /* Copy the list into the cache context (could fail for lack of mem) */
 
3007
        oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
 
3008
        indexIds = list_copy(indexIds);
 
3009
        MemoryContextSwitchTo(oldcxt);
 
3010
        /* Okay to replace old list */
 
3011
        list_free(relation->rd_indexlist);
 
3012
        relation->rd_indexlist = indexIds;
 
3013
        relation->rd_oidindex = oidIndex;
 
3014
        relation->rd_indexvalid = 2;    /* mark list as forced */
 
3015
        /* must flag that we have a forced index list */
 
3016
        need_eoxact_work = true;
 
3017
}
 
3018
 
 
3019
/*
 
3020
 * RelationGetOidIndex -- get the pg_class OID of the relation's OID index
 
3021
 *
 
3022
 * Returns InvalidOid if there is no such index.
 
3023
 */
 
3024
Oid
 
3025
RelationGetOidIndex(Relation relation)
 
3026
{
 
3027
        List       *ilist;
 
3028
 
 
3029
        /*
 
3030
         * If relation doesn't have OIDs at all, caller is probably confused. (We
 
3031
         * could just silently return InvalidOid, but it seems better to throw an
 
3032
         * assertion.)
 
3033
         */
 
3034
        Assert(relation->rd_rel->relhasoids);
 
3035
 
 
3036
        if (relation->rd_indexvalid == 0)
 
3037
        {
 
3038
                /* RelationGetIndexList does the heavy lifting. */
 
3039
                ilist = RelationGetIndexList(relation);
 
3040
                list_free(ilist);
 
3041
                Assert(relation->rd_indexvalid != 0);
 
3042
        }
 
3043
 
 
3044
        return relation->rd_oidindex;
 
3045
}
 
3046
 
 
3047
/*
 
3048
 * RelationGetIndexExpressions -- get the index expressions for an index
 
3049
 *
 
3050
 * We cache the result of transforming pg_index.indexprs into a node tree.
 
3051
 * If the rel is not an index or has no expressional columns, we return NIL.
 
3052
 * Otherwise, the returned tree is copied into the caller's memory context.
 
3053
 * (We don't want to return a pointer to the relcache copy, since it could
 
3054
 * disappear due to relcache invalidation.)
 
3055
 */
 
3056
List *
 
3057
RelationGetIndexExpressions(Relation relation)
 
3058
{
 
3059
        List       *result;
 
3060
        Datum           exprsDatum;
 
3061
        bool            isnull;
 
3062
        char       *exprsString;
 
3063
        MemoryContext oldcxt;
 
3064
 
 
3065
        /* Quick exit if we already computed the result. */
 
3066
        if (relation->rd_indexprs)
 
3067
                return (List *) copyObject(relation->rd_indexprs);
 
3068
 
 
3069
        /* Quick exit if there is nothing to do. */
 
3070
        if (relation->rd_indextuple == NULL ||
 
3071
                heap_attisnull(relation->rd_indextuple, Anum_pg_index_indexprs))
 
3072
                return NIL;
 
3073
 
 
3074
        /*
 
3075
         * We build the tree we intend to return in the caller's context. After
 
3076
         * successfully completing the work, we copy it into the relcache entry.
 
3077
         * This avoids problems if we get some sort of error partway through.
 
3078
         */
 
3079
        exprsDatum = heap_getattr(relation->rd_indextuple,
 
3080
                                                          Anum_pg_index_indexprs,
 
3081
                                                          GetPgIndexDescriptor(),
 
3082
                                                          &isnull);
 
3083
        Assert(!isnull);
 
3084
        exprsString = TextDatumGetCString(exprsDatum);
 
3085
        result = (List *) stringToNode(exprsString);
 
3086
        pfree(exprsString);
 
3087
 
 
3088
        /*
 
3089
         * Run the expressions through eval_const_expressions. This is not just an
 
3090
         * optimization, but is necessary, because the planner will be comparing
 
3091
         * them to similarly-processed qual clauses, and may fail to detect valid
 
3092
         * matches without this.  We don't bother with canonicalize_qual, however.
 
3093
         */
 
3094
        result = (List *) eval_const_expressions(NULL, (Node *) result);
 
3095
 
 
3096
        /*
 
3097
         * Also mark any coercion format fields as "don't care", so that the
 
3098
         * planner can match to both explicit and implicit coercions.
 
3099
         */
 
3100
        set_coercionform_dontcare((Node *) result);
 
3101
 
 
3102
        /* May as well fix opfuncids too */
 
3103
        fix_opfuncids((Node *) result);
 
3104
 
 
3105
        /* Now save a copy of the completed tree in the relcache entry. */
 
3106
        oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
 
3107
        relation->rd_indexprs = (List *) copyObject(result);
 
3108
        MemoryContextSwitchTo(oldcxt);
 
3109
 
 
3110
        return result;
 
3111
}
 
3112
 
 
3113
/*
 
3114
 * RelationGetIndexPredicate -- get the index predicate for an index
 
3115
 *
 
3116
 * We cache the result of transforming pg_index.indpred into an implicit-AND
 
3117
 * node tree (suitable for ExecQual).
 
3118
 * If the rel is not an index or has no predicate, we return NIL.
 
3119
 * Otherwise, the returned tree is copied into the caller's memory context.
 
3120
 * (We don't want to return a pointer to the relcache copy, since it could
 
3121
 * disappear due to relcache invalidation.)
 
3122
 */
 
3123
List *
 
3124
RelationGetIndexPredicate(Relation relation)
 
3125
{
 
3126
        List       *result;
 
3127
        Datum           predDatum;
 
3128
        bool            isnull;
 
3129
        char       *predString;
 
3130
        MemoryContext oldcxt;
 
3131
 
 
3132
        /* Quick exit if we already computed the result. */
 
3133
        if (relation->rd_indpred)
 
3134
                return (List *) copyObject(relation->rd_indpred);
 
3135
 
 
3136
        /* Quick exit if there is nothing to do. */
 
3137
        if (relation->rd_indextuple == NULL ||
 
3138
                heap_attisnull(relation->rd_indextuple, Anum_pg_index_indpred))
 
3139
                return NIL;
 
3140
 
 
3141
        /*
 
3142
         * We build the tree we intend to return in the caller's context. After
 
3143
         * successfully completing the work, we copy it into the relcache entry.
 
3144
         * This avoids problems if we get some sort of error partway through.
 
3145
         */
 
3146
        predDatum = heap_getattr(relation->rd_indextuple,
 
3147
                                                         Anum_pg_index_indpred,
 
3148
                                                         GetPgIndexDescriptor(),
 
3149
                                                         &isnull);
 
3150
        Assert(!isnull);
 
3151
        predString = TextDatumGetCString(predDatum);
 
3152
        result = (List *) stringToNode(predString);
 
3153
        pfree(predString);
 
3154
 
 
3155
        /*
 
3156
         * Run the expression through const-simplification and canonicalization.
 
3157
         * This is not just an optimization, but is necessary, because the planner
 
3158
         * will be comparing it to similarly-processed qual clauses, and may fail
 
3159
         * to detect valid matches without this.  This must match the processing
 
3160
         * done to qual clauses in preprocess_expression()!  (We can skip the
 
3161
         * stuff involving subqueries, however, since we don't allow any in index
 
3162
         * predicates.)
 
3163
         */
 
3164
        result = (List *) eval_const_expressions(NULL, (Node *) result);
 
3165
 
 
3166
        result = (List *) canonicalize_qual((Expr *) result);
 
3167
 
 
3168
        /*
 
3169
         * Also mark any coercion format fields as "don't care", so that the
 
3170
         * planner can match to both explicit and implicit coercions.
 
3171
         */
 
3172
        set_coercionform_dontcare((Node *) result);
 
3173
 
 
3174
        /* Also convert to implicit-AND format */
 
3175
        result = make_ands_implicit((Expr *) result);
 
3176
 
 
3177
        /* May as well fix opfuncids too */
 
3178
        fix_opfuncids((Node *) result);
 
3179
 
 
3180
        /* Now save a copy of the completed tree in the relcache entry. */
 
3181
        oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
 
3182
        relation->rd_indpred = (List *) copyObject(result);
 
3183
        MemoryContextSwitchTo(oldcxt);
 
3184
 
 
3185
        return result;
 
3186
}
 
3187
 
 
3188
/*
 
3189
 * RelationGetIndexAttrBitmap -- get a bitmap of index attribute numbers
 
3190
 *
 
3191
 * The result has a bit set for each attribute used anywhere in the index
 
3192
 * definitions of all the indexes on this relation.  (This includes not only
 
3193
 * simple index keys, but attributes used in expressions and partial-index
 
3194
 * predicates.)
 
3195
 *
 
3196
 * Attribute numbers are offset by FirstLowInvalidHeapAttributeNumber so that
 
3197
 * we can include system attributes (e.g., OID) in the bitmap representation.
 
3198
 *
 
3199
 * The returned result is palloc'd in the caller's memory context and should
 
3200
 * be bms_free'd when not needed anymore.
 
3201
 */
 
3202
Bitmapset *
 
3203
RelationGetIndexAttrBitmap(Relation relation)
 
3204
{
 
3205
        Bitmapset  *indexattrs;
 
3206
        List       *indexoidlist;
 
3207
        ListCell   *l;
 
3208
        MemoryContext oldcxt;
 
3209
 
 
3210
        /* Quick exit if we already computed the result. */
 
3211
        if (relation->rd_indexattr != NULL)
 
3212
                return bms_copy(relation->rd_indexattr);
 
3213
 
 
3214
        /* Fast path if definitely no indexes */
 
3215
        if (!RelationGetForm(relation)->relhasindex)
 
3216
                return NULL;
 
3217
 
 
3218
        /*
 
3219
         * Get cached list of index OIDs
 
3220
         */
 
3221
        indexoidlist = RelationGetIndexList(relation);
 
3222
 
 
3223
        /* Fall out if no indexes (but relhasindex was set) */
 
3224
        if (indexoidlist == NIL)
 
3225
                return NULL;
 
3226
 
 
3227
        /*
 
3228
         * For each index, add referenced attributes to indexattrs.
 
3229
         */
 
3230
        indexattrs = NULL;
 
3231
        foreach(l, indexoidlist)
 
3232
        {
 
3233
                Oid                     indexOid = lfirst_oid(l);
 
3234
                Relation        indexDesc;
 
3235
                IndexInfo  *indexInfo;
 
3236
                int                     i;
 
3237
 
 
3238
                indexDesc = index_open(indexOid, AccessShareLock);
 
3239
 
 
3240
                /* Extract index key information from the index's pg_index row */
 
3241
                indexInfo = BuildIndexInfo(indexDesc);
 
3242
 
 
3243
                /* Collect simple attribute references */
 
3244
                for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++)
 
3245
                {
 
3246
                        int                     attrnum = indexInfo->ii_KeyAttrNumbers[i];
 
3247
 
 
3248
                        if (attrnum != 0)
 
3249
                                indexattrs = bms_add_member(indexattrs,
 
3250
                                                           attrnum - FirstLowInvalidHeapAttributeNumber);
 
3251
                }
 
3252
 
 
3253
                /* Collect all attributes used in expressions, too */
 
3254
                pull_varattnos((Node *) indexInfo->ii_Expressions, &indexattrs);
 
3255
 
 
3256
                /* Collect all attributes in the index predicate, too */
 
3257
                pull_varattnos((Node *) indexInfo->ii_Predicate, &indexattrs);
 
3258
 
 
3259
                index_close(indexDesc, AccessShareLock);
 
3260
        }
 
3261
 
 
3262
        list_free(indexoidlist);
 
3263
 
 
3264
        /* Now save a copy of the bitmap in the relcache entry. */
 
3265
        oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
 
3266
        relation->rd_indexattr = bms_copy(indexattrs);
 
3267
        MemoryContextSwitchTo(oldcxt);
 
3268
 
 
3269
        /* We return our original working copy for caller to play with */
 
3270
        return indexattrs;
 
3271
}
 
3272
 
 
3273
 
 
3274
/*
 
3275
 *      load_relcache_init_file, write_relcache_init_file
 
3276
 *
 
3277
 *              In late 1992, we started regularly having databases with more than
 
3278
 *              a thousand classes in them.  With this number of classes, it became
 
3279
 *              critical to do indexed lookups on the system catalogs.
 
3280
 *
 
3281
 *              Bootstrapping these lookups is very hard.  We want to be able to
 
3282
 *              use an index on pg_attribute, for example, but in order to do so,
 
3283
 *              we must have read pg_attribute for the attributes in the index,
 
3284
 *              which implies that we need to use the index.
 
3285
 *
 
3286
 *              In order to get around the problem, we do the following:
 
3287
 *
 
3288
 *                 +  When the database system is initialized (at initdb time), we
 
3289
 *                        don't use indexes.  We do sequential scans.
 
3290
 *
 
3291
 *                 +  When the backend is started up in normal mode, we load an image
 
3292
 *                        of the appropriate relation descriptors, in internal format,
 
3293
 *                        from an initialization file in the data/base/... directory.
 
3294
 *
 
3295
 *                 +  If the initialization file isn't there, then we create the
 
3296
 *                        relation descriptors using sequential scans and write 'em to
 
3297
 *                        the initialization file for use by subsequent backends.
 
3298
 *
 
3299
 *              We could dispense with the initialization file and just build the
 
3300
 *              critical reldescs the hard way on every backend startup, but that
 
3301
 *              slows down backend startup noticeably.
 
3302
 *
 
3303
 *              We can in fact go further, and save more relcache entries than
 
3304
 *              just the ones that are absolutely critical; this allows us to speed
 
3305
 *              up backend startup by not having to build such entries the hard way.
 
3306
 *              Presently, all the catalog and index entries that are referred to
 
3307
 *              by catcaches are stored in the initialization file.
 
3308
 *
 
3309
 *              The same mechanism that detects when catcache and relcache entries
 
3310
 *              need to be invalidated (due to catalog updates) also arranges to
 
3311
 *              unlink the initialization file when its contents may be out of date.
 
3312
 *              The file will then be rebuilt during the next backend startup.
 
3313
 */
 
3314
 
 
3315
/*
 
3316
 * load_relcache_init_file -- attempt to load cache from the init file
 
3317
 *
 
3318
 * If successful, return TRUE and set criticalRelcachesBuilt to true.
 
3319
 * If not successful, return FALSE.
 
3320
 *
 
3321
 * NOTE: we assume we are already switched into CacheMemoryContext.
 
3322
 */
 
3323
static bool
 
3324
load_relcache_init_file(void)
 
3325
{
 
3326
        FILE       *fp;
 
3327
        char            initfilename[MAXPGPATH];
 
3328
        Relation   *rels;
 
3329
        int                     relno,
 
3330
                                num_rels,
 
3331
                                max_rels,
 
3332
                                nailed_rels,
 
3333
                                nailed_indexes,
 
3334
                                magic;
 
3335
        int                     i;
 
3336
 
 
3337
        snprintf(initfilename, sizeof(initfilename), "%s/%s",
 
3338
                         DatabasePath, RELCACHE_INIT_FILENAME);
 
3339
 
 
3340
        fp = AllocateFile(initfilename, PG_BINARY_R);
 
3341
        if (fp == NULL)
 
3342
                return false;
 
3343
 
 
3344
        /*
 
3345
         * Read the index relcache entries from the file.  Note we will not enter
 
3346
         * any of them into the cache if the read fails partway through; this
 
3347
         * helps to guard against broken init files.
 
3348
         */
 
3349
        max_rels = 100;
 
3350
        rels = (Relation *) palloc(max_rels * sizeof(Relation));
 
3351
        num_rels = 0;
 
3352
        nailed_rels = nailed_indexes = 0;
 
3353
        initFileRelationIds = NIL;
 
3354
 
 
3355
        /* check for correct magic number (compatible version) */
 
3356
        if (fread(&magic, 1, sizeof(magic), fp) != sizeof(magic))
 
3357
                goto read_failed;
 
3358
        if (magic != RELCACHE_INIT_FILEMAGIC)
 
3359
                goto read_failed;
 
3360
 
 
3361
        for (relno = 0;; relno++)
 
3362
        {
 
3363
                Size            len;
 
3364
                size_t          nread;
 
3365
                Relation        rel;
 
3366
                Form_pg_class relform;
 
3367
                bool            has_not_null;
 
3368
 
 
3369
                /* first read the relation descriptor length */
 
3370
                if ((nread = fread(&len, 1, sizeof(len), fp)) != sizeof(len))
 
3371
                {
 
3372
                        if (nread == 0)
 
3373
                                break;                  /* end of file */
 
3374
                        goto read_failed;
 
3375
                }
 
3376
 
 
3377
                /* safety check for incompatible relcache layout */
 
3378
                if (len != sizeof(RelationData))
 
3379
                        goto read_failed;
 
3380
 
 
3381
                /* allocate another relcache header */
 
3382
                if (num_rels >= max_rels)
 
3383
                {
 
3384
                        max_rels *= 2;
 
3385
                        rels = (Relation *) repalloc(rels, max_rels * sizeof(Relation));
 
3386
                }
 
3387
 
 
3388
                rel = rels[num_rels++] = (Relation) palloc(len);
 
3389
 
 
3390
                /* then, read the Relation structure */
 
3391
                if ((nread = fread(rel, 1, len, fp)) != len)
 
3392
                        goto read_failed;
 
3393
 
 
3394
                /* next read the relation tuple form */
 
3395
                if ((nread = fread(&len, 1, sizeof(len), fp)) != sizeof(len))
 
3396
                        goto read_failed;
 
3397
 
 
3398
                relform = (Form_pg_class) palloc(len);
 
3399
                if ((nread = fread(relform, 1, len, fp)) != len)
 
3400
                        goto read_failed;
 
3401
 
 
3402
                rel->rd_rel = relform;
 
3403
 
 
3404
                /* initialize attribute tuple forms */
 
3405
                rel->rd_att = CreateTemplateTupleDesc(relform->relnatts,
 
3406
                                                                                          relform->relhasoids);
 
3407
                rel->rd_att->tdrefcount = 1;    /* mark as refcounted */
 
3408
 
 
3409
                rel->rd_att->tdtypeid = relform->reltype;
 
3410
                rel->rd_att->tdtypmod = -1;             /* unnecessary, but... */
 
3411
 
 
3412
                /* next read all the attribute tuple form data entries */
 
3413
                has_not_null = false;
 
3414
                for (i = 0; i < relform->relnatts; i++)
 
3415
                {
 
3416
                        if ((nread = fread(&len, 1, sizeof(len), fp)) != sizeof(len))
 
3417
                                goto read_failed;
 
3418
                        if (len != ATTRIBUTE_FIXED_PART_SIZE)
 
3419
                                goto read_failed;
 
3420
                        if ((nread = fread(rel->rd_att->attrs[i], 1, len, fp)) != len)
 
3421
                                goto read_failed;
 
3422
 
 
3423
                        has_not_null |= rel->rd_att->attrs[i]->attnotnull;
 
3424
                }
 
3425
 
 
3426
                /* next read the access method specific field */
 
3427
                if ((nread = fread(&len, 1, sizeof(len), fp)) != sizeof(len))
 
3428
                        goto read_failed;
 
3429
                if (len > 0)
 
3430
                {
 
3431
                        rel->rd_options = palloc(len);
 
3432
                        if ((nread = fread(rel->rd_options, 1, len, fp)) != len)
 
3433
                                goto read_failed;
 
3434
                        if (len != VARSIZE(rel->rd_options))
 
3435
                                goto read_failed;               /* sanity check */
 
3436
                }
 
3437
                else
 
3438
                {
 
3439
                        rel->rd_options = NULL;
 
3440
                }
 
3441
 
 
3442
                /* mark not-null status */
 
3443
                if (has_not_null)
 
3444
                {
 
3445
                        TupleConstr *constr = (TupleConstr *) palloc0(sizeof(TupleConstr));
 
3446
 
 
3447
                        constr->has_not_null = true;
 
3448
                        rel->rd_att->constr = constr;
 
3449
                }
 
3450
 
 
3451
                /* If it's an index, there's more to do */
 
3452
                if (rel->rd_rel->relkind == RELKIND_INDEX)
 
3453
                {
 
3454
                        Form_pg_am      am;
 
3455
                        MemoryContext indexcxt;
 
3456
                        Oid                *opfamily;
 
3457
                        Oid                *opcintype;
 
3458
                        Oid                *operator;
 
3459
                        RegProcedure *support;
 
3460
                        int                     nsupport;
 
3461
                        int16      *indoption;
 
3462
 
 
3463
                        /* Count nailed indexes to ensure we have 'em all */
 
3464
                        if (rel->rd_isnailed)
 
3465
                                nailed_indexes++;
 
3466
 
 
3467
                        /* next, read the pg_index tuple */
 
3468
                        if ((nread = fread(&len, 1, sizeof(len), fp)) != sizeof(len))
 
3469
                                goto read_failed;
 
3470
 
 
3471
                        rel->rd_indextuple = (HeapTuple) palloc(len);
 
3472
                        if ((nread = fread(rel->rd_indextuple, 1, len, fp)) != len)
 
3473
                                goto read_failed;
 
3474
 
 
3475
                        /* Fix up internal pointers in the tuple -- see heap_copytuple */
 
3476
                        rel->rd_indextuple->t_data = (HeapTupleHeader) ((char *) rel->rd_indextuple + HEAPTUPLESIZE);
 
3477
                        rel->rd_index = (Form_pg_index) GETSTRUCT(rel->rd_indextuple);
 
3478
 
 
3479
                        /* next, read the access method tuple form */
 
3480
                        if ((nread = fread(&len, 1, sizeof(len), fp)) != sizeof(len))
 
3481
                                goto read_failed;
 
3482
 
 
3483
                        am = (Form_pg_am) palloc(len);
 
3484
                        if ((nread = fread(am, 1, len, fp)) != len)
 
3485
                                goto read_failed;
 
3486
                        rel->rd_am = am;
 
3487
 
 
3488
                        /*
 
3489
                         * prepare index info context --- parameters should match
 
3490
                         * RelationInitIndexAccessInfo
 
3491
                         */
 
3492
                        indexcxt = AllocSetContextCreate(CacheMemoryContext,
 
3493
                                                                                         RelationGetRelationName(rel),
 
3494
                                                                                         ALLOCSET_SMALL_MINSIZE,
 
3495
                                                                                         ALLOCSET_SMALL_INITSIZE,
 
3496
                                                                                         ALLOCSET_SMALL_MAXSIZE);
 
3497
                        rel->rd_indexcxt = indexcxt;
 
3498
 
 
3499
                        /* next, read the vector of opfamily OIDs */
 
3500
                        if ((nread = fread(&len, 1, sizeof(len), fp)) != sizeof(len))
 
3501
                                goto read_failed;
 
3502
 
 
3503
                        opfamily = (Oid *) MemoryContextAlloc(indexcxt, len);
 
3504
                        if ((nread = fread(opfamily, 1, len, fp)) != len)
 
3505
                                goto read_failed;
 
3506
 
 
3507
                        rel->rd_opfamily = opfamily;
 
3508
 
 
3509
                        /* next, read the vector of opcintype OIDs */
 
3510
                        if ((nread = fread(&len, 1, sizeof(len), fp)) != sizeof(len))
 
3511
                                goto read_failed;
 
3512
 
 
3513
                        opcintype = (Oid *) MemoryContextAlloc(indexcxt, len);
 
3514
                        if ((nread = fread(opcintype, 1, len, fp)) != len)
 
3515
                                goto read_failed;
 
3516
 
 
3517
                        rel->rd_opcintype = opcintype;
 
3518
 
 
3519
                        /* next, read the vector of operator OIDs */
 
3520
                        if ((nread = fread(&len, 1, sizeof(len), fp)) != sizeof(len))
 
3521
                                goto read_failed;
 
3522
 
 
3523
                        operator = (Oid *) MemoryContextAlloc(indexcxt, len);
 
3524
                        if ((nread = fread(operator, 1, len, fp)) != len)
 
3525
                                goto read_failed;
 
3526
 
 
3527
                        rel->rd_operator = operator;
 
3528
 
 
3529
                        /* next, read the vector of support procedures */
 
3530
                        if ((nread = fread(&len, 1, sizeof(len), fp)) != sizeof(len))
 
3531
                                goto read_failed;
 
3532
                        support = (RegProcedure *) MemoryContextAlloc(indexcxt, len);
 
3533
                        if ((nread = fread(support, 1, len, fp)) != len)
 
3534
                                goto read_failed;
 
3535
 
 
3536
                        rel->rd_support = support;
 
3537
 
 
3538
                        /* finally, read the vector of indoption values */
 
3539
                        if ((nread = fread(&len, 1, sizeof(len), fp)) != sizeof(len))
 
3540
                                goto read_failed;
 
3541
 
 
3542
                        indoption = (int16 *) MemoryContextAlloc(indexcxt, len);
 
3543
                        if ((nread = fread(indoption, 1, len, fp)) != len)
 
3544
                                goto read_failed;
 
3545
 
 
3546
                        rel->rd_indoption = indoption;
 
3547
 
 
3548
                        /* set up zeroed fmgr-info vectors */
 
3549
                        rel->rd_aminfo = (RelationAmInfo *)
 
3550
                                MemoryContextAllocZero(indexcxt, sizeof(RelationAmInfo));
 
3551
                        nsupport = relform->relnatts * am->amsupport;
 
3552
                        rel->rd_supportinfo = (FmgrInfo *)
 
3553
                                MemoryContextAllocZero(indexcxt, nsupport * sizeof(FmgrInfo));
 
3554
                }
 
3555
                else
 
3556
                {
 
3557
                        /* Count nailed rels to ensure we have 'em all */
 
3558
                        if (rel->rd_isnailed)
 
3559
                                nailed_rels++;
 
3560
 
 
3561
                        Assert(rel->rd_index == NULL);
 
3562
                        Assert(rel->rd_indextuple == NULL);
 
3563
                        Assert(rel->rd_am == NULL);
 
3564
                        Assert(rel->rd_indexcxt == NULL);
 
3565
                        Assert(rel->rd_aminfo == NULL);
 
3566
                        Assert(rel->rd_opfamily == NULL);
 
3567
                        Assert(rel->rd_opcintype == NULL);
 
3568
                        Assert(rel->rd_operator == NULL);
 
3569
                        Assert(rel->rd_support == NULL);
 
3570
                        Assert(rel->rd_supportinfo == NULL);
 
3571
                        Assert(rel->rd_indoption == NULL);
 
3572
                }
 
3573
 
 
3574
                /*
 
3575
                 * Rules and triggers are not saved (mainly because the internal
 
3576
                 * format is complex and subject to change).  They must be rebuilt if
 
3577
                 * needed by RelationCacheInitializePhase2.  This is not expected to
 
3578
                 * be a big performance hit since few system catalogs have such. Ditto
 
3579
                 * for index expressions and predicates.
 
3580
                 */
 
3581
                rel->rd_rules = NULL;
 
3582
                rel->rd_rulescxt = NULL;
 
3583
                rel->trigdesc = NULL;
 
3584
                rel->rd_indexprs = NIL;
 
3585
                rel->rd_indpred = NIL;
 
3586
 
 
3587
                /*
 
3588
                 * Reset transient-state fields in the relcache entry
 
3589
                 */
 
3590
                rel->rd_smgr = NULL;
 
3591
                rel->rd_targblock = InvalidBlockNumber;
 
3592
                rel->rd_fsm_nblocks = InvalidBlockNumber;
 
3593
                rel->rd_vm_nblocks = InvalidBlockNumber;
 
3594
                if (rel->rd_isnailed)
 
3595
                        rel->rd_refcnt = 1;
 
3596
                else
 
3597
                        rel->rd_refcnt = 0;
 
3598
                rel->rd_indexvalid = 0;
 
3599
                rel->rd_indexlist = NIL;
 
3600
                rel->rd_indexattr = NULL;
 
3601
                rel->rd_oidindex = InvalidOid;
 
3602
                rel->rd_createSubid = InvalidSubTransactionId;
 
3603
                rel->rd_newRelfilenodeSubid = InvalidSubTransactionId;
 
3604
                rel->rd_amcache = NULL;
 
3605
                MemSet(&rel->pgstat_info, 0, sizeof(rel->pgstat_info));
 
3606
 
 
3607
                /*
 
3608
                 * Recompute lock and physical addressing info.  This is needed in
 
3609
                 * case the pg_internal.init file was copied from some other database
 
3610
                 * by CREATE DATABASE.
 
3611
                 */
 
3612
                RelationInitLockInfo(rel);
 
3613
                RelationInitPhysicalAddr(rel);
 
3614
        }
 
3615
 
 
3616
        /*
 
3617
         * We reached the end of the init file without apparent problem. Did we
 
3618
         * get the right number of nailed items?  (This is a useful crosscheck in
 
3619
         * case the set of critical rels or indexes changes.)
 
3620
         */
 
3621
        if (nailed_rels != NUM_CRITICAL_RELS ||
 
3622
                nailed_indexes != NUM_CRITICAL_INDEXES)
 
3623
                goto read_failed;
 
3624
 
 
3625
        /*
 
3626
         * OK, all appears well.
 
3627
         *
 
3628
         * Now insert all the new relcache entries into the cache.
 
3629
         */
 
3630
        for (relno = 0; relno < num_rels; relno++)
 
3631
        {
 
3632
                RelationCacheInsert(rels[relno]);
 
3633
                /* also make a list of their OIDs, for RelationIdIsInInitFile */
 
3634
                initFileRelationIds = lcons_oid(RelationGetRelid(rels[relno]),
 
3635
                                                                                initFileRelationIds);
 
3636
        }
 
3637
 
 
3638
        pfree(rels);
 
3639
        FreeFile(fp);
 
3640
 
 
3641
        criticalRelcachesBuilt = true;
 
3642
        return true;
 
3643
 
 
3644
        /*
 
3645
         * init file is broken, so do it the hard way.  We don't bother trying to
 
3646
         * free the clutter we just allocated; it's not in the relcache so it
 
3647
         * won't hurt.
 
3648
         */
 
3649
read_failed:
 
3650
        pfree(rels);
 
3651
        FreeFile(fp);
 
3652
 
 
3653
        return false;
 
3654
}
 
3655
 
 
3656
/*
 
3657
 * Write out a new initialization file with the current contents
 
3658
 * of the relcache.
 
3659
 */
 
3660
static void
 
3661
write_relcache_init_file(void)
 
3662
{
 
3663
        FILE       *fp;
 
3664
        char            tempfilename[MAXPGPATH];
 
3665
        char            finalfilename[MAXPGPATH];
 
3666
        int                     magic;
 
3667
        HASH_SEQ_STATUS status;
 
3668
        RelIdCacheEnt *idhentry;
 
3669
        MemoryContext oldcxt;
 
3670
        int                     i;
 
3671
 
 
3672
        /*
 
3673
         * We must write a temporary file and rename it into place. Otherwise,
 
3674
         * another backend starting at about the same time might crash trying to
 
3675
         * read the partially-complete file.
 
3676
         */
 
3677
        snprintf(tempfilename, sizeof(tempfilename), "%s/%s.%d",
 
3678
                         DatabasePath, RELCACHE_INIT_FILENAME, MyProcPid);
 
3679
        snprintf(finalfilename, sizeof(finalfilename), "%s/%s",
 
3680
                         DatabasePath, RELCACHE_INIT_FILENAME);
 
3681
 
 
3682
        unlink(tempfilename);           /* in case it exists w/wrong permissions */
 
3683
 
 
3684
        fp = AllocateFile(tempfilename, PG_BINARY_W);
 
3685
        if (fp == NULL)
 
3686
        {
 
3687
                /*
 
3688
                 * We used to consider this a fatal error, but we might as well
 
3689
                 * continue with backend startup ...
 
3690
                 */
 
3691
                ereport(WARNING,
 
3692
                                (errcode_for_file_access(),
 
3693
                                 errmsg("could not create relation-cache initialization file \"%s\": %m",
 
3694
                                                tempfilename),
 
3695
                          errdetail("Continuing anyway, but there's something wrong.")));
 
3696
                return;
 
3697
        }
 
3698
 
 
3699
        /*
 
3700
         * Write a magic number to serve as a file version identifier.  We can
 
3701
         * change the magic number whenever the relcache layout changes.
 
3702
         */
 
3703
        magic = RELCACHE_INIT_FILEMAGIC;
 
3704
        if (fwrite(&magic, 1, sizeof(magic), fp) != sizeof(magic))
 
3705
                elog(FATAL, "could not write init file");
 
3706
 
 
3707
        /*
 
3708
         * Write all the reldescs (in no particular order).
 
3709
         */
 
3710
        hash_seq_init(&status, RelationIdCache);
 
3711
 
 
3712
        initFileRelationIds = NIL;
 
3713
 
 
3714
        while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
 
3715
        {
 
3716
                Relation        rel = idhentry->reldesc;
 
3717
                Form_pg_class relform = rel->rd_rel;
 
3718
 
 
3719
                /* first write the relcache entry proper */
 
3720
                write_item(rel, sizeof(RelationData), fp);
 
3721
 
 
3722
                /* next write the relation tuple form */
 
3723
                write_item(relform, CLASS_TUPLE_SIZE, fp);
 
3724
 
 
3725
                /* next, do all the attribute tuple form data entries */
 
3726
                for (i = 0; i < relform->relnatts; i++)
 
3727
                {
 
3728
                        write_item(rel->rd_att->attrs[i], ATTRIBUTE_FIXED_PART_SIZE, fp);
 
3729
                }
 
3730
 
 
3731
                /* next, do the access method specific field */
 
3732
                write_item(rel->rd_options,
 
3733
                                   (rel->rd_options ? VARSIZE(rel->rd_options) : 0),
 
3734
                                   fp);
 
3735
 
 
3736
                /* If it's an index, there's more to do */
 
3737
                if (rel->rd_rel->relkind == RELKIND_INDEX)
 
3738
                {
 
3739
                        Form_pg_am      am = rel->rd_am;
 
3740
 
 
3741
                        /* write the pg_index tuple */
 
3742
                        /* we assume this was created by heap_copytuple! */
 
3743
                        write_item(rel->rd_indextuple,
 
3744
                                           HEAPTUPLESIZE + rel->rd_indextuple->t_len,
 
3745
                                           fp);
 
3746
 
 
3747
                        /* next, write the access method tuple form */
 
3748
                        write_item(am, sizeof(FormData_pg_am), fp);
 
3749
 
 
3750
                        /* next, write the vector of opfamily OIDs */
 
3751
                        write_item(rel->rd_opfamily,
 
3752
                                           relform->relnatts * sizeof(Oid),
 
3753
                                           fp);
 
3754
 
 
3755
                        /* next, write the vector of opcintype OIDs */
 
3756
                        write_item(rel->rd_opcintype,
 
3757
                                           relform->relnatts * sizeof(Oid),
 
3758
                                           fp);
 
3759
 
 
3760
                        /* next, write the vector of operator OIDs */
 
3761
                        write_item(rel->rd_operator,
 
3762
                                           relform->relnatts * (am->amstrategies * sizeof(Oid)),
 
3763
                                           fp);
 
3764
 
 
3765
                        /* next, write the vector of support procedures */
 
3766
                        write_item(rel->rd_support,
 
3767
                                  relform->relnatts * (am->amsupport * sizeof(RegProcedure)),
 
3768
                                           fp);
 
3769
 
 
3770
                        /* finally, write the vector of indoption values */
 
3771
                        write_item(rel->rd_indoption,
 
3772
                                           relform->relnatts * sizeof(int16),
 
3773
                                           fp);
 
3774
                }
 
3775
 
 
3776
                /* also make a list of their OIDs, for RelationIdIsInInitFile */
 
3777
                oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
 
3778
                initFileRelationIds = lcons_oid(RelationGetRelid(rel),
 
3779
                                                                                initFileRelationIds);
 
3780
                MemoryContextSwitchTo(oldcxt);
 
3781
        }
 
3782
 
 
3783
        if (FreeFile(fp))
 
3784
                elog(FATAL, "could not write init file");
 
3785
 
 
3786
        /*
 
3787
         * Now we have to check whether the data we've so painstakingly
 
3788
         * accumulated is already obsolete due to someone else's just-committed
 
3789
         * catalog changes.  If so, we just delete the temp file and leave it to
 
3790
         * the next backend to try again.  (Our own relcache entries will be
 
3791
         * updated by SI message processing, but we can't be sure whether what we
 
3792
         * wrote out was up-to-date.)
 
3793
         *
 
3794
         * This mustn't run concurrently with RelationCacheInitFileInvalidate, so
 
3795
         * grab a serialization lock for the duration.
 
3796
         */
 
3797
        LWLockAcquire(RelCacheInitLock, LW_EXCLUSIVE);
 
3798
 
 
3799
        /* Make sure we have seen all incoming SI messages */
 
3800
        AcceptInvalidationMessages();
 
3801
 
 
3802
        /*
 
3803
         * If we have received any SI relcache invals since backend start, assume
 
3804
         * we may have written out-of-date data.
 
3805
         */
 
3806
        if (relcacheInvalsReceived == 0L)
 
3807
        {
 
3808
                /*
 
3809
                 * OK, rename the temp file to its final name, deleting any
 
3810
                 * previously-existing init file.
 
3811
                 *
 
3812
                 * Note: a failure here is possible under Cygwin, if some other
 
3813
                 * backend is holding open an unlinked-but-not-yet-gone init file. So
 
3814
                 * treat this as a noncritical failure; just remove the useless temp
 
3815
                 * file on failure.
 
3816
                 */
 
3817
                if (rename(tempfilename, finalfilename) < 0)
 
3818
                        unlink(tempfilename);
 
3819
        }
 
3820
        else
 
3821
        {
 
3822
                /* Delete the already-obsolete temp file */
 
3823
                unlink(tempfilename);
 
3824
        }
 
3825
 
 
3826
        LWLockRelease(RelCacheInitLock);
 
3827
}
 
3828
 
 
3829
/* write a chunk of data preceded by its length */
 
3830
static void
 
3831
write_item(const void *data, Size len, FILE *fp)
 
3832
{
 
3833
        if (fwrite(&len, 1, sizeof(len), fp) != sizeof(len))
 
3834
                elog(FATAL, "could not write init file");
 
3835
        if (fwrite(data, 1, len, fp) != len)
 
3836
                elog(FATAL, "could not write init file");
 
3837
}
 
3838
 
 
3839
/*
 
3840
 * Detect whether a given relation (identified by OID) is one of the ones
 
3841
 * we store in the init file.
 
3842
 *
 
3843
 * Note that we effectively assume that all backends running in a database
 
3844
 * would choose to store the same set of relations in the init file;
 
3845
 * otherwise there are cases where we'd fail to detect the need for an init
 
3846
 * file invalidation.  This does not seem likely to be a problem in practice.
 
3847
 */
 
3848
bool
 
3849
RelationIdIsInInitFile(Oid relationId)
 
3850
{
 
3851
        return list_member_oid(initFileRelationIds, relationId);
 
3852
}
 
3853
 
 
3854
/*
 
3855
 * Invalidate (remove) the init file during commit of a transaction that
 
3856
 * changed one or more of the relation cache entries that are kept in the
 
3857
 * init file.
 
3858
 *
 
3859
 * We actually need to remove the init file twice: once just before sending
 
3860
 * the SI messages that include relcache inval for such relations, and once
 
3861
 * just after sending them.  The unlink before ensures that a backend that's
 
3862
 * currently starting cannot read the now-obsolete init file and then miss
 
3863
 * the SI messages that will force it to update its relcache entries.  (This
 
3864
 * works because the backend startup sequence gets into the PGPROC array before
 
3865
 * trying to load the init file.)  The unlink after is to synchronize with a
 
3866
 * backend that may currently be trying to write an init file based on data
 
3867
 * that we've just rendered invalid.  Such a backend will see the SI messages,
 
3868
 * but we can't leave the init file sitting around to fool later backends.
 
3869
 *
 
3870
 * Ignore any failure to unlink the file, since it might not be there if
 
3871
 * no backend has been started since the last removal.
 
3872
 */
 
3873
void
 
3874
RelationCacheInitFileInvalidate(bool beforeSend)
 
3875
{
 
3876
        char            initfilename[MAXPGPATH];
 
3877
 
 
3878
        snprintf(initfilename, sizeof(initfilename), "%s/%s",
 
3879
                         DatabasePath, RELCACHE_INIT_FILENAME);
 
3880
 
 
3881
        if (beforeSend)
 
3882
        {
 
3883
                /* no interlock needed here */
 
3884
                unlink(initfilename);
 
3885
        }
 
3886
        else
 
3887
        {
 
3888
                /*
 
3889
                 * We need to interlock this against write_relcache_init_file, to
 
3890
                 * guard against possibility that someone renames a new-but-
 
3891
                 * already-obsolete init file into place just after we unlink. With
 
3892
                 * the interlock, it's certain that write_relcache_init_file will
 
3893
                 * notice our SI inval message before renaming into place, or else
 
3894
                 * that we will execute second and successfully unlink the file.
 
3895
                 */
 
3896
                LWLockAcquire(RelCacheInitLock, LW_EXCLUSIVE);
 
3897
                unlink(initfilename);
 
3898
                LWLockRelease(RelCacheInitLock);
 
3899
        }
 
3900
}
 
3901
 
 
3902
/*
 
3903
 * Remove the init file for a given database during postmaster startup.
 
3904
 *
 
3905
 * We used to keep the init file across restarts, but that is unsafe in PITR
 
3906
 * scenarios, and even in simple crash-recovery cases there are windows for
 
3907
 * the init file to become out-of-sync with the database.  So now we just
 
3908
 * remove it during startup and expect the first backend launch to rebuild it.
 
3909
 * Of course, this has to happen in each database of the cluster.  For
 
3910
 * simplicity this is driven by flatfiles.c, which has to scan pg_database
 
3911
 * anyway.
 
3912
 */
 
3913
void
 
3914
RelationCacheInitFileRemove(const char *dbPath)
 
3915
{
 
3916
        char            initfilename[MAXPGPATH];
 
3917
 
 
3918
        snprintf(initfilename, sizeof(initfilename), "%s/%s",
 
3919
                         dbPath, RELCACHE_INIT_FILENAME);
 
3920
        unlink(initfilename);
 
3921
        /* ignore any error, since it might not be there at all */
 
3922
}