clkao / plv8js-migrated

Automatically exported from code.google.com/p/plv8js
Other
0 stars 0 forks source link

Exposing plv8 to each other automatically #87

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
plv8 1.4.2 / PostgreSQL 9.3.4

Would like some guidance on the following:

We have many functions that we want to expose to each other to promote among 
other things code reuse.

We know about plv8.find_function, but it seems a bit awkward to have to do that 
lookup everytime we want to reference another function.

So what we've done is create this generic SQL function query:

==============
CREATE OR REPLACE FUNCTION list_functions()
RETURNS setof record
AS
$$
    SELECT
        proname,
        (SELECT array_to_json(ARRAY(
            SELECT pg_type.typname
            FROM unnest(proargtypes) AS pat, pg_type
            WHERE pat = pg_type.oid))
        ) AS argstypes,
        array_to_json(proargnames) as argsnames,
        pg_type.typname AS rettype,
        pg_language.lanname AS lang,
        nspname AS namespace
    FROM
        pg_proc,
        pg_type,
        pg_language,
        pg_namespace
    WHERE
        pg_namespace.oid = pg_proc.pronamespace
        AND pg_namespace.nspname = 'public'
        AND prorettype = pg_type.oid
        AND prolang = pg_language.oid
        -- exclude triggers as they are not callable
        -- separetely (parameters auto-injected by postgres)
        AND NOT EXISTS
        (
            SELECT tgfoid
            FROM pg_trigger r
            WHERE r.tgfoid = pg_proc.oid
        )
    ORDER BY
        proname
$$
LANGUAGE sql;
==============

...with an init function (that also contains plv8.execute for non-plv8 
functions, constants and prototype modifications - not shown)...

==============
CREATE OR REPLACE FUNCTION docstore() RETURNS void AS
$$
plv8.docstore = {};

function list_functions_plv8(target) {
    var funcs = plv8.execute('select list_functions()');
    funcs.forEach(function(row) {
        if(row.list_functions.lang === 'plv8') {
            var funcname = row.list_functions.proname;
            target[funcname] = plv8.find_function(funcname);
        }
    }); 
}

list_functions_plv8(plv8.docstore);
$$
LANGUAGE plv8;
==============

which is than called once for every GUC by setting the following after every 
new connection:

==============
SET plv8.start_proc = "docstore"
==============

This gives us every plv8 function publically available callable directly as 
plv8.docstore.FUNCTION_NAME without having to use find_function for each or 
awkward "SELECT FUNCTION_NAME()" statements.

Apart from the initialization query (once per GUC), we think this should have 
better performance than springling find_function lookups or plv8.execute.

Does that make sense? Is there any downside to this approach? Better ways to do 
this? If it's a good approach, would there be a way to integrate this to plv8 
itself?

Original issue reported on code.google.com by rnga...@gmail.com on 4 Apr 2014 at 5:32

GoogleCodeExporter commented 9 years ago
From my (old) javascript experience, some people do care the namespace 
pollution by this kind of auto registry.  Sure, you could add a root object, 
then what should be the name?  Also, one of the big differences between js and 
pg functions is overloading.  find_function can find functions by 
'proc(argtype1)' style because it's not clear from plv8 side which function is 
necessary.

That said I agree it's useful for some other people and there should be some 
common platform.  I wanted to have some common library that you can use on top 
of plv8 language and to keep the language itself plain and neutral.

Original comment by umi.tan...@gmail.com on 25 Apr 2014 at 5:02