1 /*-------------------------------------------------------------------------
2  *
3  * pg_range.c
4  *	  routines to support manipulation of the pg_range relation
5  *
6  * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *	  src/backend/catalog/pg_range.c
12  *
13  *-------------------------------------------------------------------------
14  */
15 #include "postgres.h"
16 
17 #include "access/genam.h"
18 #include "access/htup_details.h"
19 #include "access/table.h"
20 #include "catalog/dependency.h"
21 #include "catalog/indexing.h"
22 #include "catalog/pg_collation.h"
23 #include "catalog/pg_opclass.h"
24 #include "catalog/pg_proc.h"
25 #include "catalog/pg_range.h"
26 #include "catalog/pg_type.h"
27 #include "utils/fmgroids.h"
28 #include "utils/rel.h"
29 
30 
31 /*
32  * RangeCreate
33  *		Create an entry in pg_range.
34  */
35 void
RangeCreate(Oid rangeTypeOid,Oid rangeSubType,Oid rangeCollation,Oid rangeSubOpclass,RegProcedure rangeCanonical,RegProcedure rangeSubDiff,Oid multirangeTypeOid)36 RangeCreate(Oid rangeTypeOid, Oid rangeSubType, Oid rangeCollation,
37 			Oid rangeSubOpclass, RegProcedure rangeCanonical,
38 			RegProcedure rangeSubDiff, Oid multirangeTypeOid)
39 {
40 	Relation	pg_range;
41 	Datum		values[Natts_pg_range];
42 	bool		nulls[Natts_pg_range];
43 	HeapTuple	tup;
44 	ObjectAddress myself;
45 	ObjectAddress referenced;
46 	ObjectAddress referencing;
47 	ObjectAddresses *addrs;
48 
49 	pg_range = table_open(RangeRelationId, RowExclusiveLock);
50 
51 	memset(nulls, 0, sizeof(nulls));
52 
53 	values[Anum_pg_range_rngtypid - 1] = ObjectIdGetDatum(rangeTypeOid);
54 	values[Anum_pg_range_rngsubtype - 1] = ObjectIdGetDatum(rangeSubType);
55 	values[Anum_pg_range_rngcollation - 1] = ObjectIdGetDatum(rangeCollation);
56 	values[Anum_pg_range_rngsubopc - 1] = ObjectIdGetDatum(rangeSubOpclass);
57 	values[Anum_pg_range_rngcanonical - 1] = ObjectIdGetDatum(rangeCanonical);
58 	values[Anum_pg_range_rngsubdiff - 1] = ObjectIdGetDatum(rangeSubDiff);
59 	values[Anum_pg_range_rngmultitypid - 1] = ObjectIdGetDatum(multirangeTypeOid);
60 
61 	tup = heap_form_tuple(RelationGetDescr(pg_range), values, nulls);
62 
63 	CatalogTupleInsert(pg_range, tup);
64 	heap_freetuple(tup);
65 
66 	/* record type's dependencies on range-related items */
67 	addrs = new_object_addresses();
68 
69 	ObjectAddressSet(myself, TypeRelationId, rangeTypeOid);
70 
71 	ObjectAddressSet(referenced, TypeRelationId, rangeSubType);
72 	add_exact_object_address(&referenced, addrs);
73 
74 	ObjectAddressSet(referenced, OperatorClassRelationId, rangeSubOpclass);
75 	add_exact_object_address(&referenced, addrs);
76 
77 	if (OidIsValid(rangeCollation))
78 	{
79 		ObjectAddressSet(referenced, CollationRelationId, rangeCollation);
80 		add_exact_object_address(&referenced, addrs);
81 	}
82 
83 	if (OidIsValid(rangeCanonical))
84 	{
85 		ObjectAddressSet(referenced, ProcedureRelationId, rangeCanonical);
86 		add_exact_object_address(&referenced, addrs);
87 	}
88 
89 	if (OidIsValid(rangeSubDiff))
90 	{
91 		ObjectAddressSet(referenced, ProcedureRelationId, rangeSubDiff);
92 		add_exact_object_address(&referenced, addrs);
93 	}
94 
95 	record_object_address_dependencies(&myself, addrs, DEPENDENCY_NORMAL);
96 	free_object_addresses(addrs);
97 
98 	/* record multirange type's dependency on the range type */
99 	referencing.classId = TypeRelationId;
100 	referencing.objectId = multirangeTypeOid;
101 	referencing.objectSubId = 0;
102 	recordDependencyOn(&referencing, &myself, DEPENDENCY_INTERNAL);
103 
104 	table_close(pg_range, RowExclusiveLock);
105 }
106 
107 
108 /*
109  * RangeDelete
110  *		Remove the pg_range entry for the specified type.
111  */
112 void
RangeDelete(Oid rangeTypeOid)113 RangeDelete(Oid rangeTypeOid)
114 {
115 	Relation	pg_range;
116 	ScanKeyData key[1];
117 	SysScanDesc scan;
118 	HeapTuple	tup;
119 
120 	pg_range = table_open(RangeRelationId, RowExclusiveLock);
121 
122 	ScanKeyInit(&key[0],
123 				Anum_pg_range_rngtypid,
124 				BTEqualStrategyNumber, F_OIDEQ,
125 				ObjectIdGetDatum(rangeTypeOid));
126 
127 	scan = systable_beginscan(pg_range, RangeTypidIndexId, true,
128 							  NULL, 1, key);
129 
130 	while (HeapTupleIsValid(tup = systable_getnext(scan)))
131 	{
132 		CatalogTupleDelete(pg_range, &tup->t_self);
133 	}
134 
135 	systable_endscan(scan);
136 
137 	table_close(pg_range, RowExclusiveLock);
138 }
139