From: Tom Lane Date: Wed, 20 Mar 2002 19:45:13 +0000 (+0000) Subject: Code review for DOMAIN patch. X-Git-Tag: REL7_3~1861 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=337b22cb473f1c5cca011a511c488d20e153eec4;p=postgresql Code review for DOMAIN patch. --- diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml index 451c9dcaa8..5db408f6d0 100644 --- a/doc/src/sgml/catalogs.sgml +++ b/doc/src/sgml/catalogs.sgml @@ -1,6 +1,6 @@ @@ -2274,7 +2274,8 @@ This catalog stores information about datatypes. Scalar types (base types) are created with CREATE TYPE. A complex type is also created for each table in the database, to - represent the row structure of the table. + represent the row structure of the table. It is also possible to create + derived types with CREATE DOMAIN. @@ -2345,11 +2346,10 @@ typtype is b for - a base type and c for a complex type (i.e., - a table's row type). If typtype is - c, typrelid is - the OID of the type's entry in - pg_class. + a base type, c for a complex type (i.e., + a table's row type), or d for a derived type (i.e., + a domain). See also typrelid + and typbasetype. @@ -2382,6 +2382,7 @@ the pg_class entry that defines the corresponding table. A table could theoretically be used as a composite data type, but this is not fully functional. + Zero for non-complex types. @@ -2511,38 +2512,53 @@ - typbasetype - oid + typnotnull + bool - typbasetype is the type that this one is based - on. Normally references the domains parent type, and is 0 otherwise. + typnotnull represents a NOT NULL + constraint on a type. Presently used for domains only. - - typnotnull - boolean - - - typnotnull represents a NOT NULL - constraint on a type. Used for domains only. - - + + typbasetype + oid + pg_type.oid + + If this is a derived type (see typtype), + then typbasetype identifies + the type that this one is based on. Zero if not a derived type. + + - typmod - integer + typtypmod + int4 - typmod records type-specific data + typtypmod records type-specific data supplied at table creation time (for example, the maximum length of a varchar column). It is passed to type-specific input and output functions as the third argument. The value will generally be -1 for types that do not - need typmod. This data is copied to - pg_attribute.atttypmod on creation - of a table using a domain as it's field type. + need typmod. This value is copied to + pg_attribute.atttypmod when + creating a column of a domain type. + + + + + typndims + int4 + + + typndims is the number of array dimensions + for a domain that is an array. (The array element type is + typbasetype.) Zero for non-domains and non-array domains. + This value is copied to + pg_attribute.attndims when + creating a column of a domain type. @@ -2551,9 +2567,9 @@ text - typdefaultbin is NULL for types without a - default value. If it's not NULL, it contains the internal string - representation of the default expression node. + If typdefaultbin is not NULL, it is the nodeToString + representation of a default expression for the type. Currently this is + only used for domains. @@ -2562,9 +2578,14 @@ text - typdefault is NULL for types without a - default value. If it's not NULL, it contains the external string - representation of the type's default value. + typdefault is NULL if the type has no associated + default value. If typdefaultbin is not NULL, + typdefault must contain a human-readable version of the + default expression represented by typdefaultbin. If + typdefaultbin is NULL and typdefault is + not, then typdefault is the external representation of + the type's default value, which may be fed to the type's input + converter to produce a constant. diff --git a/doc/src/sgml/ref/create_domain.sgml b/doc/src/sgml/ref/create_domain.sgml index 5f79dc63b5..222d49da5d 100644 --- a/doc/src/sgml/ref/create_domain.sgml +++ b/doc/src/sgml/ref/create_domain.sgml @@ -1,5 +1,5 @@ @@ -23,13 +23,14 @@ PostgreSQL documentation 2002-02-24 -CREATE DOMAIN domainname data_type [ DEFAULT default_expr ] [ column_constraint [, ... ] ] +CREATE DOMAIN domainname [AS] data_type + [ DEFAULT default_expr ] + [ constraint [, ... ] ] + +where constraint is: + [ CONSTRAINT constraint_name ] -{ NOT NULL | NULL } - +{ NOT NULL | NULL } @@ -67,23 +68,26 @@ CREATE DOMAIN domainname default_expr - The DEFAULT clause assigns a default data value for - the column whose column definition it appears within. The value - is any variable-free expression (subselects and cross-references - to other columns in the current table are not allowed). The + The DEFAULT clause specifies a default value for + columns of the domain data type. The value + is any variable-free expression (but subselects are not allowed). + The data type of the default expression must match the data type of the domain. The default expression will be used in any insert operation that - does not specify a value for the domain. If there is no default + does not specify a value for the column. If there is no default for a domain, then the default is NULL. - The default of a column will be tested before that of the domain. + If a default value is specified for a particular column, it + overrides any default associated with the domain. In turn, + the domain default overrides any default value associated with + the underlying data type. @@ -93,7 +97,7 @@ CREATE DOMAIN domainname CONSTRAINT constraint_name - An optional name for a domain. If not specified, + An optional name for a constraint. If not specified, the system generates a name. @@ -103,7 +107,7 @@ CREATE DOMAIN domainname NOT NULL - The column is not allowed to contain NULL values. This is + Values of this domain are not allowed to be NULL. This is equivalent to the column constraint CHECK (column NOT NULL). @@ -114,7 +118,7 @@ CREATE DOMAIN domainname NULL - The column is allowed to contain NULL values. This is the default. + Values of this domain are allowed to be NULL. This is the default. @@ -175,7 +179,7 @@ CREATE DOMAIN Domains are useful for abstracting common fields between tables into a single location for maintenance. An email address column may be used in several tables, all with the same properties. Define a domain and - use that rather than setting up each tables constraints individually. + use that rather than setting up each table's constraints individually. @@ -195,9 +199,9 @@ CREATE TABLE countrylist (id INT4, country country_code); Compatibility - This CREATE DOMAIN command is a - PostgreSQL extension. CHECK and FOREIGN KEY - constraints are currently unsupported. + SQL99 defines CREATE DOMAIN, but says that the only allowed constraint + type is CHECK constraints. CHECK constraints for domains are not yet + supported by PostgreSQL. diff --git a/doc/src/sgml/ref/drop_domain.sgml b/doc/src/sgml/ref/drop_domain.sgml index e9bc38ad28..63eb0dc057 100644 --- a/doc/src/sgml/ref/drop_domain.sgml +++ b/doc/src/sgml/ref/drop_domain.sgml @@ -1,5 +1,5 @@ @@ -23,7 +23,7 @@ PostgreSQL documentation 1999-07-20 -DROP DOMAIN domainname [, ...] +DROP DOMAIN domainname [, ...] [ CASCADE | RESTRICT ] @@ -43,6 +43,25 @@ DROP DOMAIN domainname [, ...] + + + CASCADE + + + Automatically drop objects that depend on the domain. This + behavior is not currently supported. + + + + + + RESTRICT + + + Do not drop dependent objects. This is the default. + + + @@ -117,7 +136,7 @@ ERROR: RemoveDomain: type 'domainnamebox domain: -DROP DOMAIN box RESTRICT; +DROP DOMAIN box; @@ -134,9 +153,8 @@ DROP DOMAIN box RESTRICT; DROP DOMAIN name { CASCADE | RESTRICT } - PostgreSQL enforces the existance of - RESTRICT or CASCADE but ignores their enforcement against the - system tables. + PostgreSQL accepts only the RESTRICT + option, and currently does not check for existence of dependent objects. diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml index 350128fa72..40ba18716c 100644 --- a/doc/src/sgml/ref/psql-ref.sgml +++ b/doc/src/sgml/ref/psql-ref.sgml @@ -1,5 +1,5 @@ @@ -419,21 +419,10 @@ testdb=> \dD [ pattern ] - Lists all database domains. - - - - Descriptions for objects can be generated with the COMMENT ON - SQL command. - - - - - PostgreSQL stores the object descriptions in the - pg_description system table. + Lists all available domains (derived types). + If pattern + (a regular expression) is specified, only matching domains are shown. - - diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index b2359e4725..e7bb128076 100644 --- a/src/backend/catalog/heap.c +++ b/src/backend/catalog/heap.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.188 2002/03/19 02:58:19 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.189 2002/03/20 19:43:34 tgl Exp $ * * * INTERFACE ROUTINES @@ -705,7 +705,7 @@ AddNewRelationType(char *typeName, Oid new_rel_oid, Oid new_type_oid) true, /* passed by value */ 'i', /* default alignment - same as for OID */ 'p', /* Not TOASTable */ - -1, /* Type mod length */ + -1, /* typmod */ 0, /* array dimensions for typBaseType */ false); /* Type NOT NULL */ } @@ -1589,10 +1589,7 @@ AddRelationRawConstraints(Relation rel, RangeTblEntry *rte; int numchecks; List *listptr; - - /* Probably shouldn't be null by default */ - Node *expr = NULL; - + Node *expr; /* * Get info about existing constraints. @@ -1624,17 +1621,11 @@ AddRelationRawConstraints(Relation rel, foreach(listptr, rawColDefaults) { RawColumnDefault *colDef = (RawColumnDefault *) lfirst(listptr); - - Form_pg_attribute atp = rel->rd_att->attrs[colDef->attnum - 1]; - expr = cookDefault(pstate, colDef->raw_default - , atp->atttypid, atp->atttypmod - , NameStr(atp->attname)); - - /* - * OK, store it. - */ + expr = cookDefault(pstate, colDef->raw_default, + atp->atttypid, atp->atttypmod, + NameStr(atp->attname)); StoreAttrDefault(rel, colDef->attnum, nodeToString(expr)); } @@ -1646,7 +1637,6 @@ AddRelationRawConstraints(Relation rel, { Constraint *cdef = (Constraint *) lfirst(listptr); char *ccname; - Node *expr; if (cdef->contype != CONSTR_CHECK || cdef->raw_expr == NULL) continue; @@ -1851,17 +1841,21 @@ SetRelationNumChecks(Relation rel, int numchecks) * Take a raw default and convert it to a cooked format ready for * storage. * - * Parse state, attypid, attypmod and attname are required for - * CoerceTargetExpr() and more importantly transformExpr(). + * Parse state should be set up to recognize any vars that might appear + * in the expression. (Even though we plan to reject vars, it's more + * user-friendly to give the correct error message than "unknown var".) + * + * If atttypid is not InvalidOid, check that the expression is coercible + * to the specified type. atttypmod is needed in this case, and attname + * is used in the error message if any. */ Node * cookDefault(ParseState *pstate, Node *raw_default, Oid atttypid, int32 atttypmod, - char *attname) { - - Oid type_id; + char *attname) +{ Node *expr; Assert(raw_default != NULL); @@ -1896,22 +1890,20 @@ cookDefault(ParseState *pstate, * will actually do the coercion, to ensure we don't accept an * unusable default expression. */ - type_id = exprType(expr); - if (type_id != InvalidOid && atttypid != InvalidOid) { - if (type_id != atttypid) { + if (OidIsValid(atttypid)) + { + Oid type_id = exprType(expr); - /* Try coercing to the base type of the domain if available */ + if (type_id != atttypid) + { if (CoerceTargetExpr(pstate, expr, type_id, - getBaseType(atttypid), - atttypmod) == NULL) { - + atttypid, atttypmod) == NULL) elog(ERROR, "Column \"%s\" is of type %s" - " but default expression is of type %s" - "\n\tYou will need to rewrite or cast the expression", + " but default expression is of type %s" + "\n\tYou will need to rewrite or cast the expression", attname, format_type_be(atttypid), format_type_be(type_id)); - } } } diff --git a/src/backend/catalog/pg_aggregate.c b/src/backend/catalog/pg_aggregate.c index f037852bb5..8de1a52c3f 100644 --- a/src/backend/catalog/pg_aggregate.c +++ b/src/backend/catalog/pg_aggregate.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/pg_aggregate.c,v 1.40 2001/10/25 05:49:23 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/pg_aggregate.c,v 1.41 2002/03/20 19:43:35 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -135,14 +135,13 @@ AggregateCreate(char *aggName, /* * If the transfn is strict and the initval is NULL, make sure input - * type and transtype are the same (or at least binary- compatible), + * type and transtype are the same (or at least binary-compatible), * so that it's OK to use the first input value as the initial * transValue. */ if (proc->proisstrict && agginitval == NULL) { - if (basetype != transtype && - !IS_BINARY_COMPATIBLE(basetype, transtype)) + if (!IsBinaryCompatible(basetype, transtype)) elog(ERROR, "must not omit initval when transfn is strict and transtype is not compatible with input type"); } ReleaseSysCache(tup); diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c index 2c398bc036..78041ac585 100644 --- a/src/backend/catalog/pg_proc.c +++ b/src/backend/catalog/pg_proc.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.65 2002/03/06 06:09:26 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.66 2002/03/20 19:43:36 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -423,7 +423,7 @@ checkretval(Oid rettype, List *queryTreeList) format_type_be(rettype)); restype = ((TargetEntry *) lfirst(tlist))->resdom->restype; - if (restype != rettype && !IS_BINARY_COMPATIBLE(restype, rettype)) + if (!IsBinaryCompatible(restype, rettype)) elog(ERROR, "return type mismatch in function: declared to return %s, returns %s", format_type_be(rettype), format_type_be(restype)); @@ -440,7 +440,7 @@ checkretval(Oid rettype, List *queryTreeList) if (tlistlen == 1) { restype = ((TargetEntry *) lfirst(tlist))->resdom->restype; - if (restype == rettype || IS_BINARY_COMPATIBLE(restype, rettype)) + if (IsBinaryCompatible(restype, rettype)) return; } @@ -470,7 +470,7 @@ checkretval(Oid rettype, List *queryTreeList) continue; tletype = exprType(tle->expr); atttype = reln->rd_att->attrs[i]->atttypid; - if (tletype != atttype && !IS_BINARY_COMPATIBLE(tletype, atttype)) + if (!IsBinaryCompatible(tletype, atttype)) elog(ERROR, "function declared to return %s returns %s instead of %s at column %d", format_type_be(rettype), format_type_be(tletype), diff --git a/src/backend/catalog/pg_type.c b/src/backend/catalog/pg_type.c index 3516466919..6878691241 100644 --- a/src/backend/catalog/pg_type.c +++ b/src/backend/catalog/pg_type.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.68 2002/03/19 02:18:14 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.69 2002/03/20 19:43:38 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -179,13 +179,11 @@ TypeShellMakeWithOpenRelation(Relation pg_type_desc, char *typeName) values[i++] = CharGetDatum('i'); /* 15 */ values[i++] = CharGetDatum('p'); /* 16 */ values[i++] = BoolGetDatum(false); /* 17 */ - values[i++] = Int32GetDatum(-1); /* 18 */ - values[i++] = ObjectIdGetDatum(InvalidOid); /* 19 */ + values[i++] = ObjectIdGetDatum(InvalidOid); /* 18 */ + values[i++] = Int32GetDatum(-1); /* 19 */ values[i++] = Int32GetDatum(0); /* 20 */ - values[i++] = DirectFunctionCall1(textin, - CStringGetDatum(typeName)); /* 21 */ - values[i++] = DirectFunctionCall1(textin, - CStringGetDatum(typeName)); /* 22 */ + nulls[i++] = 'n'; /* 21 */ + nulls[i++] = 'n'; /* 22 */ /* * create a new type tuple with FormHeapTuple @@ -288,7 +286,7 @@ TypeCreate(char *typeName, char storage, int32 typeMod, int32 typNDims, /* Array dimensions for baseTypeName */ - bool typeNotNull) /* binary default representation (cooked) */ + bool typeNotNull) { int i, j; @@ -452,21 +450,10 @@ TypeCreate(char *typeName, */ values[i++] = CharGetDatum(storage); /* 16 */ - /* - * set the typenotnull value - */ - values[i++] = BoolGetDatum(typeNotNull); /* 17 */ - - /* - * set the typemod value - */ - values[i++] = Int32GetDatum(typeMod); /* 18 */ - - values[i++] = ObjectIdGetDatum(baseObjectId); /* 19 */ - - /* - * Dimension number for an array base type - */ + /* set typnotnull, typbasetype, typtypmod, typndims */ + values[i++] = BoolGetDatum(typeNotNull); /* 17 */ + values[i++] = ObjectIdGetDatum(baseObjectId); /* 18 */ + values[i++] = Int32GetDatum(typeMod); /* 19 */ values[i++] = Int32GetDatum(typNDims); /* 20 */ /* @@ -475,17 +462,17 @@ TypeCreate(char *typeName, */ if (defaultTypeBin) values[i] = DirectFunctionCall1(textin, - CStringGetDatum(defaultTypeBin)); + CStringGetDatum(defaultTypeBin)); else nulls[i] = 'n'; - i++; /* 21 */ + i++; /* 21 */ /* * initialize the default value for this type. */ if (defaultTypeValue) values[i] = DirectFunctionCall1(textin, - CStringGetDatum(defaultTypeValue)); + CStringGetDatum(defaultTypeValue)); else nulls[i] = 'n'; i++; /* 22 */ diff --git a/src/backend/commands/creatinh.c b/src/backend/commands/creatinh.c index d6af805715..c9dee0cbbe 100644 --- a/src/backend/commands/creatinh.c +++ b/src/backend/commands/creatinh.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/Attic/creatinh.c,v 1.87 2002/03/19 02:58:19 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/Attic/creatinh.c,v 1.88 2002/03/20 19:43:42 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -42,6 +42,7 @@ static int findAttrByName(const char *attributeName, List *schema); static void setRelhassubclassInRelation(Oid relationId, bool relhassubclass); static List *MergeDomainAttributes(List *schema); + /* ---------------------------------------------------------------- * DefineRelation * Creates a new relation. @@ -71,9 +72,9 @@ DefineRelation(CreateStmt *stmt, char relkind) StrNCpy(relname, stmt->relname, NAMEDATALEN); /* - * Inherit domain attributes into the known columns before table inheritance - * applies it's changes otherwise we risk adding double constraints - * to a domain thats inherited. + * Merge domain attributes into the known columns before processing table + * inheritance. Otherwise we risk adding double constraints to a + * domain-type column that's inherited. */ schema = MergeDomainAttributes(schema); @@ -273,11 +274,8 @@ TruncateRelation(const char *relname) /* * MergeDomainAttributes * Returns a new table schema with the constraints, types, and other - * attributes of the domain resolved for fields using the domain as - * their type. - * - * Defaults are pulled out by the table attribute as required, similar to - * how all types defaults are processed. + * attributes of domains resolved for fields using a domain as + * their type. */ static List * MergeDomainAttributes(List *schema) @@ -295,34 +293,25 @@ MergeDomainAttributes(List *schema) HeapTuple tuple; Form_pg_type typeTup; - tuple = SearchSysCache(TYPENAME, CStringGetDatum(coldef->typename->name), 0,0,0); - if (!HeapTupleIsValid(tuple)) elog(ERROR, "MergeDomainAttributes: Type %s does not exist", coldef->typename->name); - typeTup = (Form_pg_type) GETSTRUCT(tuple); - if (typeTup->typtype == 'd') { - /* - * This is a domain, lets force the properties of the domain on to - * the new column. - */ - - /* Enforce the typmod value */ - coldef->typename->typmod = typeTup->typmod; - /* Enforce type NOT NULL || column definition NOT NULL -> NOT NULL */ - coldef->is_not_null |= typeTup->typnotnull; + if (typeTup->typtype == 'd') + { + /* Force the column to have the correct typmod. */ + coldef->typename->typmod = typeTup->typtypmod; + /* XXX more to do here? */ + } - /* Enforce the element type in the event the domain is an array - * - * BUG: How do we fill out arrayBounds and attrname from typelem and typNDimms? - */ + /* Enforce type NOT NULL || column definition NOT NULL -> NOT NULL */ + /* Currently only used for domains, but could be valid for all */ + coldef->is_not_null |= typeTup->typnotnull; - } ReleaseSysCache(tuple); } diff --git a/src/backend/commands/define.c b/src/backend/commands/define.c index 72aa7a3a15..2441e49bca 100644 --- a/src/backend/commands/define.c +++ b/src/backend/commands/define.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.70 2002/03/19 02:18:15 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.71 2002/03/20 19:43:44 tgl Exp $ * * DESCRIPTION * The "DefineFoo" routines take the parse tree and pick out the @@ -483,38 +483,29 @@ DefineAggregate(char *aggName, List *parameters) void DefineDomain(CreateDomainStmt *stmt) { - int16 internalLength = -1; /* int2 */ - int16 externalLength = -1; /* int2 */ - char *inputName = NULL; - char *outputName = NULL; - char *sendName = NULL; - char *receiveName = NULL; - - /* - * Domains store the external representation in defaultValue - * and the interal Node representation in defaultValueBin - */ - char *defaultValue = NULL; - char *defaultValueBin = NULL; - - bool byValue = false; - char delimiter = DEFAULT_TYPDELIM; - char alignment = 'i'; /* default alignment */ - char storage = 'p'; /* default TOAST storage method */ + int16 internalLength; + int16 externalLength; + char *inputName; + char *outputName; + char *sendName; + char *receiveName; + bool byValue; + char delimiter; + char alignment; + char storage; char typtype; Datum datum; + bool isnull; + char *defaultValue = NULL; + char *defaultValueBin = NULL; bool typNotNull = false; + Oid basetypelem; char *elemName = NULL; int32 typNDims = 0; /* No array dimensions by default */ - - bool isnull; - Relation pg_type_rel; - TupleDesc pg_type_dsc; HeapTuple typeTup; char *typeName = stmt->typename->name; - - List *listptr; List *schema = stmt->constraints; + List *listptr; /* * Domainnames, unlike typenames don't need to account for the '_' @@ -524,25 +515,13 @@ DefineDomain(CreateDomainStmt *stmt) elog(ERROR, "CREATE DOMAIN: domain names must be %d characters or less", NAMEDATALEN - 1); - /* Test for existing Domain (or type) of that name */ - typeTup = SearchSysCache( TYPENAME - , PointerGetDatum(stmt->domainname) - , 0, 0, 0 - ); - + typeTup = SearchSysCache(TYPENAME, + PointerGetDatum(stmt->domainname), + 0, 0, 0); if (HeapTupleIsValid(typeTup)) - { - elog(ERROR, "CREATE DOMAIN: domain or type %s already exists", + elog(ERROR, "CREATE DOMAIN: domain or type %s already exists", stmt->domainname); - } - - /* - * Get the information about old types - */ - pg_type_rel = heap_openr(TypeRelationName, RowExclusiveLock); - pg_type_dsc = RelationGetDescr(pg_type_rel); - /* * When the type is an array for some reason we don't actually receive @@ -555,22 +534,12 @@ DefineDomain(CreateDomainStmt *stmt) typNDims = length(stmt->typename->arrayBounds); } - - typeTup = SearchSysCache( TYPENAME - , PointerGetDatum(typeName) - , 0, 0, 0 - ); - + typeTup = SearchSysCache(TYPENAME, + PointerGetDatum(typeName), + 0, 0, 0); if (!HeapTupleIsValid(typeTup)) - { elog(ERROR, "CREATE DOMAIN: type %s does not exist", stmt->typename->name); - } - - - /* Check that this is a basetype */ - typtype = DatumGetChar(heap_getattr(typeTup, Anum_pg_type_typtype, pg_type_dsc, &isnull)); - Assert(!isnull); /* * What we really don't want is domains of domains. This could cause all sorts @@ -578,9 +547,10 @@ DefineDomain(CreateDomainStmt *stmt) * * With testing, we may determine complex types should be allowed */ - if (typtype != 'b') { - elog(ERROR, "DefineDomain: %s is not a basetype", stmt->typename->name); - } + typtype = ((Form_pg_type) GETSTRUCT(typeTup))->typtype; + if (typtype != 'b') + elog(ERROR, "DefineDomain: %s is not a basetype", + stmt->typename->name); /* passed by value */ byValue = ((Form_pg_type) GETSTRUCT(typeTup))->typbyval; @@ -588,6 +558,9 @@ DefineDomain(CreateDomainStmt *stmt) /* Required Alignment */ alignment = ((Form_pg_type) GETSTRUCT(typeTup))->typalign; + /* TOAST Strategy */ + storage = ((Form_pg_type) GETSTRUCT(typeTup))->typstorage; + /* Storage Length */ internalLength = ((Form_pg_type) GETSTRUCT(typeTup))->typlen; @@ -597,70 +570,66 @@ DefineDomain(CreateDomainStmt *stmt) /* Array element Delimiter */ delimiter = ((Form_pg_type) GETSTRUCT(typeTup))->typdelim; + /* + * XXX this is pretty bogus: should be passing function OIDs to + * TypeCreate, not names which aren't unique. + */ + /* Input Function Name */ - datum = heap_getattr(typeTup, Anum_pg_type_typinput, pg_type_dsc, &isnull); + datum = SysCacheGetAttr(TYPENAME, typeTup, Anum_pg_type_typinput, &isnull); Assert(!isnull); inputName = DatumGetCString(DirectFunctionCall1(regprocout, datum)); /* Output Function Name */ - datum = heap_getattr(typeTup, Anum_pg_type_typoutput, pg_type_dsc, &isnull); + datum = SysCacheGetAttr(TYPENAME, typeTup, Anum_pg_type_typoutput, &isnull); Assert(!isnull); outputName = DatumGetCString(DirectFunctionCall1(regprocout, datum)); /* ReceiveName */ - datum = heap_getattr(typeTup, Anum_pg_type_typreceive, pg_type_dsc, &isnull); + datum = SysCacheGetAttr(TYPENAME, typeTup, Anum_pg_type_typreceive, &isnull); Assert(!isnull); receiveName = DatumGetCString(DirectFunctionCall1(regprocout, datum)); /* SendName */ - datum = heap_getattr(typeTup, Anum_pg_type_typsend, pg_type_dsc, &isnull); + datum = SysCacheGetAttr(TYPENAME, typeTup, Anum_pg_type_typsend, &isnull); Assert(!isnull); sendName = DatumGetCString(DirectFunctionCall1(regprocout, datum)); - /* TOAST Strategy */ - storage = ((Form_pg_type) GETSTRUCT(typeTup))->typstorage; - Assert(!isnull); - /* Inherited default value */ - datum = heap_getattr(typeTup, Anum_pg_type_typdefault, pg_type_dsc, &isnull); - if (!isnull) { - defaultValue = DatumGetCString(DirectFunctionCall1(textout, datum)); - } + datum = SysCacheGetAttr(TYPENAME, typeTup, + Anum_pg_type_typdefault, &isnull); + if (!isnull) + defaultValue = DatumGetCString(DirectFunctionCall1(textout, datum)); /* Inherited default binary value */ - datum = heap_getattr(typeTup, Anum_pg_type_typdefaultbin, pg_type_dsc, &isnull); - if (!isnull) { - defaultValueBin = DatumGetCString(DirectFunctionCall1(textout, datum)); - } + datum = SysCacheGetAttr(TYPENAME, typeTup, + Anum_pg_type_typdefaultbin, &isnull); + if (!isnull) + defaultValueBin = DatumGetCString(DirectFunctionCall1(textout, datum)); /* * Pull out the typelem name of the parent OID. * * This is what enables us to make a domain of an array */ - datum = heap_getattr(typeTup, Anum_pg_type_typelem, pg_type_dsc, &isnull); - Assert(!isnull); - - if (DatumGetObjectId(datum) != InvalidOid) { + basetypelem = ((Form_pg_type) GETSTRUCT(typeTup))->typelem; + if (basetypelem != InvalidOid) + { HeapTuple tup; - tup = SearchSysCache( TYPEOID - , datum - , 0, 0, 0 - ); - - elemName = NameStr(((Form_pg_type) GETSTRUCT(tup))->typname); - + tup = SearchSysCache(TYPEOID, + ObjectIdGetDatum(basetypelem), + 0, 0, 0); + elemName = pstrdup(NameStr(((Form_pg_type) GETSTRUCT(tup))->typname)); ReleaseSysCache(tup); } - /* - * Run through constraints manually avoids the additional + * Run through constraints manually to avoid the additional * processing conducted by DefineRelation() and friends. * * Besides, we don't want any constraints to be cooked. We'll @@ -668,20 +637,13 @@ DefineDomain(CreateDomainStmt *stmt) */ foreach(listptr, schema) { + Constraint *colDef = lfirst(listptr); bool nullDefined = false; Node *expr; - Constraint *colDef = lfirst(listptr); - - /* Used for the statement transformation */ ParseState *pstate; - /* - * Create a dummy ParseState and insert the target relation as its - * sole rangetable entry. We need a ParseState for transformExpr. - */ - pstate = make_parsestate(NULL); - - switch(colDef->contype) { + switch (colDef->contype) + { /* * The inherited default value may be overridden by the user * with the DEFAULT statement. @@ -690,27 +652,26 @@ DefineDomain(CreateDomainStmt *stmt) * don't want to cook or fiddle too much. */ case CONSTR_DEFAULT: - + /* Create a dummy ParseState for transformExpr */ + pstate = make_parsestate(NULL); /* - * Cook the colDef->raw_expr into an expression to ensure - * that it can be done. We store the text version of the - * raw value. - * + * Cook the colDef->raw_expr into an expression. * Note: Name is strictly for error message */ - expr = cookDefault(pstate, colDef->raw_expr - , typeTup->t_data->t_oid - , stmt->typename->typmod - , stmt->typename->name); - - /* Binary default required */ + expr = cookDefault(pstate, colDef->raw_expr, + typeTup->t_data->t_oid, + stmt->typename->typmod, + stmt->typename->name); + /* + * Expression must be stored as a nodeToString result, + * but we also require a valid textual representation + * (mainly to make life easier for pg_dump). + */ defaultValue = deparse_expression(expr, deparse_context_for(stmt->domainname, InvalidOid), false); - defaultValueBin = nodeToString(expr); - break; /* @@ -723,7 +684,6 @@ DefineDomain(CreateDomainStmt *stmt) typNotNull = true; nullDefined = true; } - break; case CONSTR_NULL: @@ -733,31 +693,31 @@ DefineDomain(CreateDomainStmt *stmt) typNotNull = false; nullDefined = true; } - break; case CONSTR_UNIQUE: - elog(ERROR, "CREATE DOMAIN / UNIQUE indecies not supported"); + elog(ERROR, "CREATE DOMAIN / UNIQUE indexes not supported"); break; case CONSTR_PRIMARY: - elog(ERROR, "CREATE DOMAIN / PRIMARY KEY indecies not supported"); + elog(ERROR, "CREATE DOMAIN / PRIMARY KEY indexes not supported"); break; - case CONSTR_CHECK: - - elog(ERROR, "defineDomain: CHECK Constraints not supported"); + elog(ERROR, "DefineDomain: CHECK Constraints not supported"); break; case CONSTR_ATTR_DEFERRABLE: case CONSTR_ATTR_NOT_DEFERRABLE: case CONSTR_ATTR_DEFERRED: case CONSTR_ATTR_IMMEDIATE: - elog(ERROR, "defineDomain: DEFERRABLE, NON DEFERRABLE, DEFERRED and IMMEDIATE not supported"); + elog(ERROR, "DefineDomain: DEFERRABLE, NON DEFERRABLE, DEFERRED and IMMEDIATE not supported"); break; - } + default: + elog(ERROR, "DefineDomain: unrecognized constraint node type"); + break; + } } /* @@ -776,8 +736,8 @@ DefineDomain(CreateDomainStmt *stmt) sendName, /* send procedure */ elemName, /* element type name */ typeName, /* base type name */ - defaultValue, /* default type value */ - defaultValueBin, /* default type value */ + defaultValue, /* default type value (text) */ + defaultValueBin, /* default type value (binary) */ byValue, /* passed by value */ alignment, /* required alignment */ storage, /* TOAST strategy */ @@ -789,10 +749,8 @@ DefineDomain(CreateDomainStmt *stmt) * Now we can clean up. */ ReleaseSysCache(typeTup); - heap_close(pg_type_rel, NoLock); } - /* * DefineType * Registers a new type. @@ -808,8 +766,6 @@ DefineType(char *typeName, List *parameters) char *sendName = NULL; char *receiveName = NULL; char *defaultValue = NULL; - char *defaultValueBin = NULL; - Node *defaultRaw = (Node *) NULL; bool byValue = false; char delimiter = DEFAULT_TYPDELIM; char *shadow_type; @@ -851,7 +807,7 @@ DefineType(char *typeName, List *parameters) else if (strcasecmp(defel->defname, "element") == 0) elemName = defGetString(defel); else if (strcasecmp(defel->defname, "default") == 0) - defaultRaw = defel->arg; + defaultValue = defGetString(defel); else if (strcasecmp(defel->defname, "passedbyvalue") == 0) byValue = true; else if (strcasecmp(defel->defname, "alignment") == 0) @@ -911,32 +867,6 @@ DefineType(char *typeName, List *parameters) if (outputName == NULL) elog(ERROR, "Define: \"output\" unspecified"); - - if (defaultRaw) { - Node *expr; - ParseState *pstate; - - /* - * Create a dummy ParseState and insert the target relation as its - * sole rangetable entry. We need a ParseState for transformExpr. - */ - pstate = make_parsestate(NULL); - - expr = cookDefault(pstate, defaultRaw, - InvalidOid, - -1, - typeName); - - /* Binary default required */ - defaultValue = deparse_expression(expr, - deparse_context_for(typeName, - InvalidOid), - false); - - defaultValueBin = nodeToString(expr); - } - - /* * now have TypeCreate do all the real work. */ @@ -952,9 +882,9 @@ DefineType(char *typeName, List *parameters) receiveName, /* receive procedure */ sendName, /* send procedure */ elemName, /* element type name */ - NULL, /* base type name (Non-zero for domains) */ + NULL, /* base type name (only for domains) */ defaultValue, /* default type value */ - defaultValueBin, /* default type value (Binary form) */ + NULL, /* no binary form available */ byValue, /* passed by value */ alignment, /* required alignment */ storage, /* TOAST strategy */ diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c index b04ec8a9b4..677f130637 100644 --- a/src/backend/commands/indexcmds.c +++ b/src/backend/commands/indexcmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.63 2002/03/06 06:09:33 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.64 2002/03/20 19:43:47 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -314,8 +314,7 @@ FuncIndexArgs(IndexInfo *indexInfo, for (i = 0; i < nargs; i++) { - if (argTypes[i] != true_typeids[i] && - !IS_BINARY_COMPATIBLE(argTypes[i], true_typeids[i])) + if (!IsBinaryCompatible(argTypes[i], true_typeids[i])) func_error("DefineIndex", funcIndex->name, nargs, argTypes, "Index function must be binary-compatible with table datatype"); } @@ -418,8 +417,7 @@ GetAttrOpClass(IndexElem *attribute, Oid attrType, opInputType = ((Form_pg_opclass) GETSTRUCT(tuple))->opcintype; ReleaseSysCache(tuple); - if (attrType != opInputType && - !IS_BINARY_COMPATIBLE(attrType, opInputType)) + if (!IsBinaryCompatible(attrType, opInputType)) elog(ERROR, "operator class \"%s\" does not accept data type %s", attribute->class, format_type_be(attrType)); @@ -470,7 +468,7 @@ GetDefaultOpClass(Oid attrType, Oid accessMethodId) nexact++; exactOid = tuple->t_data->t_oid; } - else if (IS_BINARY_COMPATIBLE(opclass->opcintype, attrType)) + else if (IsBinaryCompatible(opclass->opcintype, attrType)) { ncompatible++; compatibleOid = tuple->t_data->t_oid; diff --git a/src/backend/commands/remove.c b/src/backend/commands/remove.c index 297b351df8..99b243ed4f 100644 --- a/src/backend/commands/remove.c +++ b/src/backend/commands/remove.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/Attic/remove.c,v 1.69 2002/03/19 02:18:16 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/Attic/remove.c,v 1.70 2002/03/20 19:43:49 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -282,23 +282,18 @@ RemoveType(char *typeName) /* type name to be removed */ * use it. */ void -RemoveDomain(char *domainName, int behavior) /* domain name to be removed */ +RemoveDomain(char *domainName, int behavior) { Relation relation; HeapTuple tup; - TupleDesc description; char typtype; - bool isnull; - /* Domains are stored as types. Check for permissions on the type */ if (!pg_ownercheck(GetUserId(), domainName, TYPENAME)) elog(ERROR, "RemoveDomain: type '%s': permission denied", domainName); - relation = heap_openr(TypeRelationName, RowExclusiveLock); - description = RelationGetDescr(relation); tup = SearchSysCache(TYPENAME, PointerGetDatum(domainName), @@ -306,14 +301,11 @@ RemoveDomain(char *domainName, int behavior) /* domain name to be removed */ if (!HeapTupleIsValid(tup)) elog(ERROR, "RemoveType: type '%s' does not exist", domainName); - /* Check that this is actually a domain */ - typtype = DatumGetChar(heap_getattr(tup, Anum_pg_type_typtype, description, &isnull)); - Assert(!isnull); + typtype = ((Form_pg_type) GETSTRUCT(tup))->typtype; - if (typtype != 'd') { + if (typtype != 'd') elog(ERROR, "%s is not a domain", domainName); - } /* CASCADE unsupported */ if (behavior == CASCADE) { diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c index 7331cfe796..e7da9e5af5 100644 --- a/src/backend/executor/nodeAgg.c +++ b/src/backend/executor/nodeAgg.c @@ -46,7 +46,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/nodeAgg.c,v 1.79 2002/03/02 21:39:25 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/nodeAgg.c,v 1.80 2002/03/20 19:43:54 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -896,8 +896,7 @@ ExecInitAgg(Agg *node, EState *estate, Plan *parent) */ Oid inputType = exprType(aggref->target); - if (inputType != aggform->aggtranstype && - !IS_BINARY_COMPATIBLE(inputType, aggform->aggtranstype)) + if (!IsBinaryCompatible(inputType, aggform->aggtranstype)) elog(ERROR, "Aggregate %s needs to have compatible input type and transition type", aggname); } diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index 070a6da517..ebdc7cf116 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -15,7 +15,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.170 2002/03/19 02:18:16 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.171 2002/03/20 19:43:58 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -2026,6 +2026,7 @@ _copyDropStmt(DropStmt *from) Node_Copy(from, newnode, names); newnode->removeType = from->removeType; + newnode->behavior = from->behavior; return newnode; } @@ -2238,7 +2239,6 @@ _copyCreateDomainStmt(CreateDomainStmt *from) if (from->domainname) newnode->domainname = pstrdup(from->domainname); - Node_Copy(from, newnode, typename); Node_Copy(from, newnode, constraints); diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index f6f39f2f24..c7ed489e09 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -20,7 +20,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.118 2002/03/19 02:18:16 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.119 2002/03/20 19:44:01 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -878,6 +878,8 @@ _equalDropStmt(DropStmt *a, DropStmt *b) return false; if (a->removeType != b->removeType) return false; + if (a->behavior != b->behavior) + return false; return true; } diff --git a/src/backend/nodes/makefuncs.c b/src/backend/nodes/makefuncs.c index d8f8310c5b..36f8460b46 100644 --- a/src/backend/nodes/makefuncs.c +++ b/src/backend/nodes/makefuncs.c @@ -8,16 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/makefuncs.c,v 1.26 2001/03/22 03:59:32 momjian Exp $ - * - * NOTES - * Creator functions in POSTGRES 4.2 are generated automatically. Most of - * them are rarely used. Now we don't generate them any more. If you want - * one, you have to write it yourself. - * - * HISTORY - * AUTHOR DATE MAJOR EVENT - * Andrew Yu Oct 20, 1994 file creation + * $Header: /cvsroot/pgsql/src/backend/nodes/makefuncs.c,v 1.27 2002/03/20 19:44:04 tgl Exp $ */ #include "postgres.h" @@ -184,3 +175,19 @@ makeAttr(char *relname, char *attname) return a; } + +/* + * makeRelabelType - + * creates a RelabelType node + */ +RelabelType * +makeRelabelType(Node *arg, Oid rtype, int32 rtypmod) +{ + RelabelType *r = makeNode(RelabelType); + + r->arg = arg; + r->resulttype = rtype; + r->resulttypmod = rtypmod; + + return r; +} diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c index b07f0fb006..3458c69f1b 100644 --- a/src/backend/optimizer/path/indxpath.c +++ b/src/backend/optimizer/path/indxpath.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.113 2002/03/02 21:39:26 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.114 2002/03/20 19:44:09 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -900,9 +900,9 @@ indexable_operator(Expr *clause, Oid opclass, bool indexkey_on_left) */ if (ltype == indexkeytype && rtype == indexkeytype) return InvalidOid; /* no chance for a different operator */ - if (ltype != indexkeytype && !IS_BINARY_COMPATIBLE(ltype, indexkeytype)) + if (!IsBinaryCompatible(ltype, indexkeytype)) return InvalidOid; - if (rtype != indexkeytype && !IS_BINARY_COMPATIBLE(rtype, indexkeytype)) + if (!IsBinaryCompatible(rtype, indexkeytype)) return InvalidOid; /* diff --git a/src/backend/optimizer/prep/preptlist.c b/src/backend/optimizer/prep/preptlist.c index cc992c7f3a..8fb1426748 100644 --- a/src/backend/optimizer/prep/preptlist.c +++ b/src/backend/optimizer/prep/preptlist.c @@ -15,7 +15,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/preptlist.c,v 1.49 2002/03/19 02:18:17 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/preptlist.c,v 1.50 2002/03/20 19:44:15 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -355,9 +355,9 @@ build_column_default(Relation rel, int attrno) Form_pg_attribute att_tup = rd_att->attrs[attrno - 1]; Oid atttype = att_tup->atttypid; int32 atttypmod = att_tup->atttypmod; - int16 typlen; - bool typbyval; - Node *expr; + int16 typlen = att_tup->attlen; + bool typbyval = att_tup->attbyval; + Node *expr = NULL; /* * Scan to see if relation has a default for this column. @@ -371,110 +371,86 @@ build_column_default(Relation rel, int attrno) { if (attrno == defval[ndef].adnum) { - Oid type_id; - /* * Found it, convert string representation to node tree. */ expr = stringToNode(defval[ndef].adbin); - - /* - * Make sure the value is coerced to the target column - * type (might not be right type yet if it's not a - * constant!) This should match the parser's processing of - * non-defaulted expressions --- see - * updateTargetListEntry(). - */ - type_id = exprType(expr); - - if (type_id != atttype) - { - expr = CoerceTargetExpr(NULL, expr, type_id, - getBaseType(atttype), atttypmod); - - /* - * This really shouldn't fail; should have checked the - * default's type when it was created ... - */ - if (expr == NULL) - elog(ERROR, "Column \"%s\" is of type %s" - " but default expression is of type %s" - "\n\tYou will need to rewrite or cast the expression", - NameStr(att_tup->attname), - format_type_be(atttype), - format_type_be(type_id)); - } - - /* - * If the column is a fixed-length type, it may need a - * length coercion as well as a type coercion. - */ - expr = coerce_type_typmod(NULL, expr, - atttype, atttypmod); - return expr; + break; } } } - /* - * No per-column default, so look for a default for the type itself. - * If there isn't one, we generate a NULL constant of the correct - * type. - */ - if (att_tup->attisset) + if (expr == NULL) { /* - * Set attributes are represented as OIDs no matter what the set - * element type is, and the element type's default is irrelevant - * too. + * No per-column default, so look for a default for the type itself. */ - typlen = sizeof(Oid); - typbyval = true; + if (att_tup->attisset) + { + /* + * Set attributes are represented as OIDs no matter what the set + * element type is, and the element type's default is irrelevant + * too. + */ + typlen = sizeof(Oid); + typbyval = true; + } + else + { + expr = get_typdefault(atttype); + } + } + if (expr == NULL) + { + /* + * No default anywhere, so generate a NULL constant. + */ expr = (Node *) makeConst(atttype, typlen, (Datum) 0, - true, + true, /* isnull */ typbyval, - false, /* not a set */ + false, /* not a set */ false); } else { -#ifdef _DROP_COLUMN_HACK__ - if (COLUMN_IS_DROPPED(att_tup)) + Oid exprtype; + + /* + * Make sure the value is coerced to the target column + * type (might not be right type yet if it's not a + * constant!) This should match the parser's processing of + * non-defaulted expressions --- see + * updateTargetListEntry(). + */ + exprtype = exprType(expr); + + if (exprtype != atttype) { + expr = CoerceTargetExpr(NULL, expr, exprtype, + atttype, atttypmod); - expr = (Node *) makeConst(atttype, - typlen, - (Datum) 0, - true, - typbyval, - false, /* not a set */ - false); - } - else -#endif /* _DROP_COLUMN_HACK__ */ - expr = get_typdefault(atttype, atttypmod); - - if (expr == NULL) { - expr = (Node *) makeConst(atttype, - typlen, - (Datum) 0, - true, - typbyval, - false, /* not a set */ - false); + /* + * This really shouldn't fail; should have checked the + * default's type when it was created ... + */ + if (expr == NULL) + elog(ERROR, "Column \"%s\" is of type %s" + " but default expression is of type %s" + "\n\tYou will need to rewrite or cast the expression", + NameStr(att_tup->attname), + format_type_be(atttype), + format_type_be(exprtype)); } - get_typlenbyval(atttype, &typlen, &typbyval); - } - /* - * If the column is a fixed-length type, it may need a length coercion - * as well as a type coercion, as well as direction to the final type. - */ - expr = coerce_type_typmod(NULL, expr, - atttype, atttypmod); + /* + * If the column is a fixed-length type, it may need a + * length coercion as well as a type coercion. + */ + expr = coerce_type_typmod(NULL, expr, atttype, atttypmod); + } return expr; } diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 1994875bd1..6951653ce8 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.293 2002/03/19 12:52:20 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.294 2002/03/20 19:44:21 tgl Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -135,8 +135,7 @@ static void doNegateFloat(Value *v); ClosePortalStmt, ClusterStmt, CommentStmt, ConstraintsSetStmt, CopyStmt, CreateAsStmt, CreateDomainStmt, CreateGroupStmt, CreatePLangStmt, CreateSchemaStmt, CreateSeqStmt, CreateStmt, CreateTrigStmt, - CreateUserStmt, CreatedbStmt, CursorStmt, - DefineStmt, DeleteStmt, + CreateUserStmt, CreatedbStmt, CursorStmt, DefineStmt, DeleteStmt, DropGroupStmt, DropPLangStmt, DropSchemaStmt, DropStmt, DropTrigStmt, DropUserStmt, DropdbStmt, ExplainStmt, FetchStmt, GrantStmt, IndexStmt, InsertStmt, ListenStmt, LoadStmt, LockStmt, @@ -151,7 +150,7 @@ static void doNegateFloat(Value *v); simple_select %type alter_column_default -%type drop_behavior +%type drop_behavior, opt_drop_behavior %type createdb_opt_list, createdb_opt_item %type opt_equal @@ -1181,6 +1180,10 @@ drop_behavior: CASCADE { $$ = CASCADE; } | RESTRICT { $$ = RESTRICT; } ; +opt_drop_behavior: CASCADE { $$ = CASCADE; } + | RESTRICT { $$ = RESTRICT; } + | /* EMPTY */ { $$ = RESTRICT; /* default */ } + ; /***************************************************************************** @@ -2030,22 +2033,13 @@ def_list: def_elem { $$ = makeList1($1); } | def_list ',' def_elem { $$ = lappend($1, $3); } ; -def_elem: DEFAULT '=' b_expr - { - $$ = makeNode(DefElem); - $$->defname = "default"; - if (exprIsNullConstant($3)) - $$->arg = (Node *)NULL; - else - $$->arg = $3; - } - | ColId '=' def_arg +def_elem: ColLabel '=' def_arg { $$ = makeNode(DefElem); $$->defname = $1; $$->arg = (Node *)$3; } - | ColId + | ColLabel { $$ = makeNode(DefElem); $$->defname = $1; @@ -2069,19 +2063,11 @@ def_arg: func_return { $$ = (Node *)$1; } * *****************************************************************************/ -DropStmt: DROP drop_type name_list +DropStmt: DROP drop_type name_list opt_drop_behavior { DropStmt *n = makeNode(DropStmt); n->removeType = $2; n->names = $3; - n->behavior = RESTRICT; /* Restricted by default */ - $$ = (Node *)n; - } - | DROP DOMAIN_P name_list drop_behavior - { - DropStmt *n = makeNode(DropStmt); - n->removeType = DROP_DOMAIN_P; - n->names = $3; n->behavior = $4; $$ = (Node *)n; } @@ -2092,7 +2078,8 @@ drop_type: TABLE { $$ = DROP_TABLE; } | VIEW { $$ = DROP_VIEW; } | INDEX { $$ = DROP_INDEX; } | RULE { $$ = DROP_RULE; } - | TYPE_P { $$ = DROP_TYPE_P; } + | TYPE_P { $$ = DROP_TYPE; } + | DOMAIN_P { $$ = DROP_DOMAIN; } ; /***************************************************************************** @@ -3194,12 +3181,19 @@ createdb_opt_item: LOCATION opt_equal Sconst } ; +/* + * Though the equals sign doesn't match other WITH options, pg_dump uses + * equals for backward compability, and it doesn't seem worth remove it. + */ +opt_equal: '=' { $$ = TRUE; } + | /*EMPTY*/ { $$ = FALSE; } + ; + /***************************************************************************** * * DROP DATABASE * - * *****************************************************************************/ DropdbStmt: DROP DATABASE database_name @@ -3210,20 +3204,11 @@ DropdbStmt: DROP DATABASE database_name } ; -/* - * Though the equals sign doesn't match other WITH options, pg_dump uses - * equals for backward compability, and it doesn't seem worth remove it. - */ -opt_equal: '=' { $$ = TRUE; } - | /*EMPTY*/ { $$ = FALSE; } - ; - /***************************************************************************** * * ALTER DATABASE * - * *****************************************************************************/ AlterDatabaseSetStmt: ALTER DATABASE database_name VariableSetStmt diff --git a/src/backend/parser/parse_coerce.c b/src/backend/parser/parse_coerce.c index 7aaaa65c61..690a047915 100644 --- a/src/backend/parser/parse_coerce.c +++ b/src/backend/parser/parse_coerce.c @@ -8,25 +8,31 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.67 2002/03/19 02:18:20 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.68 2002/03/20 19:44:22 tgl Exp $ * *------------------------------------------------------------------------- */ #include "postgres.h" #include "catalog/pg_proc.h" +#include "nodes/makefuncs.h" #include "optimizer/clauses.h" #include "parser/parse_coerce.h" #include "parser/parse_expr.h" #include "parser/parse_func.h" #include "parser/parse_type.h" #include "utils/builtins.h" +#include "utils/lsyscache.h" #include "utils/syscache.h" + Oid DemoteType(Oid inType); Oid PromoteTypeToNext(Oid inType); static Oid PreferredType(CATEGORY category, Oid type); +static Node *build_func_call(Oid funcid, Oid rettype, List *args); +static Oid find_coercion_function(Oid targetTypeId, Oid inputTypeId, + Oid secondArgType); /* coerce_type() @@ -87,32 +93,28 @@ coerce_type(ParseState *pstate, Node *node, Oid inputTypeId, result = (Node *) newcon; } - else if (IS_BINARY_COMPATIBLE(inputTypeId, targetTypeId)) + else if (IsBinaryCompatible(inputTypeId, targetTypeId)) { /* * We don't really need to do a conversion, but we do need to * attach a RelabelType node so that the expression will be seen * to have the intended type when inspected by higher-level code. - */ - RelabelType *relabel = makeNode(RelabelType); - - relabel->arg = node; - relabel->resulttype = targetTypeId; - - /* + * * XXX could we label result with exprTypmod(node) instead of * default -1 typmod, to save a possible length-coercion later? * Would work if both types have same interpretation of typmod, * which is likely but not certain. */ - relabel->resulttypmod = -1; - - result = (Node *) relabel; + result = (Node *) makeRelabelType(node, targetTypeId, -1); } else if (typeInheritsFrom(inputTypeId, targetTypeId)) { - /* Input class type is a subclass of target, so nothing to do */ - result = node; + /* + * Input class type is a subclass of target, so nothing to do + * --- except relabel the type. This is binary compatibility + * for complex types. + */ + result = (Node *) makeRelabelType(node, targetTypeId, -1); } else { @@ -121,21 +123,24 @@ coerce_type(ParseState *pstate, Node *node, Oid inputTypeId, * (caller should have determined that there is one), and generate * an expression tree representing run-time application of the * conversion function. + * + * For domains, we use the coercion function for the base type. */ - FuncCall *n = makeNode(FuncCall); + Oid baseTypeId = getBaseType(targetTypeId); + Oid funcId; - n->funcname = typeidTypeName(targetTypeId); - n->args = makeList1(node); - n->agg_star = false; - n->agg_distinct = false; + funcId = find_coercion_function(baseTypeId, + getBaseType(inputTypeId), + InvalidOid); + if (!OidIsValid(funcId)) + elog(ERROR, "coerce_type: no conversion function from %s to %s", + format_type_be(inputTypeId), format_type_be(targetTypeId)); - result = transformExpr(pstate, (Node *) n, EXPR_COLUMN_FIRST); + result = build_func_call(funcId, baseTypeId, makeList1(node)); - /* safety check that we got the right thing */ - if (exprType(result) != targetTypeId) - elog(ERROR, "coerce_type: conversion function %s produced %s", - typeidTypeName(targetTypeId), - typeidTypeName(exprType(result))); + /* if domain, relabel with domain type ID */ + if (targetTypeId != baseTypeId) + result = (Node *) makeRelabelType(result, targetTypeId, -1); /* * If the input is a constant, apply the type conversion function @@ -152,7 +157,8 @@ coerce_type(ParseState *pstate, Node *node, Oid inputTypeId, * nodes that mustn't be collapsed. (It'd be a lot cleaner to * make a separate node type for that purpose...) */ - if (IsA(node, Const) &&!((Const *) node)->constisnull) + if (IsA(node, Const) && + !((Const *) node)->constisnull) result = eval_const_expressions(result); } @@ -169,23 +175,18 @@ coerce_type(ParseState *pstate, Node *node, Oid inputTypeId, * * Notes: * This uses the same mechanism as the CAST() SQL construct in gram.y. - * We should also check the function return type on candidate conversion - * routines just to be safe but we do not do that yet... - * - thomas 1998-03-31 */ bool can_coerce_type(int nargs, Oid *input_typeids, Oid *func_typeids) { int i; - HeapTuple ftup; - Form_pg_proc pform; - Oid oid_array[FUNC_MAX_ARGS]; /* run through argument list... */ for (i = 0; i < nargs; i++) { Oid inputTypeId = input_typeids[i]; Oid targetTypeId = func_typeids[i]; + Oid funcId; /* no problem if same type */ if (inputTypeId == targetTypeId) @@ -195,7 +196,7 @@ can_coerce_type(int nargs, Oid *input_typeids, Oid *func_typeids) * one of the known-good transparent conversions? then drop * through... */ - if (IS_BINARY_COMPATIBLE(inputTypeId, targetTypeId)) + if (IsBinaryCompatible(inputTypeId, targetTypeId)) continue; /* don't know what to do for the output type? then quit... */ @@ -232,25 +233,14 @@ can_coerce_type(int nargs, Oid *input_typeids, Oid *func_typeids) * Else, try for explicit conversion using functions: look for a * single-argument function named with the target type name and * accepting the source type. + * + * If either type is a domain, use its base type instead. */ - MemSet(oid_array, 0, FUNC_MAX_ARGS * sizeof(Oid)); - oid_array[0] = inputTypeId; - - ftup = SearchSysCache(PROCNAME, - PointerGetDatum(typeidTypeName(targetTypeId)), - Int32GetDatum(1), - PointerGetDatum(oid_array), - 0); - if (!HeapTupleIsValid(ftup)) - return false; - /* Make sure the function's result type is as expected, too */ - pform = (Form_pg_proc) GETSTRUCT(ftup); - if (pform->prorettype != targetTypeId) - { - ReleaseSysCache(ftup); + funcId = find_coercion_function(getBaseType(targetTypeId), + getBaseType(inputTypeId), + InvalidOid); + if (!OidIsValid(funcId)) return false; - } - ReleaseSysCache(ftup); } return true; @@ -277,8 +267,8 @@ Node * coerce_type_typmod(ParseState *pstate, Node *node, Oid targetTypeId, int32 atttypmod) { - char *funcname; - Oid oid_array[FUNC_MAX_ARGS]; + Oid baseTypeId; + Oid funcId; /* * A negative typmod is assumed to mean that no coercion is wanted. @@ -286,30 +276,28 @@ coerce_type_typmod(ParseState *pstate, Node *node, if (atttypmod < 0 || atttypmod == exprTypmod(node)) return node; - funcname = typeidTypeName(targetTypeId); - MemSet(oid_array, 0, FUNC_MAX_ARGS * sizeof(Oid)); - oid_array[0] = targetTypeId; - oid_array[1] = INT4OID; - - /* attempt to find with arguments exactly as specified... */ - if (SearchSysCacheExists(PROCNAME, - PointerGetDatum(funcname), - Int32GetDatum(2), - PointerGetDatum(oid_array), - 0)) + /* If given type is a domain, use base type instead */ + baseTypeId = getBaseType(targetTypeId); + + funcId = find_coercion_function(baseTypeId, baseTypeId, INT4OID); + + if (OidIsValid(funcId)) { - A_Const *cons = makeNode(A_Const); - FuncCall *func = makeNode(FuncCall); + Const *cons; - cons->val.type = T_Integer; - cons->val.val.ival = atttypmod; + cons = makeConst(INT4OID, + sizeof(int32), + Int32GetDatum(atttypmod), + false, + true, + false, + false); - func->funcname = funcname; - func->args = makeList2(node, cons); - func->agg_star = false; - func->agg_distinct = false; + node = build_func_call(funcId, baseTypeId, makeList2(node, cons)); - node = transformExpr(pstate, (Node *) func, EXPR_COLUMN_FIRST); + /* relabel if it's domain case */ + if (targetTypeId != baseTypeId) + node = (Node *) makeRelabelType(node, targetTypeId, atttypmod); } return node; @@ -532,6 +520,64 @@ TypeCategory(Oid inType) } /* TypeCategory() */ +/* IsBinaryCompatible() + * Check if two types are binary-compatible. + * + * This notion allows us to cheat and directly exchange values without + * going through the trouble of calling a conversion function. + * + * XXX This should be moved to system catalog lookups + * to allow for better type extensibility. + */ + +/* + * This macro describes hard-coded knowledge of binary compatibility + * for built-in types. + */ +#define IS_BINARY_COMPATIBLE(a,b) \ + (((a) == BPCHAROID && (b) == TEXTOID) \ + || ((a) == BPCHAROID && (b) == VARCHAROID) \ + || ((a) == VARCHAROID && (b) == TEXTOID) \ + || ((a) == VARCHAROID && (b) == BPCHAROID) \ + || ((a) == TEXTOID && (b) == BPCHAROID) \ + || ((a) == TEXTOID && (b) == VARCHAROID) \ + || ((a) == OIDOID && (b) == INT4OID) \ + || ((a) == OIDOID && (b) == REGPROCOID) \ + || ((a) == INT4OID && (b) == OIDOID) \ + || ((a) == INT4OID && (b) == REGPROCOID) \ + || ((a) == REGPROCOID && (b) == OIDOID) \ + || ((a) == REGPROCOID && (b) == INT4OID) \ + || ((a) == ABSTIMEOID && (b) == INT4OID) \ + || ((a) == INT4OID && (b) == ABSTIMEOID) \ + || ((a) == RELTIMEOID && (b) == INT4OID) \ + || ((a) == INT4OID && (b) == RELTIMEOID) \ + || ((a) == INETOID && (b) == CIDROID) \ + || ((a) == CIDROID && (b) == INETOID) \ + || ((a) == BITOID && (b) == VARBITOID) \ + || ((a) == VARBITOID && (b) == BITOID)) + +bool +IsBinaryCompatible(Oid type1, Oid type2) +{ + if (type1 == type2) + return true; + if (IS_BINARY_COMPATIBLE(type1, type2)) + return true; + /* + * Perhaps the types are domains; if so, look at their base types + */ + if (OidIsValid(type1)) + type1 = getBaseType(type1); + if (OidIsValid(type2)) + type2 = getBaseType(type2); + if (type1 == type2) + return true; + if (IS_BINARY_COMPATIBLE(type1, type2)) + return true; + return false; +} + + /* IsPreferredType() * Check if this type is a preferred type. * XXX This should be moved to system catalog lookups @@ -606,31 +652,81 @@ PreferredType(CATEGORY category, Oid type) return result; } /* PreferredType() */ - /* - * If the targetTypeId is a domain, we really want to coerce - * the tuple to the domain type -- not the domain itself + * find_coercion_function + * Look for a coercion function between two types. + * + * A coercion function must be named after (the internal name of) its + * result type, and must accept exactly the specified input type. + * + * This routine is also used to look for length-coercion functions, which + * are similar but accept a second argument. secondArgType is the type + * of the second argument (normally INT4OID), or InvalidOid if we are + * looking for a regular coercion function. + * + * If a function is found, return its pg_proc OID; else return InvalidOid. */ -Oid -getBaseType(Oid inType) +static Oid +find_coercion_function(Oid targetTypeId, Oid inputTypeId, Oid secondArgType) { - HeapTuple tup; - Form_pg_type typTup; + char *funcname; + Oid oid_array[FUNC_MAX_ARGS]; + int nargs; + HeapTuple ftup; + Form_pg_proc pform; + Oid funcid; - tup = SearchSysCache(TYPEOID, - ObjectIdGetDatum(inType), - 0, 0, 0); + funcname = typeidTypeName(targetTypeId); + MemSet(oid_array, 0, FUNC_MAX_ARGS * sizeof(Oid)); + oid_array[0] = inputTypeId; + if (OidIsValid(secondArgType)) + { + oid_array[1] = secondArgType; + nargs = 2; + } + else + nargs = 1; + + ftup = SearchSysCache(PROCNAME, + PointerGetDatum(funcname), + Int32GetDatum(nargs), + PointerGetDatum(oid_array), + 0); + if (!HeapTupleIsValid(ftup)) + return InvalidOid; + /* Make sure the function's result type is as expected, too */ + pform = (Form_pg_proc) GETSTRUCT(ftup); + if (pform->prorettype != targetTypeId) + { + ReleaseSysCache(ftup); + return InvalidOid; + } + funcid = ftup->t_data->t_oid; + ReleaseSysCache(ftup); + return funcid; +} - typTup = ((Form_pg_type) GETSTRUCT(tup)); +/* + * Build an expression tree representing a function call. + * + * The argument expressions must have been transformed already. + */ +static Node * +build_func_call(Oid funcid, Oid rettype, List *args) +{ + Func *funcnode; + Expr *expr; - /* - * Assume that typbasetype exists and is a base type, where inType - * was a domain - */ - if (typTup->typtype == 'd') - inType = typTup->typbasetype; + funcnode = makeNode(Func); + funcnode->funcid = funcid; + funcnode->functype = rettype; + funcnode->func_fcache = NULL; - ReleaseSysCache(tup); + expr = makeNode(Expr); + expr->typeOid = rettype; + expr->opType = FUNC_EXPR; + expr->oper = (Node *) funcnode; + expr->args = args; - return inType; + return (Node *) expr; } diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c index 5cbc26f5cb..6409ef3226 100644 --- a/src/backend/parser/parse_expr.c +++ b/src/backend/parser/parse_expr.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.109 2002/03/19 02:18:20 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.110 2002/03/20 19:44:25 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1027,8 +1027,7 @@ parser_typecast_expression(ParseState *pstate, if (inputType != targetType) { expr = CoerceTargetExpr(pstate, expr, inputType, - getBaseType(targetType), - typename->typmod); + targetType, typename->typmod); if (expr == NULL) elog(ERROR, "Cannot cast type '%s' to '%s'", format_type_be(inputType), @@ -1040,7 +1039,7 @@ parser_typecast_expression(ParseState *pstate, * as well as a type coercion. */ expr = coerce_type_typmod(pstate, expr, - getBaseType(targetType), typename->typmod); + targetType, typename->typmod); return expr; } diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c index ed39d6c103..6dc7b440fa 100644 --- a/src/backend/parser/parse_func.c +++ b/src/backend/parser/parse_func.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.117 2002/03/12 00:51:55 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.118 2002/03/20 19:44:29 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -575,8 +575,7 @@ agg_select_candidate(Oid typeid, CandidateList candidates) { current_typeid = current_candidate->args[0]; - if (current_typeid == typeid - || IS_BINARY_COMPATIBLE(current_typeid, typeid)) + if (IsBinaryCompatible(current_typeid, typeid)) { last_candidate = current_candidate; ncandidates++; @@ -815,9 +814,7 @@ func_select_candidate(int nargs, { if (input_typeids[i] != UNKNOWNOID) { - if (current_typeids[i] == input_typeids[i] || - IS_BINARY_COMPATIBLE(current_typeids[i], - input_typeids[i])) + if (IsBinaryCompatible(current_typeids[i], input_typeids[i])) nmatch++; } } @@ -1115,8 +1112,7 @@ func_get_detail(char *funcname, Node *arg1 = lfirst(fargs); if ((sourceType == UNKNOWNOID && IsA(arg1, Const)) || - sourceType == targetType || - IS_BINARY_COMPATIBLE(sourceType, targetType)) + IsBinaryCompatible(sourceType, targetType)) { /* Yup, it's a type coercion */ *funcid = InvalidOid; diff --git a/src/backend/parser/parse_oper.c b/src/backend/parser/parse_oper.c index 318f1b9eb7..8495f9f9e6 100644 --- a/src/backend/parser/parse_oper.c +++ b/src/backend/parser/parse_oper.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_oper.c,v 1.52 2002/02/19 20:11:15 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_oper.c,v 1.53 2002/03/20 19:44:31 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -354,9 +354,7 @@ oper_select_candidate(int nargs, { if (input_typeids[i] != UNKNOWNOID) { - if (current_typeids[i] == input_typeids[i] || - IS_BINARY_COMPATIBLE(current_typeids[i], - input_typeids[i])) + if (IsBinaryCompatible(current_typeids[i], input_typeids[i])) nmatch++; } } @@ -736,10 +734,8 @@ compatible_oper(char *op, Oid arg1, Oid arg2, bool noError) /* but is it good enough? */ opform = (Form_pg_operator) GETSTRUCT(optup); - if ((opform->oprleft == arg1 || - IS_BINARY_COMPATIBLE(opform->oprleft, arg1)) && - (opform->oprright == arg2 || - IS_BINARY_COMPATIBLE(opform->oprright, arg2))) + if (IsBinaryCompatible(opform->oprleft, arg1) && + IsBinaryCompatible(opform->oprright, arg2)) return optup; /* nope... */ diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index 0c1ead0331..db8d440034 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.134 2002/03/19 02:58:19 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.135 2002/03/20 19:44:35 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -276,12 +276,12 @@ ProcessUtility(Node *parsetree, } break; - case DROP_TYPE_P: + case DROP_TYPE: /* RemoveType does its own permissions checks */ RemoveType(relname); break; - case DROP_DOMAIN_P: + case DROP_DOMAIN: /* RemoveDomain does its own permissions checks */ RemoveDomain(relname, stmt->behavior); break; diff --git a/src/backend/utils/adt/format_type.c b/src/backend/utils/adt/format_type.c index fc8733e960..c85d7ea088 100644 --- a/src/backend/utils/adt/format_type.c +++ b/src/backend/utils/adt/format_type.c @@ -8,7 +8,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/format_type.c,v 1.27 2002/03/19 02:18:21 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/format_type.c,v 1.28 2002/03/20 19:44:40 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -123,10 +123,10 @@ format_type_internal(Oid type_oid, int32 typemod, HeapTuple tuple; Oid array_base_type; int16 typlen; + char typtype; bool is_array; char *name; char *buf; - char typtype; if (type_oid == InvalidOid && allow_invalid) return pstrdup("-"); @@ -143,34 +143,16 @@ format_type_internal(Oid type_oid, int32 typemod, type_oid); } + /* + * Check if it's an array (and not a domain --- we don't want to show + * the substructure of a domain type). Fixed-length array types such + * as "name" shouldn't get deconstructed either. + */ array_base_type = ((Form_pg_type) GETSTRUCT(tuple))->typelem; typlen = ((Form_pg_type) GETSTRUCT(tuple))->typlen; typtype = ((Form_pg_type) GETSTRUCT(tuple))->typtype; - /* - * Domains look alot like arrays, so lets process them first, and return - * back to avoid the array and 'standard' formatting procedures that are - * use for base types. - */ - if (typtype == 'd') { - name = NameStr(((Form_pg_type) GETSTRUCT(tuple))->typname); - - /* - * Double-quote the name if it's not a standard identifier. - * Note this is *necessary* for ruleutils.c's use. - */ - if (strspn(name, "abcdefghijklmnopqrstuvwxyz0123456789_") != strlen(name) - || isdigit((unsigned char) name[0])) - buf = psnprintf(strlen(name) + 3, "\"%s\"", name); - else - buf = pstrdup(name); - - ReleaseSysCache(tuple); - - return buf; - } - - if (array_base_type != InvalidOid && typlen < 0) + if (array_base_type != InvalidOid && typlen < 0 && typtype != 'd') { /* Switch our attention to the array element type */ ReleaseSysCache(tuple); diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c index 760e07ce5e..f4ebb6261c 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 - * $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.63 2002/03/19 02:18:21 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.64 2002/03/20 19:44:42 tgl Exp $ * * NOTES * Eventually, the index information should go through here, too. @@ -23,7 +23,7 @@ #include "catalog/pg_shadow.h" #include "catalog/pg_statistic.h" #include "catalog/pg_type.h" -#include "parser/parse_coerce.h" +#include "nodes/makefuncs.h" #include "utils/array.h" #include "utils/builtins.h" #include "utils/lsyscache.h" @@ -818,19 +818,19 @@ get_typstorage(Oid typid) /* * get_typdefault - * * Given a type OID, return the type's default value, if any. - * Returns FALSE if there is no default (effectively, default is NULL). - * The result points to palloc'd storage for pass-by-reference types. + * + * The result is a palloc'd expression node tree, or NULL if there + * is no defined default for the datatype. + * + * NB: caller should be prepared to coerce result to correct datatype; + * the returned expression tree might produce something of the wrong type. */ Node * -get_typdefault(Oid typid, int32 atttypmod) +get_typdefault(Oid typid) { HeapTuple typeTuple; Form_pg_type type; - Oid typinput; - Oid typbasetype; - char typtype; Datum datum; bool isNull; Node *expr; @@ -838,48 +838,102 @@ get_typdefault(Oid typid, int32 atttypmod) typeTuple = SearchSysCache(TYPEOID, ObjectIdGetDatum(typid), 0, 0, 0); - if (!HeapTupleIsValid(typeTuple)) elog(ERROR, "get_typdefault: failed to lookup type %u", typid); - type = (Form_pg_type) GETSTRUCT(typeTuple); - typinput = type->typinput; - typbasetype = type->typbasetype; - typtype = type->typtype; - /* - * typdefaultbin is potentially null, so don't try to access it as a - * struct field. Must do it the hard way with SysCacheGetAttr. + * typdefault and typdefaultbin are potentially null, so don't try to + * access 'em as struct fields. Must do it the hard way with + * SysCacheGetAttr. */ datum = SysCacheGetAttr(TYPEOID, typeTuple, Anum_pg_type_typdefaultbin, &isNull); - ReleaseSysCache(typeTuple); - if (isNull) - return (Node *) NULL; + if (!isNull) + { + /* We have an expression default */ + expr = stringToNode(DatumGetCString(DirectFunctionCall1(textout, + datum))); + } + else + { + /* Perhaps we have a plain literal default */ + datum = SysCacheGetAttr(TYPEOID, + typeTuple, + Anum_pg_type_typdefault, + &isNull); - /* Convert Datum to a Node */ - expr = stringToNode(DatumGetCString( - DirectFunctionCall1(textout, datum))); + if (!isNull) + { + char *strDefaultVal; + + /* Convert text datum to C string */ + strDefaultVal = DatumGetCString(DirectFunctionCall1(textout, + datum)); + /* Convert C string to a value of the given type */ + datum = OidFunctionCall3(type->typinput, + CStringGetDatum(strDefaultVal), + ObjectIdGetDatum(type->typelem), + Int32GetDatum(-1)); + /* Build a Const node containing the value */ + expr = (Node *) makeConst(typid, + type->typlen, + datum, + false, + type->typbyval, + false, /* not a set */ + false); + pfree(strDefaultVal); + } + else + { + /* No default */ + expr = NULL; + } + } + ReleaseSysCache(typeTuple); + return expr; +} + +/* + * getBaseType + * If the given type is a domain, return its base type; + * otherwise return the type's own OID. + */ +Oid +getBaseType(Oid typid) +{ /* - * Ensure we goto the basetype before the domain type. - * - * Prevents scenarios like the below from failing: - * CREATE DOMAIN dom text DEFAULT random(); - * + * We loop to find the bottom base type in a stack of domains. */ - if (typbasetype != InvalidOid) { - expr = coerce_type(NULL, expr, typid, - typbasetype, atttypmod); - } + for (;;) + { + HeapTuple tup; + Form_pg_type typTup; + + tup = SearchSysCache(TYPEOID, + ObjectIdGetDatum(typid), + 0, 0, 0); + if (!HeapTupleIsValid(tup)) + elog(ERROR, "getBaseType: failed to lookup type %u", typid); + typTup = (Form_pg_type) GETSTRUCT(tup); + if (typTup->typtype != 'd') + { + /* Not a domain, so done */ + ReleaseSysCache(tup); + break; + } + typid = typTup->typbasetype; + ReleaseSysCache(tup); + } - return expr; + return typid; } /* diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c index c45b81c7a8..0c6f5441ca 100644 --- a/src/bin/psql/describe.c +++ b/src/bin/psql/describe.c @@ -3,7 +3,7 @@ * * Copyright 2000 by PostgreSQL Global Development Group * - * $Header: /cvsroot/pgsql/src/bin/psql/describe.c,v 1.46 2002/03/19 02:32:21 momjian Exp $ + * $Header: /cvsroot/pgsql/src/bin/psql/describe.c,v 1.47 2002/03/20 19:44:45 tgl Exp $ */ #include "postgres_fe.h" #include "describe.h" @@ -1053,7 +1053,7 @@ listDomains(const char *name) snprintf(buf, sizeof(buf), "SELECT t.typname as \"%s\",\n" - " format_type( t.typbasetype, t.typmod) as \"%s\",\n" + " format_type( t.typbasetype, t.typtypmod) as \"%s\",\n" " CASE WHEN t.typnotnull AND t.typdefault IS NOT NULL THEN 'not null default '||t.typdefault\n" " WHEN t.typnotnull AND t.typdefault IS NULL THEN 'not null'\n" " WHEN NOT t.typnotnull AND t.typdefault IS NOT NULL THEN 'default '||t.typdefault\n" diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index 882a29246f..a049a23935 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -37,7 +37,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: catversion.h,v 1.106 2002/03/12 00:51:59 tgl Exp $ + * $Id: catversion.h,v 1.107 2002/03/20 19:44:48 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 200203111 +#define CATALOG_VERSION_NO 200203191 #endif diff --git a/src/include/catalog/heap.h b/src/include/catalog/heap.h index 4298f53bdc..b2bcfb71bd 100644 --- a/src/include/catalog/heap.h +++ b/src/include/catalog/heap.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: heap.h,v 1.45 2002/03/19 02:58:19 momjian Exp $ + * $Id: heap.h,v 1.46 2002/03/20 19:44:52 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -47,11 +47,11 @@ extern void AddRelationRawConstraints(Relation rel, List *rawColDefaults, List *rawConstraints); -extern Node *cookDefault(ParseState *pstate - , Node *raw_default - , Oid atttypid - , int32 atttypmod - , char *attname); +extern Node *cookDefault(ParseState *pstate, + Node *raw_default, + Oid atttypid, + int32 atttypmod, + char *attname); extern int RemoveCheckConstraint(Relation rel, const char *constrName, bool inh); diff --git a/src/include/catalog/pg_attribute.h b/src/include/catalog/pg_attribute.h index 6efbe3223a..df7cec8397 100644 --- a/src/include/catalog/pg_attribute.h +++ b/src/include/catalog/pg_attribute.h @@ -8,7 +8,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: pg_attribute.h,v 1.84 2002/03/19 02:18:22 momjian Exp $ + * $Id: pg_attribute.h,v 1.85 2002/03/20 19:44:55 tgl Exp $ * * NOTES * the genbki.sh script reads this file and generates .bki @@ -241,8 +241,8 @@ typedef FormData_pg_attribute *Form_pg_attribute; { 1247, {"typalign"}, 18, 0, 1, 15, 0, -1, -1, true, 'p', false, 'c', false, false }, \ { 1247, {"typstorage"}, 18, 0, 1, 16, 0, -1, -1, true, 'p', false, 'c', false, false }, \ { 1247, {"typnotnull"}, 16, 0, 1, 17, 0, -1, -1, true, 'p', false, 'c', false, false }, \ -{ 1247, {"typmod"}, 23, 0, 4, 18, 0, -1, -1, true, 'p', false, 'i', false, false }, \ -{ 1247, {"typbasetype"}, 26, 0, 4, 19, 0, -1, -1, true, 'p', false, 'i', false, false }, \ +{ 1247, {"typbasetype"}, 26, 0, 4, 18, 0, -1, -1, true, 'p', false, 'i', false, false }, \ +{ 1247, {"typtypmod"}, 23, 0, 4, 19, 0, -1, -1, true, 'p', false, 'i', false, false }, \ { 1247, {"typndims"}, 23, 0, 4, 20, 0, -1, -1, true, 'p', false, 'i', false, false }, \ { 1247, {"typdefaultbin"}, 25, 0, -1, 21, 0, -1, -1, false, 'x', false, 'i', false, false }, \ { 1247, {"typdefault"}, 25, 0, -1, 22, 0, -1, -1, false, 'x', false, 'i', false, false } @@ -265,8 +265,8 @@ DATA(insert ( 1247 typsend 24 0 4 14 0 -1 -1 t p f i f f)); DATA(insert ( 1247 typalign 18 0 1 15 0 -1 -1 t p f c f f)); DATA(insert ( 1247 typstorage 18 0 1 16 0 -1 -1 t p f c f f)); DATA(insert ( 1247 typnotnull 16 0 1 17 0 -1 -1 t p f c f f)); -DATA(insert ( 1247 typmod 23 0 4 18 0 -1 -1 t p f i f f)); -DATA(insert ( 1247 typbasetype 26 0 4 19 0 -1 -1 t p f i f f)); +DATA(insert ( 1247 typbasetype 26 0 4 18 0 -1 -1 t p f i f f)); +DATA(insert ( 1247 typtypmod 23 0 4 19 0 -1 -1 t p f i f f)); DATA(insert ( 1247 typndims 23 0 4 20 0 -1 -1 t p f i f f)); DATA(insert ( 1247 typdefaultbin 25 0 -1 21 0 -1 -1 f x f i f f)); DATA(insert ( 1247 typdefault 25 0 -1 22 0 -1 -1 f x f i f f)); diff --git a/src/include/catalog/pg_type.h b/src/include/catalog/pg_type.h index 9aaea0cb3b..d1d2c02f78 100644 --- a/src/include/catalog/pg_type.h +++ b/src/include/catalog/pg_type.h @@ -8,7 +8,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: pg_type.h,v 1.117 2002/03/19 02:18:23 momjian Exp $ + * $Id: pg_type.h,v 1.118 2002/03/20 19:44:57 tgl Exp $ * * NOTES * the genbki.sh script reads this file and generates .bki @@ -151,36 +151,41 @@ CATALOG(pg_type) BOOTSTRAP bool typnotnull; /* - * typmod records type-specific data supplied at domain creation - * time (for example, the max length of a varchar field). It is - * passed to type-specific input and output functions as the third - * argument. The value will generally be -1 for types that do not need - * typmod. This value is copied to pg_attribute.atttypmod. + * Domains use typbasetype to show the base (or complex) type that + * the domain is based on. Zero if the type is not a domain. */ - int4 typmod; + Oid typbasetype; /* - * Domains use typbasetype to determine the base (or complex)type that - * the domain is based off. It must be non-zero if the type is a - * domain. + * typtypmod records type-specific data supplied at domain creation + * time (for example, the max length of a varchar field). It is + * passed to type-specific input and output functions as the third + * argument. The value will generally be -1 for types that do not need + * typmod. This value is copied to pg_attribute.atttypmod when + * creating a column of a domain type. */ - Oid typbasetype; + int4 typtypmod; /* - * typndims is the declared number of dimensions, if an array typbasetype, - * otherwise zero. + * typndims is the declared number of dimensions for a domain type that + * is an array (with element type typbasetype). Otherwise zero. */ int4 typndims; /* - * typdefaultbin is the binary representation of typdefault + * If typdefaultbin is not NULL, it is the nodeToString representation + * of a default expression for the type. Currently this is only used + * for domains. */ text typdefaultbin; /* VARIABLE LENGTH FIELD */ /* * typdefault is NULL if the type has no associated default value. If - * it's not NULL, it contains the external representation of the - * type's default value + * typdefaultbin is not NULL, typdefault must contain a human-readable + * version of the default expression represented by typdefaultbin. + * If typdefaultbin is NULL and typdefault is not, then typdefault is + * the external representation of the type's default value, which may + * be fed to the type's input converter to produce a constant. */ text typdefault; /* VARIABLE LENGTH FIELD */ @@ -215,8 +220,8 @@ typedef FormData_pg_type *Form_pg_type; #define Anum_pg_type_typalign 15 #define Anum_pg_type_typstorage 16 #define Anum_pg_type_typnotnull 17 -#define Anum_pg_type_typmod 18 -#define Anum_pg_type_typbasetype 19 +#define Anum_pg_type_typbasetype 18 +#define Anum_pg_type_typtypmod 19 #define Anum_pg_type_typndims 20 #define Anum_pg_type_typdefaultbin 21 #define Anum_pg_type_typdefault 22 @@ -235,82 +240,82 @@ typedef FormData_pg_type *Form_pg_type; */ /* OIDS 1 - 99 */ -DATA(insert OID = 16 ( bool PGUID 1 1 t b t \054 0 0 boolin boolout boolin boolout c p f -1 0 0 _null_ _null_ )); +DATA(insert OID = 16 ( bool PGUID 1 1 t b t \054 0 0 boolin boolout boolin boolout c p f 0 -1 0 _null_ _null_ )); DESCR("boolean, 'true'/'false'"); #define BOOLOID 16 -DATA(insert OID = 17 ( bytea PGUID -1 -1 f b t \054 0 0 byteain byteaout byteain byteaout i x f -1 0 0 _null_ _null_ )); +DATA(insert OID = 17 ( bytea PGUID -1 -1 f b t \054 0 0 byteain byteaout byteain byteaout i x f 0 -1 0 _null_ _null_ )); DESCR("variable-length string, binary values escaped"); #define BYTEAOID 17 -DATA(insert OID = 18 ( char PGUID 1 1 t b t \054 0 0 charin charout charin charout c p f -1 0 0 _null_ _null_ )); +DATA(insert OID = 18 ( char PGUID 1 1 t b t \054 0 0 charin charout charin charout c p f 0 -1 0 _null_ _null_ )); DESCR("single character"); #define CHAROID 18 -DATA(insert OID = 19 ( name PGUID NAMEDATALEN NAMEDATALEN f b t \054 0 18 namein nameout namein nameout i p f -1 0 0 _null_ _null_ )); +DATA(insert OID = 19 ( name PGUID NAMEDATALEN NAMEDATALEN f b t \054 0 18 namein nameout namein nameout i p f 0 -1 0 _null_ _null_ )); DESCR("31-character type for storing system identifiers"); #define NAMEOID 19 -DATA(insert OID = 20 ( int8 PGUID 8 20 f b t \054 0 0 int8in int8out int8in int8out d p f -1 0 0 _null_ _null_ )); +DATA(insert OID = 20 ( int8 PGUID 8 20 f b t \054 0 0 int8in int8out int8in int8out d p f 0 -1 0 _null_ _null_ )); DESCR("~18 digit integer, 8-byte storage"); #define INT8OID 20 -DATA(insert OID = 21 ( int2 PGUID 2 5 t b t \054 0 0 int2in int2out int2in int2out s p f -1 0 0 _null_ _null_ )); +DATA(insert OID = 21 ( int2 PGUID 2 5 t b t \054 0 0 int2in int2out int2in int2out 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 PGUID INDEX_MAX_KEYS*2 -1 f b t \054 0 21 int2vectorin int2vectorout int2vectorin int2vectorout i p f -1 0 0 _null_ _null_ )); +DATA(insert OID = 22 ( int2vector PGUID INDEX_MAX_KEYS*2 -1 f b t \054 0 21 int2vectorin int2vectorout int2vectorin int2vectorout i p f 0 -1 0 _null_ _null_ )); DESCR("array of INDEX_MAX_KEYS int2 integers, used in system tables"); #define INT2VECTOROID 22 -DATA(insert OID = 23 ( int4 PGUID 4 10 t b t \054 0 0 int4in int4out int4in int4out i p f -1 0 0 _null_ _null_ )); +DATA(insert OID = 23 ( int4 PGUID 4 10 t b t \054 0 0 int4in int4out int4in int4out 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 PGUID 4 16 t b t \054 0 0 regprocin regprocout regprocin regprocout i p f -1 0 0 _null_ _null_ )); +DATA(insert OID = 24 ( regproc PGUID 4 16 t b t \054 0 0 regprocin regprocout regprocin regprocout i p f 0 -1 0 _null_ _null_ )); DESCR("registered procedure"); #define REGPROCOID 24 -DATA(insert OID = 25 ( text PGUID -1 -1 f b t \054 0 0 textin textout textin textout i x f -1 0 0 _null_ _null_ )); +DATA(insert OID = 25 ( text PGUID -1 -1 f b t \054 0 0 textin textout textin textout i x f 0 -1 0 _null_ _null_ )); DESCR("variable-length string, no limit specified"); #define TEXTOID 25 -DATA(insert OID = 26 ( oid PGUID 4 10 t b t \054 0 0 oidin oidout oidin oidout i p f -1 0 0 _null_ _null_ )); +DATA(insert OID = 26 ( oid PGUID 4 10 t b t \054 0 0 oidin oidout oidin oidout i p f 0 -1 0 _null_ _null_ )); DESCR("object identifier(oid), maximum 4 billion"); #define OIDOID 26 -DATA(insert OID = 27 ( tid PGUID 6 19 f b t \054 0 0 tidin tidout tidin tidout i p f -1 0 0 _null_ _null_ )); +DATA(insert OID = 27 ( tid PGUID 6 19 f b t \054 0 0 tidin tidout tidin tidout i p f 0 -1 0 _null_ _null_ )); DESCR("(Block, offset), physical location of tuple"); #define TIDOID 27 -DATA(insert OID = 28 ( xid PGUID 4 12 t b t \054 0 0 xidin xidout xidin xidout i p f -1 0 0 _null_ _null_ )); +DATA(insert OID = 28 ( xid PGUID 4 12 t b t \054 0 0 xidin xidout xidin xidout i p f 0 -1 0 _null_ _null_ )); DESCR("transaction id"); #define XIDOID 28 -DATA(insert OID = 29 ( cid PGUID 4 10 t b t \054 0 0 cidin cidout cidin cidout i p f -1 0 0 _null_ _null_ )); +DATA(insert OID = 29 ( cid PGUID 4 10 t b t \054 0 0 cidin cidout cidin cidout i p f 0 -1 0 _null_ _null_ )); DESCR("command identifier type, sequence in transaction id"); #define CIDOID 29 -DATA(insert OID = 30 ( oidvector PGUID INDEX_MAX_KEYS*4 -1 f b t \054 0 26 oidvectorin oidvectorout oidvectorin oidvectorout i p f -1 0 0 _null_ _null_ )); +DATA(insert OID = 30 ( oidvector PGUID INDEX_MAX_KEYS*4 -1 f b t \054 0 26 oidvectorin oidvectorout oidvectorin oidvectorout i p f 0 -1 0 _null_ _null_ )); DESCR("array of INDEX_MAX_KEYS oids, used in system tables"); #define OIDVECTOROID 30 -DATA(insert OID = 32 ( SET PGUID -1 -1 f b t \054 0 0 textin textout textin textout i p f -1 0 0 _null_ _null_ )); +DATA(insert OID = 32 ( SET PGUID -1 -1 f b t \054 0 0 textin textout textin textout i p f 0 -1 0 _null_ _null_ )); DESCR("set of tuples"); -DATA(insert OID = 71 ( pg_type PGUID 4 4 t c t \054 1247 0 int4in int4out int4in int4out i p f -1 0 0 _null_ _null_ )); -DATA(insert OID = 75 ( pg_attribute PGUID 4 4 t c t \054 1249 0 int4in int4out int4in int4out i p f -1 0 0 _null_ _null_ )); -DATA(insert OID = 81 ( pg_proc PGUID 4 4 t c t \054 1255 0 int4in int4out int4in int4out i p f -1 0 0 _null_ _null_ )); -DATA(insert OID = 83 ( pg_class PGUID 4 4 t c t \054 1259 0 int4in int4out int4in int4out i p f -1 0 0 _null_ _null_ )); -DATA(insert OID = 86 ( pg_shadow PGUID 4 4 t c t \054 1260 0 int4in int4out int4in int4out i p f -1 0 0 _null_ _null_ )); -DATA(insert OID = 87 ( pg_group PGUID 4 4 t c t \054 1261 0 int4in int4out int4in int4out i p f -1 0 0 _null_ _null_ )); -DATA(insert OID = 88 ( pg_database PGUID 4 4 t c t \054 1262 0 int4in int4out int4in int4out i p f -1 0 0 _null_ _null_ )); +DATA(insert OID = 71 ( pg_type PGUID 4 4 t c t \054 1247 0 int4in int4out int4in int4out i p f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 75 ( pg_attribute PGUID 4 4 t c t \054 1249 0 int4in int4out int4in int4out i p f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 81 ( pg_proc PGUID 4 4 t c t \054 1255 0 int4in int4out int4in int4out i p f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 83 ( pg_class PGUID 4 4 t c t \054 1259 0 int4in int4out int4in int4out i p f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 86 ( pg_shadow PGUID 4 4 t c t \054 1260 0 int4in int4out int4in int4out i p f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 87 ( pg_group PGUID 4 4 t c t \054 1261 0 int4in int4out int4in int4out i p f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 88 ( pg_database PGUID 4 4 t c t \054 1262 0 int4in int4out int4in int4out i p f 0 -1 0 _null_ _null_ )); /* OIDS 100 - 199 */ /* OIDS 200 - 299 */ -DATA(insert OID = 210 ( smgr PGUID 2 12 t b t \054 0 0 smgrin smgrout smgrin smgrout s p f -1 0 0 _null_ _null_ )); +DATA(insert OID = 210 ( smgr PGUID 2 12 t b t \054 0 0 smgrin smgrout smgrin smgrout s p f 0 -1 0 _null_ _null_ )); DESCR("storage manager"); /* OIDS 300 - 399 */ @@ -320,167 +325,167 @@ DESCR("storage manager"); /* OIDS 500 - 599 */ /* OIDS 600 - 699 */ -DATA(insert OID = 600 ( point PGUID 16 24 f b t \054 0 701 point_in point_out point_in point_out d p f -1 0 0 _null_ _null_ )); +DATA(insert OID = 600 ( point PGUID 16 24 f b t \054 0 701 point_in point_out point_in point_out d p f 0 -1 0 _null_ _null_ )); DESCR("geometric point '(x, y)'"); #define POINTOID 600 -DATA(insert OID = 601 ( lseg PGUID 32 48 f b t \054 0 600 lseg_in lseg_out lseg_in lseg_out d p f -1 0 0 _null_ _null_ )); +DATA(insert OID = 601 ( lseg PGUID 32 48 f b t \054 0 600 lseg_in lseg_out lseg_in lseg_out d p f 0 -1 0 _null_ _null_ )); DESCR("geometric line segment '(pt1,pt2)'"); #define LSEGOID 601 -DATA(insert OID = 602 ( path PGUID -1 -1 f b t \054 0 0 path_in path_out path_in path_out d x f -1 0 0 _null_ _null_ )); +DATA(insert OID = 602 ( path PGUID -1 -1 f b t \054 0 0 path_in path_out path_in path_out d x f 0 -1 0 _null_ _null_ )); DESCR("geometric path '(pt1,...)'"); #define PATHOID 602 -DATA(insert OID = 603 ( box PGUID 32 100 f b t \073 0 600 box_in box_out box_in box_out d p f -1 0 0 _null_ _null_ )); +DATA(insert OID = 603 ( box PGUID 32 100 f b t \073 0 600 box_in box_out box_in box_out d p f 0 -1 0 _null_ _null_ )); DESCR("geometric box '(lower left,upper right)'"); #define BOXOID 603 -DATA(insert OID = 604 ( polygon PGUID -1 -1 f b t \054 0 0 poly_in poly_out poly_in poly_out d x f -1 0 0 _null_ _null_ )); +DATA(insert OID = 604 ( polygon PGUID -1 -1 f b t \054 0 0 poly_in poly_out poly_in poly_out d x f 0 -1 0 _null_ _null_ )); DESCR("geometric polygon '(pt1,...)'"); #define POLYGONOID 604 -DATA(insert OID = 628 ( line PGUID 32 48 f b t \054 0 701 line_in line_out line_in line_out d p f -1 0 0 _null_ _null_ )); +DATA(insert OID = 628 ( line PGUID 32 48 f b t \054 0 701 line_in line_out line_in line_out d p f 0 -1 0 _null_ _null_ )); DESCR("geometric line '(pt1,pt2)'"); #define LINEOID 628 -DATA(insert OID = 629 ( _line PGUID -1 -1 f b t \054 0 628 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ )); +DATA(insert OID = 629 ( _line PGUID -1 -1 f b t \054 0 628 array_in array_out array_in array_out d x f 0 -1 0 _null_ _null_ )); DESCR(""); /* OIDS 700 - 799 */ -DATA(insert OID = 700 ( float4 PGUID 4 12 f b t \054 0 0 float4in float4out float4in float4out i p f -1 0 0 _null_ _null_ )); +DATA(insert OID = 700 ( float4 PGUID 4 12 f b t \054 0 0 float4in float4out float4in float4out 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 PGUID 8 24 f b t \054 0 0 float8in float8out float8in float8out d p f -1 0 0 _null_ _null_ )); +DATA(insert OID = 701 ( float8 PGUID 8 24 f b t \054 0 0 float8in float8out float8in float8out 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 PGUID 4 20 t b t \054 0 0 nabstimein nabstimeout nabstimein nabstimeout i p f -1 0 0 _null_ _null_ )); +DATA(insert OID = 702 ( abstime PGUID 4 20 t b t \054 0 0 nabstimein nabstimeout nabstimein nabstimeout 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 PGUID 4 20 t b t \054 0 0 reltimein reltimeout reltimein reltimeout i p f -1 0 0 _null_ _null_ )); +DATA(insert OID = 703 ( reltime PGUID 4 20 t b t \054 0 0 reltimein reltimeout reltimein reltimeout 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 PGUID 12 47 f b t \054 0 0 tintervalin tintervalout tintervalin tintervalout i p f -1 0 0 _null_ _null_ )); +DATA(insert OID = 704 ( tinterval PGUID 12 47 f b t \054 0 0 tintervalin tintervalout tintervalin tintervalout i p f 0 -1 0 _null_ _null_ )); DESCR("(abstime,abstime), time interval"); #define TINTERVALOID 704 -DATA(insert OID = 705 ( unknown PGUID -1 -1 f b t \054 0 0 textin textout textin textout i p f -1 0 0 _null_ _null_ )); +DATA(insert OID = 705 ( unknown PGUID -1 -1 f b t \054 0 0 textin textout textin textout i p f 0 -1 0 _null_ _null_ )); DESCR(""); #define UNKNOWNOID 705 -DATA(insert OID = 718 ( circle PGUID 24 47 f b t \054 0 0 circle_in circle_out circle_in circle_out d p f -1 0 0 _null_ _null_ )); +DATA(insert OID = 718 ( circle PGUID 24 47 f b t \054 0 0 circle_in circle_out circle_in circle_out d p f 0 -1 0 _null_ _null_ )); DESCR("geometric circle '(center,radius)'"); #define CIRCLEOID 718 -DATA(insert OID = 719 ( _circle PGUID -1 -1 f b t \054 0 718 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ )); -DATA(insert OID = 790 ( money PGUID 4 24 f b t \054 0 0 cash_in cash_out cash_in cash_out i p f -1 0 0 _null_ _null_ )); +DATA(insert OID = 719 ( _circle PGUID -1 -1 f b t \054 0 718 array_in array_out array_in array_out d x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 790 ( money PGUID 4 24 f b t \054 0 0 cash_in cash_out cash_in cash_out i p f 0 -1 0 _null_ _null_ )); DESCR("$d,ddd.cc, money"); #define CASHOID 790 -DATA(insert OID = 791 ( _money PGUID -1 -1 f b t \054 0 790 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ )); +DATA(insert OID = 791 ( _money PGUID -1 -1 f b t \054 0 790 array_in array_out array_in array_out i x f 0 -1 0 _null_ _null_ )); /* OIDS 800 - 899 */ -DATA(insert OID = 829 ( macaddr PGUID 6 -1 f b t \054 0 0 macaddr_in macaddr_out macaddr_in macaddr_out i p f -1 0 0 _null_ _null_ )); +DATA(insert OID = 829 ( macaddr PGUID 6 -1 f b t \054 0 0 macaddr_in macaddr_out macaddr_in macaddr_out 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 PGUID -1 -1 f b t \054 0 0 inet_in inet_out inet_in inet_out i p f -1 0 0 _null_ _null_ )); +DATA(insert OID = 869 ( inet PGUID -1 -1 f b t \054 0 0 inet_in inet_out inet_in inet_out i p f 0 -1 0 _null_ _null_ )); DESCR("IP address/netmask, host address, netmask optional"); #define INETOID 869 -DATA(insert OID = 650 ( cidr PGUID -1 -1 f b t \054 0 0 cidr_in cidr_out cidr_in cidr_out i p f -1 0 0 _null_ _null_ )); +DATA(insert OID = 650 ( cidr PGUID -1 -1 f b t \054 0 0 cidr_in cidr_out cidr_in cidr_out i p 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 PGUID -1 -1 f b t \054 0 16 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ )); -DATA(insert OID = 1001 ( _bytea PGUID -1 -1 f b t \054 0 17 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ )); -DATA(insert OID = 1002 ( _char PGUID -1 -1 f b t \054 0 18 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ )); -DATA(insert OID = 1003 ( _name PGUID -1 -1 f b t \054 0 19 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ )); -DATA(insert OID = 1005 ( _int2 PGUID -1 -1 f b t \054 0 21 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ )); -DATA(insert OID = 1006 ( _int2vector PGUID -1 -1 f b t \054 0 22 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ )); -DATA(insert OID = 1007 ( _int4 PGUID -1 -1 f b t \054 0 23 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ )); -DATA(insert OID = 1008 ( _regproc PGUID -1 -1 f b t \054 0 24 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ )); -DATA(insert OID = 1009 ( _text PGUID -1 -1 f b t \054 0 25 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ )); -DATA(insert OID = 1028 ( _oid PGUID -1 -1 f b t \054 0 26 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ )); -DATA(insert OID = 1010 ( _tid PGUID -1 -1 f b t \054 0 27 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ )); -DATA(insert OID = 1011 ( _xid PGUID -1 -1 f b t \054 0 28 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ )); -DATA(insert OID = 1012 ( _cid PGUID -1 -1 f b t \054 0 29 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ )); -DATA(insert OID = 1013 ( _oidvector PGUID -1 -1 f b t \054 0 30 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ )); -DATA(insert OID = 1014 ( _bpchar PGUID -1 -1 f b t \054 0 1042 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ )); -DATA(insert OID = 1015 ( _varchar PGUID -1 -1 f b t \054 0 1043 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ )); -DATA(insert OID = 1016 ( _int8 PGUID -1 -1 f b t \054 0 20 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ )); -DATA(insert OID = 1017 ( _point PGUID -1 -1 f b t \054 0 600 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ )); -DATA(insert OID = 1018 ( _lseg PGUID -1 -1 f b t \054 0 601 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ )); -DATA(insert OID = 1019 ( _path PGUID -1 -1 f b t \054 0 602 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ )); -DATA(insert OID = 1020 ( _box PGUID -1 -1 f b t \073 0 603 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ )); -DATA(insert OID = 1021 ( _float4 PGUID -1 -1 f b t \054 0 700 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ )); -DATA(insert OID = 1022 ( _float8 PGUID -1 -1 f b t \054 0 701 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ )); -DATA(insert OID = 1023 ( _abstime PGUID -1 -1 f b t \054 0 702 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ )); -DATA(insert OID = 1024 ( _reltime PGUID -1 -1 f b t \054 0 703 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ )); -DATA(insert OID = 1025 ( _tinterval PGUID -1 -1 f b t \054 0 704 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ )); -DATA(insert OID = 1027 ( _polygon PGUID -1 -1 f b t \054 0 604 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ )); +DATA(insert OID = 1000 ( _bool PGUID -1 -1 f b t \054 0 16 array_in array_out array_in array_out i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1001 ( _bytea PGUID -1 -1 f b t \054 0 17 array_in array_out array_in array_out i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1002 ( _char PGUID -1 -1 f b t \054 0 18 array_in array_out array_in array_out i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1003 ( _name PGUID -1 -1 f b t \054 0 19 array_in array_out array_in array_out i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1005 ( _int2 PGUID -1 -1 f b t \054 0 21 array_in array_out array_in array_out i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1006 ( _int2vector PGUID -1 -1 f b t \054 0 22 array_in array_out array_in array_out i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1007 ( _int4 PGUID -1 -1 f b t \054 0 23 array_in array_out array_in array_out i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1008 ( _regproc PGUID -1 -1 f b t \054 0 24 array_in array_out array_in array_out i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1009 ( _text PGUID -1 -1 f b t \054 0 25 array_in array_out array_in array_out i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1028 ( _oid PGUID -1 -1 f b t \054 0 26 array_in array_out array_in array_out i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1010 ( _tid PGUID -1 -1 f b t \054 0 27 array_in array_out array_in array_out i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1011 ( _xid PGUID -1 -1 f b t \054 0 28 array_in array_out array_in array_out i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1012 ( _cid PGUID -1 -1 f b t \054 0 29 array_in array_out array_in array_out i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1013 ( _oidvector PGUID -1 -1 f b t \054 0 30 array_in array_out array_in array_out i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1014 ( _bpchar PGUID -1 -1 f b t \054 0 1042 array_in array_out array_in array_out i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1015 ( _varchar PGUID -1 -1 f b t \054 0 1043 array_in array_out array_in array_out i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1016 ( _int8 PGUID -1 -1 f b t \054 0 20 array_in array_out array_in array_out d x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1017 ( _point PGUID -1 -1 f b t \054 0 600 array_in array_out array_in array_out d x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1018 ( _lseg PGUID -1 -1 f b t \054 0 601 array_in array_out array_in array_out d x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1019 ( _path PGUID -1 -1 f b t \054 0 602 array_in array_out array_in array_out d x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1020 ( _box PGUID -1 -1 f b t \073 0 603 array_in array_out array_in array_out d x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1021 ( _float4 PGUID -1 -1 f b t \054 0 700 array_in array_out array_in array_out i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1022 ( _float8 PGUID -1 -1 f b t \054 0 701 array_in array_out array_in array_out d x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1023 ( _abstime PGUID -1 -1 f b t \054 0 702 array_in array_out array_in array_out i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1024 ( _reltime PGUID -1 -1 f b t \054 0 703 array_in array_out array_in array_out i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1025 ( _tinterval PGUID -1 -1 f b t \054 0 704 array_in array_out array_in array_out i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1027 ( _polygon PGUID -1 -1 f b t \054 0 604 array_in array_out array_in array_out d x f 0 -1 0 _null_ _null_ )); /* * Note: the size of aclitem needs to match sizeof(AclItem) in acl.h. * Thanks to some padding, this will be 8 on all platforms. * We also have an Assert to make sure. */ #define ACLITEMSIZE 8 -DATA(insert OID = 1033 ( aclitem PGUID 8 -1 f b t \054 0 0 aclitemin aclitemout aclitemin aclitemout i p f -1 0 0 _null_ _null_ )); +DATA(insert OID = 1033 ( aclitem PGUID 8 -1 f b t \054 0 0 aclitemin aclitemout aclitemin aclitemout i p f 0 -1 0 _null_ _null_ )); DESCR("access control list"); -DATA(insert OID = 1034 ( _aclitem PGUID -1 -1 f b t \054 0 1033 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ )); -DATA(insert OID = 1040 ( _macaddr PGUID -1 -1 f b t \054 0 829 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ )); -DATA(insert OID = 1041 ( _inet PGUID -1 -1 f b t \054 0 869 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ )); -DATA(insert OID = 651 ( _cidr PGUID -1 -1 f b t \054 0 650 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ )); -DATA(insert OID = 1042 ( bpchar PGUID -1 -1 f b t \054 0 0 bpcharin bpcharout bpcharin bpcharout i x f -1 0 0 _null_ _null_ )); +DATA(insert OID = 1034 ( _aclitem PGUID -1 -1 f b t \054 0 1033 array_in array_out array_in array_out i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1040 ( _macaddr PGUID -1 -1 f b t \054 0 829 array_in array_out array_in array_out i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1041 ( _inet PGUID -1 -1 f b t \054 0 869 array_in array_out array_in array_out i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 651 ( _cidr PGUID -1 -1 f b t \054 0 650 array_in array_out array_in array_out i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1042 ( bpchar PGUID -1 -1 f b t \054 0 0 bpcharin bpcharout bpcharin bpcharout 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 PGUID -1 -1 f b t \054 0 0 varcharin varcharout varcharin varcharout i x f -1 0 0 _null_ _null_ )); +DATA(insert OID = 1043 ( varchar PGUID -1 -1 f b t \054 0 0 varcharin varcharout varcharin varcharout 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 PGUID 4 10 t b t \054 0 0 date_in date_out date_in date_out i p f -1 0 0 _null_ _null_ )); +DATA(insert OID = 1082 ( date PGUID 4 10 t b t \054 0 0 date_in date_out date_in date_out i p f 0 -1 0 _null_ _null_ )); DESCR("ANSI SQL date"); #define DATEOID 1082 -DATA(insert OID = 1083 ( time PGUID 8 16 f b t \054 0 0 time_in time_out time_in time_out d p f -1 0 0 _null_ _null_ )); +DATA(insert OID = 1083 ( time PGUID 8 16 f b t \054 0 0 time_in time_out time_in time_out 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 PGUID 8 47 f b t \054 0 0 timestamp_in timestamp_out timestamp_in timestamp_out d p f -1 0 0 _null_ _null_ )); +DATA(insert OID = 1114 ( timestamp PGUID 8 47 f b t \054 0 0 timestamp_in timestamp_out timestamp_in timestamp_out d p f 0 -1 0 _null_ _null_ )); DESCR("date and time"); #define TIMESTAMPOID 1114 -DATA(insert OID = 1115 ( _timestamp PGUID -1 -1 f b t \054 0 1184 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ )); -DATA(insert OID = 1182 ( _date PGUID -1 -1 f b t \054 0 1082 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ )); -DATA(insert OID = 1183 ( _time PGUID -1 -1 f b t \054 0 1083 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ )); -DATA(insert OID = 1184 ( timestamptz PGUID 8 47 f b t \054 0 0 timestamptz_in timestamptz_out timestamptz_in timestamptz_out d p f -1 0 0 _null_ _null_ )); +DATA(insert OID = 1115 ( _timestamp PGUID -1 -1 f b t \054 0 1184 array_in array_out array_in array_out d x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1182 ( _date PGUID -1 -1 f b t \054 0 1082 array_in array_out array_in array_out i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1183 ( _time PGUID -1 -1 f b t \054 0 1083 array_in array_out array_in array_out d x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1184 ( timestamptz PGUID 8 47 f b t \054 0 0 timestamptz_in timestamptz_out timestamptz_in timestamptz_out d p f 0 -1 0 _null_ _null_ )); DESCR("date and time with time zone"); #define TIMESTAMPTZOID 1184 -DATA(insert OID = 1185 ( _timestamptz PGUID -1 -1 f b t \054 0 1184 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ )); -DATA(insert OID = 1186 ( interval PGUID 12 47 f b t \054 0 0 interval_in interval_out interval_in interval_out d p f -1 0 0 _null_ _null_ )); +DATA(insert OID = 1185 ( _timestamptz PGUID -1 -1 f b t \054 0 1184 array_in array_out array_in array_out d x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1186 ( interval PGUID 12 47 f b t \054 0 0 interval_in interval_out interval_in interval_out d p f 0 -1 0 _null_ _null_ )); DESCR("@ , time interval"); #define INTERVALOID 1186 -DATA(insert OID = 1187 ( _interval PGUID -1 -1 f b t \054 0 1186 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ )); +DATA(insert OID = 1187 ( _interval PGUID -1 -1 f b t \054 0 1186 array_in array_out array_in array_out d x f 0 -1 0 _null_ _null_ )); /* OIDS 1200 - 1299 */ -DATA(insert OID = 1231 ( _numeric PGUID -1 -1 f b t \054 0 1700 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ )); -DATA(insert OID = 1266 ( timetz PGUID 12 22 f b t \054 0 0 timetz_in timetz_out timetz_in timetz_out d p f -1 0 0 _null_ _null_ )); +DATA(insert OID = 1231 ( _numeric PGUID -1 -1 f b t \054 0 1700 array_in array_out array_in array_out i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1266 ( timetz PGUID 12 22 f b t \054 0 0 timetz_in timetz_out timetz_in timetz_out d p f 0 -1 0 _null_ _null_ )); DESCR("hh:mm:ss, ANSI SQL time"); #define TIMETZOID 1266 -DATA(insert OID = 1270 ( _timetz PGUID -1 -1 f b t \054 0 1266 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ )); +DATA(insert OID = 1270 ( _timetz PGUID -1 -1 f b t \054 0 1266 array_in array_out array_in array_out d x f 0 -1 0 _null_ _null_ )); /* OIDS 1500 - 1599 */ -DATA(insert OID = 1560 ( bit PGUID -1 -1 f b t \054 0 0 bit_in bit_out bit_in bit_out i x f -1 0 0 _null_ _null_ )); +DATA(insert OID = 1560 ( bit PGUID -1 -1 f b t \054 0 0 bit_in bit_out bit_in bit_out i x f 0 -1 0 _null_ _null_ )); DESCR("fixed-length bit string"); #define BITOID 1560 -DATA(insert OID = 1561 ( _bit PGUID -1 -1 f b t \054 0 1560 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ )); -DATA(insert OID = 1562 ( varbit PGUID -1 -1 f b t \054 0 0 varbit_in varbit_out varbit_in varbit_out i x f -1 0 0 _null_ _null_ )); +DATA(insert OID = 1561 ( _bit PGUID -1 -1 f b t \054 0 1560 array_in array_out array_in array_out i x f 0 -1 0 _null_ _null_ )); +DATA(insert OID = 1562 ( varbit PGUID -1 -1 f b t \054 0 0 varbit_in varbit_out varbit_in varbit_out i x f 0 -1 0 _null_ _null_ )); DESCR("variable-length bit string"); #define VARBITOID 1562 -DATA(insert OID = 1563 ( _varbit PGUID -1 -1 f b t \054 0 1562 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ )); +DATA(insert OID = 1563 ( _varbit PGUID -1 -1 f b t \054 0 1562 array_in array_out array_in array_out i x f 0 -1 0 _null_ _null_ )); /* OIDS 1600 - 1699 */ /* OIDS 1700 - 1799 */ -DATA(insert OID = 1700 ( numeric PGUID -1 -1 f b t \054 0 0 numeric_in numeric_out numeric_in numeric_out i m f -1 0 0 _null_ _null_ )); +DATA(insert OID = 1700 ( numeric PGUID -1 -1 f b t \054 0 0 numeric_in numeric_out numeric_in numeric_out i m f 0 -1 0 _null_ _null_ )); DESCR("numeric(precision, decimal), arbitrary precision number"); #define NUMERICOID 1700 /* OID 1790 */ -DATA(insert OID = 1790 ( refcursor PGUID -1 -1 f b t \054 0 0 textin textout textin textout i x f -1 0 0 _null_ _null_ )); +DATA(insert OID = 1790 ( refcursor PGUID -1 -1 f b t \054 0 0 textin textout textin textout i x f 0 -1 0 _null_ _null_ )); DESCR("reference cursor (portal name)"); #define REFCURSOROID 1790 diff --git a/src/include/nodes/makefuncs.h b/src/include/nodes/makefuncs.h index d8f7abc1d8..384241990b 100644 --- a/src/include/nodes/makefuncs.h +++ b/src/include/nodes/makefuncs.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: makefuncs.h,v 1.30 2001/11/05 17:46:34 momjian Exp $ + * $Id: makefuncs.h,v 1.31 2002/03/20 19:45:01 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -46,4 +46,6 @@ extern Const *makeNullConst(Oid consttype); extern Attr *makeAttr(char *relname, char *attname); +extern RelabelType *makeRelabelType(Node *arg, Oid rtype, int32 rtypmod); + #endif /* MAKEFUNC_H */ diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index 71552abbc7..1b1f01bd28 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: parsenodes.h,v 1.161 2002/03/19 02:18:24 momjian Exp $ + * $Id: parsenodes.h,v 1.162 2002/03/20 19:45:02 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -407,23 +407,6 @@ typedef struct DefElem } DefElem; -/**************************************************************************** - * Nodes for a Domain Creation tree - ****************************************************************************/ -/* ---------------------- - * CreateDomain Statement - * ---------------------- - * Down here as it required TypeName to be defined first. - */ -typedef struct CreateDomainStmt -{ - NodeTag type; - char *domainname; /* name of domain to create */ - TypeName *typename; /* the typecast */ - List *constraints; /* constraints (list of Constraint nodes) */ -} CreateDomainStmt; - - /**************************************************************************** * Nodes for a Query tree ****************************************************************************/ @@ -1056,11 +1039,23 @@ typedef struct VersionStmt typedef struct DefineStmt { NodeTag type; - int defType; /* OPERATOR|P_TYPE|AGGREGATE */ + int defType; /* OPERATOR|TYPE_P|AGGREGATE */ char *defname; List *definition; /* a list of DefElem */ } DefineStmt; +/* ---------------------- + * Create Domain Statement + * ---------------------- + */ +typedef struct CreateDomainStmt +{ + NodeTag type; + char *domainname; /* name of domain to create */ + TypeName *typename; /* the base type */ + List *constraints; /* constraints (list of Constraint nodes) */ +} CreateDomainStmt; + /* ---------------------- * Drop Table|Sequence|View|Index|Rule|Type Statement * ---------------------- @@ -1071,8 +1066,8 @@ typedef struct DefineStmt #define DROP_VIEW 3 #define DROP_INDEX 4 #define DROP_RULE 5 -#define DROP_TYPE_P 6 -#define DROP_DOMAIN_P 7 +#define DROP_TYPE 6 +#define DROP_DOMAIN 7 typedef struct DropStmt { diff --git a/src/include/parser/parse_coerce.h b/src/include/parser/parse_coerce.h index d2c91ed25f..1c503aed65 100644 --- a/src/include/parser/parse_coerce.h +++ b/src/include/parser/parse_coerce.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: parse_coerce.h,v 1.40 2002/03/19 02:18:24 momjian Exp $ + * $Id: parse_coerce.h,v 1.41 2002/03/20 19:45:07 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -34,38 +34,7 @@ typedef enum CATEGORY } CATEGORY; -/* IS_BINARY_COMPATIBLE() - * Check for types with the same underlying binary representation. - * This allows us to cheat and directly exchange values without - * going through the trouble of calling a conversion function. - * - * Remove equivalencing of FLOAT8 and TIMESTAMP. They really are not - * close enough in behavior, with the TIMESTAMP reserved values - * and special formatting. - thomas 1999-01-24 - */ -#define IS_BINARY_COMPATIBLE(a,b) \ - (((a) == BPCHAROID && (b) == TEXTOID) \ - || ((a) == BPCHAROID && (b) == VARCHAROID) \ - || ((a) == VARCHAROID && (b) == TEXTOID) \ - || ((a) == VARCHAROID && (b) == BPCHAROID) \ - || ((a) == TEXTOID && (b) == BPCHAROID) \ - || ((a) == TEXTOID && (b) == VARCHAROID) \ - || ((a) == OIDOID && (b) == INT4OID) \ - || ((a) == OIDOID && (b) == REGPROCOID) \ - || ((a) == INT4OID && (b) == OIDOID) \ - || ((a) == INT4OID && (b) == REGPROCOID) \ - || ((a) == REGPROCOID && (b) == OIDOID) \ - || ((a) == REGPROCOID && (b) == INT4OID) \ - || ((a) == ABSTIMEOID && (b) == INT4OID) \ - || ((a) == INT4OID && (b) == ABSTIMEOID) \ - || ((a) == RELTIMEOID && (b) == INT4OID) \ - || ((a) == INT4OID && (b) == RELTIMEOID) \ - || ((a) == INETOID && (b) == CIDROID) \ - || ((a) == CIDROID && (b) == INETOID) \ - || ((a) == BITOID && (b) == VARBITOID) \ - || ((a) == VARBITOID && (b) == BITOID)) - - +extern bool IsBinaryCompatible(Oid type1, Oid type2); extern bool IsPreferredType(CATEGORY category, Oid type); extern CATEGORY TypeCategory(Oid type); @@ -81,6 +50,5 @@ extern Oid select_common_type(List *typeids, const char *context); extern Node *coerce_to_common_type(ParseState *pstate, Node *node, Oid targetTypeId, const char *context); -extern Oid getBaseType(Oid inType); #endif /* PARSE_COERCE_H */ diff --git a/src/include/utils/lsyscache.h b/src/include/utils/lsyscache.h index 9b0ff8514d..fbdb5f6634 100644 --- a/src/include/utils/lsyscache.h +++ b/src/include/utils/lsyscache.h @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: lsyscache.h,v 1.43 2002/03/19 02:18:24 momjian Exp $ + * $Id: lsyscache.h,v 1.44 2002/03/20 19:45:09 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -44,7 +44,8 @@ extern int16 get_typlen(Oid typid); extern bool get_typbyval(Oid typid); extern void get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval); extern char get_typstorage(Oid typid); -extern Node *get_typdefault(Oid typid, int32 atttypmod); +extern Node *get_typdefault(Oid typid); +extern Oid getBaseType(Oid typid); extern int32 get_typavgwidth(Oid typid, int32 typmod); extern int32 get_attavgwidth(Oid relid, AttrNumber attnum); extern bool get_attstatsslot(HeapTuple statstuple, diff --git a/src/test/regress/expected/domain.out b/src/test/regress/expected/domain.out index 4d8d13ec2d..7127215869 100644 --- a/src/test/regress/expected/domain.out +++ b/src/test/regress/expected/domain.out @@ -3,9 +3,9 @@ create domain domaindroptest int4; comment on domain domaindroptest is 'About to drop this..'; create domain basetypetest domaindroptest; ERROR: DefineDomain: domaindroptest is not a basetype +drop domain domaindroptest cascade; +ERROR: DROP DOMAIN does not support the CASCADE keyword drop domain domaindroptest; -ERROR: parser: parse error at or near ";" -drop domain domaindroptest restrict; -- TEST Domains. create domain domainvarchar varchar(5); create domain domainnumeric numeric(8,2); @@ -29,11 +29,21 @@ select * from basictest; 88 | haha | short | 123.12 (2 rows) +-- check that domains inherit operations from base types +-- XXX shouldn't have to quote the constant here +select testtext || testvarchar as concat, testnumeric + '42' as sum +from basictest; + concat | sum +-----------+-------- + hahashort | 165.12 + hahashort | 165.12 +(2 rows) + drop table basictest; drop domain domainvarchar restrict; drop domain domainnumeric restrict; drop domain domainint4 restrict; -drop domain domaintext restrict; +drop domain domaintext; -- Array Test create domain domainint4arr int4[1]; create domain domaintextarr text[2][3]; @@ -46,6 +56,26 @@ INSERT INTO domarrtest values ('{{2,2}{2,2}}', '{{"a","b"}}'); INSERT INTO domarrtest values ('{2,2}', '{{"a","b"}{"c","d"}{"e"}}'); INSERT INTO domarrtest values ('{2,2}', '{{"a"}{"c"}}'); INSERT INTO domarrtest values (NULL, '{{"a","b"}{"c","d","e"}}'); +select * from domarrtest; + testint4arr | testtextarr +---------------+--------------------- + {2,2} | {{a,c},{"",d}} + {{2,2},{0,2}} | {{a,b}} + {2,2} | {{a},{c},{e}} + {2,2} | {{c},{""}} + | {{a,c,""},{"",d,e}} +(5 rows) + +select testint4arr[1], testtextarr[2:2] from domarrtest; + testint4arr | testtextarr +-------------+------------- + 2 | {{"",d}} + | + 2 | {{c}} + 2 | {{""}} + | {{"",d,e}} +(5 rows) + drop table domarrtest; drop domain domainint4arr restrict; drop domain domaintextarr restrict; diff --git a/src/test/regress/sql/domain.sql b/src/test/regress/sql/domain.sql index 1417fe3189..cecb876c38 100644 --- a/src/test/regress/sql/domain.sql +++ b/src/test/regress/sql/domain.sql @@ -6,8 +6,8 @@ comment on domain domaindroptest is 'About to drop this..'; create domain basetypetest domaindroptest; +drop domain domaindroptest cascade; drop domain domaindroptest; -drop domain domaindroptest restrict; -- TEST Domains. @@ -31,11 +31,16 @@ INSERT INTO basictest values ('88', 'haha', 'short text', '123.12'); -- Bad varc INSERT INTO basictest values ('88', 'haha', 'short', '123.1212'); -- Truncate numeric select * from basictest; +-- check that domains inherit operations from base types +-- XXX shouldn't have to quote the constant here +select testtext || testvarchar as concat, testnumeric + '42' as sum +from basictest; + drop table basictest; drop domain domainvarchar restrict; drop domain domainnumeric restrict; drop domain domainint4 restrict; -drop domain domaintext restrict; +drop domain domaintext; -- Array Test @@ -51,6 +56,8 @@ INSERT INTO domarrtest values ('{{2,2}{2,2}}', '{{"a","b"}}'); INSERT INTO domarrtest values ('{2,2}', '{{"a","b"}{"c","d"}{"e"}}'); INSERT INTO domarrtest values ('{2,2}', '{{"a"}{"c"}}'); INSERT INTO domarrtest values (NULL, '{{"a","b"}{"c","d","e"}}'); +select * from domarrtest; +select testint4arr[1], testtextarr[2:2] from domarrtest; drop table domarrtest; drop domain domainint4arr restrict;