~vcs-imports/mammoth-replicator/trunk

« back to all changes in this revision

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

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

Show diffs side-by-side

added added

removed removed

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