00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "postgres.h"
00016
00017 #include "access/heapam.h"
00018 #include "access/htup_details.h"
00019 #include "access/xact.h"
00020 #include "catalog/dependency.h"
00021 #include "catalog/indexing.h"
00022 #include "catalog/objectaccess.h"
00023 #include "catalog/pg_collation.h"
00024 #include "catalog/pg_namespace.h"
00025 #include "catalog/pg_proc.h"
00026 #include "catalog/pg_type.h"
00027 #include "catalog/pg_type_fn.h"
00028 #include "commands/typecmds.h"
00029 #include "miscadmin.h"
00030 #include "parser/scansup.h"
00031 #include "utils/acl.h"
00032 #include "utils/builtins.h"
00033 #include "utils/fmgroids.h"
00034 #include "utils/lsyscache.h"
00035 #include "utils/rel.h"
00036 #include "utils/syscache.h"
00037
00038
00039 Oid binary_upgrade_next_pg_type_oid = InvalidOid;
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054 Oid
00055 TypeShellMake(const char *typeName, Oid typeNamespace, Oid ownerId)
00056 {
00057 Relation pg_type_desc;
00058 TupleDesc tupDesc;
00059 int i;
00060 HeapTuple tup;
00061 Datum values[Natts_pg_type];
00062 bool nulls[Natts_pg_type];
00063 Oid typoid;
00064 NameData name;
00065
00066 Assert(PointerIsValid(typeName));
00067
00068
00069
00070
00071 pg_type_desc = heap_open(TypeRelationId, RowExclusiveLock);
00072 tupDesc = pg_type_desc->rd_att;
00073
00074
00075
00076
00077 for (i = 0; i < Natts_pg_type; ++i)
00078 {
00079 nulls[i] = false;
00080 values[i] = (Datum) NULL;
00081 }
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091 namestrcpy(&name, typeName);
00092 values[Anum_pg_type_typname - 1] = NameGetDatum(&name);
00093 values[Anum_pg_type_typnamespace - 1] = ObjectIdGetDatum(typeNamespace);
00094 values[Anum_pg_type_typowner - 1] = ObjectIdGetDatum(ownerId);
00095 values[Anum_pg_type_typlen - 1] = Int16GetDatum(sizeof(int32));
00096 values[Anum_pg_type_typbyval - 1] = BoolGetDatum(true);
00097 values[Anum_pg_type_typtype - 1] = CharGetDatum(TYPTYPE_PSEUDO);
00098 values[Anum_pg_type_typcategory - 1] = CharGetDatum(TYPCATEGORY_PSEUDOTYPE);
00099 values[Anum_pg_type_typispreferred - 1] = BoolGetDatum(false);
00100 values[Anum_pg_type_typisdefined - 1] = BoolGetDatum(false);
00101 values[Anum_pg_type_typdelim - 1] = CharGetDatum(DEFAULT_TYPDELIM);
00102 values[Anum_pg_type_typrelid - 1] = ObjectIdGetDatum(InvalidOid);
00103 values[Anum_pg_type_typelem - 1] = ObjectIdGetDatum(InvalidOid);
00104 values[Anum_pg_type_typarray - 1] = ObjectIdGetDatum(InvalidOid);
00105 values[Anum_pg_type_typinput - 1] = ObjectIdGetDatum(F_SHELL_IN);
00106 values[Anum_pg_type_typoutput - 1] = ObjectIdGetDatum(F_SHELL_OUT);
00107 values[Anum_pg_type_typreceive - 1] = ObjectIdGetDatum(InvalidOid);
00108 values[Anum_pg_type_typsend - 1] = ObjectIdGetDatum(InvalidOid);
00109 values[Anum_pg_type_typmodin - 1] = ObjectIdGetDatum(InvalidOid);
00110 values[Anum_pg_type_typmodout - 1] = ObjectIdGetDatum(InvalidOid);
00111 values[Anum_pg_type_typanalyze - 1] = ObjectIdGetDatum(InvalidOid);
00112 values[Anum_pg_type_typalign - 1] = CharGetDatum('i');
00113 values[Anum_pg_type_typstorage - 1] = CharGetDatum('p');
00114 values[Anum_pg_type_typnotnull - 1] = BoolGetDatum(false);
00115 values[Anum_pg_type_typbasetype - 1] = ObjectIdGetDatum(InvalidOid);
00116 values[Anum_pg_type_typtypmod - 1] = Int32GetDatum(-1);
00117 values[Anum_pg_type_typndims - 1] = Int32GetDatum(0);
00118 values[Anum_pg_type_typcollation - 1] = ObjectIdGetDatum(InvalidOid);
00119 nulls[Anum_pg_type_typdefaultbin - 1] = true;
00120 nulls[Anum_pg_type_typdefault - 1] = true;
00121 nulls[Anum_pg_type_typacl - 1] = true;
00122
00123
00124
00125
00126 tup = heap_form_tuple(tupDesc, values, nulls);
00127
00128
00129 if (IsBinaryUpgrade && OidIsValid(binary_upgrade_next_pg_type_oid))
00130 {
00131 HeapTupleSetOid(tup, binary_upgrade_next_pg_type_oid);
00132 binary_upgrade_next_pg_type_oid = InvalidOid;
00133 }
00134
00135
00136
00137
00138 typoid = simple_heap_insert(pg_type_desc, tup);
00139
00140 CatalogUpdateIndexes(pg_type_desc, tup);
00141
00142
00143
00144
00145 if (!IsBootstrapProcessingMode())
00146 GenerateTypeDependencies(typeNamespace,
00147 typoid,
00148 InvalidOid,
00149 0,
00150 ownerId,
00151 F_SHELL_IN,
00152 F_SHELL_OUT,
00153 InvalidOid,
00154 InvalidOid,
00155 InvalidOid,
00156 InvalidOid,
00157 InvalidOid,
00158 InvalidOid,
00159 false,
00160 InvalidOid,
00161 InvalidOid,
00162 NULL,
00163 false);
00164
00165
00166 InvokeObjectPostCreateHook(TypeRelationId, typoid, 0);
00167
00168
00169
00170
00171 heap_freetuple(tup);
00172 heap_close(pg_type_desc, RowExclusiveLock);
00173
00174 return typoid;
00175 }
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187 Oid
00188 TypeCreate(Oid newTypeOid,
00189 const char *typeName,
00190 Oid typeNamespace,
00191 Oid relationOid,
00192 char relationKind,
00193 Oid ownerId,
00194 int16 internalSize,
00195 char typeType,
00196 char typeCategory,
00197 bool typePreferred,
00198 char typDelim,
00199 Oid inputProcedure,
00200 Oid outputProcedure,
00201 Oid receiveProcedure,
00202 Oid sendProcedure,
00203 Oid typmodinProcedure,
00204 Oid typmodoutProcedure,
00205 Oid analyzeProcedure,
00206 Oid elementType,
00207 bool isImplicitArray,
00208 Oid arrayType,
00209 Oid baseType,
00210 const char *defaultTypeValue,
00211 char *defaultTypeBin,
00212 bool passedByValue,
00213 char alignment,
00214 char storage,
00215 int32 typeMod,
00216 int32 typNDims,
00217 bool typeNotNull,
00218 Oid typeCollation)
00219 {
00220 Relation pg_type_desc;
00221 Oid typeObjectId;
00222 bool rebuildDeps = false;
00223 HeapTuple tup;
00224 bool nulls[Natts_pg_type];
00225 bool replaces[Natts_pg_type];
00226 Datum values[Natts_pg_type];
00227 NameData name;
00228 int i;
00229 Acl *typacl = NULL;
00230
00231
00232
00233
00234
00235
00236
00237
00238 if (!(internalSize > 0 ||
00239 internalSize == -1 ||
00240 internalSize == -2))
00241 ereport(ERROR,
00242 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
00243 errmsg("invalid type internal size %d",
00244 internalSize)));
00245
00246 if (passedByValue)
00247 {
00248
00249
00250
00251
00252
00253
00254 if (internalSize == (int16) sizeof(char))
00255 {
00256 if (alignment != 'c')
00257 ereport(ERROR,
00258 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
00259 errmsg("alignment \"%c\" is invalid for passed-by-value type of size %d",
00260 alignment, internalSize)));
00261 }
00262 else if (internalSize == (int16) sizeof(int16))
00263 {
00264 if (alignment != 's')
00265 ereport(ERROR,
00266 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
00267 errmsg("alignment \"%c\" is invalid for passed-by-value type of size %d",
00268 alignment, internalSize)));
00269 }
00270 else if (internalSize == (int16) sizeof(int32))
00271 {
00272 if (alignment != 'i')
00273 ereport(ERROR,
00274 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
00275 errmsg("alignment \"%c\" is invalid for passed-by-value type of size %d",
00276 alignment, internalSize)));
00277 }
00278 #if SIZEOF_DATUM == 8
00279 else if (internalSize == (int16) sizeof(Datum))
00280 {
00281 if (alignment != 'd')
00282 ereport(ERROR,
00283 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
00284 errmsg("alignment \"%c\" is invalid for passed-by-value type of size %d",
00285 alignment, internalSize)));
00286 }
00287 #endif
00288 else
00289 ereport(ERROR,
00290 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
00291 errmsg("internal size %d is invalid for passed-by-value type",
00292 internalSize)));
00293 }
00294 else
00295 {
00296
00297 if (internalSize == -1 && !(alignment == 'i' || alignment == 'd'))
00298 ereport(ERROR,
00299 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
00300 errmsg("alignment \"%c\" is invalid for variable-length type",
00301 alignment)));
00302
00303 if (internalSize == -2 && !(alignment == 'c'))
00304 ereport(ERROR,
00305 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
00306 errmsg("alignment \"%c\" is invalid for variable-length type",
00307 alignment)));
00308 }
00309
00310
00311 if (storage != 'p' && internalSize != -1)
00312 ereport(ERROR,
00313 (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
00314 errmsg("fixed-size types must have storage PLAIN")));
00315
00316
00317
00318
00319 for (i = 0; i < Natts_pg_type; ++i)
00320 {
00321 nulls[i] = false;
00322 replaces[i] = true;
00323 values[i] = (Datum) 0;
00324 }
00325
00326
00327
00328
00329 namestrcpy(&name, typeName);
00330 values[Anum_pg_type_typname - 1] = NameGetDatum(&name);
00331 values[Anum_pg_type_typnamespace - 1] = ObjectIdGetDatum(typeNamespace);
00332 values[Anum_pg_type_typowner - 1] = ObjectIdGetDatum(ownerId);
00333 values[Anum_pg_type_typlen - 1] = Int16GetDatum(internalSize);
00334 values[Anum_pg_type_typbyval - 1] = BoolGetDatum(passedByValue);
00335 values[Anum_pg_type_typtype - 1] = CharGetDatum(typeType);
00336 values[Anum_pg_type_typcategory - 1] = CharGetDatum(typeCategory);
00337 values[Anum_pg_type_typispreferred - 1] = BoolGetDatum(typePreferred);
00338 values[Anum_pg_type_typisdefined - 1] = BoolGetDatum(true);
00339 values[Anum_pg_type_typdelim - 1] = CharGetDatum(typDelim);
00340 values[Anum_pg_type_typrelid - 1] = ObjectIdGetDatum(relationOid);
00341 values[Anum_pg_type_typelem - 1] = ObjectIdGetDatum(elementType);
00342 values[Anum_pg_type_typarray - 1] = ObjectIdGetDatum(arrayType);
00343 values[Anum_pg_type_typinput - 1] = ObjectIdGetDatum(inputProcedure);
00344 values[Anum_pg_type_typoutput - 1] = ObjectIdGetDatum(outputProcedure);
00345 values[Anum_pg_type_typreceive - 1] = ObjectIdGetDatum(receiveProcedure);
00346 values[Anum_pg_type_typsend - 1] = ObjectIdGetDatum(sendProcedure);
00347 values[Anum_pg_type_typmodin - 1] = ObjectIdGetDatum(typmodinProcedure);
00348 values[Anum_pg_type_typmodout - 1] = ObjectIdGetDatum(typmodoutProcedure);
00349 values[Anum_pg_type_typanalyze - 1] = ObjectIdGetDatum(analyzeProcedure);
00350 values[Anum_pg_type_typalign - 1] = CharGetDatum(alignment);
00351 values[Anum_pg_type_typstorage - 1] = CharGetDatum(storage);
00352 values[Anum_pg_type_typnotnull - 1] = BoolGetDatum(typeNotNull);
00353 values[Anum_pg_type_typbasetype - 1] = ObjectIdGetDatum(baseType);
00354 values[Anum_pg_type_typtypmod - 1] = Int32GetDatum(typeMod);
00355 values[Anum_pg_type_typndims - 1] = Int32GetDatum(typNDims);
00356 values[Anum_pg_type_typcollation - 1] = ObjectIdGetDatum(typeCollation);
00357
00358
00359
00360
00361
00362 if (defaultTypeBin)
00363 values[Anum_pg_type_typdefaultbin - 1] = CStringGetTextDatum(defaultTypeBin);
00364 else
00365 nulls[Anum_pg_type_typdefaultbin - 1] = true;
00366
00367
00368
00369
00370 if (defaultTypeValue)
00371 values[Anum_pg_type_typdefault - 1] = CStringGetTextDatum(defaultTypeValue);
00372 else
00373 nulls[Anum_pg_type_typdefault - 1] = true;
00374
00375 typacl = get_user_default_acl(ACL_OBJECT_TYPE, ownerId,
00376 typeNamespace);
00377 if (typacl != NULL)
00378 values[Anum_pg_type_typacl - 1] = PointerGetDatum(typacl);
00379 else
00380 nulls[Anum_pg_type_typacl - 1] = true;
00381
00382
00383
00384
00385
00386
00387
00388 pg_type_desc = heap_open(TypeRelationId, RowExclusiveLock);
00389
00390 tup = SearchSysCacheCopy2(TYPENAMENSP,
00391 CStringGetDatum(typeName),
00392 ObjectIdGetDatum(typeNamespace));
00393 if (HeapTupleIsValid(tup))
00394 {
00395
00396
00397
00398
00399 if (((Form_pg_type) GETSTRUCT(tup))->typisdefined)
00400 ereport(ERROR,
00401 (errcode(ERRCODE_DUPLICATE_OBJECT),
00402 errmsg("type \"%s\" already exists", typeName)));
00403
00404
00405
00406
00407 if (((Form_pg_type) GETSTRUCT(tup))->typowner != ownerId)
00408 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TYPE, typeName);
00409
00410
00411 if (OidIsValid(newTypeOid))
00412 elog(ERROR, "cannot assign new OID to existing shell type");
00413
00414
00415
00416
00417 tup = heap_modify_tuple(tup,
00418 RelationGetDescr(pg_type_desc),
00419 values,
00420 nulls,
00421 replaces);
00422
00423 simple_heap_update(pg_type_desc, &tup->t_self, tup);
00424
00425 typeObjectId = HeapTupleGetOid(tup);
00426
00427 rebuildDeps = true;
00428 }
00429 else
00430 {
00431 tup = heap_form_tuple(RelationGetDescr(pg_type_desc),
00432 values,
00433 nulls);
00434
00435
00436 if (OidIsValid(newTypeOid))
00437 HeapTupleSetOid(tup, newTypeOid);
00438
00439 else if (IsBinaryUpgrade && OidIsValid(binary_upgrade_next_pg_type_oid))
00440 {
00441 HeapTupleSetOid(tup, binary_upgrade_next_pg_type_oid);
00442 binary_upgrade_next_pg_type_oid = InvalidOid;
00443 }
00444
00445
00446 typeObjectId = simple_heap_insert(pg_type_desc, tup);
00447 }
00448
00449
00450 CatalogUpdateIndexes(pg_type_desc, tup);
00451
00452
00453
00454
00455 if (!IsBootstrapProcessingMode())
00456 GenerateTypeDependencies(typeNamespace,
00457 typeObjectId,
00458 relationOid,
00459 relationKind,
00460 ownerId,
00461 inputProcedure,
00462 outputProcedure,
00463 receiveProcedure,
00464 sendProcedure,
00465 typmodinProcedure,
00466 typmodoutProcedure,
00467 analyzeProcedure,
00468 elementType,
00469 isImplicitArray,
00470 baseType,
00471 typeCollation,
00472 (defaultTypeBin ?
00473 stringToNode(defaultTypeBin) :
00474 NULL),
00475 rebuildDeps);
00476
00477
00478 InvokeObjectPostCreateHook(TypeRelationId, typeObjectId, 0);
00479
00480
00481
00482
00483 heap_close(pg_type_desc, RowExclusiveLock);
00484
00485 return typeObjectId;
00486 }
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499 void
00500 GenerateTypeDependencies(Oid typeNamespace,
00501 Oid typeObjectId,
00502 Oid relationOid,
00503 char relationKind,
00504 Oid owner,
00505 Oid inputProcedure,
00506 Oid outputProcedure,
00507 Oid receiveProcedure,
00508 Oid sendProcedure,
00509 Oid typmodinProcedure,
00510 Oid typmodoutProcedure,
00511 Oid analyzeProcedure,
00512 Oid elementType,
00513 bool isImplicitArray,
00514 Oid baseType,
00515 Oid typeCollation,
00516 Node *defaultExpr,
00517 bool rebuild)
00518 {
00519 ObjectAddress myself,
00520 referenced;
00521
00522
00523 if (rebuild)
00524 {
00525 deleteDependencyRecordsFor(TypeRelationId, typeObjectId, true);
00526 deleteSharedDependencyRecordsFor(TypeRelationId, typeObjectId, 0);
00527 }
00528
00529 myself.classId = TypeRelationId;
00530 myself.objectId = typeObjectId;
00531 myself.objectSubId = 0;
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541 if ((!OidIsValid(relationOid) || relationKind == RELKIND_COMPOSITE_TYPE) &&
00542 !isImplicitArray)
00543 {
00544 referenced.classId = NamespaceRelationId;
00545 referenced.objectId = typeNamespace;
00546 referenced.objectSubId = 0;
00547 recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
00548
00549 recordDependencyOnOwner(TypeRelationId, typeObjectId, owner);
00550
00551 recordDependencyOnCurrentExtension(&myself, rebuild);
00552 }
00553
00554
00555 if (OidIsValid(inputProcedure))
00556 {
00557 referenced.classId = ProcedureRelationId;
00558 referenced.objectId = inputProcedure;
00559 referenced.objectSubId = 0;
00560 recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
00561 }
00562
00563 if (OidIsValid(outputProcedure))
00564 {
00565 referenced.classId = ProcedureRelationId;
00566 referenced.objectId = outputProcedure;
00567 referenced.objectSubId = 0;
00568 recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
00569 }
00570
00571 if (OidIsValid(receiveProcedure))
00572 {
00573 referenced.classId = ProcedureRelationId;
00574 referenced.objectId = receiveProcedure;
00575 referenced.objectSubId = 0;
00576 recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
00577 }
00578
00579 if (OidIsValid(sendProcedure))
00580 {
00581 referenced.classId = ProcedureRelationId;
00582 referenced.objectId = sendProcedure;
00583 referenced.objectSubId = 0;
00584 recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
00585 }
00586
00587 if (OidIsValid(typmodinProcedure))
00588 {
00589 referenced.classId = ProcedureRelationId;
00590 referenced.objectId = typmodinProcedure;
00591 referenced.objectSubId = 0;
00592 recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
00593 }
00594
00595 if (OidIsValid(typmodoutProcedure))
00596 {
00597 referenced.classId = ProcedureRelationId;
00598 referenced.objectId = typmodoutProcedure;
00599 referenced.objectSubId = 0;
00600 recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
00601 }
00602
00603 if (OidIsValid(analyzeProcedure))
00604 {
00605 referenced.classId = ProcedureRelationId;
00606 referenced.objectId = analyzeProcedure;
00607 referenced.objectSubId = 0;
00608 recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
00609 }
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620 if (OidIsValid(relationOid))
00621 {
00622 referenced.classId = RelationRelationId;
00623 referenced.objectId = relationOid;
00624 referenced.objectSubId = 0;
00625
00626 if (relationKind != RELKIND_COMPOSITE_TYPE)
00627 recordDependencyOn(&myself, &referenced, DEPENDENCY_INTERNAL);
00628 else
00629 recordDependencyOn(&referenced, &myself, DEPENDENCY_INTERNAL);
00630 }
00631
00632
00633
00634
00635
00636
00637 if (OidIsValid(elementType))
00638 {
00639 referenced.classId = TypeRelationId;
00640 referenced.objectId = elementType;
00641 referenced.objectSubId = 0;
00642 recordDependencyOn(&myself, &referenced,
00643 isImplicitArray ? DEPENDENCY_INTERNAL : DEPENDENCY_NORMAL);
00644 }
00645
00646
00647 if (OidIsValid(baseType))
00648 {
00649 referenced.classId = TypeRelationId;
00650 referenced.objectId = baseType;
00651 referenced.objectSubId = 0;
00652 recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
00653 }
00654
00655
00656
00657 if (OidIsValid(typeCollation) && typeCollation != DEFAULT_COLLATION_OID)
00658 {
00659 referenced.classId = CollationRelationId;
00660 referenced.objectId = typeCollation;
00661 referenced.objectSubId = 0;
00662 recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
00663 }
00664
00665
00666 if (defaultExpr)
00667 recordDependencyOnExpr(&myself, defaultExpr, NIL, DEPENDENCY_NORMAL);
00668 }
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679 void
00680 RenameTypeInternal(Oid typeOid, const char *newTypeName, Oid typeNamespace)
00681 {
00682 Relation pg_type_desc;
00683 HeapTuple tuple;
00684 Form_pg_type typ;
00685 Oid arrayOid;
00686
00687 pg_type_desc = heap_open(TypeRelationId, RowExclusiveLock);
00688
00689 tuple = SearchSysCacheCopy1(TYPEOID, ObjectIdGetDatum(typeOid));
00690 if (!HeapTupleIsValid(tuple))
00691 elog(ERROR, "cache lookup failed for type %u", typeOid);
00692 typ = (Form_pg_type) GETSTRUCT(tuple);
00693
00694
00695 Assert(typeNamespace == typ->typnamespace);
00696
00697 arrayOid = typ->typarray;
00698
00699
00700 if (SearchSysCacheExists2(TYPENAMENSP,
00701 CStringGetDatum(newTypeName),
00702 ObjectIdGetDatum(typeNamespace)))
00703 ereport(ERROR,
00704 (errcode(ERRCODE_DUPLICATE_OBJECT),
00705 errmsg("type \"%s\" already exists", newTypeName)));
00706
00707
00708 namestrcpy(&(typ->typname), newTypeName);
00709
00710 simple_heap_update(pg_type_desc, &tuple->t_self, tuple);
00711
00712
00713 CatalogUpdateIndexes(pg_type_desc, tuple);
00714
00715 InvokeObjectPostAlterHook(TypeRelationId, typeOid, 0);
00716
00717 heap_freetuple(tuple);
00718 heap_close(pg_type_desc, RowExclusiveLock);
00719
00720
00721 if (OidIsValid(arrayOid))
00722 {
00723 char *arrname = makeArrayTypeName(newTypeName, typeNamespace);
00724
00725 RenameTypeInternal(arrayOid, arrname, typeNamespace);
00726 pfree(arrname);
00727 }
00728 }
00729
00730
00731
00732
00733
00734
00735
00736
00737 char *
00738 makeArrayTypeName(const char *typeName, Oid typeNamespace)
00739 {
00740 char *arr = (char *) palloc(NAMEDATALEN);
00741 int namelen = strlen(typeName);
00742 Relation pg_type_desc;
00743 int i;
00744
00745
00746
00747
00748
00749 pg_type_desc = heap_open(TypeRelationId, AccessShareLock);
00750
00751 for (i = 1; i < NAMEDATALEN - 1; i++)
00752 {
00753 arr[i - 1] = '_';
00754 if (i + namelen < NAMEDATALEN)
00755 strcpy(arr + i, typeName);
00756 else
00757 {
00758 memcpy(arr + i, typeName, NAMEDATALEN - i);
00759 truncate_identifier(arr, NAMEDATALEN, false);
00760 }
00761 if (!SearchSysCacheExists2(TYPENAMENSP,
00762 CStringGetDatum(arr),
00763 ObjectIdGetDatum(typeNamespace)))
00764 break;
00765 }
00766
00767 heap_close(pg_type_desc, AccessShareLock);
00768
00769 if (i >= NAMEDATALEN - 1)
00770 ereport(ERROR,
00771 (errcode(ERRCODE_DUPLICATE_OBJECT),
00772 errmsg("could not form array type name for type \"%s\"",
00773 typeName)));
00774
00775 return arr;
00776 }
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803 bool
00804 moveArrayTypeName(Oid typeOid, const char *typeName, Oid typeNamespace)
00805 {
00806 Oid elemOid;
00807 char *newname;
00808
00809
00810 if (!get_typisdefined(typeOid))
00811 return true;
00812
00813
00814 elemOid = get_element_type(typeOid);
00815 if (!OidIsValid(elemOid) ||
00816 get_array_type(elemOid) != typeOid)
00817 return false;
00818
00819
00820
00821
00822
00823
00824
00825 newname = makeArrayTypeName(typeName, typeNamespace);
00826
00827
00828 RenameTypeInternal(typeOid, newname, typeNamespace);
00829
00830
00831
00832
00833
00834 CommandCounterIncrement();
00835
00836 pfree(newname);
00837
00838 return true;
00839 }