00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "postgres.h"
00016
00017 #include "access/genam.h"
00018 #include "access/heapam.h"
00019 #include "access/htup_details.h"
00020 #include "catalog/indexing.h"
00021 #include "catalog/objectaddress.h"
00022 #include "catalog/pg_description.h"
00023 #include "catalog/pg_shdescription.h"
00024 #include "commands/comment.h"
00025 #include "commands/dbcommands.h"
00026 #include "miscadmin.h"
00027 #include "utils/builtins.h"
00028 #include "utils/fmgroids.h"
00029 #include "utils/rel.h"
00030 #include "utils/tqual.h"
00031
00032
00033
00034
00035
00036
00037
00038
00039 Oid
00040 CommentObject(CommentStmt *stmt)
00041 {
00042 ObjectAddress address;
00043 Relation relation;
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054 if (stmt->objtype == OBJECT_DATABASE && list_length(stmt->objname) == 1)
00055 {
00056 char *database = strVal(linitial(stmt->objname));
00057
00058 if (!OidIsValid(get_database_oid(database, true)))
00059 {
00060 ereport(WARNING,
00061 (errcode(ERRCODE_UNDEFINED_DATABASE),
00062 errmsg("database \"%s\" does not exist", database)));
00063 return InvalidOid;
00064 }
00065 }
00066
00067
00068
00069
00070
00071
00072
00073 address = get_object_address(stmt->objtype, stmt->objname, stmt->objargs,
00074 &relation, ShareUpdateExclusiveLock, false);
00075
00076
00077 check_object_ownership(GetUserId(), stmt->objtype, address,
00078 stmt->objname, stmt->objargs, relation);
00079
00080
00081 switch (stmt->objtype)
00082 {
00083 case OBJECT_COLUMN:
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094 if (relation->rd_rel->relkind != RELKIND_RELATION &&
00095 relation->rd_rel->relkind != RELKIND_VIEW &&
00096 relation->rd_rel->relkind != RELKIND_MATVIEW &&
00097 relation->rd_rel->relkind != RELKIND_COMPOSITE_TYPE &&
00098 relation->rd_rel->relkind != RELKIND_FOREIGN_TABLE)
00099 ereport(ERROR,
00100 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
00101 errmsg("\"%s\" is not a table, view, composite type, or foreign table",
00102 RelationGetRelationName(relation))));
00103 break;
00104 default:
00105 break;
00106 }
00107
00108
00109
00110
00111
00112
00113 if (stmt->objtype == OBJECT_DATABASE || stmt->objtype == OBJECT_TABLESPACE
00114 || stmt->objtype == OBJECT_ROLE)
00115 CreateSharedComments(address.objectId, address.classId, stmt->comment);
00116 else
00117 CreateComments(address.objectId, address.classId, address.objectSubId,
00118 stmt->comment);
00119
00120
00121
00122
00123
00124
00125
00126 if (relation != NULL)
00127 relation_close(relation, NoLock);
00128
00129 return address.objectId;
00130 }
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141 void
00142 CreateComments(Oid oid, Oid classoid, int32 subid, char *comment)
00143 {
00144 Relation description;
00145 ScanKeyData skey[3];
00146 SysScanDesc sd;
00147 HeapTuple oldtuple;
00148 HeapTuple newtuple = NULL;
00149 Datum values[Natts_pg_description];
00150 bool nulls[Natts_pg_description];
00151 bool replaces[Natts_pg_description];
00152 int i;
00153
00154
00155 if (comment != NULL && strlen(comment) == 0)
00156 comment = NULL;
00157
00158
00159 if (comment != NULL)
00160 {
00161 for (i = 0; i < Natts_pg_description; i++)
00162 {
00163 nulls[i] = false;
00164 replaces[i] = true;
00165 }
00166 values[Anum_pg_description_objoid - 1] = ObjectIdGetDatum(oid);
00167 values[Anum_pg_description_classoid - 1] = ObjectIdGetDatum(classoid);
00168 values[Anum_pg_description_objsubid - 1] = Int32GetDatum(subid);
00169 values[Anum_pg_description_description - 1] = CStringGetTextDatum(comment);
00170 }
00171
00172
00173
00174 ScanKeyInit(&skey[0],
00175 Anum_pg_description_objoid,
00176 BTEqualStrategyNumber, F_OIDEQ,
00177 ObjectIdGetDatum(oid));
00178 ScanKeyInit(&skey[1],
00179 Anum_pg_description_classoid,
00180 BTEqualStrategyNumber, F_OIDEQ,
00181 ObjectIdGetDatum(classoid));
00182 ScanKeyInit(&skey[2],
00183 Anum_pg_description_objsubid,
00184 BTEqualStrategyNumber, F_INT4EQ,
00185 Int32GetDatum(subid));
00186
00187 description = heap_open(DescriptionRelationId, RowExclusiveLock);
00188
00189 sd = systable_beginscan(description, DescriptionObjIndexId, true,
00190 SnapshotNow, 3, skey);
00191
00192 while ((oldtuple = systable_getnext(sd)) != NULL)
00193 {
00194
00195
00196 if (comment == NULL)
00197 simple_heap_delete(description, &oldtuple->t_self);
00198 else
00199 {
00200 newtuple = heap_modify_tuple(oldtuple, RelationGetDescr(description), values,
00201 nulls, replaces);
00202 simple_heap_update(description, &oldtuple->t_self, newtuple);
00203 }
00204
00205 break;
00206 }
00207
00208 systable_endscan(sd);
00209
00210
00211
00212 if (newtuple == NULL && comment != NULL)
00213 {
00214 newtuple = heap_form_tuple(RelationGetDescr(description),
00215 values, nulls);
00216 simple_heap_insert(description, newtuple);
00217 }
00218
00219
00220 if (newtuple != NULL)
00221 {
00222 CatalogUpdateIndexes(description, newtuple);
00223 heap_freetuple(newtuple);
00224 }
00225
00226
00227
00228 heap_close(description, NoLock);
00229 }
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240 void
00241 CreateSharedComments(Oid oid, Oid classoid, char *comment)
00242 {
00243 Relation shdescription;
00244 ScanKeyData skey[2];
00245 SysScanDesc sd;
00246 HeapTuple oldtuple;
00247 HeapTuple newtuple = NULL;
00248 Datum values[Natts_pg_shdescription];
00249 bool nulls[Natts_pg_shdescription];
00250 bool replaces[Natts_pg_shdescription];
00251 int i;
00252
00253
00254 if (comment != NULL && strlen(comment) == 0)
00255 comment = NULL;
00256
00257
00258 if (comment != NULL)
00259 {
00260 for (i = 0; i < Natts_pg_shdescription; i++)
00261 {
00262 nulls[i] = false;
00263 replaces[i] = true;
00264 }
00265 values[Anum_pg_shdescription_objoid - 1] = ObjectIdGetDatum(oid);
00266 values[Anum_pg_shdescription_classoid - 1] = ObjectIdGetDatum(classoid);
00267 values[Anum_pg_shdescription_description - 1] = CStringGetTextDatum(comment);
00268 }
00269
00270
00271
00272 ScanKeyInit(&skey[0],
00273 Anum_pg_shdescription_objoid,
00274 BTEqualStrategyNumber, F_OIDEQ,
00275 ObjectIdGetDatum(oid));
00276 ScanKeyInit(&skey[1],
00277 Anum_pg_shdescription_classoid,
00278 BTEqualStrategyNumber, F_OIDEQ,
00279 ObjectIdGetDatum(classoid));
00280
00281 shdescription = heap_open(SharedDescriptionRelationId, RowExclusiveLock);
00282
00283 sd = systable_beginscan(shdescription, SharedDescriptionObjIndexId, true,
00284 SnapshotNow, 2, skey);
00285
00286 while ((oldtuple = systable_getnext(sd)) != NULL)
00287 {
00288
00289
00290 if (comment == NULL)
00291 simple_heap_delete(shdescription, &oldtuple->t_self);
00292 else
00293 {
00294 newtuple = heap_modify_tuple(oldtuple, RelationGetDescr(shdescription),
00295 values, nulls, replaces);
00296 simple_heap_update(shdescription, &oldtuple->t_self, newtuple);
00297 }
00298
00299 break;
00300 }
00301
00302 systable_endscan(sd);
00303
00304
00305
00306 if (newtuple == NULL && comment != NULL)
00307 {
00308 newtuple = heap_form_tuple(RelationGetDescr(shdescription),
00309 values, nulls);
00310 simple_heap_insert(shdescription, newtuple);
00311 }
00312
00313
00314 if (newtuple != NULL)
00315 {
00316 CatalogUpdateIndexes(shdescription, newtuple);
00317 heap_freetuple(newtuple);
00318 }
00319
00320
00321
00322 heap_close(shdescription, NoLock);
00323 }
00324
00325
00326
00327
00328
00329
00330
00331
00332 void
00333 DeleteComments(Oid oid, Oid classoid, int32 subid)
00334 {
00335 Relation description;
00336 ScanKeyData skey[3];
00337 int nkeys;
00338 SysScanDesc sd;
00339 HeapTuple oldtuple;
00340
00341
00342
00343 ScanKeyInit(&skey[0],
00344 Anum_pg_description_objoid,
00345 BTEqualStrategyNumber, F_OIDEQ,
00346 ObjectIdGetDatum(oid));
00347 ScanKeyInit(&skey[1],
00348 Anum_pg_description_classoid,
00349 BTEqualStrategyNumber, F_OIDEQ,
00350 ObjectIdGetDatum(classoid));
00351
00352 if (subid != 0)
00353 {
00354 ScanKeyInit(&skey[2],
00355 Anum_pg_description_objsubid,
00356 BTEqualStrategyNumber, F_INT4EQ,
00357 Int32GetDatum(subid));
00358 nkeys = 3;
00359 }
00360 else
00361 nkeys = 2;
00362
00363 description = heap_open(DescriptionRelationId, RowExclusiveLock);
00364
00365 sd = systable_beginscan(description, DescriptionObjIndexId, true,
00366 SnapshotNow, nkeys, skey);
00367
00368 while ((oldtuple = systable_getnext(sd)) != NULL)
00369 simple_heap_delete(description, &oldtuple->t_self);
00370
00371
00372
00373 systable_endscan(sd);
00374 heap_close(description, RowExclusiveLock);
00375 }
00376
00377
00378
00379
00380 void
00381 DeleteSharedComments(Oid oid, Oid classoid)
00382 {
00383 Relation shdescription;
00384 ScanKeyData skey[2];
00385 SysScanDesc sd;
00386 HeapTuple oldtuple;
00387
00388
00389
00390 ScanKeyInit(&skey[0],
00391 Anum_pg_shdescription_objoid,
00392 BTEqualStrategyNumber, F_OIDEQ,
00393 ObjectIdGetDatum(oid));
00394 ScanKeyInit(&skey[1],
00395 Anum_pg_shdescription_classoid,
00396 BTEqualStrategyNumber, F_OIDEQ,
00397 ObjectIdGetDatum(classoid));
00398
00399 shdescription = heap_open(SharedDescriptionRelationId, RowExclusiveLock);
00400
00401 sd = systable_beginscan(shdescription, SharedDescriptionObjIndexId, true,
00402 SnapshotNow, 2, skey);
00403
00404 while ((oldtuple = systable_getnext(sd)) != NULL)
00405 simple_heap_delete(shdescription, &oldtuple->t_self);
00406
00407
00408
00409 systable_endscan(sd);
00410 heap_close(shdescription, RowExclusiveLock);
00411 }
00412
00413
00414
00415
00416 char *
00417 GetComment(Oid oid, Oid classoid, int32 subid)
00418 {
00419 Relation description;
00420 ScanKeyData skey[3];
00421 SysScanDesc sd;
00422 TupleDesc tupdesc;
00423 HeapTuple tuple;
00424 char *comment;
00425
00426
00427
00428 ScanKeyInit(&skey[0],
00429 Anum_pg_description_objoid,
00430 BTEqualStrategyNumber, F_OIDEQ,
00431 ObjectIdGetDatum(oid));
00432 ScanKeyInit(&skey[1],
00433 Anum_pg_description_classoid,
00434 BTEqualStrategyNumber, F_OIDEQ,
00435 ObjectIdGetDatum(classoid));
00436 ScanKeyInit(&skey[2],
00437 Anum_pg_description_objsubid,
00438 BTEqualStrategyNumber, F_INT4EQ,
00439 Int32GetDatum(subid));
00440
00441 description = heap_open(DescriptionRelationId, AccessShareLock);
00442 tupdesc = RelationGetDescr(description);
00443
00444 sd = systable_beginscan(description, DescriptionObjIndexId, true,
00445 SnapshotNow, 3, skey);
00446
00447 comment = NULL;
00448 while ((tuple = systable_getnext(sd)) != NULL)
00449 {
00450 Datum value;
00451 bool isnull;
00452
00453
00454 value = heap_getattr(tuple, Anum_pg_description_description, tupdesc, &isnull);
00455 if (!isnull)
00456 comment = TextDatumGetCString(value);
00457 break;
00458 }
00459
00460 systable_endscan(sd);
00461
00462
00463 heap_close(description, AccessShareLock);
00464
00465 return comment;
00466 }