Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit35508d1

Browse files
committed
Add ALTER object SET SCHEMA capability for a limited but useful set of
object kinds (tables, functions, types). Documentation is not here yet.Original code by Bernd Helmle, extensive rework by Bruce Momjian andTom Lane.
1 parenta85e5d1 commit35508d1

File tree

22 files changed

+1095
-41
lines changed

22 files changed

+1095
-41
lines changed

‎src/backend/catalog/namespace.c

Lines changed: 50 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
* Portions Copyright (c) 1994, Regents of the University of California
1414
*
1515
* IDENTIFICATION
16-
* $PostgreSQL: pgsql/src/backend/catalog/namespace.c,v 1.76 2005/06/28 05:08:52 tgl Exp $
16+
* $PostgreSQL: pgsql/src/backend/catalog/namespace.c,v 1.77 2005/08/01 04:03:54 tgl Exp $
1717
*
1818
*-------------------------------------------------------------------------
1919
*/
@@ -1235,12 +1235,43 @@ LookupExplicitNamespace(const char *nspname)
12351235
returnnamespaceId;
12361236
}
12371237

1238+
/*
1239+
* LookupCreationNamespace
1240+
*Look up the schema and verify we have CREATE rights on it.
1241+
*
1242+
* This is just like LookupExplicitNamespace except for the permission check.
1243+
*/
1244+
Oid
1245+
LookupCreationNamespace(constchar*nspname)
1246+
{
1247+
OidnamespaceId;
1248+
AclResultaclresult;
1249+
1250+
namespaceId=GetSysCacheOid(NAMESPACENAME,
1251+
CStringGetDatum(nspname),
1252+
0,0,0);
1253+
if (!OidIsValid(namespaceId))
1254+
ereport(ERROR,
1255+
(errcode(ERRCODE_UNDEFINED_SCHEMA),
1256+
errmsg("schema \"%s\" does not exist",nspname)));
1257+
1258+
aclresult=pg_namespace_aclcheck(namespaceId,GetUserId(),ACL_CREATE);
1259+
if (aclresult!=ACLCHECK_OK)
1260+
aclcheck_error(aclresult,ACL_KIND_NAMESPACE,
1261+
nspname);
1262+
1263+
returnnamespaceId;
1264+
}
1265+
12381266
/*
12391267
* QualifiedNameGetCreationNamespace
12401268
*Given a possibly-qualified name for an object (in List-of-Values
12411269
*format), determine what namespace the object should be created in.
12421270
*Also extract and return the object name (last component of list).
12431271
*
1272+
* Note: this does not apply any permissions check. Callers must check
1273+
* for CREATE rights on the selected namespace when appropriate.
1274+
*
12441275
* This is *not* used for tables. Hence, the TEMP table namespace is
12451276
* never selected as the creation target.
12461277
*/
@@ -1277,8 +1308,6 @@ QualifiedNameGetCreationNamespace(List *names, char **objname_p)
12771308
errmsg("no schema has been selected to create in")));
12781309
}
12791310

1280-
/* Note: callers will check for CREATE rights when appropriate */
1281-
12821311
*objname_p=objname;
12831312
returnnamespaceId;
12841313
}
@@ -1379,19 +1408,16 @@ isTempNamespace(Oid namespaceId)
13791408
}
13801409

13811410
/*
1382-
*isOtherTempNamespace - is the given namespacesome other backend's
1383-
*temporary-table namespace?
1411+
*isAnyTempNamespace - is the given namespacea temporary-table namespace
1412+
*(either my own, or another backend's)?
13841413
*/
13851414
bool
1386-
isOtherTempNamespace(OidnamespaceId)
1415+
isAnyTempNamespace(OidnamespaceId)
13871416
{
13881417
boolresult;
13891418
char*nspname;
13901419

1391-
/* If it's my own temp namespace, say "false" */
1392-
if (isTempNamespace(namespaceId))
1393-
return false;
1394-
/* Else, if the namespace name starts with "pg_temp_", say "true" */
1420+
/* If the namespace name starts with "pg_temp_", say "true" */
13951421
nspname=get_namespace_name(namespaceId);
13961422
if (!nspname)
13971423
return false;/* no such namespace? */
@@ -1400,6 +1426,20 @@ isOtherTempNamespace(Oid namespaceId)
14001426
returnresult;
14011427
}
14021428

1429+
/*
1430+
* isOtherTempNamespace - is the given namespace some other backend's
1431+
* temporary-table namespace?
1432+
*/
1433+
bool
1434+
isOtherTempNamespace(OidnamespaceId)
1435+
{
1436+
/* If it's my own temp namespace, say "false" */
1437+
if (isTempNamespace(namespaceId))
1438+
return false;
1439+
/* Else, if the namespace name starts with "pg_temp_", say "true" */
1440+
returnisAnyTempNamespace(namespaceId);
1441+
}
1442+
14031443
/*
14041444
* PushSpecialNamespace - push a "special" namespace onto the front of the
14051445
* search path.

‎src/backend/catalog/pg_constraint.c

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/catalog/pg_constraint.c,v 1.25 2005/04/14 20:03:23 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/catalog/pg_constraint.c,v 1.26 2005/08/01 04:03:54 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -599,3 +599,69 @@ GetConstraintNameForTrigger(Oid triggerId)
599599

600600
returnresult;
601601
}
602+
603+
/*
604+
* AlterConstraintNamespaces
605+
*Find any constraints belonging to the specified object,
606+
*and move them to the specified new namespace.
607+
*
608+
* isType indicates whether the owning object is a type or a relation.
609+
*/
610+
void
611+
AlterConstraintNamespaces(OidownerId,OidoldNspId,
612+
OidnewNspId,boolisType)
613+
{
614+
RelationconRel;
615+
ScanKeyDatakey[1];
616+
SysScanDescscan;
617+
HeapTupletup;
618+
619+
conRel=heap_open(ConstraintRelationId,RowExclusiveLock);
620+
621+
if (isType)
622+
{
623+
ScanKeyInit(&key[0],
624+
Anum_pg_constraint_contypid,
625+
BTEqualStrategyNumber,F_OIDEQ,
626+
ObjectIdGetDatum(ownerId));
627+
628+
scan=systable_beginscan(conRel,ConstraintTypidIndexId, true,
629+
SnapshotNow,1,key);
630+
}
631+
else
632+
{
633+
ScanKeyInit(&key[0],
634+
Anum_pg_constraint_conrelid,
635+
BTEqualStrategyNumber,F_OIDEQ,
636+
ObjectIdGetDatum(ownerId));
637+
638+
scan=systable_beginscan(conRel,ConstraintRelidIndexId, true,
639+
SnapshotNow,1,key);
640+
}
641+
642+
while (HeapTupleIsValid((tup=systable_getnext(scan))))
643+
{
644+
Form_pg_constraintconform= (Form_pg_constraint)GETSTRUCT(tup);
645+
646+
if (conform->connamespace==oldNspId)
647+
{
648+
tup=heap_copytuple(tup);
649+
conform= (Form_pg_constraint)GETSTRUCT(tup);
650+
651+
conform->connamespace=newNspId;
652+
653+
simple_heap_update(conRel,&tup->t_self,tup);
654+
CatalogUpdateIndexes(conRel,tup);
655+
656+
/*
657+
* Note: currently, the constraint will not have its own
658+
* dependency on the namespace, so we don't need to do
659+
* changeDependencyFor().
660+
*/
661+
}
662+
}
663+
664+
systable_endscan(scan);
665+
666+
heap_close(conRel,RowExclusiveLock);
667+
}

‎src/backend/catalog/pg_depend.c

Lines changed: 100 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/catalog/pg_depend.c,v 1.13 2005/04/14 20:03:23 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/catalog/pg_depend.c,v 1.14 2005/08/01 04:03:54 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -162,6 +162,105 @@ deleteDependencyRecordsFor(Oid classId, Oid objectId)
162162
returncount;
163163
}
164164

165+
/*
166+
* Adjust dependency record(s) to point to a different object of the same type
167+
*
168+
* classId/objectId specify the referencing object.
169+
* refClassId/oldRefObjectId specify the old referenced object.
170+
* newRefObjectId is the new referenced object (must be of class refClassId).
171+
*
172+
* Note the lack of objsubid parameters. If there are subobject references
173+
* they will all be readjusted.
174+
*
175+
* Returns the number of records updated.
176+
*/
177+
long
178+
changeDependencyFor(OidclassId,OidobjectId,
179+
OidrefClassId,OidoldRefObjectId,
180+
OidnewRefObjectId)
181+
{
182+
longcount=0;
183+
RelationdepRel;
184+
ScanKeyDatakey[2];
185+
SysScanDescscan;
186+
HeapTupletup;
187+
ObjectAddressobjAddr;
188+
boolnewIsPinned;
189+
190+
depRel=heap_open(DependRelationId,RowExclusiveLock);
191+
192+
/*
193+
* If oldRefObjectId is pinned, there won't be any dependency entries
194+
* on it --- we can't cope in that case. (This isn't really worth
195+
* expending code to fix, in current usage; it just means you can't
196+
* rename stuff out of pg_catalog, which would likely be a bad move
197+
* anyway.)
198+
*/
199+
objAddr.classId=refClassId;
200+
objAddr.objectId=oldRefObjectId;
201+
objAddr.objectSubId=0;
202+
203+
if (isObjectPinned(&objAddr,depRel))
204+
ereport(ERROR,
205+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
206+
errmsg("cannot remove dependency on %s because it is a system object",
207+
getObjectDescription(&objAddr))));
208+
209+
/*
210+
* We can handle adding a dependency on something pinned, though,
211+
* since that just means deleting the dependency entry.
212+
*/
213+
objAddr.objectId=newRefObjectId;
214+
215+
newIsPinned=isObjectPinned(&objAddr,depRel);
216+
217+
/* Now search for dependency records */
218+
ScanKeyInit(&key[0],
219+
Anum_pg_depend_classid,
220+
BTEqualStrategyNumber,F_OIDEQ,
221+
ObjectIdGetDatum(classId));
222+
ScanKeyInit(&key[1],
223+
Anum_pg_depend_objid,
224+
BTEqualStrategyNumber,F_OIDEQ,
225+
ObjectIdGetDatum(objectId));
226+
227+
scan=systable_beginscan(depRel,DependDependerIndexId, true,
228+
SnapshotNow,2,key);
229+
230+
while (HeapTupleIsValid((tup=systable_getnext(scan))))
231+
{
232+
Form_pg_dependdepform= (Form_pg_depend)GETSTRUCT(tup);
233+
234+
if (depform->refclassid==refClassId&&
235+
depform->refobjid==oldRefObjectId)
236+
{
237+
if (newIsPinned)
238+
simple_heap_delete(depRel,&tup->t_self);
239+
else
240+
{
241+
/* make a modifiable copy */
242+
tup=heap_copytuple(tup);
243+
depform= (Form_pg_depend)GETSTRUCT(tup);
244+
245+
depform->refobjid=newRefObjectId;
246+
247+
simple_heap_update(depRel,&tup->t_self,tup);
248+
CatalogUpdateIndexes(depRel,tup);
249+
250+
heap_freetuple(tup);
251+
}
252+
253+
count++;
254+
}
255+
}
256+
257+
systable_endscan(scan);
258+
259+
heap_close(depRel,RowExclusiveLock);
260+
261+
returncount;
262+
}
263+
165264
/*
166265
* isObjectPinned()
167266
*

‎src/backend/commands/alter.c

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/commands/alter.c,v 1.13 2005/06/28 05:08:53 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/commands/alter.c,v 1.14 2005/08/01 04:03:55 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -142,6 +142,38 @@ ExecRenameStmt(RenameStmt *stmt)
142142
}
143143
}
144144

145+
/*
146+
* Executes an ALTER OBJECT / SET SCHEMA statement. Based on the object
147+
* type, the function appropriate to that type is executed.
148+
*/
149+
void
150+
ExecAlterObjectSchemaStmt(AlterObjectSchemaStmt*stmt)
151+
{
152+
switch (stmt->objectType)
153+
{
154+
caseOBJECT_AGGREGATE:
155+
caseOBJECT_FUNCTION:
156+
AlterFunctionNamespace(stmt->object,stmt->objarg,
157+
stmt->newschema);
158+
break;
159+
160+
caseOBJECT_SEQUENCE:
161+
caseOBJECT_TABLE:
162+
CheckRelationOwnership(stmt->relation, true);
163+
AlterTableNamespace(stmt->relation,stmt->newschema);
164+
break;
165+
166+
caseOBJECT_TYPE:
167+
caseOBJECT_DOMAIN:
168+
AlterTypeNamespace(stmt->object,stmt->newschema);
169+
break;
170+
171+
default:
172+
elog(ERROR,"unrecognized AlterObjectSchemaStmt type: %d",
173+
(int)stmt->objectType);
174+
}
175+
}
176+
145177
/*
146178
* Executes an ALTER OBJECT / OWNER TO statement. Based on the object
147179
* type, the function appropriate to that type is executed.

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp