mirror of
				https://github.com/postgres/postgres.git
				synced 2025-10-31 00:03:57 -04:00 
			
		
		
		
	Allow the syntax CREATE TYPE foo, with no parameters, to permit explicit
creation of a shell type. This allows a less hacky way of dealing with the mutual dependency between a datatype and its I/O functions: make a shell type, then make the functions, then define the datatype fully. We should fix pg_dump to handle things this way, but this commit just deals with the backend. Martijn van Oosterhout, with some corrections by Tom Lane.
This commit is contained in:
		
							parent
							
								
									7f19339cca
								
							
						
					
					
						commit
						8e68d78390
					
				| @ -1,5 +1,5 @@ | ||||
| <!-- | ||||
| $PostgreSQL: pgsql/doc/src/sgml/ref/create_type.sgml,v 1.60 2006/01/13 18:06:45 tgl Exp $ | ||||
| $PostgreSQL: pgsql/doc/src/sgml/ref/create_type.sgml,v 1.61 2006/02/28 22:37:25 tgl Exp $ | ||||
| PostgreSQL documentation | ||||
| --> | ||||
| 
 | ||||
| @ -37,6 +37,8 @@ CREATE TYPE <replaceable class="parameter">name</replaceable> ( | ||||
|     [ , ELEMENT = <replaceable class="parameter">element</replaceable> ] | ||||
|     [ , DELIMITER = <replaceable class="parameter">delimiter</replaceable> ] | ||||
| ) | ||||
| 
 | ||||
| CREATE TYPE <replaceable class="parameter">name</replaceable> | ||||
| </synopsis> | ||||
|  </refsynopsisdiv> | ||||
| 
 | ||||
| @ -142,17 +144,16 @@ CREATE TYPE <replaceable class="parameter">name</replaceable> ( | ||||
| 
 | ||||
|   <para> | ||||
|    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. | ||||
|    <productname>PostgreSQL</productname> will first see the name of the new | ||||
|    data type as the return type of the input function.  It will create a | ||||
|    <quote>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, <command>CREATE TYPE</> replaces the | ||||
|    shell entry with a complete type definition, and the new type can be used. | ||||
|    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 type should first be defined as a <firstterm>shell type</>, which is a | ||||
|    placeholder type that has no properties except a name and an owner.  This | ||||
|    is done by issuing the command <literal>CREATE TYPE | ||||
|    <replaceable>name</></literal>, with no additional parameters.  Then the | ||||
|    I/O functions can be defined referencing the shell type.  Finally, | ||||
|    <command>CREATE TYPE</> with a full definition replaces the shell entry | ||||
|    with a complete, valid type definition, after which the new type can be | ||||
|    used normally. | ||||
|   </para> | ||||
| 
 | ||||
|   <para> | ||||
| @ -457,17 +458,33 @@ CREATE TYPE <replaceable class="parameter">name</replaceable> ( | ||||
|    while converting it to or from external form. | ||||
|   </para> | ||||
| 
 | ||||
|   <para> | ||||
|    Before <productname>PostgreSQL</productname> version 8.2, the syntax | ||||
|    <literal>CREATE TYPE <replaceable>name</></literal> did not exist. | ||||
|    The way to create a new base type was to create its input function first. | ||||
|    In this approach, <productname>PostgreSQL</productname> will first see | ||||
|    the name of the new data type as the return type of the input function. | ||||
|    The shell type is implicitly created in this situation, and then it | ||||
|    can be referenced in the definitions of the remaining I/O functions. | ||||
|    This approach still works, but is deprecated and may be disallowed in | ||||
|    some future release.  Also, to avoid accidentally cluttering | ||||
|    the catalogs with shell types as a result of simple typos in function | ||||
|    definitions, a shell type will only be made this way when the input | ||||
|    function is written in C. | ||||
|   </para> | ||||
| 
 | ||||
|   <para> | ||||
|    In <productname>PostgreSQL</productname> versions before 7.3, it | ||||
|    was customary to avoid creating a shell type by replacing the | ||||
|    was customary to avoid creating a shell type at all, by replacing the | ||||
|    functions' forward references to the type name with the placeholder | ||||
|    pseudotype <type>opaque</>.  The <type>cstring</> arguments and | ||||
|    results also had to be declared as <type>opaque</> before 7.3.  To | ||||
|    support loading of old dump files, <command>CREATE TYPE</> will | ||||
|    accept functions declared using <type>opaque</>, but it will issue | ||||
|    a notice and change the function's declaration to use the correct | ||||
|    accept I/O functions declared using <type>opaque</>, but it will issue | ||||
|    a notice and change the function declarations to use the correct | ||||
|    types. | ||||
|   </para> | ||||
| 
 | ||||
|  </refsect1> | ||||
|   | ||||
|  <refsect1> | ||||
| @ -489,6 +506,11 @@ $$ LANGUAGE SQL; | ||||
|    This example creates the base data type <type>box</type> and then uses the | ||||
|    type in a table definition: | ||||
| <programlisting> | ||||
| CREATE TYPE box; | ||||
| 
 | ||||
| CREATE FUNCTION my_box_in_function(cstring) RETURNS box AS ... ; | ||||
| CREATE FUNCTION my_box_out_function(box) RETURNS cstring AS ... ; | ||||
| 
 | ||||
| CREATE TYPE box ( | ||||
|     INTERNALLENGTH = 16, | ||||
|     INPUT = my_box_in_function, | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| <!-- | ||||
| $PostgreSQL: pgsql/doc/src/sgml/xtypes.sgml,v 1.25 2005/01/10 00:04:38 tgl Exp $ | ||||
| $PostgreSQL: pgsql/doc/src/sgml/xtypes.sgml,v 1.26 2006/02/28 22:37:25 tgl Exp $ | ||||
| --> | ||||
| 
 | ||||
|  <sect1 id="xtypes"> | ||||
| @ -168,8 +168,16 @@ complex_send(PG_FUNCTION_ARGS) | ||||
|  </para> | ||||
| 
 | ||||
|  <para> | ||||
|   To define the <type>complex</type> type, we need to create the | ||||
|   user-defined I/O functions before creating the type: | ||||
|   Once we have written the I/O functions and compiled them into a shared | ||||
|   library, we can define the <type>complex</type> type in SQL. | ||||
|   First we declare it as a shell type: | ||||
| 
 | ||||
| <programlisting> | ||||
| CREATE TYPE complex; | ||||
| </programlisting> | ||||
| 
 | ||||
|   This serves as a placeholder that allows us to reference the type while | ||||
|   defining its I/O functions.  Now we can define the I/O functions: | ||||
| 
 | ||||
| <programlisting> | ||||
| CREATE FUNCTION complex_in(cstring) | ||||
| @ -192,15 +200,10 @@ CREATE FUNCTION complex_send(complex) | ||||
|    AS '<replaceable>filename</replaceable>' | ||||
|    LANGUAGE C IMMUTABLE STRICT; | ||||
| </programlisting> | ||||
| 
 | ||||
|   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. | ||||
|  </para> | ||||
| 
 | ||||
|  <para> | ||||
|   Finally, we can declare the data type: | ||||
|   Finally, we can provide the full definition of the data type: | ||||
| <programlisting> | ||||
| CREATE TYPE complex ( | ||||
|    internallength = 16,  | ||||
|  | ||||
| @ -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, | ||||
|  | ||||
| @ -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); | ||||
| @ -240,22 +271,6 @@ DefineType(List *names, List *parameters) | ||||
| 				(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. | ||||
| 	 */ | ||||
| 	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 | ||||
| 	 */ | ||||
|  | ||||
| @ -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); | ||||
|  | ||||
| @ -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 */ | ||||
| } | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
| @ -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 )); | ||||
|  | ||||
| @ -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_ )); | ||||
|  | ||||
| @ -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); | ||||
|  | ||||
| @ -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; | ||||
|  | ||||
| @ -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; | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user