# Function Calls PLV8 has the ability to execute multiple types of function calls inside of PostgreSQL. ## Scalar Function Calls In PLV8, you can write your invoked function call in Javascript, using the usual `CREATE FUNCTION` statement. Here is an example of a `scalar` function call: ``` CREATE FUNCTION plv8_test(keys TEXT[], vals TEXT[]) RETURNS JSON AS $$ var o = {}; for(var i=0; i= 9.2) - `JSONB` (>= 9.4) and the Javascript value looks compatible, then the conversion succeeds. Otherwise, PLV8 tries to convert them via the `cstring` representation. An `array` type is supported only if the dimension is one. A Javascript `object` will be mapped to a `tuple` when applicable. In addition to these types, PLV8 supports polymorphic types such like `ANYELEMENT` and `ANYARRAY`. Conversion of `BYTEA` is a little different story. See the [TypedArray section](#Typed%20Array). ## Typed Array The `typed array` is something `v8` provides to allow fast access to native memory, mainly for the purpose of their canvas support in browsers. PLV8 uses this to map `BYTEA` and various array types to a Javascript `array`. In the case of `BYTEA`, you can access each byte as an array of unsigned bytes. For `int2`/`int4`/`float4`/`float8` array types, PLV8 provides direct access to each element by using PLV8 domain types. - `plv8_int2array` maps `int2[]` - `plv8_int4array` maps `int4[]` - `plv8_float4array` maps `float4[]` - `plv8_float8array` maps `float8[]` These are only annotations that tell PLV8 to use the fast access method instead of the regular one. For these typed arrays, only 1-dimensional arrays without any `NULL` elements. There is currently no way to create such typed array inside PLV8 functions, only arguments can be typed array. You can modify the element and return the value. An example for these types are as follows: ``` CREATE FUNCTION int4sum(ary plv8_int4array) RETURNS int8 AS $$ var sum = 0; for (var i = 0; i < ary.length; i++) { sum += ary[i]; } return sum; $$ LANGUAGE plv8 IMMUTABLE STRICT; SELECT int4sum(ARRAY[1, 2, 3, 4, 5]); int4sum --------- 15 (1 row) ``` ## Records A `RECORD` is fundamental in Postgres, and can be used as both input and output for functions. ``` CREATE TYPE record_type AS (i integer, t text); CREATE FUNCTION mutate_record(rec record_type) RETURNS record_type AS $$ return { i: i * 2, t: `t => ${t}` }; $$ LANGUAGE plv8; SELECT * FROM mutate_record('(17, skidoo)'::record_type); i | t ----+-------------- 34 | t => skidoo (1 row) ``` In addition, a function can simply return a `RECORD`. ``` CREATE FUNCTION return_record(i integer, t text) RETURNS record AS $$ return { "i": i, "t": t }; $$ LANGUAGE plv8; ``` But it is required that the expected response is returned as part of the query. ``` SELECT * FROM return_record(17, 'skidoo') AS ( i INT, t TEXT ); i | t ----+-------- 17 | skidoo (1 row) ``` ## IN/OUT/INOUT Handling There are some specific function declarations that PLV8 handles differently than some other procedural languages. ``` CREATE FUNCTION inout_test(IN t1 TEXT, INOUT i1 INTEGER, OUT o1 TEXT) AS $$ return { i1: 23, o1: t1 + i1, foo: 'bar' }; $$ LANGUAGE plv8; ``` When we execute this we call it with only parameters that are inputs to the function, in this case `t1` and `i1`. Note that only named parameters in the function definition get returned. ``` SELECT * FROM inout_test('hello', 5); i1 | o1 ----+-------- 23 | hello5 (1 row) ``` When only one variable occurs in the function definition that as an output, then the return type must be a scalar value. ``` CREATE FUNCTION scalar_test(INOUT i1 INTEGER) AS $$ return i1 + 5; $$ LANGUAGE plv8; SELECT * FROM scalar_test(23); i1 ---- 28 (1 row) ``` Procedures work similarly to functions. ``` CREATE PROCEDURE procedure_inout_test(IN t1 TEXT, INOUT i1 INTEGER, OUT o1 TEXT) AS $$ return { i1: 23, o1: t1 + i1, foo: 'bar' }; $$ LANGUAGE plv8; ``` The main difference is that `OUT` arguments _must_ be explicitly used as part of the `CALL`. ``` CALL procedure_inout_test('hello', 5, 'foo'); i1 | o1 ----+-------- 23 | hello5 (1 row) ``` Again, extraneous output is ignored.