]> granicus.if.org Git - postgresql/blob - src/backend/catalog/namespace.c
pg_type has a typnamespace column; system now supports creating types
[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.2 2002/03/29 19:06:01 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 Oid
86 RangeVarGetCreationNamespace(const RangeVar *newRelation)
87 {
88         Oid                     namespaceId;
89
90         /*
91          * We check the catalog name and then ignore it.
92          */
93         if (newRelation->catalogname)
94         {
95                 if (strcmp(newRelation->catalogname, DatabaseName) != 0)
96                         elog(ERROR, "Cross-database references are not implemented");
97         }
98
99         if (newRelation->schemaname)
100         {
101                 namespaceId = GetSysCacheOid(NAMESPACENAME,
102                                                                          CStringGetDatum(newRelation->schemaname),
103                                                                          0, 0, 0);
104                 if (!OidIsValid(namespaceId))
105                         elog(ERROR, "Namespace \"%s\" does not exist",
106                                  newRelation->schemaname);
107         }
108         else
109         {
110                 /* XXX Wrong!  Need to get a default schema from somewhere */
111                 namespaceId = PG_CATALOG_NAMESPACE;
112         }
113
114         return namespaceId;
115 }
116
117 /*
118  * RelnameGetRelid
119  *              Try to resolve an unqualified relation name.
120  *              Returns OID if relation found in search path, else InvalidOid.
121  */
122 Oid
123 RelnameGetRelid(const char *relname)
124 {
125         /* XXX Wrong!  must search search path */
126         return get_relname_relid(relname, PG_CATALOG_NAMESPACE);
127 }
128
129 /*
130  * QualifiedNameGetCreationNamespace
131  *              Given a possibly-qualified name for an object (in List-of-Values
132  *              format), determine what namespace the object should be created in.
133  *              Also extract and return the object name (last component of list).
134  */
135 Oid
136 QualifiedNameGetCreationNamespace(List *names, char **objname_p)
137 {
138         char       *catalogname;
139         char       *schemaname = NULL;
140         char       *objname = NULL;
141         Oid                     namespaceId;
142
143         /* deconstruct the name list */
144         switch (length(names))
145         {
146                 case 1:
147                         objname = strVal(lfirst(names));
148                         break;
149                 case 2:
150                         schemaname = strVal(lfirst(names));
151                         objname = strVal(lsecond(names));
152                         break;
153                 case 3:
154                         catalogname = strVal(lfirst(names));
155                         schemaname = strVal(lsecond(names));
156                         objname = strVal(lfirst(lnext(lnext(names))));
157                         /*
158                          * We check the catalog name and then ignore it.
159                          */
160                         if (strcmp(catalogname, DatabaseName) != 0)
161                                 elog(ERROR, "Cross-database references are not implemented");
162                         break;
163                 default:
164                         elog(ERROR, "Improper qualified name (too many dotted names)");
165                         break;
166         }
167
168         if (schemaname)
169         {
170                 namespaceId = GetSysCacheOid(NAMESPACENAME,
171                                                                          CStringGetDatum(schemaname),
172                                                                          0, 0, 0);
173                 if (!OidIsValid(namespaceId))
174                         elog(ERROR, "Namespace \"%s\" does not exist",
175                                  schemaname);
176         }
177         else
178         {
179                 /* XXX Wrong!  Need to get a default schema from somewhere */
180                 namespaceId = PG_CATALOG_NAMESPACE;
181         }
182
183         *objname_p = objname;
184         return namespaceId;
185 }
186
187 /*
188  * makeRangeVarFromNameList
189  *              Utility routine to convert a qualified-name list into RangeVar form.
190  */
191 RangeVar *
192 makeRangeVarFromNameList(List *names)
193 {
194         RangeVar   *rel = makeRangeVar(NULL, NULL);
195
196         switch (length(names))
197         {
198                 case 1:
199                         rel->relname = strVal(lfirst(names));
200                         break;
201                 case 2:
202                         rel->schemaname = strVal(lfirst(names));
203                         rel->relname = strVal(lsecond(names));
204                         break;
205                 case 3:
206                         rel->catalogname = strVal(lfirst(names));
207                         rel->schemaname = strVal(lsecond(names));
208                         rel->relname = strVal(lfirst(lnext(lnext(names))));
209                         break;
210                 default:
211                         elog(ERROR, "Improper relation name (too many dotted names)");
212                         break;
213         }
214
215         return rel;
216 }