aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/catalog/pg_type.c74
-rw-r--r--src/backend/commands/typecmds.c49
-rw-r--r--src/backend/parser/gram.y11
-rw-r--r--src/backend/utils/adt/pseudotypes.c28
-rw-r--r--src/include/catalog/catversion.h4
-rw-r--r--src/include/catalog/pg_operator.h6
-rw-r--r--src/include/catalog/pg_proc.h8
-rw-r--r--src/include/utils/builtins.h4
-rw-r--r--src/test/regress/expected/create_type.out28
-rw-r--r--src/test/regress/sql/create_type.sql21
10 files changed, 171 insertions, 62 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 */
+}
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index 1a391bad3f3..dbca22ea761 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.316 2006/02/26 18:36:21 neilc Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.317 2006/02/28 22:37:26 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -53,6 +53,6 @@
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 200602251
+#define CATALOG_VERSION_NO 200602281
#endif
diff --git a/src/include/catalog/pg_operator.h b/src/include/catalog/pg_operator.h
index a746bff2711..84fb254f97b 100644
--- a/src/include/catalog/pg_operator.h
+++ b/src/include/catalog/pg_operator.h
@@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/catalog/pg_operator.h,v 1.140 2006/02/26 18:36:21 neilc Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_operator.h,v 1.141 2006/02/28 22:37:26 tgl Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
@@ -128,9 +128,9 @@ DATA(insert OID = 388 ( "!" PGNSP PGUID r f 20 0 1700 0 0 0 0 0
DATA(insert OID = 389 ( "!!" PGNSP PGUID l f 0 20 1700 0 0 0 0 0 0 numeric_fac - - ));
DATA(insert OID = 385 ( "=" PGNSP PGUID b t 29 29 16 385 0 0 0 0 0 cideq eqsel eqjoinsel ));
DATA(insert OID = 386 ( "=" PGNSP PGUID b t 22 22 16 386 0 0 0 0 0 int2vectoreq eqsel eqjoinsel ));
-DATA(insert OID = 387 ( "=" PGNSP PGUID b f 27 27 16 387 0 0 0 0 0 tideq eqsel eqjoinsel ));
+DATA(insert OID = 387 ( "=" PGNSP PGUID b f 27 27 16 387 402 0 0 0 0 tideq eqsel eqjoinsel ));
#define TIDEqualOperator 387
-DATA(insert OID = 402 ( "<>" PGNSP PGUID b f 27 27 16 402 0 0 0 0 0 tidne neqsel neqjoinsel ));
+DATA(insert OID = 402 ( "<>" PGNSP PGUID b f 27 27 16 402 387 0 0 0 0 tidne neqsel neqjoinsel ));
DATA(insert OID = 410 ( "=" PGNSP PGUID b t 20 20 16 410 411 412 412 412 413 int8eq eqsel eqjoinsel ));
DATA(insert OID = 411 ( "<>" PGNSP PGUID b f 20 20 16 411 410 0 0 0 0 int8ne neqsel neqjoinsel ));
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index ec43235eef3..4a9da19366e 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.398 2006/02/26 18:36:21 neilc Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.399 2006/02/28 22:37:26 tgl Exp $
*
* NOTES
* The script catalog/genbki.sh reads this file and generates .bki
@@ -1598,7 +1598,7 @@ DATA(insert OID = 1293 ( currtid PGNSP PGUID 12 f f t f v 2 27 "26 27" _null
DESCR("latest tid of a tuple");
DATA(insert OID = 1294 ( currtid2 PGNSP PGUID 12 f f t f v 2 27 "25 27" _null_ _null_ _null_ currtid_byrelname - _null_ ));
DESCR("latest tid of a tuple");
-DATA(insert OID = 2398 ( tidne PGNSP PGUID 12 f f t f i 2 16 "27 27" _null_ _null_ _null_ tidne - _null_ ));
+DATA(insert OID = 1265 ( tidne PGNSP PGUID 12 f f t f i 2 16 "27 27" _null_ _null_ _null_ tidne - _null_ ));
DESCR("not equal");
DATA(insert OID = 2168 ( pg_database_size PGNSP PGUID 12 f f t f v 1 20 "19" _null_ _null_ _null_ pg_database_size_name - _null_ ));
@@ -3321,6 +3321,10 @@ DATA(insert OID = 2312 ( anyelement_in PGNSP PGUID 12 f f t f i 1 2283 "2275"
DESCR("I/O");
DATA(insert OID = 2313 ( anyelement_out PGNSP PGUID 12 f f t f i 1 2275 "2283" _null_ _null_ _null_ anyelement_out - _null_ ));
DESCR("I/O");
+DATA(insert OID = 2398 ( shell_in PGNSP PGUID 12 f f t f i 1 2282 "2275" _null_ _null_ _null_ shell_in - _null_ ));
+DESCR("I/O");
+DATA(insert OID = 2399 ( shell_out PGNSP PGUID 12 f f t f i 1 2275 "2282" _null_ _null_ _null_ shell_out - _null_ ));
+DESCR("I/O");
/* cryptographic */
DATA(insert OID = 2311 ( md5 PGNSP PGUID 12 f f t f i 1 25 "25" _null_ _null_ _null_ md5_text - _null_ ));
diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h
index 28a70d11ce7..50f349abdfd 100644
--- a/src/include/utils/builtins.h
+++ b/src/include/utils/builtins.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.274 2006/02/26 18:36:22 neilc Exp $
+ * $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.275 2006/02/28 22:37:27 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -443,6 +443,8 @@ extern Datum opaque_in(PG_FUNCTION_ARGS);
extern Datum opaque_out(PG_FUNCTION_ARGS);
extern Datum anyelement_in(PG_FUNCTION_ARGS);
extern Datum anyelement_out(PG_FUNCTION_ARGS);
+extern Datum shell_in(PG_FUNCTION_ARGS);
+extern Datum shell_out(PG_FUNCTION_ARGS);
/* regexp.c */
extern Datum nameregexeq(PG_FUNCTION_ARGS);
diff --git a/src/test/regress/expected/create_type.out b/src/test/regress/expected/create_type.out
index 4e2d44d5c41..3e2edeb1e0b 100644
--- a/src/test/regress/expected/create_type.out
+++ b/src/test/regress/expected/create_type.out
@@ -1,6 +1,11 @@
--
-- CREATE_TYPE
--
+--
+-- Note: widget_in/out were created in create_function_1, without any
+-- prior shell-type creation. These commands therefore complete a test
+-- of the "old style" approach of making the functions first.
+--
CREATE TYPE widget (
internallength = 24,
input = widget_in,
@@ -13,14 +18,27 @@ CREATE TYPE city_budget (
output = int44out,
element = int4
);
+-- Test creation and destruction of shell types
+CREATE TYPE shell;
+CREATE TYPE shell; -- fail, type already present
+ERROR: type "shell" already exists
+DROP TYPE shell;
+DROP TYPE shell; -- fail, type not exist
+ERROR: type "shell" does not exist
+--
-- Test type-related default values (broken in releases before PG 7.2)
+--
+-- This part of the test also exercises the "new style" approach of making
+-- a shell type and then filling it in.
+--
+CREATE TYPE int42;
+CREATE TYPE text_w_default;
-- Make dummy I/O routines using the existing internal support for int4, text
CREATE FUNCTION int42_in(cstring)
RETURNS int42
AS 'int4in'
LANGUAGE internal STRICT;
-NOTICE: type "int42" is not yet defined
-DETAIL: Creating a shell type definition.
+NOTICE: return type int42 is only a shell
CREATE FUNCTION int42_out(int42)
RETURNS cstring
AS 'int4out'
@@ -30,8 +48,7 @@ CREATE FUNCTION text_w_default_in(cstring)
RETURNS text_w_default
AS 'textin'
LANGUAGE internal STRICT;
-NOTICE: type "text_w_default" is not yet defined
-DETAIL: Creating a shell type definition.
+NOTICE: return type text_w_default is only a shell
CREATE FUNCTION text_w_default_out(text_w_default)
RETURNS cstring
AS 'textout'
@@ -76,6 +93,9 @@ COMMENT ON TYPE bad IS 'bad comment';
ERROR: type "bad" does not exist
COMMENT ON TYPE default_test_row IS 'good comment';
COMMENT ON TYPE default_test_row IS NULL;
+-- Check shell type create for existing types
+CREATE TYPE text_w_default; -- should fail
+ERROR: type "text_w_default" already exists
DROP TYPE default_test_row CASCADE;
NOTICE: drop cascades to function get_default_test()
DROP TABLE default_test;
diff --git a/src/test/regress/sql/create_type.sql b/src/test/regress/sql/create_type.sql
index 66d78c9216b..097d51fc925 100644
--- a/src/test/regress/sql/create_type.sql
+++ b/src/test/regress/sql/create_type.sql
@@ -2,6 +2,11 @@
-- CREATE_TYPE
--
+--
+-- Note: widget_in/out were created in create_function_1, without any
+-- prior shell-type creation. These commands therefore complete a test
+-- of the "old style" approach of making the functions first.
+--
CREATE TYPE widget (
internallength = 24,
input = widget_in,
@@ -16,7 +21,20 @@ CREATE TYPE city_budget (
element = int4
);
+-- Test creation and destruction of shell types
+CREATE TYPE shell;
+CREATE TYPE shell; -- fail, type already present
+DROP TYPE shell;
+DROP TYPE shell; -- fail, type not exist
+
+--
-- Test type-related default values (broken in releases before PG 7.2)
+--
+-- This part of the test also exercises the "new style" approach of making
+-- a shell type and then filling it in.
+--
+CREATE TYPE int42;
+CREATE TYPE text_w_default;
-- Make dummy I/O routines using the existing internal support for int4, text
CREATE FUNCTION int42_in(cstring)
@@ -74,6 +92,9 @@ COMMENT ON TYPE bad IS 'bad comment';
COMMENT ON TYPE default_test_row IS 'good comment';
COMMENT ON TYPE default_test_row IS NULL;
+-- Check shell type create for existing types
+CREATE TYPE text_w_default; -- should fail
+
DROP TYPE default_test_row CASCADE;
DROP TABLE default_test;