indexing.c 10.4 KB
Newer Older
1 2 3
/*-------------------------------------------------------------------------
 *
 * indexing.c--
4 5
 *	  This file contains routines to support indices defined on system
 *	  catalogs.
6 7 8 9 10
 *
 * Copyright (c) 1994, Regents of the University of California
 *
 *
 * IDENTIFICATION
Bruce Momjian's avatar
Bruce Momjian committed
11
 *	  $Header: /cvsroot/pgsql/src/backend/catalog/indexing.c,v 1.30 1998/09/02 23:05:23 momjian Exp $
12 13 14
 *
 *-------------------------------------------------------------------------
 */
15 16
#include <string.h>

Bruce Momjian's avatar
Bruce Momjian committed
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
#include "postgres.h"

#include "access/genam.h"
#include "access/heapam.h"
#include "catalog/catalog.h"
#include "catalog/catname.h"
#include "catalog/index.h"
#include "catalog/indexing.h"
#include "catalog/pg_index.h"
#include "catalog/pg_proc.h"
#include "fmgr.h"
#include "miscadmin.h"
#include "nodes/execnodes.h"
#include "storage/bufmgr.h"
#include "utils/builtins.h"
#include "utils/syscache.h"
33

34 35 36
/*
 * Names of indices on the following system catalogs:
 *
37 38 39 40 41 42 43 44
 *		pg_attribute
 *		pg_proc
 *		pg_type
 *		pg_naming
 *		pg_class
 *		pg_attrdef
 *		pg_relcheck
 *		pg_trigger
45 46
 */

47
char	   *Name_pg_attr_indices[Num_pg_attr_indices] = {AttributeNameIndex,
Bruce Momjian's avatar
Bruce Momjian committed
48 49
			AttributeNumIndex,
			AttributeRelidIndex};
50
char	   *Name_pg_proc_indices[Num_pg_proc_indices] = {ProcedureNameIndex,
Bruce Momjian's avatar
Bruce Momjian committed
51 52
			ProcedureOidIndex,
			ProcedureSrcIndex};
53
char	   *Name_pg_type_indices[Num_pg_type_indices] = {TypeNameIndex,
Bruce Momjian's avatar
Bruce Momjian committed
54
			TypeOidIndex};
55
char	   *Name_pg_class_indices[Num_pg_class_indices] = {ClassNameIndex,
Bruce Momjian's avatar
Bruce Momjian committed
56
			ClassOidIndex};
57
char	   *Name_pg_attrdef_indices[Num_pg_attrdef_indices] = {AttrDefaultIndex};
58

59
char	   *Name_pg_relcheck_indices[Num_pg_relcheck_indices] = {RelCheckIndex};
60

61
char	   *Name_pg_trigger_indices[Num_pg_trigger_indices] = {TriggerRelidIndex};
Vadim B. Mikheev's avatar
Vadim B. Mikheev committed
62

63

64
static HeapTuple CatalogIndexFetchTuple(Relation heapRelation,
65
					   Relation idesc,
66 67
					   ScanKey skey,
					   int16 num_keys);
68 69 70 71 72 73 74 75 76


/*
 * Changes (appends) to catalogs can (and does) happen at various places
 * throughout the code.  We need a generic routine that will open all of
 * the indices defined on a given catalog a return the relation descriptors
 * associated with them.
 */
void
77
CatalogOpenIndices(int nIndices, char **names, Relation *idescs)
78
{
79
	int			i;
80 81 82

	for (i = 0; i < nIndices; i++)
		idescs[i] = index_openr(names[i]);
83 84 85 86 87 88
}

/*
 * This is the inverse routine to CatalogOpenIndices()
 */
void
89
CatalogCloseIndices(int nIndices, Relation *idescs)
90
{
91
	int			i;
92 93 94

	for (i = 0; i < nIndices; i++)
		index_close(idescs[i]);
95 96 97 98 99
}


/*
 * For the same reasons outlined above CatalogOpenIndices() we need a routine
100
 * that takes a new catalog tuple and inserts an associated index tuple into
101 102 103
 * each catalog index.
 */
void
104
CatalogIndexInsert(Relation *idescs,
105 106 107
				   int nIndices,
				   Relation heapRelation,
				   HeapTuple heapTuple)
108
{
Bruce Momjian's avatar
Bruce Momjian committed
109
	HeapTuple	index_tup;
110
	TupleDesc	heapDescriptor;
Bruce Momjian's avatar
Bruce Momjian committed
111
	Form_pg_index index_form;
Bruce Momjian's avatar
Bruce Momjian committed
112 113
	Datum		datum[INDEX_MAX_KEYS];
	char		nulls[INDEX_MAX_KEYS];
114 115 116 117 118
	int			natts;
	AttrNumber *attnumP;
	FuncIndexInfo finfo,
			   *finfoP;
	int			i;
119

120
	heapDescriptor = RelationGetDescr(heapRelation);
121 122

	for (i = 0; i < nIndices; i++)
123
	{
124 125
		InsertIndexResult indexRes;

Bruce Momjian's avatar
Bruce Momjian committed
126
		index_tup = SearchSysCacheTupleCopy(INDEXRELID,
127 128
									  ObjectIdGetDatum(idescs[i]->rd_id),
											 0, 0, 0);
Bruce Momjian's avatar
Bruce Momjian committed
129 130
		Assert(index_tup);
		index_form = (Form_pg_index) GETSTRUCT(index_tup);
131 132

		/*
Bruce Momjian's avatar
Bruce Momjian committed
133
		 * Compute the number of attributes we are indexing upon.
134
		 */
Bruce Momjian's avatar
Bruce Momjian committed
135
		for (attnumP = index_form->indkey, natts = 0;
136 137 138 139
			 *attnumP != InvalidAttrNumber;
			 attnumP++, natts++)
			;

Bruce Momjian's avatar
Bruce Momjian committed
140
		if (index_form->indproc != InvalidOid)
141
		{
142 143
			FIgetnArgs(&finfo) = natts;
			natts = 1;
Bruce Momjian's avatar
Bruce Momjian committed
144
			FIgetProcOid(&finfo) = index_form->indproc;
145 146
			*(FIgetname(&finfo)) = '\0';
			finfoP = &finfo;
147
		}
148 149 150 151
		else
			finfoP = (FuncIndexInfo *) NULL;

		FormIndexDatum(natts,
Bruce Momjian's avatar
Bruce Momjian committed
152
					   (AttrNumber *) index_form->indkey,
153 154
					   heapTuple,
					   heapDescriptor,
Bruce Momjian's avatar
Bruce Momjian committed
155
					   datum,
156 157 158
					   nulls,
					   finfoP);

Bruce Momjian's avatar
Bruce Momjian committed
159
		indexRes = index_insert(idescs[i], datum, nulls,
160
								&heapTuple->t_ctid, heapRelation);
161 162
		if (indexRes)
			pfree(indexRes);
Bruce Momjian's avatar
Bruce Momjian committed
163
		pfree(index_tup);
164 165 166 167 168 169 170 171 172 173
	}
}

/*
 * This is needed at initialization when reldescs for some of the crucial
 * system catalogs are created and nailed into the cache.
 */
bool
CatalogHasIndex(char *catName, Oid catId)
{
174 175 176 177
	Relation	pg_class;
	HeapTuple	htup;
	Form_pg_class pgRelP;
	int			i;
178 179 180 181 182 183 184 185 186 187 188 189 190 191

	Assert(IsSystemRelationName(catName));

	/*
	 * If we're bootstraping we don't have pg_class (or any indices).
	 */
	if (IsBootstrapProcessingMode())
		return false;

	if (IsInitProcessingMode())
	{
		for (i = 0; IndexedCatalogNames[i] != NULL; i++)
		{
			if (strcmp(IndexedCatalogNames[i], catName) == 0)
192
				return true;
193
		}
194
		return false;
195
	}
196 197 198 199 200 201 202 203 204 205 206 207

	pg_class = heap_openr(RelationRelationName);
	htup = ClassOidIndexScan(pg_class, catId);
	heap_close(pg_class);

	if (!HeapTupleIsValid(htup))
	{
		elog(NOTICE, "CatalogHasIndex: no relation with oid %d", catId);
		return false;
	}

	pgRelP = (Form_pg_class) GETSTRUCT(htup);
208
	return pgRelP->relhasindex;
209 210 211
}

/*
212 213
 *	CatalogIndexFetchTuple() -- Get a tuple that satisfies a scan key
 *								from a catalog relation.
214
 *
215 216 217
 *		Since the index may contain pointers to dead tuples, we need to
 *		iterate until we find a tuple that's valid and satisfies the scan
 *		key.
218
 */
219
static HeapTuple
220
CatalogIndexFetchTuple(Relation heapRelation,
221
					   Relation idesc,
222 223
					   ScanKey skey,
					   int16 num_keys)
224
{
225
	IndexScanDesc sd;
226
	RetrieveIndexResult indexRes;
227
	HeapTuple	tuple = NULL;
228
	Buffer		buffer;
229

230
	sd = index_beginscan(idesc, false, num_keys, skey);
231
	while ((indexRes = index_getnext(sd, ForwardScanDirection)))
232
	{
Bruce Momjian's avatar
Bruce Momjian committed
233 234
		tuple = heap_fetch(heapRelation, SnapshotNow, &indexRes->heap_iptr,
							&buffer);
235 236
		pfree(indexRes);
		if (HeapTupleIsValid(tuple))
237
			break;
238
	}
239 240

	if (HeapTupleIsValid(tuple))
241
	{
242 243
		tuple = heap_copytuple(tuple);
		ReleaseBuffer(buffer);
244
	}
245 246 247

	index_endscan(sd);
	pfree(sd);
Bruce Momjian's avatar
Bruce Momjian committed
248
	return tuple;
249 250 251 252 253 254 255 256 257 258
}

/*
 * The remainder of the file is for individual index scan routines.  Each
 * index should be scanned according to how it was defined during bootstrap
 * (that is, functional or normal) and what arguments the cache lookup
 * requires.  Each routine returns the heap tuple that qualifies.
 */
HeapTuple
AttributeNameIndexScan(Relation heapRelation,
259 260
					   Oid relid,
					   char *attname)
261
{
262
	Relation	idesc;
263
	ScanKeyData skey[2];
264
	HeapTuple	tuple;
265

266
	ScanKeyEntryInitialize(&skey[0],
267 268
						   (bits16) 0x0,
						   (AttrNumber) 1,
269
						   (RegProcedure) F_OIDEQ,
Bruce Momjian's avatar
Bruce Momjian committed
270
						   ObjectIdGetDatum(relid));
271 272 273 274

	ScanKeyEntryInitialize(&skey[1],
						   (bits16) 0x0,
						   (AttrNumber) 2,
275
						   (RegProcedure) F_NAMEEQ,
276
						   NameGetDatum(attname));
277 278

	idesc = index_openr(AttributeNameIndex);
279
	tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 2);
280 281 282 283

	index_close(idesc);

	return tuple;
284 285 286 287
}

HeapTuple
AttributeNumIndexScan(Relation heapRelation,
288 289
					  Oid relid,
					  AttrNumber attnum)
290
{
291
	Relation	idesc;
292
	ScanKeyData skey[2];
293
	HeapTuple	tuple;
294

295
	ScanKeyEntryInitialize(&skey[0],
296 297
						   (bits16) 0x0,
						   (AttrNumber) 1,
298
						   (RegProcedure) F_OIDEQ,
Bruce Momjian's avatar
Bruce Momjian committed
299
						   ObjectIdGetDatum(relid));
300 301 302 303

	ScanKeyEntryInitialize(&skey[1],
						   (bits16) 0x0,
						   (AttrNumber) 2,
304
						   (RegProcedure) F_INT2EQ,
305
						   Int16GetDatum(attnum));
306 307

	idesc = index_openr(AttributeNumIndex);
308
	tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 2);
309 310 311 312

	index_close(idesc);

	return tuple;
313 314 315 316 317
}

HeapTuple
ProcedureOidIndexScan(Relation heapRelation, Oid procId)
{
318
	Relation	idesc;
319
	ScanKeyData skey[1];
320
	HeapTuple	tuple;
321

322
	ScanKeyEntryInitialize(&skey[0],
323 324
						   (bits16) 0x0,
						   (AttrNumber) 1,
Bruce Momjian's avatar
Bruce Momjian committed
325
						   (RegProcedure) F_OIDEQ,
326
						   ObjectIdGetDatum(procId));
327 328

	idesc = index_openr(ProcedureOidIndex);
329
	tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 1);
330 331 332 333

	index_close(idesc);

	return tuple;
334 335
}

336 337


338 339
HeapTuple
ProcedureNameIndexScan(Relation heapRelation,
340
					   char *procName,
341
					   int2 nargs,
342
					   Oid *argTypes)
343
{
344
	Relation	idesc;
345 346
	ScanKeyData skey[3];
	HeapTuple	tuple;
347

348
	ScanKeyEntryInitialize(&skey[0],
349 350
						   (bits16) 0x0,
						   (AttrNumber) 1,
Bruce Momjian's avatar
Bruce Momjian committed
351
						   (RegProcedure) F_NAMEEQ,
352
						   PointerGetDatum(procName));
353

354 355 356 357 358
	ScanKeyEntryInitialize(&skey[1],
						   (bits16) 0x0,
						   (AttrNumber) 2,
						   (RegProcedure) F_INT2EQ,
						   Int16GetDatum(nargs));
359

360 361 362 363
	ScanKeyEntryInitialize(&skey[2],
						   (bits16) 0x0,
						   (AttrNumber) 3,
						   (RegProcedure) F_OID8EQ,
364
						   PointerGetDatum(argTypes));
365

366 367
	idesc = index_openr(ProcedureNameIndex);
	tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 3);
368 369 370

	index_close(idesc);

371
	return tuple;
372 373
}

374 375


376
HeapTuple
377
ProcedureSrcIndexScan(Relation heapRelation, text *procSrc)
378
{
379
	Relation	idesc;
380
	ScanKeyData skey[1];
381
	HeapTuple	tuple;
382

383
	ScanKeyEntryInitialize(&skey[0],
384
						   (bits16) 0x0,
385
						   (AttrNumber) 1,
Bruce Momjian's avatar
Bruce Momjian committed
386
						   (RegProcedure) F_TEXTEQ,
387
						   PointerGetDatum(procSrc));
388 389

	idesc = index_openr(ProcedureSrcIndex);
390
	tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 1);
391

392
	index_close(idesc);
393 394

	return tuple;
395 396 397 398 399
}

HeapTuple
TypeOidIndexScan(Relation heapRelation, Oid typeId)
{
400
	Relation	idesc;
401
	ScanKeyData skey[1];
402
	HeapTuple	tuple;
403

404
	ScanKeyEntryInitialize(&skey[0],
405 406
						   (bits16) 0x0,
						   (AttrNumber) 1,
Bruce Momjian's avatar
Bruce Momjian committed
407
						   (RegProcedure) F_OIDEQ,
408
						   ObjectIdGetDatum(typeId));
409 410

	idesc = index_openr(TypeOidIndex);
411
	tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 1);
412 413 414 415

	index_close(idesc);

	return tuple;
416 417 418 419 420
}

HeapTuple
TypeNameIndexScan(Relation heapRelation, char *typeName)
{
421
	Relation	idesc;
422
	ScanKeyData skey[1];
423
	HeapTuple	tuple;
424

425
	ScanKeyEntryInitialize(&skey[0],
426 427
						   (bits16) 0x0,
						   (AttrNumber) 1,
Bruce Momjian's avatar
Bruce Momjian committed
428
						   (RegProcedure) F_NAMEEQ,
429
						   PointerGetDatum(typeName));
430 431

	idesc = index_openr(TypeNameIndex);
432
	tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 1);
433 434 435 436

	index_close(idesc);

	return tuple;
437 438 439 440 441
}

HeapTuple
ClassNameIndexScan(Relation heapRelation, char *relName)
{
442
	Relation	idesc;
443
	ScanKeyData skey[1];
444
	HeapTuple	tuple;
445

446
	ScanKeyEntryInitialize(&skey[0],
447 448
						   (bits16) 0x0,
						   (AttrNumber) 1,
Bruce Momjian's avatar
Bruce Momjian committed
449
						   (RegProcedure) F_NAMEEQ,
Bruce Momjian's avatar
Bruce Momjian committed
450
						   PointerGetDatum(relName));
451 452

	idesc = index_openr(ClassNameIndex);
453
	tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 1);
454 455 456

	index_close(idesc);
	return tuple;
457 458 459 460 461
}

HeapTuple
ClassOidIndexScan(Relation heapRelation, Oid relId)
{
462
	Relation	idesc;
463
	ScanKeyData skey[1];
464
	HeapTuple	tuple;
465

466
	ScanKeyEntryInitialize(&skey[0],
467 468
						   (bits16) 0x0,
						   (AttrNumber) 1,
Bruce Momjian's avatar
Bruce Momjian committed
469
						   (RegProcedure) F_OIDEQ,
470
						   ObjectIdGetDatum(relId));
471 472

	idesc = index_openr(ClassOidIndex);
473
	tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 1);
474 475 476 477

	index_close(idesc);

	return tuple;
478
}