Index: doc/src/sgml/xtypes.sgml
===================================================================
RCS file: /projects/cvsroot/pgsql/doc/src/sgml/xtypes.sgml,v
retrieving revision 1.25
diff -c -r1.25 xtypes.sgml
*** doc/src/sgml/xtypes.sgml 10 Jan 2005 00:04:38 -0000 1.25
--- doc/src/sgml/xtypes.sgml 20 Feb 2006 11:50:06 -0000
***************
*** 168,175 ****
! To define the complex type, we need to create the
! user-defined I/O functions before creating the type:
CREATE FUNCTION complex_in(cstring)
--- 168,180 ----
! To define the complex type, we first declare it as a shell type:
!
!
! CREATE TYPE complex;
!
!
! Then we create the user-defined I/O functions needed to create the type:
CREATE FUNCTION complex_in(cstring)
***************
*** 193,206 ****
LANGUAGE C IMMUTABLE STRICT;
- Notice that the declarations of the input and output functions must
- reference the not-yet-defined type. This is allowed, but will draw
- warning messages that may be ignored. The input function must
- appear first.
! Finally, we can declare the data type:
CREATE TYPE complex (
internallength = 16,
--- 198,207 ----
LANGUAGE C IMMUTABLE STRICT;
! Finally, we can declare the data type properly:
CREATE TYPE complex (
internallength = 16,
Index: doc/src/sgml/ref/create_type.sgml
===================================================================
RCS file: /projects/cvsroot/pgsql/doc/src/sgml/ref/create_type.sgml,v
retrieving revision 1.60
diff -c -r1.60 create_type.sgml
*** doc/src/sgml/ref/create_type.sgml 13 Jan 2006 18:06:45 -0000 1.60
--- doc/src/sgml/ref/create_type.sgml 20 Feb 2006 11:50:07 -0000
***************
*** 23,29 ****
CREATE TYPE name AS
( attribute_name data_type [, ... ] )
! CREATE TYPE name (
INPUT = input_function,
OUTPUT = output_function
[ , RECEIVE = receive_function ]
--- 23,29 ----
CREATE TYPE name AS
( attribute_name data_type [, ... ] )
! CREATE TYPE name [ (
INPUT = input_function,
OUTPUT = output_function
[ , RECEIVE = receive_function ]
***************
*** 36,42 ****
[ , DEFAULT = default ]
[ , ELEMENT = element ]
[ , DELIMITER = delimiter ]
! )
--- 36,42 ----
[ , DEFAULT = default ]
[ , ELEMENT = element ]
[ , DELIMITER = delimiter ]
! ) ]
***************
*** 142,158 ****
You should at this point be wondering how the input and output functions
! can be declared to have results or arguments of the new type, when they have
! to be created before the new type can be created. The answer is that the
! input function must be created first, then the output function (and
! the binary I/O functions if wanted), and finally the data type.
! PostgreSQL will first see the name of the new
! data type as the return type of the input function. It will create a
! shell> type, which is simply a placeholder entry in
! the system catalog, and link the input function definition to the shell
! type. Similarly the other functions will be linked to the (now already
! existing) shell type. Finally, CREATE TYPE> replaces the
! shell entry with a complete type definition, and the new type can be used.
--- 142,157 ----
You should at this point be wondering how the input and output functions
! can be declared to have results or arguments of the new type, when they
! have to be created before the new type can be created. The answer is
! that the the entire declaration portion of the type is optional. If you
! just issue the command CREATE TYPE foo>, it will create a
! shell> type, which is simply a placeholder entry in the system
! catalog. With the shell type in place, you can create the necessary
! functions. Finally, CREATE TYPE> with a full definition
! replaces the shell entry with a complete type definition and the new
! type can be used. Note that many procedural languages do not allow you to
! create functions that create or return shell types.
***************
*** 468,473 ****
--- 467,485 ----
a notice and change the function's declaration to use the correct
types.
+
+
+ Prior to version 8.2, you could not explicitly create shell types, but an
+ alternate way to create shell types was provided. For this to work the
+ input function must be created first, then the output function (and the
+ binary I/O functions if wanted), and finally the data type.
+ PostgreSQL will first see the name of the new
+ data type as the return type of the input function and create the shell
+ type. This workaround only works for types where the type input function
+ is of language C> or internal>.
+
+
+
Index: src/backend/catalog/pg_type.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/catalog/pg_type.c,v
retrieving revision 1.104
diff -c -r1.104 pg_type.c
*** src/backend/catalog/pg_type.c 15 Oct 2005 02:49:14 -0000 1.104
--- src/backend/catalog/pg_type.c 20 Feb 2006 11:50:07 -0000
***************
*** 76,90 ****
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 */
--- 76,90 ----
values[i++] = NameGetDatum(&name); /* typname */
values[i++] = ObjectIdGetDatum(typeNamespace); /* typnamespace */
values[i++] = ObjectIdGetDatum(GetUserId()); /* typowner */
! values[i++] = Int16GetDatum(4); /* typlen */
! values[i++] = BoolGetDatum(true); /* typbyval */
! values[i++] = CharGetDatum('p'); /* typtype */
values[i++] = BoolGetDatum(false); /* typisdefined */
! values[i++] = CharGetDatum('\054'); /* typdelim */
values[i++] = ObjectIdGetDatum(InvalidOid); /* typrelid */
values[i++] = ObjectIdGetDatum(InvalidOid); /* typelem */
! values[i++] = ObjectIdGetDatum(2398); /* typinput */
! values[i++] = ObjectIdGetDatum(2399); /* typoutput */
values[i++] = ObjectIdGetDatum(InvalidOid); /* typreceive */
values[i++] = ObjectIdGetDatum(InvalidOid); /* typsend */
values[i++] = ObjectIdGetDatum(InvalidOid); /* typanalyze */
Index: src/backend/commands/typecmds.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/commands/typecmds.c,v
retrieving revision 1.86
diff -c -r1.86 typecmds.c
*** src/backend/commands/typecmds.c 13 Jan 2006 18:06:45 -0000 1.86
--- src/backend/commands/typecmds.c 20 Feb 2006 11:50:08 -0000
***************
*** 229,246 ****
}
/*
- * make sure we have our required definitions
- */
- if (inputName == NIL)
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
- errmsg("type input function must be specified")));
- if (outputName == NIL)
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
- 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.
--- 229,234 ----
***************
*** 255,260 ****
--- 243,264 ----
/* Make new shell type visible for modification below */
CommandCounterIncrement();
}
+
+ /* Shell type definition, we're done */
+ if( parameters == NULL )
+ return;
+
+ /*
+ * make sure we have our required definitions
+ */
+ if (inputName == NIL)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+ errmsg("type input function must be specified")));
+ if (outputName == NIL)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+ errmsg("type output function must be specified")));
/*
* Convert I/O proc names to OIDs
Index: src/backend/parser/gram.y
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/parser/gram.y,v
retrieving revision 2.530
diff -c -r2.530 gram.y
*** src/backend/parser/gram.y 19 Feb 2006 00:04:27 -0000 2.530
--- src/backend/parser/gram.y 20 Feb 2006 11:50:14 -0000
***************
*** 2690,2695 ****
--- 2690,2703 ----
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 = NULL;
+ $$ = (Node *)n;
+ }
| CREATE TYPE_P any_name AS '(' TableFuncElementList ')'
{
CompositeTypeStmt *n = makeNode(CompositeTypeStmt);
Index: src/backend/utils/adt/pseudotypes.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/utils/adt/pseudotypes.c,v
retrieving revision 1.15
diff -c -r1.15 pseudotypes.c
*** src/backend/utils/adt/pseudotypes.c 31 Dec 2004 22:01:22 -0000 1.15
--- src/backend/utils/adt/pseudotypes.c 20 Feb 2006 11:50:14 -0000
***************
*** 321,323 ****
--- 321,350 ----
PG_RETURN_VOID(); /* keep compiler quiet */
}
+
+ /*
+ * shell_in - input routine for shell-type.
+ */
+ 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-type.
+ */
+ 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 */
+ }
+
Index: src/include/catalog/pg_proc.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/catalog/pg_proc.h,v
retrieving revision 1.397
diff -c -r1.397 pg_proc.h
*** src/include/catalog/pg_proc.h 12 Feb 2006 03:22:19 -0000 1.397
--- src/include/catalog/pg_proc.h 20 Feb 2006 11:50:20 -0000
***************
*** 3319,3324 ****
--- 3319,3328 ----
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_ ));