Thread: Proposal: stand-alone composite types
We've discussed at least a couple of times before that it would be nice to be able to create stand-alone composite types. Tom mentioned that ideally this would be done as part of a refactoring of system tables so that attributes belonged to pg_type, instead of belonging to pg_class. But it wasn't clear that this approach was worth the effort, particularly due to backwards compatability breakage. Recently Tom mentioned another alternative (see: http://archives.postgresql.org/pgsql-hackers/2002-07/msg00788.php for more). The basic idea was to "create a new 'dummy' relkind for a pg_class entry that isn't a real relation, but merely a front for a composite type in pg_type." Based on Tom's suggestion, I propose the following: 1. Define a new pg_class relkind as 'c' for composite. Currently relkind can be: 'S' sequence, 'i' index, 'r' relation,'s' special, 't' toast, and 'v' view. 2. Borrow the needed parts from CREATE and DROP VIEW to implement a new form of the CREATE TYPE command, with syntax somethinglike: CREATE TYPE typename AS ( column_name data_type [, ... ] ) This would add a pg_class entry of relkind 'c', and add a new pg_type entry of typtype 'c', with typrelid pointing tothe pg_class entry. Essentially, this new stand-alone composite type looks a lot like a view without any rules. 3. Modify CREATE FUNCTION to allow the implicit creation of a dependent composite type, e.g.: CREATE [ OR REPLACE ] FUNCTION name ( [ argtype [, ...] ] ) RETURNS [setof] { data_type | (column_name data_type [,... ]) }... This would automatically create a stand-alone composite type with a system generated name for the function. Thanks tothe new dependency tracking, the implicit composite type would go away if the function is dropped. Comments, objections, or thoughts? Thanks, Joe
> 3. Modify CREATE FUNCTION to allow the implicit creation of a dependent > composite type, e.g.: > > CREATE [ OR REPLACE ] FUNCTION name ( [ argtype [, ...] ] ) > RETURNS [setof] { data_type | (column_name data_type [, ... ]) }... > > This would automatically create a stand-alone composite type with a > system generated name for the function. Thanks to the new dependency > tracking, the implicit composite type would go away if the function > is dropped. > > > Comments, objections, or thoughts? I'm just licking my lips in anticipation of converting my entire website to SRFs ;) Chris
Joe Conway wrote: > 2. Borrow the needed parts from CREATE and DROP VIEW to implement a new > form of the CREATE TYPE command, with syntax something like: > > CREATE TYPE typename AS ( column_name data_type [, ... ] ) > > This would add a pg_class entry of relkind 'c', and add a new > pg_type entry of typtype 'c', with typrelid pointing to the > pg_class entry. Essentially, this new stand-alone composite type > looks a lot like a view without any rules. I'm working on stand-alone composite types and running into a reduce/reduce problem with the grammer. Any suggestions would be appreciated. Here's what I have: DefineStmt: CREATE AGGREGATE func_name definition { . . . } | CREATE TYPE_P qualified_name AS '(' TableFuncElementList')' { CompositeTypeStmt *n = makeNode(CompositeTypeStmt); n->typevar = $3; n->coldeflist =$6; $$ = (Node *)n; } Thanks, Joe
Joe Conway <mail@joeconway.com> writes: > I'm working on stand-alone composite types and running into a > reduce/reduce problem with the grammer. Any suggestions would be > appreciated. Here's what I have: > DefineStmt: > | CREATE TYPE_P qualified_name AS > '(' TableFuncElementList ')' Use any_name, not qualified_name. As-is, you're forcing the parser to try to distinguish the two forms of CREATE TYPE before it can see anything that would tell the difference. In hindsight I think it was a mistake to set up RangeVar/qualified_name as a distinct reduction path from non-relation qualified names --- we'd have been better off using a single production and a uniform intermediate representation. But I haven't had time to investigate simplifying the grammar that way. regards, tom lane
Joe Conway writes: > 3. Modify CREATE FUNCTION to allow the implicit creation of a dependent > composite type, e.g.: Forgive this blunt question, but: Why? Of course I can see the answer, it's convenient, but wouldn't the system be more consistent overall if all functions and types are declared explicitly? -- Peter Eisentraut peter_e@gmx.net
Peter Eisentraut wrote: > Joe Conway writes: >>3. Modify CREATE FUNCTION to allow the implicit creation of a dependent >> composite type, e.g.: > > Forgive this blunt question, but: Why? Now's a *great* time for a blunt question because I haven't started actively working on this yet. Much better than after I'm done. ;-) > Of course I can see the answer, it's convenient, but wouldn't the system > be more consistent overall if all functions and types are declared > explicitly? > And of couse you are correct. It is almost purely convenience. My reasoning was this: if I am creating a function which returns a composite type, then the fact that a named composite type exists is superfluous to me. It would be more natural for me to do: CREATE FUNCTION foo() RETURNS SETOF (f1 int, f2 text); than to do: CREATE TYPE some_arbitrary_name AS (f1 int, f2 text); CREATE FUNCTION foo() RETURNS SETOF some_arbitrary_name; But I admit it is only a "nice-to-have", not a "need-to-have". How do others feel? Do we want to be able to implicitly create a composite type during function creation? Or is it unneeded bloat? I prefer the former, but don't have a strong argument against the latter. Joe
I think it buys the same as SERIAL does for sequences. Is it likely to have more than one function using a complex type like that? If not, then allowing it's creation (not enforcing) could be useful. On Fri, 2002-08-09 at 19:03, Joe Conway wrote: > Peter Eisentraut wrote: > > Joe Conway writes: > >>3. Modify CREATE FUNCTION to allow the implicit creation of a dependent > >> composite type, e.g.: > > > > Forgive this blunt question, but: Why? > > Now's a *great* time for a blunt question because I haven't started > actively working on this yet. Much better than after I'm done. ;-) > > > > Of course I can see the answer, it's convenient, but wouldn't the system > > be more consistent overall if all functions and types are declared > > explicitly? > > > > And of couse you are correct. It is almost purely convenience. My > reasoning was this: if I am creating a function which returns a > composite type, then the fact that a named composite type exists is > superfluous to me. It would be more natural for me to do: > > CREATE FUNCTION foo() RETURNS SETOF (f1 int, f2 text); > > than to do: > > CREATE TYPE some_arbitrary_name AS (f1 int, f2 text); > CREATE FUNCTION foo() RETURNS SETOF some_arbitrary_name; > > But I admit it is only a "nice-to-have", not a "need-to-have". > > How do others feel? Do we want to be able to implicitly create a > composite type during function creation? Or is it unneeded bloat? > > I prefer the former, but don't have a strong argument against the latter. > > Joe > > > > ---------------------------(end of broadcast)--------------------------- > TIP 2: you can get off all lists at once with the unregister command > (send "unregister YourEmailAddressHere" to majordomo@postgresql.org) >
Rod Taylor wrote: > I think it buys the same as SERIAL does for sequences. That's a great analogy. > Is it likely to have more than one function using a complex type like > that? If not, then allowing it's creation (not enforcing) could be > useful. That's what I was thinking. In cases where you want to use the type for several functions, use CREATE TYPE. If you only need the type for one function, let the function creation process manage it for you. Joe
> -----Original Message----- > From: Joe Conway [mailto:mail@joeconway.com] > Sent: Friday, August 09, 2002 4:04 PM > To: Peter Eisentraut > Cc: pgsql-hackers > Subject: Re: [HACKERS] Proposal: stand-alone composite types > > > Peter Eisentraut wrote: > > Joe Conway writes: > >>3. Modify CREATE FUNCTION to allow the implicit creation of > a dependent > >> composite type, e.g.: > > > > Forgive this blunt question, but: Why? > > Now's a *great* time for a blunt question because I haven't started > actively working on this yet. Much better than after I'm done. ;-) > > > > Of course I can see the answer, it's convenient, but wouldn't the > > system be more consistent overall if all functions and types are > > declared explicitly? > > > > And of couse you are correct. It is almost purely convenience. My > reasoning was this: if I am creating a function which returns a > composite type, then the fact that a named composite type exists is > superfluous to me. It would be more natural for me to do: > > CREATE FUNCTION foo() RETURNS SETOF (f1 int, f2 text); > > than to do: > > CREATE TYPE some_arbitrary_name AS (f1 int, f2 text); > CREATE FUNCTION foo() RETURNS SETOF some_arbitrary_name; Actually, the second looks a lot more natural to me. As in most programming languages, you define the type/class first, and then you can use the type/class as an object. Further, I don't want to have to remember the implementation details, unless I need to dig into them. So: CREATE TYPE locator AS (First_Name varchar, Last_Name varchar, City varchar, State_Province char(2), Country varchar); CREATE FUNCTION CustomerList(varchar specification) RETURNS SETOF locator; Seems far more natural and convenient to me.
> > Is it likely to have more than one function using a complex type like > > that? If not, then allowing it's creation (not enforcing) could be > > useful. > > That's what I was thinking. In cases where you want to use the type for > several functions, use CREATE TYPE. If you only need the type for one > function, let the function creation process manage it for you. So long as the type dissapears with the drop of the function. But don't make stuff you don't clean up :)
> That's what I was thinking. In cases where you want to use the type for > several functions, use CREATE TYPE. If you only need the type for one > function, let the function creation process manage it for you. It would be nice then to have some mechanism for converting the "automatic type" to a named type which could be used elsewhere. Otherwise one would need to garbage collect the separate stuff later, which would probably go into the "not so convenient" category of features... - Thomas
Thomas Lockhart wrote: >>That's what I was thinking. In cases where you want to use the type for >>several functions, use CREATE TYPE. If you only need the type for one >>function, let the function creation process manage it for you. > > It would be nice then to have some mechanism for converting the > "automatic type" to a named type which could be used elsewhere. > Otherwise one would need to garbage collect the separate stuff later, > which would probably go into the "not so convenient" category of > features... Well I think that could be handled with the new dependency tracking system. Same as the SERIAL/sequence analogy -- when you drop the function, the type would automatically and transparently also get dropped. Joe
Joe Conway wrote: > Thomas Lockhart wrote: > >>That's what I was thinking. In cases where you want to use the type for > >>several functions, use CREATE TYPE. If you only need the type for one > >>function, let the function creation process manage it for you. > > > > It would be nice then to have some mechanism for converting the > > "automatic type" to a named type which could be used elsewhere. > > Otherwise one would need to garbage collect the separate stuff later, > > which would probably go into the "not so convenient" category of > > features... > > Well I think that could be handled with the new dependency tracking > system. Same as the SERIAL/sequence analogy -- when you drop the > function, the type would automatically and transparently also get dropped. All this type extension stuff is complex. If we can make it easier for people to get started with it, we should. -- Bruce Momjian | http://candle.pha.pa.us pgman@candle.pha.pa.us | (610) 359-1001+ If your life is a hard drive, | 13 Roberts Road + Christ can be your backup. | Newtown Square, Pennsylvania19073
Peter Eisentraut <peter_e@gmx.net> writes: > Joe Conway writes: >> 3. Modify CREATE FUNCTION to allow the implicit creation of a dependent >> composite type, e.g.: > Forgive this blunt question, but: Why? > Of course I can see the answer, it's convenient, but wouldn't the system > be more consistent overall if all functions and types are declared > explicitly? I was wondering about that too, in particular: what name are you going to give to the implicit type, and what if it conflicts? The already-accepted mechanism for anonymous function-result types for RECORD functions doesn't have that problem, because it has no need to create a catalog entry for the anonymous type. But I'm not sure what to do for record types that need to be present in the catalogs. regards, tom lane
Tom Lane wrote: > I was wondering about that too, in particular: what name are you going > to give to the implicit type, and what if it conflicts? > > The already-accepted mechanism for anonymous function-result types for > RECORD functions doesn't have that problem, because it has no need to > create a catalog entry for the anonymous type. But I'm not sure what > to do for record types that need to be present in the catalogs. I was intending to use the same naming method used for SERIAL sequences. But since the poll from this afternoon only showed weak support and relatively strong objections, I'm OK with putting this aside for now. If enough people seem interested once they start using table functions in 7.3, we can always resurrect this idea. The most important changes (IMHO) were the "anonymous type" and "CREATE TYPE x AS()" pieces anyway, so I'm happy where we are (at least once the stand-alone composite type patch is applied ;) ). Onward and upward... Joe
> than to do: > > CREATE TYPE some_arbitrary_name AS (f1 int, f2 text); > CREATE FUNCTION foo() RETURNS SETOF some_arbitrary_name; > > But I admit it is only a "nice-to-have", not a "need-to-have". > > How do others feel? Do we want to be able to implicitly create a > composite type during function creation? Or is it unneeded bloat? > > I prefer the former, but don't have a strong argument against the latter. The former is super sweet, but does require some extra catalog entries for every procedure - but that's the DBA's problem. They can always use the latter syntax. The format syntax is cool and easy and it Should Just Work for newbies... Chris