Skip to content

Instantly share code, notes, and snippets.

@decibel
Last active December 31, 2015 21:39
Show Gist options
  • Save decibel/f232d9788b531f4ee3f8 to your computer and use it in GitHub Desktop.
Save decibel/f232d9788b531f4ee3f8 to your computer and use it in GitHub Desktop.
CREATE OR REPLACE FUNCTION lambda(
code text
, VARIADIC inputs anyarray
) RETURNS anyelement LANGUAGE plpgsql AS $body$
DECLARE
c_prefix CONSTANT text := 'lambda_function_';
c_pattern CONSTANT text := '^' || c_prefix || '([0-9]+)$';
fname text;
foid regprocedure;
fargs regtype[];
call_args text[];
i int;
sql text;
out text;
BEGIN
RAISE DEBUG 'c_prefix = %, c_pattern = %', c_prefix, c_pattern;
-- Get highest defined number. Need to do this in case stuff is nested
SELECT INTO i
coalesce(
max( substring(proname from c_pattern)::int ) + 1
,0
)
FROM pg_proc
WHERE pronamespace=pg_my_temp_schema()
AND proname ~ c_pattern
;
fname := 'pg_temp.' || quote_ident( c_prefix || i );
sql := format(
'CREATE FUNCTION %s%s;'
, fname
, code
);
RAISE DEBUG 'sql = %', sql;
EXECUTE sql;
-- This will return an error if the function is overloaded, which is what we want
foid := fname::regproc::oid;
SELECT INTO fargs
proargtypes::regtype[]
FROM pg_proc
WHERE oid = foid
;
-- TODO: Verify # of fargs matches # of inputs
-- Build call arguments by iterating through fargs and casting our inputs appropriately.
call_args := array(
SELECT format( '%L::%s', input, argtype )
FROM unnest( inputs, fargs ) u( input, argtype )
);
sql := format(
E'SELECT %s(\n%s\n)'
, foid::oid::regproc
, array_to_string( call_args, E'\n , ' )
);
RAISE DEBUG 'sql = %', sql;
EXECUTE sql INTO out USING inputs;
sql := 'DROP FUNCTION ' || foid::text;
RAISE DEBUG 'sql = %', sql;
EXECUTE sql;
RETURN out;
END
$body$;
--SELECT pg_sleep(5);
SELECT lambda( $L1$(float,float) RETURNS float LANGUAGE sql AS $$SELECT $1 + $2$$$L1$, 1.0, 2.1);
-- vi: expandtab ts=2 sw=2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment