diff options
Diffstat (limited to 'src/backend')
| -rw-r--r-- | src/backend/catalog/pg_type.c | 74 | ||||
| -rw-r--r-- | src/backend/commands/typecmds.c | 49 | ||||
| -rw-r--r-- | src/backend/parser/gram.y | 11 | ||||
| -rw-r--r-- | src/backend/utils/adt/pseudotypes.c | 28 |
4 files changed, 112 insertions, 50 deletions
diff --git a/src/backend/catalog/pg_type.c b/src/backend/catalog/pg_type.c index ab250b02ea9..f6fbbef005e 100644 --- a/src/backend/catalog/pg_type.c +++ b/src/backend/catalog/pg_type.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/catalog/pg_type.c,v 1.104 2005/10/15 02:49:14 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/catalog/pg_type.c,v 1.105 2006/02/28 22:37:25 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -20,8 +20,11 @@ #include "catalog/pg_namespace.h" #include "catalog/pg_proc.h" #include "catalog/pg_type.h" +#include "commands/typecmds.h" #include "miscadmin.h" +#include "utils/acl.h" #include "utils/builtins.h" +#include "utils/fmgroids.h" #include "utils/lsyscache.h" #include "utils/syscache.h" @@ -29,14 +32,14 @@ /* ---------------------------------------------------------------- * TypeShellMake * - * This procedure inserts a "shell" tuple into the type - * relation. The type tuple inserted has invalid values - * and in particular, the "typisdefined" field is false. + * This procedure inserts a "shell" tuple into the pg_type relation. + * The type tuple inserted has valid but dummy values, and its + * "typisdefined" field is false indicating it's not really defined. * - * This is used so that a tuple exists in the catalogs. - * The invalid fields should be fixed up sometime after - * this routine is called, and then the "typeisdefined" - * field is set to true. -cim 6/15/90 + * This is used so that a tuple exists in the catalogs. The I/O + * functions for the type will link to this tuple. When the full + * CREATE TYPE command is issued, the bogus values will be replaced + * with correct ones, and "typisdefined" will be set to true. * ---------------------------------------------------------------- */ Oid @@ -70,30 +73,35 @@ TypeShellMake(const char *typeName, Oid typeNamespace) /* * initialize *values with the type name and dummy values + * + * The representational details are the same as int4 ... it doesn't + * really matter what they are so long as they are consistent. Also + * note that we give it typtype = 'p' (pseudotype) as extra insurance + * that it won't be mistaken for a usable type. */ i = 0; namestrcpy(&name, typeName); values[i++] = NameGetDatum(&name); /* typname */ values[i++] = ObjectIdGetDatum(typeNamespace); /* typnamespace */ values[i++] = ObjectIdGetDatum(GetUserId()); /* typowner */ - values[i++] = Int16GetDatum(0); /* typlen */ - values[i++] = BoolGetDatum(false); /* typbyval */ - values[i++] = CharGetDatum(0); /* typtype */ - values[i++] = BoolGetDatum(false); /* typisdefined */ - values[i++] = CharGetDatum(0); /* typdelim */ - values[i++] = ObjectIdGetDatum(InvalidOid); /* typrelid */ - values[i++] = ObjectIdGetDatum(InvalidOid); /* typelem */ - values[i++] = ObjectIdGetDatum(InvalidOid); /* typinput */ - values[i++] = ObjectIdGetDatum(InvalidOid); /* typoutput */ - values[i++] = ObjectIdGetDatum(InvalidOid); /* typreceive */ - values[i++] = ObjectIdGetDatum(InvalidOid); /* typsend */ - values[i++] = ObjectIdGetDatum(InvalidOid); /* typanalyze */ - values[i++] = CharGetDatum('i'); /* typalign */ - values[i++] = CharGetDatum('p'); /* typstorage */ - values[i++] = BoolGetDatum(false); /* typnotnull */ - values[i++] = ObjectIdGetDatum(InvalidOid); /* typbasetype */ - values[i++] = Int32GetDatum(-1); /* typtypmod */ - values[i++] = Int32GetDatum(0); /* typndims */ + values[i++] = Int16GetDatum(sizeof(int4)); /* typlen */ + values[i++] = BoolGetDatum(true); /* typbyval */ + values[i++] = CharGetDatum('p'); /* typtype */ + values[i++] = BoolGetDatum(false); /* typisdefined */ + values[i++] = CharGetDatum(DEFAULT_TYPDELIM); /* typdelim */ + values[i++] = ObjectIdGetDatum(InvalidOid); /* typrelid */ + values[i++] = ObjectIdGetDatum(InvalidOid); /* typelem */ + values[i++] = ObjectIdGetDatum(F_SHELL_IN); /* typinput */ + values[i++] = ObjectIdGetDatum(F_SHELL_OUT); /* typoutput */ + values[i++] = ObjectIdGetDatum(InvalidOid); /* typreceive */ + values[i++] = ObjectIdGetDatum(InvalidOid); /* typsend */ + values[i++] = ObjectIdGetDatum(InvalidOid); /* typanalyze */ + values[i++] = CharGetDatum('i'); /* typalign */ + values[i++] = CharGetDatum('p'); /* typstorage */ + values[i++] = BoolGetDatum(false); /* typnotnull */ + values[i++] = ObjectIdGetDatum(InvalidOid); /* typbasetype */ + values[i++] = Int32GetDatum(-1); /* typtypmod */ + values[i++] = Int32GetDatum(0); /* typndims */ nulls[i++] = 'n'; /* typdefaultbin */ nulls[i++] = 'n'; /* typdefault */ @@ -118,8 +126,8 @@ TypeShellMake(const char *typeName, Oid typeNamespace) InvalidOid, 0, GetUserId(), - InvalidOid, - InvalidOid, + F_SHELL_IN, + F_SHELL_OUT, InvalidOid, InvalidOid, InvalidOid, @@ -289,7 +297,13 @@ TypeCreate(const char *typeName, errmsg("type \"%s\" already exists", typeName))); /* - * Okay to update existing "shell" type tuple + * shell type must have been created by same owner + */ + if (((Form_pg_type) GETSTRUCT(tup))->typowner != GetUserId()) + aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TYPE, typeName); + + /* + * Okay to update existing shell type tuple */ tup = heap_modifytuple(tup, RelationGetDescr(pg_type_desc), @@ -350,8 +364,6 @@ TypeCreate(const char *typeName, * If rebuild is true, we remove existing dependencies and rebuild them * from scratch. This is needed for ALTER TYPE, and also when replacing * a shell type. - * - * NOTE: a shell type will have a dependency to its namespace, and no others. */ void GenerateTypeDependencies(Oid typeNamespace, diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c index 143695252f4..f8e1a2665cf 100644 --- a/src/backend/commands/typecmds.c +++ b/src/backend/commands/typecmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.86 2006/01/13 18:06:45 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.87 2006/02/28 22:37:26 tgl Exp $ * * DESCRIPTION * The "DefineFoo" routines take the parse tree and pick out the @@ -138,6 +138,37 @@ DefineType(List *names, List *parameters) errmsg("type names must be %d characters or less", NAMEDATALEN - 2))); + /* + * Look to see if type already exists (presumably as a shell; if not, + * TypeCreate will complain). If it doesn't, create it as a shell, so + * that the OID is known for use in the I/O function definitions. + */ + typoid = GetSysCacheOid(TYPENAMENSP, + CStringGetDatum(typeName), + ObjectIdGetDatum(typeNamespace), + 0, 0); + if (!OidIsValid(typoid)) + { + typoid = TypeShellMake(typeName, typeNamespace); + /* Make new shell type visible for modification below */ + CommandCounterIncrement(); + + /* + * If the command was a parameterless CREATE TYPE, we're done --- + * creating the shell type was all we're supposed to do. + */ + if (parameters == NIL) + return; + } + else + { + /* Complain if dummy CREATE TYPE and entry already exists */ + if (parameters == NIL) + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_OBJECT), + errmsg("type \"%s\" already exists", typeName))); + } + foreach(pl, parameters) { DefElem *defel = (DefElem *) lfirst(pl); @@ -241,22 +272,6 @@ DefineType(List *names, List *parameters) errmsg("type output function must be specified"))); /* - * Look to see if type already exists (presumably as a shell; if not, - * TypeCreate will complain). If it doesn't, create it as a shell, so - * that the OID is known for use in the I/O function definitions. - */ - typoid = GetSysCacheOid(TYPENAMENSP, - CStringGetDatum(typeName), - ObjectIdGetDatum(typeNamespace), - 0, 0); - if (!OidIsValid(typoid)) - { - typoid = TypeShellMake(typeName, typeNamespace); - /* Make new shell type visible for modification below */ - CommandCounterIncrement(); - } - - /* * Convert I/O proc names to OIDs */ inputOid = findTypeInputFunction(inputName, typoid); diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 6cb6f96fa4f..a60d4157b2e 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.530 2006/02/19 00:04:27 neilc Exp $ + * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.531 2006/02/28 22:37:26 tgl Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -2690,6 +2690,15 @@ DefineStmt: n->definition = $4; $$ = (Node *)n; } + | CREATE TYPE_P any_name + { + /* Shell type (identified by lack of definition) */ + DefineStmt *n = makeNode(DefineStmt); + n->kind = OBJECT_TYPE; + n->defnames = $3; + n->definition = NIL; + $$ = (Node *)n; + } | CREATE TYPE_P any_name AS '(' TableFuncElementList ')' { CompositeTypeStmt *n = makeNode(CompositeTypeStmt); diff --git a/src/backend/utils/adt/pseudotypes.c b/src/backend/utils/adt/pseudotypes.c index 105598afcce..98934328271 100644 --- a/src/backend/utils/adt/pseudotypes.c +++ b/src/backend/utils/adt/pseudotypes.c @@ -16,7 +16,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/adt/pseudotypes.c,v 1.15 2004/12/31 22:01:22 pgsql Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/pseudotypes.c,v 1.16 2006/02/28 22:37:26 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -321,3 +321,29 @@ anyelement_out(PG_FUNCTION_ARGS) PG_RETURN_VOID(); /* keep compiler quiet */ } + +/* + * shell_in - input routine for "shell" types (those not yet filled in). + */ +Datum +shell_in(PG_FUNCTION_ARGS) +{ + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot accept a value of a shell type"))); + + PG_RETURN_VOID(); /* keep compiler quiet */ +} + +/* + * shell_out - output routine for "shell" types. + */ +Datum +shell_out(PG_FUNCTION_ARGS) +{ + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot display a value of a shell type"))); + + PG_RETURN_VOID(); /* keep compiler quiet */ +} |
