Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "postgres.h"
00019
00020 #include <fcntl.h>
00021 #include <unistd.h>
00022
00023 #include "access/genam.h"
00024 #include "access/sysattr.h"
00025 #include "access/transam.h"
00026 #include "catalog/catalog.h"
00027 #include "catalog/indexing.h"
00028 #include "catalog/namespace.h"
00029 #include "catalog/pg_auth_members.h"
00030 #include "catalog/pg_authid.h"
00031 #include "catalog/pg_database.h"
00032 #include "catalog/pg_namespace.h"
00033 #include "catalog/pg_pltemplate.h"
00034 #include "catalog/pg_db_role_setting.h"
00035 #include "catalog/pg_shdepend.h"
00036 #include "catalog/pg_shdescription.h"
00037 #include "catalog/pg_shseclabel.h"
00038 #include "catalog/pg_tablespace.h"
00039 #include "catalog/toasting.h"
00040 #include "common/relpath.h"
00041 #include "miscadmin.h"
00042 #include "storage/fd.h"
00043 #include "utils/fmgroids.h"
00044 #include "utils/rel.h"
00045 #include "utils/tqual.h"
00046
00047
00048
00049
00050
00051
00052 ForkNumber
00053 forkname_to_number(char *forkName)
00054 {
00055 ForkNumber forkNum;
00056
00057 for (forkNum = 0; forkNum <= MAX_FORKNUM; forkNum++)
00058 if (strcmp(forkNames[forkNum], forkName) == 0)
00059 return forkNum;
00060
00061 ereport(ERROR,
00062 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
00063 errmsg("invalid fork name"),
00064 errhint("Valid fork names are \"main\", \"fsm\", and \"vm\".")));
00065 return InvalidForkNumber;
00066 }
00067
00068
00069
00070
00071
00072
00073
00074
00075 char *
00076 GetDatabasePath(Oid dbNode, Oid spcNode)
00077 {
00078 int pathlen;
00079 char *path;
00080
00081 if (spcNode == GLOBALTABLESPACE_OID)
00082 {
00083
00084 Assert(dbNode == 0);
00085 pathlen = 6 + 1;
00086 path = (char *) palloc(pathlen);
00087 snprintf(path, pathlen, "global");
00088 }
00089 else if (spcNode == DEFAULTTABLESPACE_OID)
00090 {
00091
00092 pathlen = 5 + OIDCHARS + 1;
00093 path = (char *) palloc(pathlen);
00094 snprintf(path, pathlen, "base/%u",
00095 dbNode);
00096 }
00097 else
00098 {
00099
00100 pathlen = 9 + 1 + OIDCHARS + 1 + strlen(TABLESPACE_VERSION_DIRECTORY) +
00101 1 + OIDCHARS + 1;
00102 path = (char *) palloc(pathlen);
00103 snprintf(path, pathlen, "pg_tblspc/%u/%s/%u",
00104 spcNode, TABLESPACE_VERSION_DIRECTORY, dbNode);
00105 }
00106 return path;
00107 }
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123 bool
00124 IsSystemRelation(Relation relation)
00125 {
00126 return IsSystemNamespace(RelationGetNamespace(relation)) ||
00127 IsToastNamespace(RelationGetNamespace(relation));
00128 }
00129
00130
00131
00132
00133
00134
00135
00136 bool
00137 IsSystemClass(Form_pg_class reltuple)
00138 {
00139 Oid relnamespace = reltuple->relnamespace;
00140
00141 return IsSystemNamespace(relnamespace) ||
00142 IsToastNamespace(relnamespace);
00143 }
00144
00145
00146
00147
00148
00149 bool
00150 IsToastRelation(Relation relation)
00151 {
00152 return IsToastNamespace(RelationGetNamespace(relation));
00153 }
00154
00155
00156
00157
00158
00159
00160
00161 bool
00162 IsToastClass(Form_pg_class reltuple)
00163 {
00164 Oid relnamespace = reltuple->relnamespace;
00165
00166 return IsToastNamespace(relnamespace);
00167 }
00168
00169
00170
00171
00172
00173
00174
00175
00176 bool
00177 IsSystemNamespace(Oid namespaceId)
00178 {
00179 return namespaceId == PG_CATALOG_NAMESPACE;
00180 }
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190 bool
00191 IsToastNamespace(Oid namespaceId)
00192 {
00193 return (namespaceId == PG_TOAST_NAMESPACE) ||
00194 isTempToastNamespace(namespaceId);
00195 }
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206 bool
00207 IsReservedName(const char *name)
00208 {
00209
00210 return (name[0] == 'p' &&
00211 name[1] == 'g' &&
00212 name[2] == '_');
00213 }
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236 bool
00237 IsSharedRelation(Oid relationId)
00238 {
00239
00240 if (relationId == AuthIdRelationId ||
00241 relationId == AuthMemRelationId ||
00242 relationId == DatabaseRelationId ||
00243 relationId == PLTemplateRelationId ||
00244 relationId == SharedDescriptionRelationId ||
00245 relationId == SharedDependRelationId ||
00246 relationId == SharedSecLabelRelationId ||
00247 relationId == TableSpaceRelationId ||
00248 relationId == DbRoleSettingRelationId)
00249 return true;
00250
00251 if (relationId == AuthIdRolnameIndexId ||
00252 relationId == AuthIdOidIndexId ||
00253 relationId == AuthMemRoleMemIndexId ||
00254 relationId == AuthMemMemRoleIndexId ||
00255 relationId == DatabaseNameIndexId ||
00256 relationId == DatabaseOidIndexId ||
00257 relationId == PLTemplateNameIndexId ||
00258 relationId == SharedDescriptionObjIndexId ||
00259 relationId == SharedDependDependerIndexId ||
00260 relationId == SharedDependReferenceIndexId ||
00261 relationId == SharedSecLabelObjectIndexId ||
00262 relationId == TablespaceOidIndexId ||
00263 relationId == TablespaceNameIndexId ||
00264 relationId == DbRoleSettingDatidRolidIndexId)
00265 return true;
00266
00267 if (relationId == PgShdescriptionToastTable ||
00268 relationId == PgShdescriptionToastIndex ||
00269 relationId == PgDbRoleSettingToastTable ||
00270 relationId == PgDbRoleSettingToastIndex)
00271 return true;
00272 return false;
00273 }
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297 Oid
00298 GetNewOid(Relation relation)
00299 {
00300 Oid oidIndex;
00301
00302
00303 Assert(relation->rd_rel->relhasoids);
00304
00305
00306 if (IsBootstrapProcessingMode())
00307 return GetNewObjectId();
00308
00309
00310 oidIndex = RelationGetOidIndex(relation);
00311
00312
00313 if (!OidIsValid(oidIndex))
00314 {
00315
00316
00317
00318
00319
00320 if (IsSystemRelation(relation))
00321 elog(WARNING, "generating possibly-non-unique OID for \"%s\"",
00322 RelationGetRelationName(relation));
00323
00324 return GetNewObjectId();
00325 }
00326
00327
00328 return GetNewOidWithIndex(relation, oidIndex, ObjectIdAttributeNumber);
00329 }
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344 Oid
00345 GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
00346 {
00347 Oid newOid;
00348 SnapshotData SnapshotDirty;
00349 SysScanDesc scan;
00350 ScanKeyData key;
00351 bool collides;
00352
00353 InitDirtySnapshot(SnapshotDirty);
00354
00355
00356 do
00357 {
00358 CHECK_FOR_INTERRUPTS();
00359
00360 newOid = GetNewObjectId();
00361
00362 ScanKeyInit(&key,
00363 oidcolumn,
00364 BTEqualStrategyNumber, F_OIDEQ,
00365 ObjectIdGetDatum(newOid));
00366
00367
00368 scan = systable_beginscan(relation, indexId, true,
00369 &SnapshotDirty, 1, &key);
00370
00371 collides = HeapTupleIsValid(systable_getnext(scan));
00372
00373 systable_endscan(scan);
00374 } while (collides);
00375
00376 return newOid;
00377 }
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395 Oid
00396 GetNewRelFileNode(Oid reltablespace, Relation pg_class, char relpersistence)
00397 {
00398 RelFileNodeBackend rnode;
00399 char *rpath;
00400 int fd;
00401 bool collides;
00402 BackendId backend;
00403
00404 switch (relpersistence)
00405 {
00406 case RELPERSISTENCE_TEMP:
00407 backend = MyBackendId;
00408 break;
00409 case RELPERSISTENCE_UNLOGGED:
00410 case RELPERSISTENCE_PERMANENT:
00411 backend = InvalidBackendId;
00412 break;
00413 default:
00414 elog(ERROR, "invalid relpersistence: %c", relpersistence);
00415 return InvalidOid;
00416 }
00417
00418
00419 rnode.node.spcNode = reltablespace ? reltablespace : MyDatabaseTableSpace;
00420 rnode.node.dbNode = (rnode.node.spcNode == GLOBALTABLESPACE_OID) ? InvalidOid : MyDatabaseId;
00421
00422
00423
00424
00425
00426
00427 rnode.backend = backend;
00428
00429 do
00430 {
00431 CHECK_FOR_INTERRUPTS();
00432
00433
00434 if (pg_class)
00435 rnode.node.relNode = GetNewOid(pg_class);
00436 else
00437 rnode.node.relNode = GetNewObjectId();
00438
00439
00440 rpath = relpath(rnode, MAIN_FORKNUM);
00441 fd = BasicOpenFile(rpath, O_RDONLY | PG_BINARY, 0);
00442
00443 if (fd >= 0)
00444 {
00445
00446 close(fd);
00447 collides = true;
00448 }
00449 else
00450 {
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462 collides = false;
00463 }
00464
00465 pfree(rpath);
00466 } while (collides);
00467
00468 return rnode.node.relNode;
00469 }