box.schema.func.create()
Create a function. The created function can be used in different usage scenarios, for example, in field or tuple constraints or functional indexes.
Using the body option, you can make a function persistent. In this case, the function is "persistent" because its definition is stored in a snapshot (the box.space._func system space) and can be recovered if the server restarts.
Parameters:
-
func_name(string) — a name of the function, which should conform to the rules for object names -
function_options(table) — see function_options
Returns
nil
Example 1: a non-persistent Lua function
The example below shows how to create a non-persistent Lua function:
box.schema.func.create('calculate')box.schema.func.create('calculate', {if_not_exists = false})box.schema.func.create('calculate', {setuid = false})box.schema.func.create('calculate', {language = 'LUA'})
Example 2: a persistent Lua function
The example below shows how to create a persistent Lua function, show
its definition using box.func.{func-name}, and call this function
using box.func.{func-name}:call([parameters]):
tarantool> lua_code = [[function(a, b) return a + b end]]tarantool> box.schema.func.create('sum', {body = lua_code})tarantool> box.func.sum---- is_sandboxed: falseis_deterministic: falseid: 2setuid: falsebody: function(a, b) return a + b endname: sumlanguage: LUA...tarantool> box.func.sum:call({1, 2})---- 3...
To call functions using net.box, use net_box:call().
Example 3: a persistent SQL expression used in a tuple constraint
The code snippet below defines a function that checks a tuple's data using the SQL expression:
box.schema.func.create('check_person', {language = 'SQL_EXPR',is_deterministic = true,body = [["age" > 21 AND "name" != 'Admin']]})
Then, this function is used to create a tuple constraint:
local customers = box.schema.space.create('customers', { constraint = 'check_person' })customers:format({{ name = 'id', type = 'number' },{ name = 'name', type = 'string' },{ name = 'age', type = 'number' },})customers:create_index('primary', { parts = { 1 } })
On an attempt to insert a tuple that doesn't meet the required criteria, an error is raised:
customers:insert { 2, "Bob", 18 }-- error: Check constraint 'check_person' failed for a tuple
: function_options A table containing options passed to the box.schema.func.create(func-name [, function_options]) function.
Specify whether there should be no error if the function already exists.
Type: boolean
Default: false
Make Tarantool treat the function's caller as the function's creator,
with full privileges. Note that setuid works only over
binary ports. setuid doesn't work if you invoke a
function using the admin console or inside a Lua
script.
Type: boolean
Default: false
Specify the function language. The possible values are:
-
LUA: define a Lua function in the body attribute. -
SQL_EXPR: define an SQL expression in the body attribute. An SQL expression can only be used as a field or tuple constraint. -
C: import a C function using its name from a.sofile. Learn how to call C code from Lua in the C tutorial.
Type: string
Default: LUA
Whether the function should be executed in an isolated environment. This means that any operation that accesses the world outside the sandbox is forbidden or has no effect. Therefore, a sandboxed function can only use modules and functions that cannot affect isolation:
assert, assert, error, ipairs, math.*, next, pairs, pcall, print, select, string.*, table.*, tonumber, tostring, type, unpack, xpcall, utf8.*.
Also, a sandboxed function cannot refer to global variables – they are treated as local variables because the sandbox is established with setfenv. So, a sandboxed function is stateless and deterministic.
Type: boolean
Default: false
Specify whether a function should be deterministic.
Type: boolean
Default: false
If true is set in the function definition for a functional index, the
function returns multiple keys. For details, see the
example.
Type: boolean
Default: false
Specify a function body. You can set a function's language using the language attribute.
The code snippet below defines a constraint function that checks a tuple's data using a Lua function:
box.schema.func.create('check_person', {language = 'LUA',is_deterministic = true,body = 'function(t, c) return (t.age >= 0 and #(t.name) > 3) end'})
In the following example, an SQL expression is used to check a tuple's data:
box.schema.func.create('check_person', {language = 'SQL_EXPR',is_deterministic = true,body = [["age" > 21 AND "name" != 'Admin']]})
Example: A persistent SQL expression used in a tuple constraint
Type: string
Default: nil
Since: 2.10.0
If set to true for a Lua function and the function is called via
net.box (conn:call()) or by
box.func.<func-name>:call(), the function arguments are passed being
wrapped in a MsgPack object:
local msgpack = require('msgpack')box.schema.func.create('my_func', {takes_raw_args = true})local my_func = function(mp)assert(msgpack.is_object(mp))local args = mp:decode() -- array of argumentsend
If a function forwards most of its arguments to another Tarantool instance or writes them to a database, the usage of this option can improve performance because it skips the MsgPack data decoding in Lua.
Type: boolean
Default: false
Specify the languages that can call the function.
Example: exports = {'LUA', 'SQL'}
See also: Calling Lua routines from SQL
Type: table
Default: {'LUA'}
Specify the Lua type names for each parameter of the function.
Example: param_list = {'number', 'number'}
See also: Calling Lua routines from SQL
Type: table
Specify the Lua type name for a function's return value.
Example: returns = 'number'
See also: Calling Lua routines from SQL
Type: string