| From: | Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us> | 
|---|---|
| To: | Philip Warner <pjw(at)rhyme(dot)com(dot)au> | 
| Cc: | pgsql-hackers(at)postgresql(dot)org | 
| Subject: | Re: [rfc] new CREATE FUNCTION (and more) | 
| Date: | 2000-11-17 03:10:56 | 
| Message-ID: | 11336.974430656@sss.pgh.pa.us | 
| Views: | Whole Thread | Raw Message | Download mbox | Resend email | 
| Thread: | |
| Lists: | pgsql-hackers | 
Philip Warner <pjw(at)rhyme(dot)com(dot)au> writes:
> For possible future compatibility, can you also do something like:
>     PG_FUNCTION_API_V2;
>     PG_FUNCTION_V2(foo);
>     PG_FUNCTION_V2(bar);
>     ...
> Where
> PG_FUNCTION_API_V2 expands to:
>     int pg_fmgr_api_version(void) { return 2; }
> And PG_FUNCTION_V2(foo) either does nothing or expands to:
>     int pg_fmgr_api2_version_foo(void) { return 2; }
I'm not following the point here.  Why two different macros?  It doesn't
look to me like the first one does anything.  The per-routine macro
calls should be capable of doing everything that needs to be done.
Per your comments and Marko's about future extension, it seems that
a single-word result might start to get a little cramped before long.
I like Marko's design:
	struct pg_function_info_header {
		int api_ver;
	};
The api_ver field is sufficient for now, but for values > 2 there
might be additional fields defined.
We can either have this struct be an initialized global variable,
or have a called function that returns a pointer to it, depending on
the question of which way seems easier to implement/more portable.
The macro can hide the details of how it's done.
> The first call will tell PG that (because it is version 2), it should
> expect the next set of entry points. Since we will not be allowing mixed
> versions in this version of the API (I think),
Yes, we will, because there is a case in the regression tests that
will break anything that doesn't cope with mixed versions ;-).
I deliberately left some of the routines in regress.c old-style ...
> This way we make it more independant of future API versions by not
> requiring a specific special entry point for each function. Then can do
> things like use the same entry point for multiple functions, possibly act
> as stubs pointing to other libraries (by loading & returning another
> library entry point) etc etc. 
Hmm.  This stub idea might be a sufficient reason to say that we want to
do a function call rather than look for a global variable.  However,
I am unpersuaded by the idea that a one-liner function per useful entry
point is an intolerable amount of overhead.  Let's keep it simple here.
>     PG_FUNCTION_V3(foo, false, true, foo_entry_point)
> expand to:
>     void pg_fmgr_api_version_foo(fmgr_info *i) 
>        { i->iscacheable=false; 
i-> isstrict=true;
i-> entrypoint=foo_entry_point; }
I prefer something like
	const inforec * pg_api_foo(void)
	{
		static inforec foo_info = { ... };
		return &foo_info;
	}
since this avoids prejudging anything.  (In your example, how does
the version function *know* how big the record it's been handed is?
Loading a version-N library into a Postgres version < N might bomb
hard because the info function scribbles on fields that aren't there.
Handing back a pointer to something that the main code then treats
as read-only seems much safer.)  The above implementation with a
preset static inforec is of course only one way it could be done
without breaking the ABI for the info function...
> Perhaps in PG_FUNCTION_API_V4 we can implement some kind of interface for
> listing supported entry points for module loading...
I think that should be seen as a separate feature, rather than
mixing it up with support information about any individual function.
regards, tom lane
| From | Date | Subject | |
|---|---|---|---|
| Next Message | Philip Warner | 2000-11-17 03:49:56 | Re: [rfc] new CREATE FUNCTION (and more) | 
| Previous Message | Philip Warner | 2000-11-17 02:36:02 | Re: [rfc] new CREATE FUNCTION (and more) |