pllua / pllua-deprecated

[DEPRECATED] This repository is no longer maintained. Please follow https://github.com/pllua/pllua
197 stars 16 forks source link

added set returning functions for pgfunc #31

Closed eugwne closed 8 years ago

eugwne commented 8 years ago

added set returning functions for pgfunc added type wrapper example

It seems to me that I have almost done everything with pgfunc that can give us interesting features.

General description: pgfunc is a function for making wrappers for postgres functions or loading pllua modules from postgres procedures .

pgfunc is not a kind of select from wrapper, it works through postgres FunctionCallInvoke.

pgfunc accepts two arguments, function signature and function options( table {only_internal=true, throwable = true} by default).

if only_internal is true, that means that only internal function accepted and no PG_TRY PG_CATCH used inside(throwable value ignored), simple use case:

do $$
local f = pgfunc("random()")
print(f())
$$ language pllua
-----
INFO:  0.56601480720565

use case with srf:

do $$
local f = pgfunc("generate_series(int,int)")
for v in f(1,5) do
    print(v)
end
$$ language pllua
-----
INFO:  1
INFO:  2
INFO:  3
INFO:  4
INFO:  5

if only_internal is false, that means that we can use almost any function and if throwable is true than function calls will be wrapped by PG_TRY PG_CATCH (if function throws and not marked as throwable that may crash, make throwable = false if you 100% sure that no exception will be thrown)

use case for plpgsql function and in/out values:

CREATE or replace FUNCTION pg_temp.inoutf(a text, INOUT b text, INOUT c text)  AS
$$
begin
b = b||a;
c = c||a;
end
$$
LANGUAGE plpgsql;

do $$
local f = pgfunc('pg_temp.inoutf(text,text,text)', {only_internal = false})
local v = f("test", "this is B ", "this is C ")
print (v.b)
print (v.c)
$$ language pllua
------
INFO:  this is B test
INFO:  this is C test

Using only pgfunc it is possible to add support for postgres types without writing C code. I've added small example to test and put it here:

do $$
local hstore = {
    fromstring = function(text)
        return fromstring('hstore',text)
    end,
    akeys = pgfunc('akeys(hstore)',{only_internal = false}),
    each = pgfunc('each(hstore)',{only_internal = false}) --orig:each(IN hs hstore, OUT key text, OUT value text)
}

local v = hstore.fromstring[[
    "paperback" => "542",
    "publisher" => "postgresql.org",
    "language"  => "English",
    "ISBN-13"   => "978-0000000000",
    "weight"    => "24.1 ounces"
]]

print("--- test print ---") 
print(v)
print("--- test  array return function ---")
for k,v in  ipairs(hstore.akeys(v)) do
    print (v)
end
print("--- test Set of record return function ---")
for hv in  hstore.each(v) do
    print ("key = " .. hv.key .. "    value = "..hv.value)
end
 $$ language pllua
INFO:  --- test print ---
INFO:  "weight"=>"24.1 ounces", "ISBN-13"=>"978-0000000000", "language"=>"English", "paperback"=>"542", "publisher"=>"postgresql.org"
INFO:  --- test  array return function ---
INFO:  weight
INFO:  ISBN-13
INFO:  language
INFO:  paperback
INFO:  publisher
INFO:  --- test Set of record return function ---
INFO:  key = weight    value = 24.1 ounces
INFO:  key = ISBN-13    value = 978-0000000000
INFO:  key = language    value = English
INFO:  key = paperback    value = 542
INFO:  key = publisher    value = postgresql.org

Some function properties may be ignored, for example there is no check if function is strict...

Ideas? Questions?

mbalmer commented 8 years ago

I think we could/should merge this to give it some exposure. Ok?