]> granicus.if.org Git - postgresql/blob - src/backend/catalog/namespace.c
Further cleanups for relations in schemas: teach nextval and other
[postgresql] / src / backend / catalog / namespace.c
1 /*-------------------------------------------------------------------------
2  *
3  * namespace.c
4  *        code to support accessing and searching namespaces
5  *
6  * This is separate from pg_namespace.c, which contains the routines that
7  * directly manipulate the pg_namespace system catalog.  This module
8  * provides routines associated with defining a "namespace search path"
9  * and implementing search-path-controlled searches.
10  *
11  *
12  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
13  * Portions Copyright (c) 1994, Regents of the University of California
14  *
15  * IDENTIFICATION
16  *        $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.3 2002/03/30 01:02:41 tgl Exp $
17  *
18  *-------------------------------------------------------------------------
19  */
20 #include "postgres.h"
21
22 #include "catalog/namespace.h"
23 #include "catalog/pg_namespace.h"
24 #include "miscadmin.h"
25 #include "nodes/makefuncs.h"
26 #include "utils/lsyscache.h"
27 #include "utils/syscache.h"
28
29
30 /*
31  * RangeVarGetRelid
32  *              Given a RangeVar describing an existing relation,
33  *              select the proper namespace and look up the relation OID.
34  *
35  * If the relation is not found, return InvalidOid if failOK = true,
36  * otherwise raise an error.
37  */
38 Oid
39 RangeVarGetRelid(const RangeVar *relation, bool failOK)
40 {
41         Oid                     namespaceId;
42         Oid                     relId;
43
44         /*
45          * We check the catalog name and then ignore it.
46          */
47         if (relation->catalogname)
48         {
49                 if (strcmp(relation->catalogname, DatabaseName) != 0)
50                         elog(ERROR, "Cross-database references are not implemented");
51         }
52
53         if (relation->schemaname)
54         {
55                 namespaceId = GetSysCacheOid(NAMESPACENAME,
56                                                                          CStringGetDatum(relation->schemaname),
57                                                                          0, 0, 0);
58                 if (!OidIsValid(namespaceId))
59                         elog(ERROR, "Namespace \"%s\" does not exist",
60                                  relation->schemaname);
61                 relId = get_relname_relid(relation->relname, namespaceId);
62         }
63         else
64         {
65                 relId = RelnameGetRelid(relation->relname);
66         }
67
68         if (!OidIsValid(relId) && !failOK)
69         {
70                 if (relation->schemaname)
71                         elog(ERROR, "Relation \"%s\".\"%s\" does not exist",
72                                  relation->schemaname, relation->relname);
73                 else
74                         elog(ERROR, "Relation \"%s\" does not exist",
75                                  relation->relname);
76         }
77         return relId;
78 }
79
80 /*
81  * RangeVarGetCreationNamespace
82  *              Given a RangeVar describing a to-be-created relation,
83  *              choose which namespace to create it in.
84  *
85  * Note: calling this may result in a CommandCounterIncrement operation.
86  * That will happen on the first request for a temp table in any particular
87  * backend run; we will need to either create or clean out the temp schema.
88  */
89 Oid
90 RangeVarGetCreationNamespace(const RangeVar *newRelation)
91 {
92         Oid                     namespaceId;
93
94         /*
95          * We check the catalog name and then ignore it.
96          */
97         if (newRelation->catalogname)
98         {
99                 if (strcmp(newRelation->catalogname, DatabaseName) != 0)
100                         elog(ERROR, "Cross-database references are not implemented");
101         }
102
103         if (newRelation->schemaname)
104         {
105                 namespaceId = GetSysCacheOid(NAMESPACENAME,
106                                                                          CStringGetDatum(newRelation->schemaname),
107                                                                          0, 0, 0);
108                 if (!OidIsValid(namespaceId))
109                         elog(ERROR, "Namespace \"%s\" does not exist",
110                                  newRelation->schemaname);
111         }
112         else
113         {
114                 /* XXX Wrong!  Need to get a default schema from somewhere */
115                 namespaceId = PG_CATALOG_NAMESPACE;
116         }
117
118         return namespaceId;
119 }
120
121 /*
122  * RelnameGetRelid
123  *              Try to resolve an unqualified relation name.
124  *              Returns OID if relation found in search path, else InvalidOid.
125  */
126 Oid
127 RelnameGetRelid(const char *relname)
128 {
129         /* XXX Wrong!  must search search path */
130         return get_relname_relid(relname, PG_CATALOG_NAMESPACE);
131 }
132
133 /*
134  * TypenameGetTypid
135  *              Try to resolve an unqualified datatype name.
136  *              Returns OID if type found in search path, else InvalidOid.
137  */
138 Oid
139 TypenameGetTypid(const char *typname)
140 {
141         /* XXX wrong, should use namespace search */
142         return GetSysCacheOid(TYPENAMENSP,
143                                                   PointerGetDatum(typname),
144                                                   ObjectIdGetDatum(PG_CATALOG_NAMESPACE),
145                                                   0, 0);
146 }
147
148 /*
149  * QualifiedNameGetCreationNamespace
150  *              Given a possibly-qualified name for an object (in List-of-Values
151  *              format), determine what namespace the object should be created in.
152  *              Also extract and return the object name (last component of list).
153  */
154 Oid
155 QualifiedNameGetCreationNamespace(List *names, char **objname_p)
156 {
157         char       *catalogname;
158         char       *schemaname = NULL;
159         char       *objname = NULL;
160         Oid                     namespaceId;
161
162         /* deconstruct the name list */
163         switch (length(names))
164         {
165                 case 1:
166                         objname = strVal(lfirst(names));
167                         break;
168                 case 2:
169                         schemaname = strVal(lfirst(names));
170                         objname = strVal(lsecond(names));
171                         break;
172                 case 3:
173                         catalogname = strVal(lfirst(names));
174                         schemaname = strVal(lsecond(names));
175                         objname = strVal(lfirst(lnext(lnext(names))));
176                         /*
177                          * We check the catalog name and then ignore it.
178                          */
179                         if (strcmp(catalogname, DatabaseName) != 0)
180                                 elog(ERROR, "Cross-database references are not implemented");
181                         break;
182                 default:
183                         elog(ERROR, "Improper qualified name (too many dotted names)");
184                         break;
185         }
186
187         if (schemaname)
188         {
189                 namespaceId = GetSysCacheOid(NAMESPACENAME,
190                                                                          CStringGetDatum(schemaname),
191                                                                          0, 0, 0);
192                 if (!OidIsValid(namespaceId))
193                         elog(ERROR, "Namespace \"%s\" does not exist",
194                                  schemaname);
195         }
196         else
197         {
198                 /* XXX Wrong!  Need to get a default schema from somewhere */
199                 namespaceId = PG_CATALOG_NAMESPACE;
200         }
201
202         *objname_p = objname;
203         return namespaceId;
204 }
205
206 /*
207  * makeRangeVarFromNameList
208  *              Utility routine to convert a qualified-name list into RangeVar form.
209  */
210 RangeVar *
211 makeRangeVarFromNameList(List *names)
212 {
213         RangeVar   *rel = makeRangeVar(NULL, NULL);
214
215         switch (length(names))
216         {
217                 case 1:
218                         rel->relname = strVal(lfirst(names));
219                         break;
220                 case 2:
221                         rel->schemaname = strVal(lfirst(names));
222                         rel->relname = strVal(lsecond(names));
223                         break;
224                 case 3:
225                         rel->catalogname = strVal(lfirst(names));
226                         rel->schemaname = strVal(lsecond(names));
227                         rel->relname = strVal(lfirst(lnext(lnext(names))));
228                         break;
229                 default:
230                         elog(ERROR, "Improper relation name (too many dotted names)");
231                         break;
232         }
233
234         return rel;
235 }