]> granicus.if.org Git - postgresql/blob - src/backend/utils/misc/database.c
69d67e5e1a471a90e247f84cb88387179c77205c
[postgresql] / src / backend / utils / misc / database.c
1 /*-------------------------------------------------------------------------
2  *
3  * database.c--
4  *        miscellanious initialization support stuff
5  *
6  * Copyright (c) 1994, Regents of the University of California
7  *
8  *
9  * IDENTIFICATION
10  *        $Header: /cvsroot/pgsql/src/backend/utils/misc/Attic/database.c,v 1.13 1998/07/26 04:31:07 scrappy Exp $
11  *
12  *-------------------------------------------------------------------------
13  */
14 #include <string.h>
15 #include <stdlib.h>
16 #include <stdio.h>
17 #include <unistd.h>
18 #include <fcntl.h>
19
20 #include "postgres.h"
21
22 #include "access/heapam.h"
23 #include "access/xact.h"
24 #include "catalog/catname.h"
25 #ifdef MULTIBYTE
26 #include "catalog/pg_database_mb.h"
27 #include "mb/pg_wchar.h"
28 #else
29 #include "catalog/pg_database.h"
30 #endif
31 #include "fmgr.h"
32 #include "miscadmin.h"
33 #include "storage/bufmgr.h"
34 #include "storage/bufpage.h"
35 #include "utils/builtins.h"
36 #include "utils/syscache.h"
37
38
39 /* GetDatabaseInfo()
40  * Pull database information from pg_database.
41  */
42 int
43 GetDatabaseInfo(char *name, Oid *owner, char *path)
44 {
45         Oid                     dbowner,
46                                 dbid;
47         char            dbpath[MAXPGPATH + 1];
48         text       *dbtext;
49
50         Relation        dbrel;
51         HeapTuple       dbtup;
52         HeapTuple       tup;
53         Buffer          buf;
54         HeapScanDesc scan;
55         ScanKeyData scanKey;
56
57         dbrel = heap_openr(DatabaseRelationName);
58         if (!RelationIsValid(dbrel))
59                 elog(FATAL, "GetDatabaseInfo: cannot open relation \"%-.*s\"",
60                          DatabaseRelationName);
61
62         ScanKeyEntryInitialize(&scanKey, 0, Anum_pg_database_datname,
63                                                    F_NAMEEQ, NameGetDatum(name));
64
65         scan = heap_beginscan(dbrel, 0, false, 1, &scanKey);
66         if (!HeapScanIsValid(scan))
67                 elog(ERROR, "GetDatabaseInfo: cannot begin scan of %s", DatabaseRelationName);
68
69         /*
70          * Since we're going to close the relation, copy the tuple.
71          */
72         tup = heap_getnext(scan, 0, &buf);
73
74         if (HeapTupleIsValid(tup))
75         {
76                 dbtup = heap_copytuple(tup);
77                 ReleaseBuffer(buf);
78         }
79         else
80                 dbtup = tup;
81
82         heap_endscan(scan);
83
84         if (!HeapTupleIsValid(dbtup))
85         {
86                 elog(NOTICE, "GetDatabaseInfo: %s entry not found %s",
87                          DatabaseRelationName, name);
88                 return TRUE;
89         }
90
91         dbowner = (Oid) heap_getattr(dbtup,
92                                                                  Anum_pg_database_datdba,
93                                                                  RelationGetTupleDescriptor(dbrel),
94                                                                  (char *) NULL);
95         dbid = dbtup->t_oid;
96
97         dbtext = (text *) heap_getattr(dbtup,
98                                                                    Anum_pg_database_datpath,
99                                                                    RelationGetTupleDescriptor(dbrel),
100                                                                    (char *) NULL);
101
102         memcpy(dbpath, VARDATA(dbtext), (VARSIZE(dbtext) - VARHDRSZ));
103         *(dbpath + (VARSIZE(dbtext) - VARHDRSZ)) = '\0';
104
105         heap_close(dbrel);
106
107         owner = palloc(sizeof(Oid));
108         *owner = dbowner;
109         path = palloc(strlen(dbpath) + 1);
110         strcpy(path, dbpath);
111
112         return FALSE;
113 }       /* GetDatabaseInfo() */
114
115 char *
116 ExpandDatabasePath(char *dbpath)
117 {
118         char       *path;
119         char       *cp;
120         char            buf[MAXPGPATH + 1];
121
122         /* leading path delimiter? then already absolute path */
123         if (*dbpath == SEP_CHAR)
124         {
125 #ifdef ALLOW_ABSOLUTE_DBPATHS
126                 cp = strrchr(dbpath, SEP_CHAR);
127                 strncpy(buf, dbpath, (cp - dbpath));
128                 sprintf(&buf[cp - dbpath], "%cbase%c%s", SEP_CHAR, SEP_CHAR, (cp + 1));
129 #else
130                 return NULL;
131 #endif
132         }
133         /* path delimiter somewhere? then has leading environment variable */
134         else if (strchr(dbpath, SEP_CHAR) != NULL)
135         {
136                 cp = strchr(dbpath, SEP_CHAR);
137                 strncpy(buf, dbpath, (cp - dbpath));
138                 buf[cp - dbpath] = '\0';
139                 path = getenv(buf);
140
141                 /*
142                  * problem getting environment variable? let calling routine
143                  * handle it
144                  */
145                 if (path == NULL)
146                         return path;
147
148                 sprintf(buf, "%s%cbase%c%s", path, SEP_CHAR, SEP_CHAR, (cp + 1));
149         }
150         /* no path delimiter? then add the default path prefixes */
151         else
152                 sprintf(buf, "%s%cbase%c%s", DataDir, SEP_CHAR, SEP_CHAR, dbpath);
153
154         path = palloc(strlen(buf) + 1);
155         strcpy(path, buf);
156
157         return path;
158 }       /* ExpandDatabasePath() */
159
160
161 /* --------------------------------
162  *      GetRawDatabaseInfo() -- Find the OID and path of the database.
163  *
164  *              The database's oid forms half of the unique key for the system
165  *              caches and lock tables.  We therefore want it initialized before
166  *              we open any relations, since opening relations puts things in the
167  *              cache.  To get around this problem, this code opens and scans the
168  *              pg_database relation by hand.
169  *
170  *              This algorithm relies on the fact that first attribute in the
171  *              pg_database relation schema is the database name.  It also knows
172  *              about the internal format of tuples on disk and the length of
173  *              the datname attribute.  It knows the location of the pg_database
174  *              file.
175  *              Actually, the code looks as though it is using the pg_database
176  *              tuple definition to locate the database name, so the above statement
177  *              seems to be no longer correct. - thomas 1997-11-01
178  *
179  *              This code is called from InitPostgres(), before we chdir() to the
180  *              local database directory and before we open any relations.
181  *              Used to be called after the chdir(), but we now want to confirm
182  *              the location of the target database using pg_database info.
183  *              - thomas 1997-11-01
184  * --------------------------------
185  */
186 void
187 #ifdef MULTIBYTE
188 GetRawDatabaseInfo(char *name, Oid *owner, Oid *db_id, char *path, int *encoding)
189 #else
190 GetRawDatabaseInfo(char *name, Oid *owner, Oid *db_id, char *path)
191 #endif
192 {
193         int                     dbfd;
194         int                     fileflags;
195         int                     nbytes;
196         int                     max,
197                                 i;
198         HeapTuple       tup;
199         Page            pg;
200         PageHeader      ph;
201         char       *dbfname;
202         Form_pg_database tup_db;
203
204         dbfname = (char *) palloc(strlen(DataDir) + strlen("pg_database") + 2);
205         sprintf(dbfname, "%s%cpg_database", DataDir, SEP_CHAR);
206         fileflags = O_RDONLY;
207
208         if ((dbfd = open(dbfname, O_RDONLY, 0)) < 0)
209                 elog(FATAL, "Cannot open %s", dbfname);
210
211         pfree(dbfname);
212
213         /* ----------------
214          *      read and examine every page in pg_database
215          *
216          *      Raw I/O! Read those tuples the hard way! Yow!
217          *
218          *      Why don't we use the access methods or move this code
219          *      someplace else?  This is really pg_database schema dependent
220          *      code.  Perhaps it should go in lib/catalog/pg_database?
221          *      -cim 10/3/90
222          *
223          *      mao replies 4 apr 91:  yeah, maybe this should be moved to
224          *      lib/catalog.  however, we CANNOT use the access methods since
225          *      those use the buffer cache, which uses the relation cache, which
226          *      requires that the dbid be set, which is what we're trying to do
227          *      here.
228          * ----------------
229          */
230         pg = (Page) palloc(BLCKSZ);
231         ph = (PageHeader) pg;
232
233         while ((nbytes = read(dbfd, pg, BLCKSZ)) == BLCKSZ)
234         {
235                 max = PageGetMaxOffsetNumber(pg);
236
237                 /* look at each tuple on the page */
238                 for (i = 0; i <= max; i++)
239                 {
240                         int                     offset;
241
242                         /* if it's a freed tuple, ignore it */
243                         if (!(ph->pd_linp[i].lp_flags & LP_USED))
244                                 continue;
245
246                         /* get a pointer to the tuple itself */
247                         offset = (int) ph->pd_linp[i].lp_off;
248                         tup = (HeapTuple) (((char *) pg) + offset);
249
250                         /*
251                          * if the tuple has been deleted (the database was destroyed),
252                          * skip this tuple.  XXX warning, will robinson:  violation of
253                          * transaction semantics happens right here.  we should check
254                          * to be sure that the xact that deleted this tuple actually
255                          * committed.  only way to do this at init time is to paw over
256                          * the log relation by hand, too.  let's be optimistic.
257                          *
258                          * XXX This is an evil type cast.  tup->t_xmax is char[5] while
259                          * TransactionId is struct * { char data[5] }.  It works but
260                          * if data is ever moved and no longer the first field this
261                          * will be broken!! -mer 11 Nov 1991.
262                          */
263                         if (TransactionIdIsValid((TransactionId) tup->t_xmax))
264                                 continue;
265
266                         /*
267                          * Okay, see if this is the one we want. XXX 1 july 91:  mao
268                          * and mer discover that tuples now squash t_bits.      Why is
269                          * this?
270                          *
271                          * 24 july 92:  mer realizes that the t_bits field is only used
272                          * in the event of null values.  If no fields are null we
273                          * reduce the header size by doing the squash.  t_hoff tells
274                          * you exactly how big the header actually is. use the PC
275                          * means of getting at sys cat attrs.
276                          */
277                         tup_db = (Form_pg_database) GETSTRUCT(tup);
278 #ifdef MULTIBYTE
279                         /* get encoding from template database.
280                            This is the "default for default" for
281                            create database command.
282                            */
283                         if (strcmp("template1",tup_db->datname.data) == 0)
284                         {
285                                 SetTemplateEncoding(tup_db->encoding);
286                         }
287 #endif
288                         if (strcmp(name, tup_db->datname.data) == 0)
289                         {
290                                 *db_id = tup->t_oid;
291                                 strncpy(path, VARDATA(&(tup_db->datpath)),
292                                                 (VARSIZE(&(tup_db->datpath)) - VARHDRSZ));
293                                 *(path + VARSIZE(&(tup_db->datpath)) - VARHDRSZ) = '\0';
294 #ifdef MULTIBYTE
295                                 *encoding = tup_db->encoding;
296 #endif
297                                 goto done;
298                         }
299                 }
300         }
301
302 done:
303         close(dbfd);
304         pfree(pg);
305 }       /* GetRawDatabaseInfo() */