From bc8036fc666a8f846b1d4b2f935af7edd90eb5aa Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Fri, 11 May 2007 17:57:14 +0000 Subject: [PATCH] Support arrays of composite types, including the rowtypes of regular tables and views (but not system catalogs, nor sequences or toast tables). Get rid of the hardwired convention that a type's array type is named exactly "_type", instead using a new column pg_type.typarray to provide the linkage. (It still will be named "_type", though, except in odd corner cases such as maximum-length type names.) Along the way, make tracking of owner and schema dependencies for types more uniform: a type directly created by the user has these dependencies, while a table rowtype or auto-generated array type does not have them, but depends on its parent object instead. David Fetter, Andrew Dunstan, Tom Lane --- doc/src/sgml/array.sgml | 7 +- doc/src/sgml/catalogs.sgml | 20 +- doc/src/sgml/ref/create_type.sgml | 38 +-- doc/src/sgml/syntax.sgml | 6 +- src/backend/catalog/README | 8 +- src/backend/catalog/heap.c | 141 +++++++++-- src/backend/catalog/pg_shdepend.c | 4 +- src/backend/catalog/pg_type.c | 102 ++++++-- src/backend/commands/tablecmds.c | 33 ++- src/backend/commands/typecmds.c | 220 +++++++++++------ src/backend/parser/parse_type.c | 10 +- src/backend/utils/cache/lsyscache.c | 36 +-- src/bin/pg_dump/pg_dump.c | 64 +++-- src/bin/pg_dump/pg_dump.h | 4 +- src/include/catalog/catversion.h | 4 +- src/include/catalog/pg_attribute.h | 64 ++--- src/include/catalog/pg_class.h | 4 +- src/include/catalog/pg_type.h | 287 +++++++++++----------- src/include/commands/typecmds.h | 8 +- src/test/regress/expected/alter_table.out | 1 - src/test/regress/expected/oidjoins.out | 16 ++ src/test/regress/expected/type_sanity.out | 10 + src/test/regress/sql/oidjoins.sql | 8 + src/test/regress/sql/type_sanity.sql | 7 + src/tools/findoidjoins/README | 3 + 25 files changed, 698 insertions(+), 407 deletions(-) diff --git a/doc/src/sgml/array.sgml b/doc/src/sgml/array.sgml index ec59d8e6a8..9646e1ab00 100644 --- a/doc/src/sgml/array.sgml +++ b/doc/src/sgml/array.sgml @@ -1,4 +1,4 @@ - + Arrays @@ -10,8 +10,9 @@ PostgreSQL allows columns of a table to be defined as variable-length multidimensional arrays. Arrays of any - built-in or user-defined base type or enum type can be created. - (Arrays of composite types or domains are not yet supported, however.) + built-in or user-defined base type, enum type, or composite type + can be created. + Arrays of domains are not yet supported. diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml index 8243dd8d04..2da4abc340 100644 --- a/doc/src/sgml/catalogs.sgml +++ b/doc/src/sgml/catalogs.sgml @@ -1,4 +1,4 @@ - + @@ -4524,6 +4524,17 @@ + + typarray + oid + pg_type.oid + + If typarray is not 0 then it + identifies another row in pg_type, which + is the true array type having this type as element + + + typinput regproc @@ -4686,9 +4697,10 @@ typndims is the number of array dimensions - for a domain that is an array (that is, typbasetype is an array type; - the domain's typelem will match the base type's typelem). - Zero for types other than array domains + for a domain that is an array (that is, typbasetype is + an array type; the domain's typelem will match the base + type's typelem). + Zero for types other than domains over array types diff --git a/doc/src/sgml/ref/create_type.sgml b/doc/src/sgml/ref/create_type.sgml index 9be57d7fcd..08f4c1464c 100644 --- a/doc/src/sgml/ref/create_type.sgml +++ b/doc/src/sgml/ref/create_type.sgml @@ -1,5 +1,5 @@ @@ -312,15 +312,17 @@ CREATE TYPE name Array Types - Whenever a user-defined base or enum data type is created, + Whenever a user-defined type is created, PostgreSQL automatically creates an associated array type, whose name consists of the base type's - name prepended with an underscore. The parser understands this - naming convention, and translates requests for columns of type - foo[] into requests for type _foo. - The implicitly-created array type is variable length and uses the + name prepended with an underscore, and truncated if necessary to keep + it less than NAMEDATALEN bytes long. (If the name + so generated collides with an existing type name, the process is + repeated until a non-colliding name is found.) + This implicitly-created array type is variable length and uses the built-in input and output functions array_in and - array_out. + array_out. The array type tracks any changes in its + element type's owner or schema, and is dropped if the element type is. @@ -330,10 +332,9 @@ CREATE TYPE name making a fixed-length type that happens to be internally an array of a number of identical things, and you want to allow these things to be accessed directly by subscripting, in addition to whatever operations you plan - to provide for the type as a whole. For example, type name - allows its constituent char elements to be accessed this way. - A 2-D point type could allow its two component numbers to be - accessed like point[0] and point[1]. + to provide for the type as a whole. For example, type point + is represented as just two floating-point numbers, which it allows to be + accessed as point[0] and point[1]. Note that this facility only works for fixed-length types whose internal form is exactly a sequence of identical fixed-length fields. A subscriptable @@ -529,12 +530,15 @@ CREATE TYPE name Notes - User-defined type names should not begin with the underscore character - (_) and should only be 62 characters - long (or in general NAMEDATALEN - 2, rather than - the NAMEDATALEN - 1 characters allowed for other - names). Type names beginning with underscore are reserved for - internally-created array type names. + It is best to avoid using type names that begin with the underscore + character (_). PostgreSQL + forms the name of an array type by prepending one or more underscores + to the element type's name, and these names may collide with user-defined + type names that begin with underscore. While the system will modify + generated array type names to avoid collisions, this does not help if the + conflicting array type already exists when you try to create your type. + Also, various old client software may assume that names beginning with + underscores always represent arrays. diff --git a/doc/src/sgml/syntax.sgml b/doc/src/sgml/syntax.sgml index 7bb9c66982..f1b5fe9411 100644 --- a/doc/src/sgml/syntax.sgml +++ b/doc/src/sgml/syntax.sgml @@ -1,4 +1,4 @@ - + SQL Syntax @@ -131,10 +131,10 @@ INSERT INTO MY_TABLE VALUES (3, 'hi there'); identifierlength The system uses no more than NAMEDATALEN-1 - characters of an identifier; longer names can be written in + bytes of an identifier; longer names can be written in commands, but they will be truncated. By default, NAMEDATALEN is 64 so the maximum identifier - length is 63. If this limit is problematic, it can be raised by + length is 63 bytes. If this limit is problematic, it can be raised by changing the NAMEDATALEN constant in src/include/pg_config_manual.h. diff --git a/src/backend/catalog/README b/src/backend/catalog/README index 3cbcc3d45e..89c6e0305a 100644 --- a/src/backend/catalog/README +++ b/src/backend/catalog/README @@ -1,4 +1,4 @@ -$PostgreSQL: pgsql/src/backend/catalog/README,v 1.10 2006/07/31 01:16:36 tgl Exp $ +$PostgreSQL: pgsql/src/backend/catalog/README,v 1.11 2007/05/11 17:57:11 tgl Exp $ This directory contains .c files that manipulate the system catalogs; src/include/catalog contains the .h files that define the structure @@ -86,9 +86,9 @@ general) assumes that the fixed-length portions of all system catalog tuples are in fact present, because it maps C struct declarations onto them. Thus, the variable-length fields must all be at the end, and only the variable-length fields of a catalog tuple are permitted to be -NULL. For example, if you set pg_type.typdelim to be NULL, a -piece of code will likely perform "typetup->typdelim" (or, worse, -"typetyp->typelem", which follows typdelim). This will result in +NULL. For example, if you set pg_type.typrelid to be NULL, a +piece of code will likely perform "typetup->typrelid" (or, worse, +"typetyp->typelem", which follows typrelid). This will result in random errors or even segmentation violations. Hence, do NOT insert catalog tuples that contain NULL attributes except in their variable-length portions! (The bootstrapping code is fairly good about diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index e6404ecd0b..8b34d685d8 100644 --- a/src/backend/catalog/heap.c +++ b/src/backend/catalog/heap.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.318 2007/04/02 03:49:37 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.319 2007/05/11 17:57:11 tgl Exp $ * * * INTERFACE ROUTINES @@ -45,6 +45,7 @@ #include "catalog/pg_statistic.h" #include "catalog/pg_type.h" #include "commands/tablecmds.h" +#include "commands/typecmds.h" #include "miscadmin.h" #include "optimizer/clauses.h" #include "optimizer/var.h" @@ -69,7 +70,8 @@ static void AddNewRelationTuple(Relation pg_class_desc, static Oid AddNewRelationType(const char *typeName, Oid typeNamespace, Oid new_rel_oid, - char new_rel_kind); + char new_rel_kind, + Oid new_array_type); static void RelationRemoveInheritance(Oid relid); static void StoreRelCheck(Relation rel, char *ccname, char *ccbin); static void StoreConstraints(Relation rel, TupleDesc tupdesc); @@ -401,26 +403,55 @@ CheckAttributeType(const char *attname, Oid atttypid) { char att_typtype = get_typtype(atttypid); - /* - * Warn user, but don't fail, if column to be created has UNKNOWN type - * (usually as a result of a 'retrieve into' - jolly) - * - * Refuse any attempt to create a pseudo-type column. - */ if (atttypid == UNKNOWNOID) + { + /* + * Warn user, but don't fail, if column to be created has UNKNOWN type + * (usually as a result of a 'retrieve into' - jolly) + */ ereport(WARNING, (errcode(ERRCODE_INVALID_TABLE_DEFINITION), errmsg("column \"%s\" has type \"unknown\"", attname), errdetail("Proceeding with relation creation anyway."))); + } else if (att_typtype == TYPTYPE_PSEUDO) { - /* Special hack for pg_statistic: allow ANYARRAY during initdb */ + /* + * Refuse any attempt to create a pseudo-type column, except for + * a special hack for pg_statistic: allow ANYARRAY during initdb + */ if (atttypid != ANYARRAYOID || IsUnderPostmaster) ereport(ERROR, (errcode(ERRCODE_INVALID_TABLE_DEFINITION), errmsg("column \"%s\" has pseudo-type %s", attname, format_type_be(atttypid)))); } + else if (att_typtype == TYPTYPE_COMPOSITE) + { + /* + * For a composite type, recurse into its attributes. You might + * think this isn't necessary, but since we allow system catalogs + * to break the rule, we have to guard against the case. + */ + Relation relation; + TupleDesc tupdesc; + int i; + + relation = relation_open(get_typ_typrelid(atttypid), AccessShareLock); + + tupdesc = RelationGetDescr(relation); + + for (i = 0; i < tupdesc->natts; i++) + { + Form_pg_attribute attr = tupdesc->attrs[i]; + + if (attr->attisdropped) + continue; + CheckAttributeType(NameStr(attr->attname), attr->atttypid); + } + + relation_close(relation, AccessShareLock); + } } /* -------------------------------- @@ -710,16 +741,18 @@ static Oid AddNewRelationType(const char *typeName, Oid typeNamespace, Oid new_rel_oid, - char new_rel_kind) + char new_rel_kind, + Oid new_array_type) { return - TypeCreate(typeName, /* type name */ + TypeCreate(InvalidOid, /* no predetermined OID */ + typeName, /* type name */ typeNamespace, /* type namespace */ new_rel_oid, /* relation oid */ new_rel_kind, /* relation kind */ -1, /* internal size (varlena) */ TYPTYPE_COMPOSITE, /* type-type (composite) */ - ',', /* default array delimiter */ + DEFAULT_TYPDELIM, /* default array delimiter */ F_RECORD_IN, /* input procedure */ F_RECORD_OUT, /* output procedure */ F_RECORD_RECV, /* receive procedure */ @@ -728,6 +761,8 @@ AddNewRelationType(const char *typeName, InvalidOid, /* typmodout procedure - none */ InvalidOid, /* analyze procedure - default */ InvalidOid, /* array element type - irrelevant */ + false, /* this is not an array type */ + new_array_type, /* array type if any */ InvalidOid, /* domain base type - irrelevant */ NULL, /* default value - none */ NULL, /* default binary representation */ @@ -763,6 +798,7 @@ heap_create_with_catalog(const char *relname, Relation pg_class_desc; Relation new_rel_desc; Oid new_type_oid; + Oid new_array_oid = InvalidOid; pg_class_desc = heap_open(RelationRelationId, RowExclusiveLock); @@ -805,7 +841,24 @@ heap_create_with_catalog(const char *relname, Assert(relid == RelationGetRelid(new_rel_desc)); /* - * since defining a relation also defines a complex type, we add a new + * Decide whether to create an array type over the relation's rowtype. + * We do not create any array types for system catalogs (ie, those made + * during initdb). We create array types for regular relations, views, + * and composite types ... but not, eg, for toast tables or sequences. + */ + if (IsUnderPostmaster && (relkind == RELKIND_RELATION || + relkind == RELKIND_VIEW || + relkind == RELKIND_COMPOSITE_TYPE)) + { + /* OK, so pre-assign a type OID for the array type */ + Relation pg_type = heap_open(TypeRelationId, AccessShareLock); + + new_array_oid = GetNewOid(pg_type); + heap_close(pg_type, AccessShareLock); + } + + /* + * Since defining a relation also defines a complex type, we add a new * system type corresponding to the new relation. * * NOTE: we could get a unique-index failure here, in case the same name @@ -814,7 +867,47 @@ heap_create_with_catalog(const char *relname, new_type_oid = AddNewRelationType(relname, relnamespace, relid, - relkind); + relkind, + new_array_oid); + /* + * Now make the array type if wanted. + */ + if (OidIsValid(new_array_oid)) + { + char *relarrayname; + + relarrayname = makeArrayTypeName(relname, relnamespace); + + TypeCreate(new_array_oid, /* force the type's OID to this */ + relarrayname, /* Array type name */ + relnamespace, /* Same namespace as parent */ + InvalidOid, /* Not composite, no relationOid */ + 0, /* relkind, also N/A here */ + -1, /* Internal size (varlena) */ + TYPTYPE_BASE, /* Not composite - typelem is */ + DEFAULT_TYPDELIM, /* default array delimiter */ + F_ARRAY_IN, /* array input proc */ + F_ARRAY_OUT, /* array output proc */ + F_ARRAY_RECV, /* array recv (bin) proc */ + F_ARRAY_SEND, /* array send (bin) proc */ + InvalidOid, /* typmodin procedure - none */ + InvalidOid, /* typmodout procedure - none */ + InvalidOid, /* analyze procedure - default */ + new_type_oid, /* array element type - the rowtype */ + true, /* yes, this is an array type */ + InvalidOid, /* this has no array type */ + InvalidOid, /* domain base type - irrelevant */ + NULL, /* default value - none */ + NULL, /* default binary representation */ + false, /* passed by reference */ + 'd', /* alignment - must be the largest! */ + 'x', /* fully TOASTable */ + -1, /* typmod */ + 0, /* array dimensions for typBaseType */ + false); /* Type NOT NULL */ + + pfree(relarrayname); + } /* * now create an entry in pg_class for the relation. @@ -838,13 +931,15 @@ heap_create_with_catalog(const char *relname, oidislocal, oidinhcount); /* - * make a dependency link to force the relation to be deleted if its - * namespace is. Skip this in bootstrap mode, since we don't make - * dependencies while bootstrapping. + * Make a dependency link to force the relation to be deleted if its + * namespace is. Also make a dependency link to its owner. * - * Also make a dependency link to its owner. + * For composite types, these dependencies are tracked for the pg_type + * entry, so we needn't record them here. Also, skip this in bootstrap + * mode, since we don't make dependencies while bootstrapping. */ - if (!IsBootstrapProcessingMode()) + if (relkind != RELKIND_COMPOSITE_TYPE && + !IsBootstrapProcessingMode()) { ObjectAddress myself, referenced; @@ -857,13 +952,7 @@ heap_create_with_catalog(const char *relname, referenced.objectSubId = 0; recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); - /* - * For composite types, the dependency on owner is tracked for the - * pg_type entry, so don't record it here. All other relkinds need - * their ownership tracked. - */ - if (relkind != RELKIND_COMPOSITE_TYPE) - recordDependencyOnOwner(RelationRelationId, relid, ownerid); + recordDependencyOnOwner(RelationRelationId, relid, ownerid); } /* diff --git a/src/backend/catalog/pg_shdepend.c b/src/backend/catalog/pg_shdepend.c index 9ad012db49..e3de61344b 100644 --- a/src/backend/catalog/pg_shdepend.c +++ b/src/backend/catalog/pg_shdepend.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/catalog/pg_shdepend.c,v 1.17 2007/03/03 19:32:54 neilc Exp $ + * $PostgreSQL: pgsql/src/backend/catalog/pg_shdepend.c,v 1.18 2007/05/11 17:57:12 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1254,7 +1254,7 @@ shdepReassignOwned(List *roleids, Oid newrole) break; case TypeRelationId: - AlterTypeOwnerInternal(sdepForm->objid, newrole); + AlterTypeOwnerInternal(sdepForm->objid, newrole, true); break; case OperatorRelationId: diff --git a/src/backend/catalog/pg_type.c b/src/backend/catalog/pg_type.c index efc3b8de09..8360149604 100644 --- a/src/backend/catalog/pg_type.c +++ b/src/backend/catalog/pg_type.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/catalog/pg_type.c,v 1.111 2007/04/02 03:49:37 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/catalog/pg_type.c,v 1.112 2007/05/11 17:57:12 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -22,6 +22,7 @@ #include "catalog/pg_type.h" #include "commands/typecmds.h" #include "miscadmin.h" +#include "parser/scansup.h" #include "utils/acl.h" #include "utils/builtins.h" #include "utils/fmgroids.h" @@ -90,6 +91,7 @@ TypeShellMake(const char *typeName, Oid typeNamespace) values[i++] = CharGetDatum(DEFAULT_TYPDELIM); /* typdelim */ values[i++] = ObjectIdGetDatum(InvalidOid); /* typrelid */ values[i++] = ObjectIdGetDatum(InvalidOid); /* typelem */ + values[i++] = ObjectIdGetDatum(InvalidOid); /* typarray */ values[i++] = ObjectIdGetDatum(F_SHELL_IN); /* typinput */ values[i++] = ObjectIdGetDatum(F_SHELL_OUT); /* typoutput */ values[i++] = ObjectIdGetDatum(InvalidOid); /* typreceive */ @@ -135,6 +137,7 @@ TypeShellMake(const char *typeName, Oid typeNamespace) InvalidOid, InvalidOid, InvalidOid, + false, InvalidOid, NULL, false); @@ -153,13 +156,16 @@ TypeShellMake(const char *typeName, Oid typeNamespace) * * This does all the necessary work needed to define a new type. * - * Returns the OID assigned to the new type. + * Returns the OID assigned to the new type. If newTypeOid is + * zero (the normal case), a new OID is created; otherwise we + * use exactly that OID. * ---------------------------------------------------------------- */ Oid -TypeCreate(const char *typeName, +TypeCreate(Oid newTypeOid, + const char *typeName, Oid typeNamespace, - Oid relationOid, /* only for composite types */ + Oid relationOid, /* only for relation rowtypes */ char relationKind, /* ditto */ int16 internalSize, char typeType, @@ -172,6 +178,8 @@ TypeCreate(const char *typeName, Oid typmodoutProcedure, Oid analyzeProcedure, Oid elementType, + bool isImplicitArray, + Oid arrayType, Oid baseType, const char *defaultTypeValue, /* human readable rep */ char *defaultTypeBin, /* cooked rep */ @@ -243,9 +251,9 @@ TypeCreate(const char *typeName, values[i++] = CharGetDatum(typeType); /* typtype */ values[i++] = BoolGetDatum(true); /* typisdefined */ values[i++] = CharGetDatum(typDelim); /* typdelim */ - values[i++] = ObjectIdGetDatum(typeType == TYPTYPE_COMPOSITE ? - relationOid : InvalidOid); /* typrelid */ + values[i++] = ObjectIdGetDatum(relationOid); /* typrelid */ values[i++] = ObjectIdGetDatum(elementType); /* typelem */ + values[i++] = ObjectIdGetDatum(arrayType); /* typarray */ values[i++] = ObjectIdGetDatum(inputProcedure); /* typinput */ values[i++] = ObjectIdGetDatum(outputProcedure); /* typoutput */ values[i++] = ObjectIdGetDatum(receiveProcedure); /* typreceive */ @@ -310,6 +318,10 @@ TypeCreate(const char *typeName, if (((Form_pg_type) GETSTRUCT(tup))->typowner != GetUserId()) aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TYPE, typeName); + /* trouble if caller wanted to force the OID */ + if (OidIsValid(newTypeOid)) + elog(ERROR, "cannot assign new OID to existing shell type"); + /* * Okay to update existing shell type tuple */ @@ -331,6 +343,10 @@ TypeCreate(const char *typeName, values, nulls); + /* Force the OID if requested by caller, else heap_insert does it */ + if (OidIsValid(newTypeOid)) + HeapTupleSetOid(tup, newTypeOid); + typeObjectId = simple_heap_insert(pg_type_desc, tup); } @@ -354,6 +370,7 @@ TypeCreate(const char *typeName, typmodoutProcedure, analyzeProcedure, elementType, + isImplicitArray, baseType, (defaultTypeBin ? stringToNode(defaultTypeBin) : @@ -378,8 +395,8 @@ TypeCreate(const char *typeName, void GenerateTypeDependencies(Oid typeNamespace, Oid typeObjectId, - Oid relationOid, /* only for composite types */ - char relationKind, /* ditto */ + Oid relationOid, /* only for relation rowtypes */ + char relationKind, /* ditto */ Oid owner, Oid inputProcedure, Oid outputProcedure, @@ -389,6 +406,7 @@ GenerateTypeDependencies(Oid typeNamespace, Oid typmodoutProcedure, Oid analyzeProcedure, Oid elementType, + bool isImplicitArray, Oid baseType, Node *defaultExpr, bool rebuild) @@ -406,14 +424,23 @@ GenerateTypeDependencies(Oid typeNamespace, myself.objectId = typeObjectId; myself.objectSubId = 0; - /* dependency on namespace */ - /* skip for relation rowtype, since we have indirect dependency */ - if (!OidIsValid(relationOid)) + /* + * Make dependency on namespace and shared dependency on owner. + * + * For a relation rowtype (that's not a composite type), we should skip + * these because we'll depend on them indirectly through the pg_class + * entry. Likewise, skip for implicit arrays since we'll depend on them + * through the element type. + */ + if ((!OidIsValid(relationOid) || relationKind == RELKIND_COMPOSITE_TYPE) && + !isImplicitArray) { referenced.classId = NamespaceRelationId; referenced.objectId = typeNamespace; referenced.objectSubId = 0; recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); + + recordDependencyOnOwner(TypeRelationId, typeObjectId, owner); } /* Normal dependencies on the I/O functions */ @@ -495,17 +522,17 @@ GenerateTypeDependencies(Oid typeNamespace, } /* - * If the type is an array type, mark it auto-dependent on the base type. - * (This is a compromise between the typical case where the array type is - * automatically generated and the case where it is manually created: we'd - * prefer INTERNAL for the former case and NORMAL for the latter.) + * If the type is an implicitly-created array type, mark it as internally + * dependent on the element type. Otherwise, if it has an element type, + * the dependency is a normal one. */ if (OidIsValid(elementType)) { referenced.classId = TypeRelationId; referenced.objectId = elementType; referenced.objectSubId = 0; - recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO); + recordDependencyOn(&myself, &referenced, + isImplicitArray ? DEPENDENCY_INTERNAL : DEPENDENCY_NORMAL); } /* Normal dependency from a domain to its base type. */ @@ -520,9 +547,6 @@ GenerateTypeDependencies(Oid typeNamespace, /* Normal dependency on the default expression. */ if (defaultExpr) recordDependencyOnExpr(&myself, defaultExpr, NIL, DEPENDENCY_NORMAL); - - /* Shared dependency on owner. */ - recordDependencyOnOwner(TypeRelationId, typeObjectId, owner); } /* @@ -570,21 +594,47 @@ TypeRename(const char *oldTypeName, Oid typeNamespace, heap_close(pg_type_desc, RowExclusiveLock); } + /* - * makeArrayTypeName(typeName); - * - given a base type name, make an array of type name out of it + * makeArrayTypeName(typeName) + * - given a base type name, make an array type name for it * * the caller is responsible for pfreeing the result */ char * -makeArrayTypeName(const char *typeName) +makeArrayTypeName(const char *typeName, Oid typeNamespace) { char *arr; + int i; + Relation pg_type_desc; - if (!typeName) - return NULL; + /* + * The idea is to prepend underscores as needed until we make a name + * that doesn't collide with anything... + */ arr = palloc(NAMEDATALEN); - snprintf(arr, NAMEDATALEN, - "_%.*s", NAMEDATALEN - 2, typeName); + + pg_type_desc = heap_open(TypeRelationId, AccessShareLock); + + for (i = 1; i < NAMEDATALEN - 1; i++) + { + arr[i - 1] = '_'; + strlcpy(arr + i, typeName, NAMEDATALEN - i); + truncate_identifier(arr, strlen(arr), false); + if (!SearchSysCacheExists(TYPENAMENSP, + CStringGetDatum(arr), + ObjectIdGetDatum(typeNamespace), + 0, 0)) + break; + } + + heap_close(pg_type_desc, AccessShareLock); + + if (i >= NAMEDATALEN-1) + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_OBJECT), + errmsg("could not form array type name for type \"%s\"", + typeName))); + return arr; } diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 8043799b88..a1bbf17789 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.219 2007/04/08 01:26:32 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.220 2007/05/11 17:57:12 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -2827,6 +2827,7 @@ find_composite_type_dependencies(Oid typeOid, const char *origTblName) ScanKeyData key[2]; SysScanDesc depScan; HeapTuple depTup; + Oid arrayOid; /* * We scan pg_depend to find those things that depend on the rowtype. (We @@ -2886,6 +2887,14 @@ find_composite_type_dependencies(Oid typeOid, const char *origTblName) systable_endscan(depScan); relation_close(depRel, AccessShareLock); + + /* + * If there's an array type for the rowtype, must check for uses of it, + * too. + */ + arrayOid = get_array_type(typeOid); + if (OidIsValid(arrayOid)) + find_composite_type_dependencies(arrayOid, origTblName); } @@ -5299,6 +5308,9 @@ ATPostAlterTypeParse(char *cmd, List **wqueue) * be changed separately from the parent table. Also, we can skip permission * checks (this is necessary not just an optimization, else we'd fail to * handle toast tables properly). + * + * recursing is also true if ALTER TYPE OWNER is calling us to fix up a + * free-standing composite type. */ void ATExecChangeOwner(Oid relationOid, Oid newOwnerId, bool recursing) @@ -5370,6 +5382,7 @@ ATExecChangeOwner(Oid relationOid, Oid newOwnerId, bool recursing) } break; case RELKIND_TOASTVALUE: + case RELKIND_COMPOSITE_TYPE: if (recursing) break; /* FALL THRU */ @@ -5448,14 +5461,22 @@ ATExecChangeOwner(Oid relationOid, Oid newOwnerId, bool recursing) heap_freetuple(newtuple); - /* Update owner dependency reference */ - changeDependencyOnOwner(RelationRelationId, relationOid, newOwnerId); + /* + * Update owner dependency reference, if any. A composite type has + * none, because it's tracked for the pg_type entry instead of here; + * indexes don't have their own entries either. + */ + if (tuple_class->relkind != RELKIND_COMPOSITE_TYPE && + tuple_class->relkind != RELKIND_INDEX) + changeDependencyOnOwner(RelationRelationId, relationOid, + newOwnerId); /* * Also change the ownership of the table's rowtype, if it has one */ if (tuple_class->relkind != RELKIND_INDEX) - AlterTypeOwnerInternal(tuple_class->reltype, newOwnerId); + AlterTypeOwnerInternal(tuple_class->reltype, newOwnerId, + tuple_class->relkind == RELKIND_COMPOSITE_TYPE); /* * If we are operating on a table, also change the ownership of any @@ -6462,7 +6483,7 @@ AlterTableNamespace(RangeVar *relation, const char *newschema) AlterRelationNamespaceInternal(classRel, relid, oldNspOid, nspOid, true); /* Fix the table's rowtype too */ - AlterTypeNamespaceInternal(rel->rd_rel->reltype, nspOid, false); + AlterTypeNamespaceInternal(rel->rd_rel->reltype, nspOid, false, false); /* Fix other dependent stuff */ if (rel->rd_rel->relkind == RELKIND_RELATION) @@ -6625,7 +6646,7 @@ AlterSeqNamespaces(Relation classRel, Relation rel, * them to the new namespace, too. */ AlterTypeNamespaceInternal(RelationGetForm(seqRel)->reltype, - newNspOid, false); + newNspOid, false, false); /* Now we can close it. Keep the lock till end of transaction. */ relation_close(seqRel, NoLock); diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c index 5c1b9f6f0e..7911f6df3a 100644 --- a/src/backend/commands/typecmds.c +++ b/src/backend/commands/typecmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.101 2007/04/02 03:49:38 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.102 2007/05/11 17:57:12 tgl Exp $ * * DESCRIPTION * The "DefineFoo" routines take the parse tree and pick out the @@ -34,6 +34,7 @@ #include "access/genam.h" #include "access/heapam.h" #include "access/xact.h" +#include "catalog/catalog.h" #include "catalog/dependency.h" #include "catalog/heap.h" #include "catalog/indexing.h" @@ -118,10 +119,12 @@ DefineType(List *names, List *parameters) Oid typmodinOid = InvalidOid; Oid typmodoutOid = InvalidOid; Oid analyzeOid = InvalidOid; - char *shadow_type; + char *array_type; + Oid array_oid; ListCell *pl; Oid typoid; Oid resulttype; + Relation pg_type; /* Convert list of names to a name and namespace */ typeNamespace = QualifiedNameGetCreationNamespace(names, &typeName); @@ -132,16 +135,6 @@ DefineType(List *names, List *parameters) aclcheck_error(aclresult, ACL_KIND_NAMESPACE, get_namespace_name(typeNamespace)); - /* - * Type names must be one character shorter than other names, allowing - * room to create the corresponding array type name with prepended "_". - */ - if (strlen(typeName) > (NAMEDATALEN - 2)) - ereport(ERROR, - (errcode(ERRCODE_INVALID_NAME), - errmsg("type names must be %d characters or less", - NAMEDATALEN - 2))); - /* * Look to see if type already exists (presumably as a shell; if not, * TypeCreate will complain). If it doesn't, create it as a shell, so @@ -396,11 +389,17 @@ DefineType(List *names, List *parameters) aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC, NameListToString(analyzeName)); + /* Preassign array type OID so we can insert it in pg_type.typarray */ + pg_type = heap_open(TypeRelationId, AccessShareLock); + array_oid = GetNewOid(pg_type); + heap_close(pg_type, AccessShareLock); + /* * now have TypeCreate do all the real work. */ typoid = - TypeCreate(typeName, /* type name */ + TypeCreate(InvalidOid, /* no predetermined type OID */ + typeName, /* type name */ typeNamespace, /* namespace */ InvalidOid, /* relation oid (n/a here) */ 0, /* relation kind (ditto) */ @@ -415,6 +414,8 @@ DefineType(List *names, List *parameters) typmodoutOid,/* typmodout procedure */ analyzeOid, /* analyze procedure */ elemType, /* element type ID */ + false, /* this is not an array type */ + array_oid, /* array type we are about to create */ InvalidOid, /* base type ID (only for domains) */ defaultValue, /* default type value */ NULL, /* no binary form available */ @@ -426,19 +427,19 @@ DefineType(List *names, List *parameters) false); /* Type NOT NULL */ /* - * When we create a base type (as opposed to a complex type) we need to - * have an array entry for it in pg_type as well. + * Create the array type that goes with it. */ - shadow_type = makeArrayTypeName(typeName); + array_type = makeArrayTypeName(typeName, typeNamespace); /* alignment must be 'i' or 'd' for arrays */ alignment = (alignment == 'd') ? 'd' : 'i'; - TypeCreate(shadow_type, /* type name */ + TypeCreate(array_oid, /* force assignment of this type OID */ + array_type, /* type name */ typeNamespace, /* namespace */ InvalidOid, /* relation oid (n/a here) */ 0, /* relation kind (ditto) */ - -1, /* internal size */ + -1, /* internal size (always varlena) */ TYPTYPE_BASE, /* type-type (base type) */ DEFAULT_TYPDELIM, /* array element delimiter */ F_ARRAY_IN, /* input procedure */ @@ -449,6 +450,8 @@ DefineType(List *names, List *parameters) typmodoutOid, /* typmodout procedure */ InvalidOid, /* analyze procedure - default */ typoid, /* element type ID */ + true, /* yes this is an array type */ + InvalidOid, /* no further array type */ InvalidOid, /* base type ID */ NULL, /* never a default type value */ NULL, /* binary default isn't sent either */ @@ -459,7 +462,7 @@ DefineType(List *names, List *parameters) 0, /* Array dimensions of typbasetype */ false); /* Type NOT NULL */ - pfree(shadow_type); + pfree(array_type); } @@ -474,6 +477,7 @@ RemoveType(List *names, DropBehavior behavior, bool missing_ok) Oid typeoid; HeapTuple tup; ObjectAddress object; + Form_pg_type typ; /* Make a TypeName so we can use standard type lookup machinery */ typename = makeTypeNameFromNameList(names); @@ -504,14 +508,19 @@ RemoveType(List *names, DropBehavior behavior, bool missing_ok) 0, 0, 0); if (!HeapTupleIsValid(tup)) elog(ERROR, "cache lookup failed for type %u", typeoid); + typ = (Form_pg_type) GETSTRUCT(tup); /* Permission check: must own type or its namespace */ if (!pg_type_ownercheck(typeoid, GetUserId()) && - !pg_namespace_ownercheck(((Form_pg_type) GETSTRUCT(tup))->typnamespace, - GetUserId())) + !pg_namespace_ownercheck(typ->typnamespace, GetUserId())) aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TYPE, TypeNameToString(typename)); + /* + * Note: we need no special check for array types here, as the normal + * treatment of internal dependencies handles it just fine + */ + ReleaseSysCache(tup); /* @@ -607,19 +616,6 @@ DefineDomain(CreateDomainStmt *stmt) aclcheck_error(aclresult, ACL_KIND_NAMESPACE, get_namespace_name(domainNamespace)); - /* - * Domainnames, unlike typenames don't need to account for the '_' prefix. - * So they can be one character longer. (This test is presently useless - * since the parser will have truncated the name to fit. But leave it - * here since we may someday support arrays of domains, in which case - * we'll be back to needing to enforce NAMEDATALEN-2.) - */ - if (strlen(domainName) > (NAMEDATALEN - 1)) - ereport(ERROR, - (errcode(ERRCODE_INVALID_NAME), - errmsg("domain names must be %d characters or less", - NAMEDATALEN - 1))); - /* * Look up the base type. */ @@ -805,7 +801,8 @@ DefineDomain(CreateDomainStmt *stmt) * Have TypeCreate do all the real work. */ domainoid = - TypeCreate(domainName, /* type name */ + TypeCreate(InvalidOid, /* no predetermined type OID */ + domainName, /* type name */ domainNamespace, /* namespace */ InvalidOid, /* relation oid (n/a here) */ 0, /* relation kind (ditto) */ @@ -820,6 +817,8 @@ DefineDomain(CreateDomainStmt *stmt) InvalidOid, /* typmodout procedure - none */ analyzeProcedure, /* analyze procedure */ typelem, /* element type ID */ + false, /* this isn't an array */ + InvalidOid, /* no arrays for domains (yet) */ basetypeoid, /* base type ID */ defaultValue, /* default type value (text) */ defaultValueBin, /* default type value (binary) */ @@ -949,6 +948,8 @@ DefineEnum(CreateEnumStmt *stmt) Oid enumNamespace; Oid enumTypeOid; AclResult aclresult; + Oid enumArrayOid; + Relation pg_type; /* Convert list of names to a name and namespace */ enumNamespace = QualifiedNameGetCreationNamespace(stmt->typename, @@ -960,19 +961,15 @@ DefineEnum(CreateEnumStmt *stmt) aclcheck_error(aclresult, ACL_KIND_NAMESPACE, get_namespace_name(enumNamespace)); - /* - * Type names must be one character shorter than other names, allowing - * room to create the corresponding array type name with prepended "_". - */ - if (strlen(enumName) > (NAMEDATALEN - 2)) - ereport(ERROR, - (errcode(ERRCODE_INVALID_NAME), - errmsg("type names must be %d characters or less", - NAMEDATALEN - 2))); + /* Preassign array type OID so we can insert it in pg_type.typarray */ + pg_type = heap_open(TypeRelationId, AccessShareLock); + enumArrayOid = GetNewOid(pg_type); + heap_close(pg_type, AccessShareLock); /* Create the pg_type entry */ enumTypeOid = - TypeCreate(enumName, /* type name */ + TypeCreate(InvalidOid, /* no predetermined type OID */ + enumName, /* type name */ enumNamespace, /* namespace */ InvalidOid, /* relation oid (n/a here) */ 0, /* relation kind (ditto) */ @@ -987,6 +984,8 @@ DefineEnum(CreateEnumStmt *stmt) InvalidOid, /* typmodout procedure - none */ InvalidOid, /* analyze procedure - default */ InvalidOid, /* element type ID */ + false, /* this is not an array type */ + enumArrayOid, /* array type we are about to create */ InvalidOid, /* base type ID (only for domains) */ NULL, /* never a default type value */ NULL, /* binary default isn't sent either */ @@ -1000,14 +999,17 @@ DefineEnum(CreateEnumStmt *stmt) /* Enter the enum's values into pg_enum */ EnumValuesCreate(enumTypeOid, stmt->vals); - /* Create array type for enum */ - enumArrayName = makeArrayTypeName(enumName); + /* + * Create the array type that goes with it. + */ + enumArrayName = makeArrayTypeName(enumName, enumNamespace); - TypeCreate(enumArrayName, /* type name */ + TypeCreate(enumArrayOid, /* force assignment of this type OID */ + enumArrayName, /* type name */ enumNamespace, /* namespace */ InvalidOid, /* relation oid (n/a here) */ 0, /* relation kind (ditto) */ - -1, /* internal size */ + -1, /* internal size (always varlena) */ TYPTYPE_BASE, /* type-type (base type) */ DEFAULT_TYPDELIM, /* array element delimiter */ F_ARRAY_IN, /* input procedure */ @@ -1018,6 +1020,8 @@ DefineEnum(CreateEnumStmt *stmt) InvalidOid, /* typmodout procedure - none */ InvalidOid, /* analyze procedure - default */ enumTypeOid, /* element type ID */ + true, /* yes this is an array type */ + InvalidOid, /* no further array type */ InvalidOid, /* base type ID */ NULL, /* never a default type value */ NULL, /* binary default isn't sent either */ @@ -1026,7 +1030,7 @@ DefineEnum(CreateEnumStmt *stmt) 'x', /* ARRAY is always toastable */ -1, /* typMod (Domains only) */ 0, /* Array dimensions of typbasetype */ - false); /* Type NOT NULL */ + false); /* Type NOT NULL */ pfree(enumArrayName); } @@ -1435,7 +1439,7 @@ AlterDomainDefault(List *names, Node *defaultRaw) /* Rebuild dependencies */ GenerateTypeDependencies(typTup->typnamespace, domainoid, - typTup->typrelid, + InvalidOid, /* typrelid is n/a */ 0, /* relation kind is n/a */ typTup->typowner, typTup->typinput, @@ -1446,6 +1450,7 @@ AlterDomainDefault(List *names, Node *defaultRaw) typTup->typmodout, typTup->typanalyze, typTup->typelem, + false, /* a domain isn't an implicit array */ typTup->typbasetype, defaultExpr, true); /* Rebuild is true */ @@ -2251,7 +2256,7 @@ AlterTypeOwner(List *names, Oid newOwnerId) /* * If it's a composite type, we need to check that it really is a - * free-standing composite type, and not a table's underlying type. We + * free-standing composite type, and not a table's rowtype. We * want people to use ALTER TABLE not ALTER TYPE for that case. */ if (typTup->typtype == TYPTYPE_COMPOSITE && @@ -2261,6 +2266,16 @@ AlterTypeOwner(List *names, Oid newOwnerId) errmsg("\"%s\" is a table's row type", TypeNameToString(typename)))); + /* don't allow direct alteration of array types, either */ + if (OidIsValid(typTup->typelem) && + get_array_type(typTup->typelem) == typeOid) + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("cannot alter array type %s", + format_type_be(typeOid)), + errhint("You can alter type %s, which will alter the array type as well.", + format_type_be(typTup->typelem)))); + /* * If the new owner is the same as the existing owner, consider the * command to have succeeded. This is for dump restoration purposes. @@ -2288,16 +2303,32 @@ AlterTypeOwner(List *names, Oid newOwnerId) } /* - * Modify the owner --- okay to scribble on typTup because it's a copy + * If it's a composite type, invoke ATExecChangeOwner so that we + * fix up the pg_class entry properly. That will call back to + * AlterTypeOwnerInternal to take care of the pg_type entry(s). */ - typTup->typowner = newOwnerId; + if (typTup->typtype == TYPTYPE_COMPOSITE) + ATExecChangeOwner(typTup->typrelid, newOwnerId, true); + else + { + /* + * We can just apply the modification directly. + * + * okay to scribble on typTup because it's a copy + */ + typTup->typowner = newOwnerId; - simple_heap_update(rel, &tup->t_self, tup); + simple_heap_update(rel, &tup->t_self, tup); - CatalogUpdateIndexes(rel, tup); + CatalogUpdateIndexes(rel, tup); - /* Update owner dependency reference */ - changeDependencyOnOwner(TypeRelationId, typeOid, newOwnerId); + /* Update owner dependency reference */ + changeDependencyOnOwner(TypeRelationId, typeOid, newOwnerId); + + /* If it has an array type, update that too */ + if (OidIsValid(typTup->typarray)) + AlterTypeOwnerInternal(typTup->typarray, newOwnerId, false); + } } /* Clean up */ @@ -2307,12 +2338,17 @@ AlterTypeOwner(List *names, Oid newOwnerId) /* * AlterTypeOwnerInternal - change type owner unconditionally * - * This is currently only used to propagate ALTER TABLE OWNER to the - * table's rowtype, and to implement REASSIGN OWNED BY. It assumes the - * caller has done all needed checks. + * This is currently only used to propagate ALTER TABLE/TYPE OWNER to a + * table's rowtype or an array type, and to implement REASSIGN OWNED BY. + * It assumes the caller has done all needed checks. The function will + * automatically recurse to an array type if the type has one. + * + * hasDependEntry should be TRUE if type is expected to have a pg_shdepend + * entry (ie, it's not a table rowtype nor an array type). */ void -AlterTypeOwnerInternal(Oid typeOid, Oid newOwnerId) +AlterTypeOwnerInternal(Oid typeOid, Oid newOwnerId, + bool hasDependEntry) { Relation rel; HeapTuple tup; @@ -2336,8 +2372,13 @@ AlterTypeOwnerInternal(Oid typeOid, Oid newOwnerId) CatalogUpdateIndexes(rel, tup); - /* Update owner dependency reference */ - changeDependencyOnOwner(TypeRelationId, typeOid, newOwnerId); + /* Update owner dependency reference, if it has one */ + if (hasDependEntry) + changeDependencyOnOwner(TypeRelationId, typeOid, newOwnerId); + + /* If it has an array type, update that too */ + if (OidIsValid(typTup->typarray)) + AlterTypeOwnerInternal(typTup->typarray, newOwnerId, false); /* Clean up */ heap_close(rel, RowExclusiveLock); @@ -2352,6 +2393,7 @@ AlterTypeNamespace(List *names, const char *newschema) TypeName *typename; Oid typeOid; Oid nspOid; + Oid elemOid; /* Make a TypeName so we can use standard type lookup machinery */ typename = makeTypeNameFromNameList(names); @@ -2365,8 +2407,18 @@ AlterTypeNamespace(List *names, const char *newschema) /* get schema OID and check its permissions */ nspOid = LookupCreationNamespace(newschema); + /* don't allow direct alteration of array types */ + elemOid = get_element_type(typeOid); + if (OidIsValid(elemOid) && get_array_type(elemOid) == typeOid) + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("cannot alter array type %s", + format_type_be(typeOid)), + errhint("You can alter type %s, which will alter the array type as well.", + format_type_be(elemOid)))); + /* and do the work */ - AlterTypeNamespaceInternal(typeOid, nspOid, true); + AlterTypeNamespaceInternal(typeOid, nspOid, false, true); } /* @@ -2374,18 +2426,24 @@ AlterTypeNamespace(List *names, const char *newschema) * * Caller must have already checked privileges. * + * The function automatically recurses to process the type's array type, + * if any. isImplicitArray should be TRUE only when doing this internal + * recursion (outside callers must never try to move an array type directly). + * * If errorOnTableType is TRUE, the function errors out if the type is * a table type. ALTER TABLE has to be used to move a table to a new * namespace. */ void AlterTypeNamespaceInternal(Oid typeOid, Oid nspOid, + bool isImplicitArray, bool errorOnTableType) { Relation rel; HeapTuple tup; Form_pg_type typform; Oid oldNspOid; + Oid arrayOid; bool isCompositeType; rel = heap_open(TypeRelationId, RowExclusiveLock); @@ -2398,6 +2456,7 @@ AlterTypeNamespaceInternal(Oid typeOid, Oid nspOid, typform = (Form_pg_type) GETSTRUCT(tup); oldNspOid = typform->typnamespace; + arrayOid = typform->typarray; if (oldNspOid == nspOid) ereport(ERROR, @@ -2463,13 +2522,9 @@ AlterTypeNamespaceInternal(Oid typeOid, Oid nspOid, classRel = heap_open(RelationRelationId, RowExclusiveLock); - /* - * The dependency on the schema is listed under the pg_class entry, so - * tell AlterRelationNamespaceInternal to fix it. - */ AlterRelationNamespaceInternal(classRel, typform->typrelid, oldNspOid, nspOid, - true); + false); heap_close(classRel, RowExclusiveLock); @@ -2485,19 +2540,24 @@ AlterTypeNamespaceInternal(Oid typeOid, Oid nspOid, /* If it's a domain, it might have constraints */ if (typform->typtype == TYPTYPE_DOMAIN) AlterConstraintNamespaces(typeOid, oldNspOid, nspOid, true); - - /* - * Update dependency on schema, if any --- a table rowtype has not got - * one. - */ - if (typform->typtype != TYPTYPE_COMPOSITE) - if (changeDependencyFor(TypeRelationId, typeOid, - NamespaceRelationId, oldNspOid, nspOid) != 1) - elog(ERROR, "failed to change schema dependency for type %s", - format_type_be(typeOid)); } + /* + * Update dependency on schema, if any --- a table rowtype has not got + * one, and neither does an implicit array. + */ + if ((isCompositeType || typform->typtype != TYPTYPE_COMPOSITE) && + !isImplicitArray) + if (changeDependencyFor(TypeRelationId, typeOid, + NamespaceRelationId, oldNspOid, nspOid) != 1) + elog(ERROR, "failed to change schema dependency for type %s", + format_type_be(typeOid)); + heap_freetuple(tup); heap_close(rel, RowExclusiveLock); + + /* Recursively alter the associated array type, if any */ + if (OidIsValid(arrayOid)) + AlterTypeNamespaceInternal(arrayOid, nspOid, true, true); } diff --git a/src/backend/parser/parse_type.c b/src/backend/parser/parse_type.c index 0263386d2a..d3198f0496 100644 --- a/src/backend/parser/parse_type.c +++ b/src/backend/parser/parse_type.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/parse_type.c,v 1.89 2007/04/27 22:05:48 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_type.c,v 1.90 2007/05/11 17:57:12 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -116,10 +116,6 @@ LookupTypeName(ParseState *pstate, const TypeName *typename) /* deconstruct the name list */ DeconstructQualifiedName(typename->names, &schemaname, &typname); - /* If an array reference, look up the array type instead */ - if (typename->arrayBounds != NIL) - typname = makeArrayTypeName(typname); - if (schemaname) { /* Look in specific schema only */ @@ -136,6 +132,10 @@ LookupTypeName(ParseState *pstate, const TypeName *typename) /* Unqualified type name, so search the search path */ restype = TypenameGetTypid(typname); } + + /* If an array reference, return the array type instead */ + if (typename->arrayBounds != NIL) + restype = get_array_type(restype); } return restype; diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c index 391870c3a6..d86a70521e 100644 --- a/src/backend/utils/cache/lsyscache.c +++ b/src/backend/utils/cache/lsyscache.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/cache/lsyscache.c,v 1.151 2007/04/02 03:49:39 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/cache/lsyscache.c,v 1.152 2007/05/11 17:57:12 tgl Exp $ * * NOTES * Eventually, the index information should go through here, too. @@ -2203,50 +2203,24 @@ get_element_type(Oid typid) /* * get_array_type * - * Given the type OID, get the corresponding array type. + * Given the type OID, get the corresponding "true" array type. * Returns InvalidOid if no array type can be found. - * - * NB: this only considers varlena arrays to be true arrays. */ Oid get_array_type(Oid typid) { HeapTuple tp; + Oid result = InvalidOid; tp = SearchSysCache(TYPEOID, ObjectIdGetDatum(typid), 0, 0, 0); if (HeapTupleIsValid(tp)) { - Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp); - char *array_typename; - Oid namespaceId; - - array_typename = makeArrayTypeName(NameStr(typtup->typname)); - namespaceId = typtup->typnamespace; + result = ((Form_pg_type) GETSTRUCT(tp))->typarray; ReleaseSysCache(tp); - - tp = SearchSysCache(TYPENAMENSP, - PointerGetDatum(array_typename), - ObjectIdGetDatum(namespaceId), - 0, 0); - - pfree(array_typename); - - if (HeapTupleIsValid(tp)) - { - Oid result; - - typtup = (Form_pg_type) GETSTRUCT(tp); - if (typtup->typlen == -1 && typtup->typelem == typid) - result = HeapTupleGetOid(tp); - else - result = InvalidOid; - ReleaseSysCache(tp); - return result; - } } - return InvalidOid; + return result; } /* diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index 6559506263..64c26c16fb 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -12,7 +12,7 @@ * by PostgreSQL * * IDENTIFICATION - * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.467 2007/04/16 18:42:10 tgl Exp $ + * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.468 2007/05/11 17:57:12 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -963,9 +963,8 @@ selectDumpableType(TypeInfo *tinfo) else if (!tinfo->isDefined) tinfo->dobj.dump = false; - /* skip all array types that start w/ underscore */ - else if ((tinfo->dobj.name[0] == '_') && - OidIsValid(tinfo->typelem)) + /* skip auto-generated array types */ + else if (tinfo->isArray) tinfo->dobj.dump = false; else @@ -1963,6 +1962,7 @@ getTypes(int *numTypes) int i_typrelkind; int i_typtype; int i_typisdefined; + int i_isarray; /* * we include even the built-in types because those may be used as array @@ -1970,13 +1970,20 @@ getTypes(int *numTypes) * * we filter out the built-in types when we dump out the types * - * same approach for undefined (shell) types + * same approach for undefined (shell) types and array types + * + * Note: as of 8.3 we can reliably detect whether a type is an + * auto-generated array type by checking the element type's typarray. + * (Before that the test is capable of generating false positives.) + * We still check for name beginning with '_', though, so as to avoid + * the cost of the subselect probe for all standard types. This would + * have to be revisited if the backend ever allows renaming of array types. */ /* Make sure we are in proper schema */ selectSourceSchema("pg_catalog"); - if (g_fout->remoteVersion >= 70300) + if (g_fout->remoteVersion >= 80300) { appendPQExpBuffer(query, "SELECT tableoid, oid, typname, " "typnamespace, " @@ -1985,7 +1992,23 @@ getTypes(int *numTypes) "typoutput::oid as typoutput, typelem, typrelid, " "CASE WHEN typrelid = 0 THEN ' '::\"char\" " "ELSE (SELECT relkind FROM pg_class WHERE oid = typrelid) END as typrelkind, " - "typtype, typisdefined " + "typtype, typisdefined, " + "typname[0] = '_' AND typelem != 0 AND " + "(SELECT typarray FROM pg_type te WHERE oid = pg_type.typelem) = oid AS isarray " + "FROM pg_type", + username_subquery); + } + else if (g_fout->remoteVersion >= 70300) + { + appendPQExpBuffer(query, "SELECT tableoid, oid, typname, " + "typnamespace, " + "(%s typowner) as rolname, " + "typinput::oid as typinput, " + "typoutput::oid as typoutput, typelem, typrelid, " + "CASE WHEN typrelid = 0 THEN ' '::\"char\" " + "ELSE (SELECT relkind FROM pg_class WHERE oid = typrelid) END as typrelkind, " + "typtype, typisdefined, " + "typname[0] = '_' AND typelem != 0 AS isarray " "FROM pg_type", username_subquery); } @@ -1998,7 +2021,8 @@ getTypes(int *numTypes) "typoutput::oid as typoutput, typelem, typrelid, " "CASE WHEN typrelid = 0 THEN ' '::\"char\" " "ELSE (SELECT relkind FROM pg_class WHERE oid = typrelid) END as typrelkind, " - "typtype, typisdefined " + "typtype, typisdefined, " + "typname[0] = '_' AND typelem != 0 AS isarray " "FROM pg_type", username_subquery); } @@ -2013,7 +2037,8 @@ getTypes(int *numTypes) "typoutput::oid as typoutput, typelem, typrelid, " "CASE WHEN typrelid = 0 THEN ' '::\"char\" " "ELSE (SELECT relkind FROM pg_class WHERE oid = typrelid) END as typrelkind, " - "typtype, typisdefined " + "typtype, typisdefined, " + "typname[0] = '_' AND typelem != 0 AS isarray " "FROM pg_type", username_subquery); } @@ -2037,6 +2062,7 @@ getTypes(int *numTypes) i_typrelkind = PQfnumber(res, "typrelkind"); i_typtype = PQfnumber(res, "typtype"); i_typisdefined = PQfnumber(res, "typisdefined"); + i_isarray = PQfnumber(res, "isarray"); for (i = 0; i < ntups; i++) { @@ -2064,20 +2090,16 @@ getTypes(int *numTypes) tinfo[i].typrelkind != RELKIND_COMPOSITE_TYPE) tinfo[i].dobj.objType = DO_TABLE_TYPE; - /* - * check for user-defined array types, omit system generated ones - */ - if (OidIsValid(tinfo[i].typelem) && - tinfo[i].dobj.name[0] != '_') - tinfo[i].isArray = true; - else - tinfo[i].isArray = false; - if (strcmp(PQgetvalue(res, i, i_typisdefined), "t") == 0) tinfo[i].isDefined = true; else tinfo[i].isDefined = false; + if (strcmp(PQgetvalue(res, i, i_isarray), "t") == 0) + tinfo[i].isArray = true; + else + tinfo[i].isArray = false; + /* Decide whether we want to dump it */ selectDumpableType(&tinfo[i]); @@ -3894,7 +3916,7 @@ getTriggers(TableInfo tblinfo[], int numTables) else if (g_fout->remoteVersion >= 70100) { appendPQExpBuffer(query, - "SELECT tgname, tgfoid::pg_catalog.regproc as tgfname, " + "SELECT tgname, tgfoid::regproc as tgfname, " "tgtype, tgnargs, tgargs, tgenabled, " "tgisconstraint, tgconstrname, tgdeferrable, " "tgconstrrelid, tginitdeferred, tableoid, oid, " @@ -3907,7 +3929,7 @@ getTriggers(TableInfo tblinfo[], int numTables) else { appendPQExpBuffer(query, - "SELECT tgname, tgfoid::pg_catalog.regproc as tgfname, " + "SELECT tgname, tgfoid::regproc as tgfname, " "tgtype, tgnargs, tgargs, tgenabled, " "tgisconstraint, tgconstrname, tgdeferrable, " "tgconstrrelid, tginitdeferred, " @@ -5473,7 +5495,7 @@ dumpBaseType(Archive *fout, TypeInfo *tinfo) appendPQExpBufferStr(q, typdefault); } - if (tinfo->isArray) + if (OidIsValid(tinfo->typelem)) { char *elemType; diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h index 8694376b52..9575cd5b19 100644 --- a/src/bin/pg_dump/pg_dump.h +++ b/src/bin/pg_dump/pg_dump.h @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.h,v 1.134 2007/03/19 23:38:30 wieck Exp $ + * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.h,v 1.135 2007/05/11 17:57:13 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -164,7 +164,7 @@ typedef struct _typeInfo Oid typrelid; char typrelkind; /* 'r', 'v', 'c', etc */ char typtype; /* 'b', 'c', etc */ - bool isArray; /* true if user-defined array type */ + bool isArray; /* true if auto-generated array type */ bool isDefined; /* true if typisdefined */ /* If it's a dumpable base type, we create a "shell type" entry for it */ struct _shellTypeInfo *shellType; /* shell-type entry, or NULL */ diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index 69ef260ad3..b0d562f842 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -37,7 +37,7 @@ * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.405 2007/05/08 18:56:47 neilc Exp $ + * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.406 2007/05/11 17:57:13 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 200705081 +#define CATALOG_VERSION_NO 200705111 #endif diff --git a/src/include/catalog/pg_attribute.h b/src/include/catalog/pg_attribute.h index 5ca45adbad..8562d468d5 100644 --- a/src/include/catalog/pg_attribute.h +++ b/src/include/catalog/pg_attribute.h @@ -8,7 +8,7 @@ * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/catalog/pg_attribute.h,v 1.130 2007/01/22 01:35:21 tgl Exp $ + * $PostgreSQL: pgsql/src/include/catalog/pg_attribute.h,v 1.131 2007/05/11 17:57:13 tgl Exp $ * * NOTES * the genbki.sh script reads this file and generates .bki @@ -232,21 +232,22 @@ typedef FormData_pg_attribute *Form_pg_attribute; { 1247, {"typdelim"}, 18, -1, 1, 8, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \ { 1247, {"typrelid"}, 26, -1, 4, 9, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \ { 1247, {"typelem"}, 26, -1, 4, 10, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \ -{ 1247, {"typinput"}, 24, -1, 4, 11, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \ -{ 1247, {"typoutput"}, 24, -1, 4, 12, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \ -{ 1247, {"typreceive"}, 24, -1, 4, 13, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \ -{ 1247, {"typsend"}, 24, -1, 4, 14, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \ -{ 1247, {"typmodin"}, 24, -1, 4, 15, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \ -{ 1247, {"typmodout"}, 24, -1, 4, 16, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \ -{ 1247, {"typanalyze"}, 24, -1, 4, 17, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \ -{ 1247, {"typalign"}, 18, -1, 1, 18, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \ -{ 1247, {"typstorage"}, 18, -1, 1, 19, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \ -{ 1247, {"typnotnull"}, 16, -1, 1, 20, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \ -{ 1247, {"typbasetype"}, 26, -1, 4, 21, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \ -{ 1247, {"typtypmod"}, 23, -1, 4, 22, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \ -{ 1247, {"typndims"}, 23, -1, 4, 23, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \ -{ 1247, {"typdefaultbin"}, 25, -1, -1, 24, 0, -1, -1, false, 'x', 'i', false, false, false, true, 0 }, \ -{ 1247, {"typdefault"}, 25, -1, -1, 25, 0, -1, -1, false, 'x', 'i', false, false, false, true, 0 } +{ 1247, {"typarray"}, 26, -1, 4, 11, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \ +{ 1247, {"typinput"}, 24, -1, 4, 12, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \ +{ 1247, {"typoutput"}, 24, -1, 4, 13, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \ +{ 1247, {"typreceive"}, 24, -1, 4, 14, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \ +{ 1247, {"typsend"}, 24, -1, 4, 15, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \ +{ 1247, {"typmodin"}, 24, -1, 4, 16, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \ +{ 1247, {"typmodout"}, 24, -1, 4, 17, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \ +{ 1247, {"typanalyze"}, 24, -1, 4, 18, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \ +{ 1247, {"typalign"}, 18, -1, 1, 19, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \ +{ 1247, {"typstorage"}, 18, -1, 1, 20, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \ +{ 1247, {"typnotnull"}, 16, -1, 1, 21, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \ +{ 1247, {"typbasetype"}, 26, -1, 4, 22, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \ +{ 1247, {"typtypmod"}, 23, -1, 4, 23, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \ +{ 1247, {"typndims"}, 23, -1, 4, 24, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \ +{ 1247, {"typdefaultbin"}, 25, -1, -1, 25, 0, -1, -1, false, 'x', 'i', false, false, false, true, 0 }, \ +{ 1247, {"typdefault"}, 25, -1, -1, 26, 0, -1, -1, false, 'x', 'i', false, false, false, true, 0 } DATA(insert ( 1247 typname 19 -1 NAMEDATALEN 1 0 -1 -1 f p i t f f t 0)); DATA(insert ( 1247 typnamespace 26 -1 4 2 0 -1 -1 t p i t f f t 0)); @@ -258,21 +259,22 @@ DATA(insert ( 1247 typisdefined 16 -1 1 7 0 -1 -1 t p c t f f t 0)); DATA(insert ( 1247 typdelim 18 -1 1 8 0 -1 -1 t p c t f f t 0)); DATA(insert ( 1247 typrelid 26 -1 4 9 0 -1 -1 t p i t f f t 0)); DATA(insert ( 1247 typelem 26 -1 4 10 0 -1 -1 t p i t f f t 0)); -DATA(insert ( 1247 typinput 24 -1 4 11 0 -1 -1 t p i t f f t 0)); -DATA(insert ( 1247 typoutput 24 -1 4 12 0 -1 -1 t p i t f f t 0)); -DATA(insert ( 1247 typreceive 24 -1 4 13 0 -1 -1 t p i t f f t 0)); -DATA(insert ( 1247 typsend 24 -1 4 14 0 -1 -1 t p i t f f t 0)); -DATA(insert ( 1247 typmodin 24 -1 4 15 0 -1 -1 t p i t f f t 0)); -DATA(insert ( 1247 typmodout 24 -1 4 16 0 -1 -1 t p i t f f t 0)); -DATA(insert ( 1247 typanalyze 24 -1 4 17 0 -1 -1 t p i t f f t 0)); -DATA(insert ( 1247 typalign 18 -1 1 18 0 -1 -1 t p c t f f t 0)); -DATA(insert ( 1247 typstorage 18 -1 1 19 0 -1 -1 t p c t f f t 0)); -DATA(insert ( 1247 typnotnull 16 -1 1 20 0 -1 -1 t p c t f f t 0)); -DATA(insert ( 1247 typbasetype 26 -1 4 21 0 -1 -1 t p i t f f t 0)); -DATA(insert ( 1247 typtypmod 23 -1 4 22 0 -1 -1 t p i t f f t 0)); -DATA(insert ( 1247 typndims 23 -1 4 23 0 -1 -1 t p i t f f t 0)); -DATA(insert ( 1247 typdefaultbin 25 -1 -1 24 0 -1 -1 f x i f f f t 0)); -DATA(insert ( 1247 typdefault 25 -1 -1 25 0 -1 -1 f x i f f f t 0)); +DATA(insert ( 1247 typarray 26 -1 4 11 0 -1 -1 t p i t f f t 0)); +DATA(insert ( 1247 typinput 24 -1 4 12 0 -1 -1 t p i t f f t 0)); +DATA(insert ( 1247 typoutput 24 -1 4 13 0 -1 -1 t p i t f f t 0)); +DATA(insert ( 1247 typreceive 24 -1 4 14 0 -1 -1 t p i t f f t 0)); +DATA(insert ( 1247 typsend 24 -1 4 15 0 -1 -1 t p i t f f t 0)); +DATA(insert ( 1247 typmodin 24 -1 4 16 0 -1 -1 t p i t f f t 0)); +DATA(insert ( 1247 typmodout 24 -1 4 17 0 -1 -1 t p i t f f t 0)); +DATA(insert ( 1247 typanalyze 24 -1 4 18 0 -1 -1 t p i t f f t 0)); +DATA(insert ( 1247 typalign 18 -1 1 19 0 -1 -1 t p c t f f t 0)); +DATA(insert ( 1247 typstorage 18 -1 1 20 0 -1 -1 t p c t f f t 0)); +DATA(insert ( 1247 typnotnull 16 -1 1 21 0 -1 -1 t p c t f f t 0)); +DATA(insert ( 1247 typbasetype 26 -1 4 22 0 -1 -1 t p i t f f t 0)); +DATA(insert ( 1247 typtypmod 23 -1 4 23 0 -1 -1 t p i t f f t 0)); +DATA(insert ( 1247 typndims 23 -1 4 24 0 -1 -1 t p i t f f t 0)); +DATA(insert ( 1247 typdefaultbin 25 -1 -1 25 0 -1 -1 f x i f f f t 0)); +DATA(insert ( 1247 typdefault 25 -1 -1 26 0 -1 -1 f x i f f f t 0)); DATA(insert ( 1247 ctid 27 0 6 -1 0 -1 -1 f p s t f f t 0)); DATA(insert ( 1247 oid 26 0 4 -2 0 -1 -1 t p i t f f t 0)); DATA(insert ( 1247 xmin 28 0 4 -3 0 -1 -1 t p i t f f t 0)); diff --git a/src/include/catalog/pg_class.h b/src/include/catalog/pg_class.h index 8ac0cb2793..580588305b 100644 --- a/src/include/catalog/pg_class.h +++ b/src/include/catalog/pg_class.h @@ -8,7 +8,7 @@ * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/catalog/pg_class.h,v 1.100 2007/01/22 01:35:22 tgl Exp $ + * $PostgreSQL: pgsql/src/include/catalog/pg_class.h,v 1.101 2007/05/11 17:57:13 tgl Exp $ * * NOTES * the genbki.sh script reads this file and generates .bki @@ -132,7 +132,7 @@ typedef FormData_pg_class *Form_pg_class; */ /* Note: "3" in the relfrozenxid column stands for FirstNormalTransactionId */ -DATA(insert OID = 1247 ( pg_type PGNSP 71 PGUID 0 1247 0 0 0 0 0 f f r 25 0 0 0 0 0 t f f f 3 _null_ _null_ )); +DATA(insert OID = 1247 ( pg_type PGNSP 71 PGUID 0 1247 0 0 0 0 0 f f r 26 0 0 0 0 0 t f f f 3 _null_ _null_ )); DESCR(""); DATA(insert OID = 1249 ( pg_attribute PGNSP 75 PGUID 0 1249 0 0 0 0 0 f f r 17 0 0 0 0 0 f f f f 3 _null_ _null_ )); DESCR(""); diff --git a/src/include/catalog/pg_type.h b/src/include/catalog/pg_type.h index 519be08afc..c663ff4ec7 100644 --- a/src/include/catalog/pg_type.h +++ b/src/include/catalog/pg_type.h @@ -8,7 +8,7 @@ * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/catalog/pg_type.h,v 1.182 2007/04/06 04:21:43 tgl Exp $ + * $PostgreSQL: pgsql/src/include/catalog/pg_type.h,v 1.183 2007/05/11 17:57:13 tgl Exp $ * * NOTES * the genbki.sh script reads this file and generates .bki @@ -97,6 +97,12 @@ CATALOG(pg_type,1247) BKI_BOOTSTRAP */ Oid typelem; + /* + * If there is a "true" array type having this type as element type, + * typarray links to it. Zero if no associated "true" array type. + */ + Oid typarray; + /* * I/O conversion procedures for the datatype. */ @@ -214,7 +220,7 @@ typedef FormData_pg_type *Form_pg_type; * compiler constants for pg_type * ---------------- */ -#define Natts_pg_type 25 +#define Natts_pg_type 26 #define Anum_pg_type_typname 1 #define Anum_pg_type_typnamespace 2 #define Anum_pg_type_typowner 3 @@ -225,21 +231,22 @@ typedef FormData_pg_type *Form_pg_type; #define Anum_pg_type_typdelim 8 #define Anum_pg_type_typrelid 9 #define Anum_pg_type_typelem 10 -#define Anum_pg_type_typinput 11 -#define Anum_pg_type_typoutput 12 -#define Anum_pg_type_typreceive 13 -#define Anum_pg_type_typsend 14 -#define Anum_pg_type_typmodin 15 -#define Anum_pg_type_typmodout 16 -#define Anum_pg_type_typanalyze 17 -#define Anum_pg_type_typalign 18 -#define Anum_pg_type_typstorage 19 -#define Anum_pg_type_typnotnull 20 -#define Anum_pg_type_typbasetype 21 -#define Anum_pg_type_typtypmod 22 -#define Anum_pg_type_typndims 23 -#define Anum_pg_type_typdefaultbin 24 -#define Anum_pg_type_typdefault 25 +#define Anum_pg_type_typarray 11 +#define Anum_pg_type_typinput 12 +#define Anum_pg_type_typoutput 13 +#define Anum_pg_type_typreceive 14 +#define Anum_pg_type_typsend 15 +#define Anum_pg_type_typmodin 16 +#define Anum_pg_type_typmodout 17 +#define Anum_pg_type_typanalyze 18 +#define Anum_pg_type_typalign 19 +#define Anum_pg_type_typstorage 20 +#define Anum_pg_type_typnotnull 21 +#define Anum_pg_type_typbasetype 22 +#define Anum_pg_type_typtypmod 23 +#define Anum_pg_type_typndims 24 +#define Anum_pg_type_typdefaultbin 25 +#define Anum_pg_type_typdefault 26 /* ---------------- @@ -255,86 +262,86 @@ typedef FormData_pg_type *Form_pg_type; */ /* OIDS 1 - 99 */ -DATA(insert OID = 16 ( bool PGNSP PGUID 1 t b t \054 0 0 boolin boolout boolrecv boolsend - - - c p f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 16 ( bool PGNSP PGUID 1 t b t \054 0 0 1000 boolin boolout boolrecv boolsend - - - c p f 0 -1 0 _null_ _null_ )); DESCR("boolean, 'true'/'false'"); #define BOOLOID 16 -DATA(insert OID = 17 ( bytea PGNSP PGUID -1 f b t \054 0 0 byteain byteaout bytearecv byteasend - - - i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 17 ( bytea PGNSP PGUID -1 f b t \054 0 0 1001 byteain byteaout bytearecv byteasend - - - i x f 0 -1 0 _null_ _null_ )); DESCR("variable-length string, binary values escaped"); #define BYTEAOID 17 -DATA(insert OID = 18 ( char PGNSP PGUID 1 t b t \054 0 0 charin charout charrecv charsend - - - c p f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 18 ( char PGNSP PGUID 1 t b t \054 0 0 1002 charin charout charrecv charsend - - - c p f 0 -1 0 _null_ _null_ )); DESCR("single character"); #define CHAROID 18 -DATA(insert OID = 19 ( name PGNSP PGUID NAMEDATALEN f b t \054 0 18 namein nameout namerecv namesend - - - i p f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 19 ( name PGNSP PGUID NAMEDATALEN f b t \054 0 18 1003 namein nameout namerecv namesend - - - i p f 0 -1 0 _null_ _null_ )); DESCR("63-character type for storing system identifiers"); #define NAMEOID 19 -DATA(insert OID = 20 ( int8 PGNSP PGUID 8 f b t \054 0 0 int8in int8out int8recv int8send - - - d p f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 20 ( int8 PGNSP PGUID 8 f b t \054 0 0 1016 int8in int8out int8recv int8send - - - d p f 0 -1 0 _null_ _null_ )); DESCR("~18 digit integer, 8-byte storage"); #define INT8OID 20 -DATA(insert OID = 21 ( int2 PGNSP PGUID 2 t b t \054 0 0 int2in int2out int2recv int2send - - - s p f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 21 ( int2 PGNSP PGUID 2 t b t \054 0 0 1005 int2in int2out int2recv int2send - - - s p f 0 -1 0 _null_ _null_ )); DESCR("-32 thousand to 32 thousand, 2-byte storage"); #define INT2OID 21 -DATA(insert OID = 22 ( int2vector PGNSP PGUID -1 f b t \054 0 21 int2vectorin int2vectorout int2vectorrecv int2vectorsend - - - i p f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 22 ( int2vector PGNSP PGUID -1 f b t \054 0 21 1006 int2vectorin int2vectorout int2vectorrecv int2vectorsend - - - i p f 0 -1 0 _null_ _null_ )); DESCR("array of int2, used in system tables"); #define INT2VECTOROID 22 -DATA(insert OID = 23 ( int4 PGNSP PGUID 4 t b t \054 0 0 int4in int4out int4recv int4send - - - i p f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 23 ( int4 PGNSP PGUID 4 t b t \054 0 0 1007 int4in int4out int4recv int4send - - - i p f 0 -1 0 _null_ _null_ )); DESCR("-2 billion to 2 billion integer, 4-byte storage"); #define INT4OID 23 -DATA(insert OID = 24 ( regproc PGNSP PGUID 4 t b t \054 0 0 regprocin regprocout regprocrecv regprocsend - - - i p f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 24 ( regproc PGNSP PGUID 4 t b t \054 0 0 1008 regprocin regprocout regprocrecv regprocsend - - - i p f 0 -1 0 _null_ _null_ )); DESCR("registered procedure"); #define REGPROCOID 24 -DATA(insert OID = 25 ( text PGNSP PGUID -1 f b t \054 0 0 textin textout textrecv textsend - - - i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 25 ( text PGNSP PGUID -1 f b t \054 0 0 1009 textin textout textrecv textsend - - - i x f 0 -1 0 _null_ _null_ )); DESCR("variable-length string, no limit specified"); #define TEXTOID 25 -DATA(insert OID = 26 ( oid PGNSP PGUID 4 t b t \054 0 0 oidin oidout oidrecv oidsend - - - i p f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 26 ( oid PGNSP PGUID 4 t b t \054 0 0 1028 oidin oidout oidrecv oidsend - - - i p f 0 -1 0 _null_ _null_ )); DESCR("object identifier(oid), maximum 4 billion"); #define OIDOID 26 -DATA(insert OID = 27 ( tid PGNSP PGUID 6 f b t \054 0 0 tidin tidout tidrecv tidsend - - - s p f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 27 ( tid PGNSP PGUID 6 f b t \054 0 0 1010 tidin tidout tidrecv tidsend - - - s p f 0 -1 0 _null_ _null_ )); DESCR("(Block, offset), physical location of tuple"); #define TIDOID 27 -DATA(insert OID = 28 ( xid PGNSP PGUID 4 t b t \054 0 0 xidin xidout xidrecv xidsend - - - i p f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 28 ( xid PGNSP PGUID 4 t b t \054 0 0 1011 xidin xidout xidrecv xidsend - - - i p f 0 -1 0 _null_ _null_ )); DESCR("transaction id"); #define XIDOID 28 -DATA(insert OID = 29 ( cid PGNSP PGUID 4 t b t \054 0 0 cidin cidout cidrecv cidsend - - - i p f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 29 ( cid PGNSP PGUID 4 t b t \054 0 0 1012 cidin cidout cidrecv cidsend - - - i p f 0 -1 0 _null_ _null_ )); DESCR("command identifier type, sequence in transaction id"); #define CIDOID 29 -DATA(insert OID = 30 ( oidvector PGNSP PGUID -1 f b t \054 0 26 oidvectorin oidvectorout oidvectorrecv oidvectorsend - - - i p f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 30 ( oidvector PGNSP PGUID -1 f b t \054 0 26 1013 oidvectorin oidvectorout oidvectorrecv oidvectorsend - - - i p f 0 -1 0 _null_ _null_ )); DESCR("array of oids, used in system tables"); #define OIDVECTOROID 30 /* hand-built rowtype entries for bootstrapped catalogs: */ -DATA(insert OID = 71 ( pg_type PGNSP PGUID -1 f c t \054 1247 0 record_in record_out record_recv record_send - - - d x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 71 ( pg_type PGNSP PGUID -1 f c t \054 1247 0 0 record_in record_out record_recv record_send - - - d x f 0 -1 0 _null_ _null_ )); #define PG_TYPE_RELTYPE_OID 71 -DATA(insert OID = 75 ( pg_attribute PGNSP PGUID -1 f c t \054 1249 0 record_in record_out record_recv record_send - - - d x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 75 ( pg_attribute PGNSP PGUID -1 f c t \054 1249 0 0 record_in record_out record_recv record_send - - - d x f 0 -1 0 _null_ _null_ )); #define PG_ATTRIBUTE_RELTYPE_OID 75 -DATA(insert OID = 81 ( pg_proc PGNSP PGUID -1 f c t \054 1255 0 record_in record_out record_recv record_send - - - d x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 81 ( pg_proc PGNSP PGUID -1 f c t \054 1255 0 0 record_in record_out record_recv record_send - - - d x f 0 -1 0 _null_ _null_ )); #define PG_PROC_RELTYPE_OID 81 -DATA(insert OID = 83 ( pg_class PGNSP PGUID -1 f c t \054 1259 0 record_in record_out record_recv record_send - - - d x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 83 ( pg_class PGNSP PGUID -1 f c t \054 1259 0 0 record_in record_out record_recv record_send - - - d x f 0 -1 0 _null_ _null_ )); #define PG_CLASS_RELTYPE_OID 83 /* OIDS 100 - 199 */ -DATA(insert OID = 142 ( xml PGNSP PGUID -1 f b t \054 0 0 xml_in xml_out xml_recv xml_send - - - i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 142 ( xml PGNSP PGUID -1 f b t \054 0 0 143 xml_in xml_out xml_recv xml_send - - - i x f 0 -1 0 _null_ _null_ )); DESCR("XML content"); #define XMLOID 142 -DATA(insert OID = 143 ( _xml PGNSP PGUID -1 f b t \054 0 142 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 143 ( _xml PGNSP PGUID -1 f b t \054 0 142 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ )); /* OIDS 200 - 299 */ -DATA(insert OID = 210 ( smgr PGNSP PGUID 2 t b t \054 0 0 smgrin smgrout - - - - - s p f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 210 ( smgr PGNSP PGUID 2 t b t \054 0 0 0 smgrin smgrout - - - - - s p f 0 -1 0 _null_ _null_ )); DESCR("storage manager"); /* OIDS 300 - 399 */ @@ -344,200 +351,200 @@ DESCR("storage manager"); /* OIDS 500 - 599 */ /* OIDS 600 - 699 */ -DATA(insert OID = 600 ( point PGNSP PGUID 16 f b t \054 0 701 point_in point_out point_recv point_send - - - d p f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 600 ( point PGNSP PGUID 16 f b t \054 0 701 1017 point_in point_out point_recv point_send - - - d p f 0 -1 0 _null_ _null_ )); DESCR("geometric point '(x, y)'"); #define POINTOID 600 -DATA(insert OID = 601 ( lseg PGNSP PGUID 32 f b t \054 0 600 lseg_in lseg_out lseg_recv lseg_send - - - d p f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 601 ( lseg PGNSP PGUID 32 f b t \054 0 600 1018 lseg_in lseg_out lseg_recv lseg_send - - - d p f 0 -1 0 _null_ _null_ )); DESCR("geometric line segment '(pt1,pt2)'"); #define LSEGOID 601 -DATA(insert OID = 602 ( path PGNSP PGUID -1 f b t \054 0 0 path_in path_out path_recv path_send - - - d x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 602 ( path PGNSP PGUID -1 f b t \054 0 0 1019 path_in path_out path_recv path_send - - - d x f 0 -1 0 _null_ _null_ )); DESCR("geometric path '(pt1,...)'"); #define PATHOID 602 -DATA(insert OID = 603 ( box PGNSP PGUID 32 f b t \073 0 600 box_in box_out box_recv box_send - - - d p f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 603 ( box PGNSP PGUID 32 f b t \073 0 600 1020 box_in box_out box_recv box_send - - - d p f 0 -1 0 _null_ _null_ )); DESCR("geometric box '(lower left,upper right)'"); #define BOXOID 603 -DATA(insert OID = 604 ( polygon PGNSP PGUID -1 f b t \054 0 0 poly_in poly_out poly_recv poly_send - - - d x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 604 ( polygon PGNSP PGUID -1 f b t \054 0 0 1027 poly_in poly_out poly_recv poly_send - - - d x f 0 -1 0 _null_ _null_ )); DESCR("geometric polygon '(pt1,...)'"); #define POLYGONOID 604 -DATA(insert OID = 628 ( line PGNSP PGUID 32 f b t \054 0 701 line_in line_out line_recv line_send - - - d p f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 628 ( line PGNSP PGUID 32 f b t \054 0 701 629 line_in line_out line_recv line_send - - - d p f 0 -1 0 _null_ _null_ )); DESCR("geometric line (not implemented)'"); #define LINEOID 628 -DATA(insert OID = 629 ( _line PGNSP PGUID -1 f b t \054 0 628 array_in array_out array_recv array_send - - - d x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 629 ( _line PGNSP PGUID -1 f b t \054 0 628 0 array_in array_out array_recv array_send - - - d x f 0 -1 0 _null_ _null_ )); DESCR(""); /* OIDS 700 - 799 */ -DATA(insert OID = 700 ( float4 PGNSP PGUID 4 f b t \054 0 0 float4in float4out float4recv float4send - - - i p f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 700 ( float4 PGNSP PGUID 4 f b t \054 0 0 1021 float4in float4out float4recv float4send - - - i p f 0 -1 0 _null_ _null_ )); DESCR("single-precision floating point number, 4-byte storage"); #define FLOAT4OID 700 -DATA(insert OID = 701 ( float8 PGNSP PGUID 8 f b t \054 0 0 float8in float8out float8recv float8send - - - d p f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 701 ( float8 PGNSP PGUID 8 f b t \054 0 0 1022 float8in float8out float8recv float8send - - - d p f 0 -1 0 _null_ _null_ )); DESCR("double-precision floating point number, 8-byte storage"); #define FLOAT8OID 701 -DATA(insert OID = 702 ( abstime PGNSP PGUID 4 t b t \054 0 0 abstimein abstimeout abstimerecv abstimesend - - - i p f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 702 ( abstime PGNSP PGUID 4 t b t \054 0 0 1023 abstimein abstimeout abstimerecv abstimesend - - - i p f 0 -1 0 _null_ _null_ )); DESCR("absolute, limited-range date and time (Unix system time)"); #define ABSTIMEOID 702 -DATA(insert OID = 703 ( reltime PGNSP PGUID 4 t b t \054 0 0 reltimein reltimeout reltimerecv reltimesend - - - i p f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 703 ( reltime PGNSP PGUID 4 t b t \054 0 0 1024 reltimein reltimeout reltimerecv reltimesend - - - i p f 0 -1 0 _null_ _null_ )); DESCR("relative, limited-range time interval (Unix delta time)"); #define RELTIMEOID 703 -DATA(insert OID = 704 ( tinterval PGNSP PGUID 12 f b t \054 0 0 tintervalin tintervalout tintervalrecv tintervalsend - - - i p f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 704 ( tinterval PGNSP PGUID 12 f b t \054 0 0 1025 tintervalin tintervalout tintervalrecv tintervalsend - - - i p f 0 -1 0 _null_ _null_ )); DESCR("(abstime,abstime), time interval"); #define TINTERVALOID 704 -DATA(insert OID = 705 ( unknown PGNSP PGUID -2 f b t \054 0 0 unknownin unknownout unknownrecv unknownsend - - - c p f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 705 ( unknown PGNSP PGUID -2 f b t \054 0 0 0 unknownin unknownout unknownrecv unknownsend - - - c p f 0 -1 0 _null_ _null_ )); DESCR(""); #define UNKNOWNOID 705 -DATA(insert OID = 718 ( circle PGNSP PGUID 24 f b t \054 0 0 circle_in circle_out circle_recv circle_send - - - d p f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 718 ( circle PGNSP PGUID 24 f b t \054 0 0 719 circle_in circle_out circle_recv circle_send - - - d p f 0 -1 0 _null_ _null_ )); DESCR("geometric circle '(center,radius)'"); #define CIRCLEOID 718 -DATA(insert OID = 719 ( _circle PGNSP PGUID -1 f b t \054 0 718 array_in array_out array_recv array_send - - - d x f 0 -1 0 _null_ _null_ )); -DATA(insert OID = 790 ( money PGNSP PGUID 8 f b t \054 0 0 cash_in cash_out cash_recv cash_send - - - d p f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 719 ( _circle PGNSP PGUID -1 f b t \054 0 718 0 array_in array_out array_recv array_send - - - d x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 790 ( money PGNSP PGUID 8 f b t \054 0 0 791 cash_in cash_out cash_recv cash_send - - - d p f 0 -1 0 _null_ _null_ )); DESCR("monetary amounts, $d,ddd.cc"); #define CASHOID 790 -DATA(insert OID = 791 ( _money PGNSP PGUID -1 f b t \054 0 790 array_in array_out array_recv array_send - - - d x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 791 ( _money PGNSP PGUID -1 f b t \054 0 790 0 array_in array_out array_recv array_send - - - d x f 0 -1 0 _null_ _null_ )); /* OIDS 800 - 899 */ -DATA(insert OID = 829 ( macaddr PGNSP PGUID 6 f b t \054 0 0 macaddr_in macaddr_out macaddr_recv macaddr_send - - - i p f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 829 ( macaddr PGNSP PGUID 6 f b t \054 0 0 1040 macaddr_in macaddr_out macaddr_recv macaddr_send - - - i p f 0 -1 0 _null_ _null_ )); DESCR("XX:XX:XX:XX:XX:XX, MAC address"); #define MACADDROID 829 -DATA(insert OID = 869 ( inet PGNSP PGUID -1 f b t \054 0 0 inet_in inet_out inet_recv inet_send - - - i m f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 869 ( inet PGNSP PGUID -1 f b t \054 0 0 1041 inet_in inet_out inet_recv inet_send - - - i m f 0 -1 0 _null_ _null_ )); DESCR("IP address/netmask, host address, netmask optional"); #define INETOID 869 -DATA(insert OID = 650 ( cidr PGNSP PGUID -1 f b t \054 0 0 cidr_in cidr_out cidr_recv cidr_send - - - i m f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 650 ( cidr PGNSP PGUID -1 f b t \054 0 0 651 cidr_in cidr_out cidr_recv cidr_send - - - i m f 0 -1 0 _null_ _null_ )); DESCR("network IP address/netmask, network address"); #define CIDROID 650 /* OIDS 900 - 999 */ /* OIDS 1000 - 1099 */ -DATA(insert OID = 1000 ( _bool PGNSP PGUID -1 f b t \054 0 16 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ )); -DATA(insert OID = 1001 ( _bytea PGNSP PGUID -1 f b t \054 0 17 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ )); -DATA(insert OID = 1002 ( _char PGNSP PGUID -1 f b t \054 0 18 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ )); -DATA(insert OID = 1003 ( _name PGNSP PGUID -1 f b t \054 0 19 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ )); -DATA(insert OID = 1005 ( _int2 PGNSP PGUID -1 f b t \054 0 21 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ )); -DATA(insert OID = 1006 ( _int2vector PGNSP PGUID -1 f b t \054 0 22 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ )); -DATA(insert OID = 1007 ( _int4 PGNSP PGUID -1 f b t \054 0 23 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1000 ( _bool PGNSP PGUID -1 f b t \054 0 16 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1001 ( _bytea PGNSP PGUID -1 f b t \054 0 17 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1002 ( _char PGNSP PGUID -1 f b t \054 0 18 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1003 ( _name PGNSP PGUID -1 f b t \054 0 19 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1005 ( _int2 PGNSP PGUID -1 f b t \054 0 21 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1006 ( _int2vector PGNSP PGUID -1 f b t \054 0 22 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1007 ( _int4 PGNSP PGUID -1 f b t \054 0 23 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ )); #define INT4ARRAYOID 1007 -DATA(insert OID = 1008 ( _regproc PGNSP PGUID -1 f b t \054 0 24 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ )); -DATA(insert OID = 1009 ( _text PGNSP PGUID -1 f b t \054 0 25 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ )); -DATA(insert OID = 1028 ( _oid PGNSP PGUID -1 f b t \054 0 26 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ )); -DATA(insert OID = 1010 ( _tid PGNSP PGUID -1 f b t \054 0 27 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ )); -DATA(insert OID = 1011 ( _xid PGNSP PGUID -1 f b t \054 0 28 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ )); -DATA(insert OID = 1012 ( _cid PGNSP PGUID -1 f b t \054 0 29 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ )); -DATA(insert OID = 1013 ( _oidvector PGNSP PGUID -1 f b t \054 0 30 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ )); -DATA(insert OID = 1014 ( _bpchar PGNSP PGUID -1 f b t \054 0 1042 array_in array_out array_recv array_send bpchartypmodin bpchartypmodout - i x f 0 -1 0 _null_ _null_ )); -DATA(insert OID = 1015 ( _varchar PGNSP PGUID -1 f b t \054 0 1043 array_in array_out array_recv array_send varchartypmodin varchartypmodout - i x f 0 -1 0 _null_ _null_ )); -DATA(insert OID = 1016 ( _int8 PGNSP PGUID -1 f b t \054 0 20 array_in array_out array_recv array_send - - - d x f 0 -1 0 _null_ _null_ )); -DATA(insert OID = 1017 ( _point PGNSP PGUID -1 f b t \054 0 600 array_in array_out array_recv array_send - - - d x f 0 -1 0 _null_ _null_ )); -DATA(insert OID = 1018 ( _lseg PGNSP PGUID -1 f b t \054 0 601 array_in array_out array_recv array_send - - - d x f 0 -1 0 _null_ _null_ )); -DATA(insert OID = 1019 ( _path PGNSP PGUID -1 f b t \054 0 602 array_in array_out array_recv array_send - - - d x f 0 -1 0 _null_ _null_ )); -DATA(insert OID = 1020 ( _box PGNSP PGUID -1 f b t \073 0 603 array_in array_out array_recv array_send - - - d x f 0 -1 0 _null_ _null_ )); -DATA(insert OID = 1021 ( _float4 PGNSP PGUID -1 f b t \054 0 700 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1008 ( _regproc PGNSP PGUID -1 f b t \054 0 24 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1009 ( _text PGNSP PGUID -1 f b t \054 0 25 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1028 ( _oid PGNSP PGUID -1 f b t \054 0 26 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1010 ( _tid PGNSP PGUID -1 f b t \054 0 27 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1011 ( _xid PGNSP PGUID -1 f b t \054 0 28 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1012 ( _cid PGNSP PGUID -1 f b t \054 0 29 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1013 ( _oidvector PGNSP PGUID -1 f b t \054 0 30 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1014 ( _bpchar PGNSP PGUID -1 f b t \054 0 1042 0 array_in array_out array_recv array_send bpchartypmodin bpchartypmodout - i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1015 ( _varchar PGNSP PGUID -1 f b t \054 0 1043 0 array_in array_out array_recv array_send varchartypmodin varchartypmodout - i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1016 ( _int8 PGNSP PGUID -1 f b t \054 0 20 0 array_in array_out array_recv array_send - - - d x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1017 ( _point PGNSP PGUID -1 f b t \054 0 600 0 array_in array_out array_recv array_send - - - d x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1018 ( _lseg PGNSP PGUID -1 f b t \054 0 601 0 array_in array_out array_recv array_send - - - d x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1019 ( _path PGNSP PGUID -1 f b t \054 0 602 0 array_in array_out array_recv array_send - - - d x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1020 ( _box PGNSP PGUID -1 f b t \073 0 603 0 array_in array_out array_recv array_send - - - d x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1021 ( _float4 PGNSP PGUID -1 f b t \054 0 700 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ )); #define FLOAT4ARRAYOID 1021 -DATA(insert OID = 1022 ( _float8 PGNSP PGUID -1 f b t \054 0 701 array_in array_out array_recv array_send - - - d x f 0 -1 0 _null_ _null_ )); -DATA(insert OID = 1023 ( _abstime PGNSP PGUID -1 f b t \054 0 702 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ )); -DATA(insert OID = 1024 ( _reltime PGNSP PGUID -1 f b t \054 0 703 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ )); -DATA(insert OID = 1025 ( _tinterval PGNSP PGUID -1 f b t \054 0 704 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ )); -DATA(insert OID = 1027 ( _polygon PGNSP PGUID -1 f b t \054 0 604 array_in array_out array_recv array_send - - - d x f 0 -1 0 _null_ _null_ )); -DATA(insert OID = 1033 ( aclitem PGNSP PGUID 12 f b t \054 0 0 aclitemin aclitemout - - - - - i p f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1022 ( _float8 PGNSP PGUID -1 f b t \054 0 701 0 array_in array_out array_recv array_send - - - d x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1023 ( _abstime PGNSP PGUID -1 f b t \054 0 702 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1024 ( _reltime PGNSP PGUID -1 f b t \054 0 703 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1025 ( _tinterval PGNSP PGUID -1 f b t \054 0 704 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1027 ( _polygon PGNSP PGUID -1 f b t \054 0 604 0 array_in array_out array_recv array_send - - - d x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1033 ( aclitem PGNSP PGUID 12 f b t \054 0 0 1034 aclitemin aclitemout - - - - - i p f 0 -1 0 _null_ _null_ )); DESCR("access control list"); #define ACLITEMOID 1033 -DATA(insert OID = 1034 ( _aclitem PGNSP PGUID -1 f b t \054 0 1033 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ )); -DATA(insert OID = 1040 ( _macaddr PGNSP PGUID -1 f b t \054 0 829 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ )); -DATA(insert OID = 1041 ( _inet PGNSP PGUID -1 f b t \054 0 869 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ )); -DATA(insert OID = 651 ( _cidr PGNSP PGUID -1 f b t \054 0 650 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ )); -DATA(insert OID = 1042 ( bpchar PGNSP PGUID -1 f b t \054 0 0 bpcharin bpcharout bpcharrecv bpcharsend bpchartypmodin bpchartypmodout - i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1034 ( _aclitem PGNSP PGUID -1 f b t \054 0 1033 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1040 ( _macaddr PGNSP PGUID -1 f b t \054 0 829 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1041 ( _inet PGNSP PGUID -1 f b t \054 0 869 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 651 ( _cidr PGNSP PGUID -1 f b t \054 0 650 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1042 ( bpchar PGNSP PGUID -1 f b t \054 0 0 1014 bpcharin bpcharout bpcharrecv bpcharsend bpchartypmodin bpchartypmodout - i x f 0 -1 0 _null_ _null_ )); DESCR("char(length), blank-padded string, fixed storage length"); #define BPCHAROID 1042 -DATA(insert OID = 1043 ( varchar PGNSP PGUID -1 f b t \054 0 0 varcharin varcharout varcharrecv varcharsend varchartypmodin varchartypmodout - i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1043 ( varchar PGNSP PGUID -1 f b t \054 0 0 1015 varcharin varcharout varcharrecv varcharsend varchartypmodin varchartypmodout - i x f 0 -1 0 _null_ _null_ )); DESCR("varchar(length), non-blank-padded string, variable storage length"); #define VARCHAROID 1043 -DATA(insert OID = 1082 ( date PGNSP PGUID 4 t b t \054 0 0 date_in date_out date_recv date_send - - - i p f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1082 ( date PGNSP PGUID 4 t b t \054 0 0 1182 date_in date_out date_recv date_send - - - i p f 0 -1 0 _null_ _null_ )); DESCR("ANSI SQL date"); #define DATEOID 1082 -DATA(insert OID = 1083 ( time PGNSP PGUID 8 f b t \054 0 0 time_in time_out time_recv time_send timetypmodin timetypmodout - d p f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1083 ( time PGNSP PGUID 8 f b t \054 0 0 1183 time_in time_out time_recv time_send timetypmodin timetypmodout - d p f 0 -1 0 _null_ _null_ )); DESCR("hh:mm:ss, ANSI SQL time"); #define TIMEOID 1083 /* OIDS 1100 - 1199 */ -DATA(insert OID = 1114 ( timestamp PGNSP PGUID 8 f b t \054 0 0 timestamp_in timestamp_out timestamp_recv timestamp_send timestamptypmodin timestamptypmodout - d p f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1114 ( timestamp PGNSP PGUID 8 f b t \054 0 0 1115 timestamp_in timestamp_out timestamp_recv timestamp_send timestamptypmodin timestamptypmodout - d p f 0 -1 0 _null_ _null_ )); DESCR("date and time"); #define TIMESTAMPOID 1114 -DATA(insert OID = 1115 ( _timestamp PGNSP PGUID -1 f b t \054 0 1114 array_in array_out array_recv array_send timestamptypmodin timestamptypmodout - d x f 0 -1 0 _null_ _null_ )); -DATA(insert OID = 1182 ( _date PGNSP PGUID -1 f b t \054 0 1082 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ )); -DATA(insert OID = 1183 ( _time PGNSP PGUID -1 f b t \054 0 1083 array_in array_out array_recv array_send timetypmodin timetypmodout - d x f 0 -1 0 _null_ _null_ )); -DATA(insert OID = 1184 ( timestamptz PGNSP PGUID 8 f b t \054 0 0 timestamptz_in timestamptz_out timestamptz_recv timestamptz_send timestamptztypmodin timestamptztypmodout - d p f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1115 ( _timestamp PGNSP PGUID -1 f b t \054 0 1114 0 array_in array_out array_recv array_send timestamptypmodin timestamptypmodout - d x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1182 ( _date PGNSP PGUID -1 f b t \054 0 1082 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1183 ( _time PGNSP PGUID -1 f b t \054 0 1083 0 array_in array_out array_recv array_send timetypmodin timetypmodout - d x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1184 ( timestamptz PGNSP PGUID 8 f b t \054 0 0 1185 timestamptz_in timestamptz_out timestamptz_recv timestamptz_send timestamptztypmodin timestamptztypmodout - d p f 0 -1 0 _null_ _null_ )); DESCR("date and time with time zone"); #define TIMESTAMPTZOID 1184 -DATA(insert OID = 1185 ( _timestamptz PGNSP PGUID -1 f b t \054 0 1184 array_in array_out array_recv array_send timestamptztypmodin timestamptztypmodout - d x f 0 -1 0 _null_ _null_ )); -DATA(insert OID = 1186 ( interval PGNSP PGUID 16 f b t \054 0 0 interval_in interval_out interval_recv interval_send intervaltypmodin intervaltypmodout - d p f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1185 ( _timestamptz PGNSP PGUID -1 f b t \054 0 1184 0 array_in array_out array_recv array_send timestamptztypmodin timestamptztypmodout - d x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1186 ( interval PGNSP PGUID 16 f b t \054 0 0 1187 interval_in interval_out interval_recv interval_send intervaltypmodin intervaltypmodout - d p f 0 -1 0 _null_ _null_ )); DESCR("@ , time interval"); #define INTERVALOID 1186 -DATA(insert OID = 1187 ( _interval PGNSP PGUID -1 f b t \054 0 1186 array_in array_out array_recv array_send intervaltypmodin intervaltypmodout - d x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1187 ( _interval PGNSP PGUID -1 f b t \054 0 1186 0 array_in array_out array_recv array_send intervaltypmodin intervaltypmodout - d x f 0 -1 0 _null_ _null_ )); /* OIDS 1200 - 1299 */ -DATA(insert OID = 1231 ( _numeric PGNSP PGUID -1 f b t \054 0 1700 array_in array_out array_recv array_send numerictypmodin numerictypmodout - i x f 0 -1 0 _null_ _null_ )); -DATA(insert OID = 1266 ( timetz PGNSP PGUID 12 f b t \054 0 0 timetz_in timetz_out timetz_recv timetz_send timetztypmodin timetztypmodout - d p f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1231 ( _numeric PGNSP PGUID -1 f b t \054 0 1700 0 array_in array_out array_recv array_send numerictypmodin numerictypmodout - i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1266 ( timetz PGNSP PGUID 12 f b t \054 0 0 1270 timetz_in timetz_out timetz_recv timetz_send timetztypmodin timetztypmodout - d p f 0 -1 0 _null_ _null_ )); DESCR("hh:mm:ss, ANSI SQL time"); #define TIMETZOID 1266 -DATA(insert OID = 1270 ( _timetz PGNSP PGUID -1 f b t \054 0 1266 array_in array_out array_recv array_send timetztypmodin timetztypmodout - d x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1270 ( _timetz PGNSP PGUID -1 f b t \054 0 1266 0 array_in array_out array_recv array_send timetztypmodin timetztypmodout - d x f 0 -1 0 _null_ _null_ )); /* OIDS 1500 - 1599 */ -DATA(insert OID = 1560 ( bit PGNSP PGUID -1 f b t \054 0 0 bit_in bit_out bit_recv bit_send bittypmodin bittypmodout - i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1560 ( bit PGNSP PGUID -1 f b t \054 0 0 1561 bit_in bit_out bit_recv bit_send bittypmodin bittypmodout - i x f 0 -1 0 _null_ _null_ )); DESCR("fixed-length bit string"); #define BITOID 1560 -DATA(insert OID = 1561 ( _bit PGNSP PGUID -1 f b t \054 0 1560 array_in array_out array_recv array_send bittypmodin bittypmodout - i x f 0 -1 0 _null_ _null_ )); -DATA(insert OID = 1562 ( varbit PGNSP PGUID -1 f b t \054 0 0 varbit_in varbit_out varbit_recv varbit_send varbittypmodin varbittypmodout - i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1561 ( _bit PGNSP PGUID -1 f b t \054 0 1560 0 array_in array_out array_recv array_send bittypmodin bittypmodout - i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1562 ( varbit PGNSP PGUID -1 f b t \054 0 0 1563 varbit_in varbit_out varbit_recv varbit_send varbittypmodin varbittypmodout - i x f 0 -1 0 _null_ _null_ )); DESCR("variable-length bit string"); #define VARBITOID 1562 -DATA(insert OID = 1563 ( _varbit PGNSP PGUID -1 f b t \054 0 1562 array_in array_out array_recv array_send varbittypmodin varbittypmodout - i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1563 ( _varbit PGNSP PGUID -1 f b t \054 0 1562 0 array_in array_out array_recv array_send varbittypmodin varbittypmodout - i x f 0 -1 0 _null_ _null_ )); /* OIDS 1600 - 1699 */ /* OIDS 1700 - 1799 */ -DATA(insert OID = 1700 ( numeric PGNSP PGUID -1 f b t \054 0 0 numeric_in numeric_out numeric_recv numeric_send numerictypmodin numerictypmodout - i m f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1700 ( numeric PGNSP PGUID -1 f b t \054 0 0 1231 numeric_in numeric_out numeric_recv numeric_send numerictypmodin numerictypmodout - i m f 0 -1 0 _null_ _null_ )); DESCR("numeric(precision, decimal), arbitrary precision number"); #define NUMERICOID 1700 -DATA(insert OID = 1790 ( refcursor PGNSP PGUID -1 f b t \054 0 0 textin textout textrecv textsend - - - i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1790 ( refcursor PGNSP PGUID -1 f b t \054 0 0 2201 textin textout textrecv textsend - - - i x f 0 -1 0 _null_ _null_ )); DESCR("reference cursor (portal name)"); #define REFCURSOROID 1790 /* OIDS 2200 - 2299 */ -DATA(insert OID = 2201 ( _refcursor PGNSP PGUID -1 f b t \054 0 1790 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 2201 ( _refcursor PGNSP PGUID -1 f b t \054 0 1790 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ )); -DATA(insert OID = 2202 ( regprocedure PGNSP PGUID 4 t b t \054 0 0 regprocedurein regprocedureout regprocedurerecv regproceduresend - - - i p f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 2202 ( regprocedure PGNSP PGUID 4 t b t \054 0 0 2207 regprocedurein regprocedureout regprocedurerecv regproceduresend - - - i p f 0 -1 0 _null_ _null_ )); DESCR("registered procedure (with args)"); #define REGPROCEDUREOID 2202 -DATA(insert OID = 2203 ( regoper PGNSP PGUID 4 t b t \054 0 0 regoperin regoperout regoperrecv regopersend - - - i p f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 2203 ( regoper PGNSP PGUID 4 t b t \054 0 0 2208 regoperin regoperout regoperrecv regopersend - - - i p f 0 -1 0 _null_ _null_ )); DESCR("registered operator"); #define REGOPEROID 2203 -DATA(insert OID = 2204 ( regoperator PGNSP PGUID 4 t b t \054 0 0 regoperatorin regoperatorout regoperatorrecv regoperatorsend - - - i p f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 2204 ( regoperator PGNSP PGUID 4 t b t \054 0 0 2209 regoperatorin regoperatorout regoperatorrecv regoperatorsend - - - i p f 0 -1 0 _null_ _null_ )); DESCR("registered operator (with args)"); #define REGOPERATOROID 2204 -DATA(insert OID = 2205 ( regclass PGNSP PGUID 4 t b t \054 0 0 regclassin regclassout regclassrecv regclasssend - - - i p f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 2205 ( regclass PGNSP PGUID 4 t b t \054 0 0 2210 regclassin regclassout regclassrecv regclasssend - - - i p f 0 -1 0 _null_ _null_ )); DESCR("registered class"); #define REGCLASSOID 2205 -DATA(insert OID = 2206 ( regtype PGNSP PGUID 4 t b t \054 0 0 regtypein regtypeout regtyperecv regtypesend - - - i p f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 2206 ( regtype PGNSP PGUID 4 t b t \054 0 0 2211 regtypein regtypeout regtyperecv regtypesend - - - i p f 0 -1 0 _null_ _null_ )); DESCR("registered type"); #define REGTYPEOID 2206 -DATA(insert OID = 2207 ( _regprocedure PGNSP PGUID -1 f b t \054 0 2202 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ )); -DATA(insert OID = 2208 ( _regoper PGNSP PGUID -1 f b t \054 0 2203 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ )); -DATA(insert OID = 2209 ( _regoperator PGNSP PGUID -1 f b t \054 0 2204 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ )); -DATA(insert OID = 2210 ( _regclass PGNSP PGUID -1 f b t \054 0 2205 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ )); -DATA(insert OID = 2211 ( _regtype PGNSP PGUID -1 f b t \054 0 2206 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 2207 ( _regprocedure PGNSP PGUID -1 f b t \054 0 2202 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 2208 ( _regoper PGNSP PGUID -1 f b t \054 0 2203 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 2209 ( _regoperator PGNSP PGUID -1 f b t \054 0 2204 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 2210 ( _regclass PGNSP PGUID -1 f b t \054 0 2205 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 2211 ( _regtype PGNSP PGUID -1 f b t \054 0 2206 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ )); #define REGTYPEARRAYOID 2211 /* uuid */ -DATA(insert OID = 2950 ( uuid PGNSP PGUID 16 f b t \054 0 0 uuid_in uuid_out uuid_recv uuid_send - - - c p f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 2950 ( uuid PGNSP PGUID 16 f b t \054 0 0 2951 uuid_in uuid_out uuid_recv uuid_send - - - c p f 0 -1 0 _null_ _null_ )); DESCR("UUID datatype"); -DATA(insert OID = 2951 ( _uuid PGNSP PGUID -1 f b t \054 0 2950 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 2951 ( _uuid PGNSP PGUID -1 f b t \054 0 2950 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 _null_ _null_ )); /* * pseudo-types @@ -548,27 +555,27 @@ DATA(insert OID = 2951 ( _uuid PGNSP PGUID -1 f b t \054 0 2950 array_in array * argument and result types (if supported by the function's implementation * language). */ -DATA(insert OID = 2249 ( record PGNSP PGUID -1 f p t \054 0 0 record_in record_out record_recv record_send - - - d x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 2249 ( record PGNSP PGUID -1 f p t \054 0 0 0 record_in record_out record_recv record_send - - - d x f 0 -1 0 _null_ _null_ )); #define RECORDOID 2249 -DATA(insert OID = 2275 ( cstring PGNSP PGUID -2 f p t \054 0 0 cstring_in cstring_out cstring_recv cstring_send - - - c p f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 2275 ( cstring PGNSP PGUID -2 f p t \054 0 0 0 cstring_in cstring_out cstring_recv cstring_send - - - c p f 0 -1 0 _null_ _null_ )); #define CSTRINGOID 2275 -DATA(insert OID = 2276 ( any PGNSP PGUID 4 t p t \054 0 0 any_in any_out - - - - - i p f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 2276 ( any PGNSP PGUID 4 t p t \054 0 0 0 any_in any_out - - - - - i p f 0 -1 0 _null_ _null_ )); #define ANYOID 2276 -DATA(insert OID = 2277 ( anyarray PGNSP PGUID -1 f p t \054 0 0 anyarray_in anyarray_out anyarray_recv anyarray_send - - - d x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 2277 ( anyarray PGNSP PGUID -1 f p t \054 0 0 0 anyarray_in anyarray_out anyarray_recv anyarray_send - - - d x f 0 -1 0 _null_ _null_ )); #define ANYARRAYOID 2277 -DATA(insert OID = 2278 ( void PGNSP PGUID 4 t p t \054 0 0 void_in void_out - - - - - i p f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 2278 ( void PGNSP PGUID 4 t p t \054 0 0 0 void_in void_out - - - - - i p f 0 -1 0 _null_ _null_ )); #define VOIDOID 2278 -DATA(insert OID = 2279 ( trigger PGNSP PGUID 4 t p t \054 0 0 trigger_in trigger_out - - - - - i p f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 2279 ( trigger PGNSP PGUID 4 t p t \054 0 0 0 trigger_in trigger_out - - - - - i p f 0 -1 0 _null_ _null_ )); #define TRIGGEROID 2279 -DATA(insert OID = 2280 ( language_handler PGNSP PGUID 4 t p t \054 0 0 language_handler_in language_handler_out - - - - - i p f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 2280 ( language_handler PGNSP PGUID 4 t p t \054 0 0 0 language_handler_in language_handler_out - - - - - i p f 0 -1 0 _null_ _null_ )); #define LANGUAGE_HANDLEROID 2280 -DATA(insert OID = 2281 ( internal PGNSP PGUID 4 t p t \054 0 0 internal_in internal_out - - - - - i p f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 2281 ( internal PGNSP PGUID 4 t p t \054 0 0 0 internal_in internal_out - - - - - i p f 0 -1 0 _null_ _null_ )); #define INTERNALOID 2281 -DATA(insert OID = 2282 ( opaque PGNSP PGUID 4 t p t \054 0 0 opaque_in opaque_out - - - - - i p f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 2282 ( opaque PGNSP PGUID 4 t p t \054 0 0 0 opaque_in opaque_out - - - - - i p f 0 -1 0 _null_ _null_ )); #define OPAQUEOID 2282 -DATA(insert OID = 2283 ( anyelement PGNSP PGUID 4 t p t \054 0 0 anyelement_in anyelement_out - - - - - i p f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 2283 ( anyelement PGNSP PGUID 4 t p t \054 0 0 0 anyelement_in anyelement_out - - - - - i p f 0 -1 0 _null_ _null_ )); #define ANYELEMENTOID 2283 -DATA(insert OID = 3500 ( anyenum PGNSP PGUID 4 t p t \054 0 0 anyenum_in anyenum_out - - - - - i p f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 3500 ( anyenum PGNSP PGUID 4 t p t \054 0 0 0 anyenum_in anyenum_out - - - - - i p f 0 -1 0 _null_ _null_ )); #define ANYENUMOID 3500 @@ -592,7 +599,8 @@ DATA(insert OID = 3500 ( anyenum PGNSP PGUID 4 t p t \054 0 0 anyenum_in anyen */ extern Oid TypeShellMake(const char *typeName, Oid typeNamespace); -extern Oid TypeCreate(const char *typeName, +extern Oid TypeCreate(Oid newTypeOid, + const char *typeName, Oid typeNamespace, Oid relationOid, char relationKind, @@ -607,6 +615,8 @@ extern Oid TypeCreate(const char *typeName, Oid typmodoutProcedure, Oid analyzeProcedure, Oid elementType, + bool isImplicitArray, + Oid arrayType, Oid baseType, const char *defaultTypeValue, char *defaultTypeBin, @@ -630,6 +640,7 @@ extern void GenerateTypeDependencies(Oid typeNamespace, Oid typmodoutProcedure, Oid analyzeProcedure, Oid elementType, + bool isImplicitArray, Oid baseType, Node *defaultExpr, bool rebuild); @@ -637,6 +648,6 @@ extern void GenerateTypeDependencies(Oid typeNamespace, extern void TypeRename(const char *oldTypeName, Oid typeNamespace, const char *newTypeName); -extern char *makeArrayTypeName(const char *typeName); +extern char *makeArrayTypeName(const char *typeName, Oid typeNamespace); #endif /* PG_TYPE_H */ diff --git a/src/include/commands/typecmds.h b/src/include/commands/typecmds.h index 91e56e12cb..de0c6aea93 100644 --- a/src/include/commands/typecmds.h +++ b/src/include/commands/typecmds.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/commands/typecmds.h,v 1.18 2007/04/02 03:49:41 tgl Exp $ + * $PostgreSQL: pgsql/src/include/commands/typecmds.h,v 1.19 2007/05/11 17:57:14 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -36,9 +36,11 @@ extern void AlterDomainDropConstraint(List *names, const char *constrName, extern List *GetDomainConstraints(Oid typeOid); extern void AlterTypeOwner(List *names, Oid newOwnerId); -extern void AlterTypeOwnerInternal(Oid typeOid, Oid newOwnerId); +extern void AlterTypeOwnerInternal(Oid typeOid, Oid newOwnerId, + bool hasDependEntry); extern void AlterTypeNamespace(List *names, const char *newschema); extern void AlterTypeNamespaceInternal(Oid typeOid, Oid nspOid, - bool errorOnTableType); + bool isImplicitArray, + bool errorOnTableType); #endif /* TYPECMDS_H */ diff --git a/src/test/regress/expected/alter_table.out b/src/test/regress/expected/alter_table.out index 11b8c24c3d..99f0c0b049 100644 --- a/src/test/regress/expected/alter_table.out +++ b/src/test/regress/expected/alter_table.out @@ -1456,7 +1456,6 @@ select alter2.plus1(41); -- clean up drop schema alter2 cascade; -NOTICE: drop cascades to composite type alter2.ctype NOTICE: drop cascades to type alter2.ctype NOTICE: drop cascades to type alter2.posint NOTICE: drop cascades to function alter2.plus1(integer) diff --git a/src/test/regress/expected/oidjoins.out b/src/test/regress/expected/oidjoins.out index 5945753a1b..b7ad2b813c 100644 --- a/src/test/regress/expected/oidjoins.out +++ b/src/test/regress/expected/oidjoins.out @@ -409,6 +409,14 @@ WHERE indrelid != 0 AND ------+---------- (0 rows) +SELECT ctid, lanowner +FROM pg_catalog.pg_language fk +WHERE lanowner != 0 AND + NOT EXISTS(SELECT 1 FROM pg_catalog.pg_authid pk WHERE pk.oid = fk.lanowner); + ctid | lanowner +------+---------- +(0 rows) + SELECT ctid, lanvalidator FROM pg_catalog.pg_language fk WHERE lanvalidator != 0 AND @@ -721,6 +729,14 @@ WHERE typelem != 0 AND ------+--------- (0 rows) +SELECT ctid, typarray +FROM pg_catalog.pg_type fk +WHERE typarray != 0 AND + NOT EXISTS(SELECT 1 FROM pg_catalog.pg_type pk WHERE pk.oid = fk.typarray); + ctid | typarray +------+---------- +(0 rows) + SELECT ctid, typinput FROM pg_catalog.pg_type fk WHERE typinput != 0 AND diff --git a/src/test/regress/expected/type_sanity.out b/src/test/regress/expected/type_sanity.out index b2db870da4..702cf7eecf 100644 --- a/src/test/regress/expected/type_sanity.out +++ b/src/test/regress/expected/type_sanity.out @@ -69,6 +69,16 @@ WHERE p1.typtype in ('b','e') AND p1.typname NOT LIKE E'\\_%' AND NOT EXISTS 705 | unknown (2 rows) +-- Make sure typarray points to a varlena array type of our own base +SELECT p1.oid, p1.typname as basetype, p2.typname as arraytype, + p2.typelem, p2.typlen +FROM pg_type p1 LEFT JOIN pg_type p2 ON (p1.typarray = p2.oid) +WHERE p1.typarray <> 0 AND + (p2.oid IS NULL OR p2.typelem <> p1.oid OR p2.typlen <> -1); + oid | basetype | arraytype | typelem | typlen +-----+----------+-----------+---------+-------- +(0 rows) + -- Text conversion routines must be provided. SELECT p1.oid, p1.typname FROM pg_type as p1 diff --git a/src/test/regress/sql/oidjoins.sql b/src/test/regress/sql/oidjoins.sql index 5eb440f0f5..7d2dd3dd1f 100644 --- a/src/test/regress/sql/oidjoins.sql +++ b/src/test/regress/sql/oidjoins.sql @@ -205,6 +205,10 @@ SELECT ctid, indrelid FROM pg_catalog.pg_index fk WHERE indrelid != 0 AND NOT EXISTS(SELECT 1 FROM pg_catalog.pg_class pk WHERE pk.oid = fk.indrelid); +SELECT ctid, lanowner +FROM pg_catalog.pg_language fk +WHERE lanowner != 0 AND + NOT EXISTS(SELECT 1 FROM pg_catalog.pg_authid pk WHERE pk.oid = fk.lanowner); SELECT ctid, lanvalidator FROM pg_catalog.pg_language fk WHERE lanvalidator != 0 AND @@ -361,6 +365,10 @@ SELECT ctid, typelem FROM pg_catalog.pg_type fk WHERE typelem != 0 AND NOT EXISTS(SELECT 1 FROM pg_catalog.pg_type pk WHERE pk.oid = fk.typelem); +SELECT ctid, typarray +FROM pg_catalog.pg_type fk +WHERE typarray != 0 AND + NOT EXISTS(SELECT 1 FROM pg_catalog.pg_type pk WHERE pk.oid = fk.typarray); SELECT ctid, typinput FROM pg_catalog.pg_type fk WHERE typinput != 0 AND diff --git a/src/test/regress/sql/type_sanity.sql b/src/test/regress/sql/type_sanity.sql index b1caa33efb..e549fd7489 100644 --- a/src/test/regress/sql/type_sanity.sql +++ b/src/test/regress/sql/type_sanity.sql @@ -59,6 +59,13 @@ WHERE p1.typtype in ('b','e') AND p1.typname NOT LIKE E'\\_%' AND NOT EXISTS WHERE p2.typname = ('_' || p1.typname)::name AND p2.typelem = p1.oid); +-- Make sure typarray points to a varlena array type of our own base +SELECT p1.oid, p1.typname as basetype, p2.typname as arraytype, + p2.typelem, p2.typlen +FROM pg_type p1 LEFT JOIN pg_type p2 ON (p1.typarray = p2.oid) +WHERE p1.typarray <> 0 AND + (p2.oid IS NULL OR p2.typelem <> p1.oid OR p2.typlen <> -1); + -- Text conversion routines must be provided. SELECT p1.oid, p1.typname diff --git a/src/tools/findoidjoins/README b/src/tools/findoidjoins/README index 598aab2bbd..be4613eaf3 100644 --- a/src/tools/findoidjoins/README +++ b/src/tools/findoidjoins/README @@ -1,3 +1,4 @@ +$PostgreSQL: pgsql/src/tools/findoidjoins/README,v 1.4 2007/05/11 17:57:14 tgl Exp $ findoidjoins @@ -87,6 +88,7 @@ Join pg_catalog.pg_depend.refclassid => pg_catalog.pg_class.oid Join pg_catalog.pg_description.classoid => pg_catalog.pg_class.oid Join pg_catalog.pg_index.indexrelid => pg_catalog.pg_class.oid Join pg_catalog.pg_index.indrelid => pg_catalog.pg_class.oid +Join pg_catalog.pg_language.lanowner => pg_catalog.pg_authid.oid Join pg_catalog.pg_language.lanvalidator => pg_catalog.pg_proc.oid Join pg_catalog.pg_namespace.nspowner => pg_catalog.pg_authid.oid Join pg_catalog.pg_opclass.opcmethod => pg_catalog.pg_am.oid @@ -126,6 +128,7 @@ Join pg_catalog.pg_type.typnamespace => pg_catalog.pg_namespace.oid Join pg_catalog.pg_type.typowner => pg_catalog.pg_authid.oid Join pg_catalog.pg_type.typrelid => pg_catalog.pg_class.oid Join pg_catalog.pg_type.typelem => pg_catalog.pg_type.oid +Join pg_catalog.pg_type.typarray => pg_catalog.pg_type.oid Join pg_catalog.pg_type.typinput => pg_catalog.pg_proc.oid Join pg_catalog.pg_type.typoutput => pg_catalog.pg_proc.oid Join pg_catalog.pg_type.typreceive => pg_catalog.pg_proc.oid