Skip to content

Developing UDF Modules

For the complete documentation index see: llms.txt

All documentation pages available in markdown.

Modules Written in Lua

A Lua module is a collection of variables and functions contained in a single file. Modules can be imported and used by other Lua modules, including UDFs. A module name must not conflict with other Lua objects pre-registered by the Aerospike server. The following module names should be avoided:

  • aerospike
  • bytes
  • geojson
  • iterator
  • list
  • map
  • record
  • stream

Module filename rules

Available in Aerospike Database 8.1.2.2, 8.0.0.17, 7.2.0.19, 7.1.0.25 and later. UDF module names must conform to a fixed allowlist. See UDF security and sandbox hardening for the rules and migration guidance for entries that fail validation after upgrade.

Sandbox modes

Aerospike runs every UDF in an embedded Lua state. The set of Lua libraries available to UDFs depends on the mod-lua.allow-unsafe-lua configuration option.

Default mode (allow-unsafe-lua=true): The following restrictions apply.

  • The Lua io library is not available.
  • The Lua os library is restricted to os.clock(), os.date(), os.difftime(), and os.time().
  • The Lua debug library is not available.
  • os.exit() is not available.

Hardened mode (allow-unsafe-lua=false): Hardened mode replaces the default sandbox with stricter restrictions:

  • The os, io, debug, dofile, loadfile, load, and loadstring globals are removed entirely. The four os.* functions allowed in default mode are not available in hardened mode.
  • package.searchpath, package.loadlib, and package.cpath are removed.
  • Native .so UDF modules cannot be registered. See Using C functions in UDF Modules later on this page.
  • Precompiled Lua bytecode UDFs are rejected at registration with a compile error; the server loads Lua chunks in text-only mode.
  • The .lua extension is checked case-sensitively at registration.

See UDF security and sandbox hardening for the full set of changes and a migration checklist.

Creating a Module

In the following example, we define a local table exports in the file mymodule.lua. This module will be populated with the functions to be exported.

local exports = {}
function exports.hello()
return "Hello "
end
function exports.world()
return "World!"
end
return exports

Registering a Module

Lua Modules must be registered with the Aerospike Server.

To install your modules, you may

  • Use the aql
  • Use the asadm tool
  • Use any of the Aerospike Clients

To register the module using asadm:

Terminal window
Admin> enable
Admin+> manage udfs add mymodule.lua path path/to/mymodule.lua
Successfully added UDF mymodule.lua
Admin+>
Admin+> show udfs
~~~~~~~~~~UDF Modules (2021-01-23 02:00:18 UTC)~~~~~~~~~~~
Filename| Hash|Type
mymodule.lua|7fae110826972135a3c3b8a812d43243e7c7a23c|LUA
Number of rows: 1

To register the module using aql:

Terminal window
aql> register module 'mymodule.lua'
OK, 1 module added.
aql> show modules
+-----------------+--------------------------------------------+-------+
| filename | hash | type |
+-----------------+--------------------------------------------+-------+
| "mymodule.lua" | "4e4dfd2ac120e161f69d1dfbab14eec157d0eaaf" | "LUA" |
+-----------------+--------------------------------------------+-------+

Another module can now require mymodule.lua into a local variable and use it.

Example: A Hello World UDF

In a file example.lua

local mm = require('mymodule')
function helloworld(rec)
return mm.hello() .. mm.world()
end

In aql

Terminal window
aql> register module 'example.lua'
OK, 1 module added.
aql> show modules
+-----------------+--------------------------------------------+-------+
| filename | hash | type |
+-----------------+--------------------------------------------+-------+
| "example.lua" | "c42bf3f4a6f8f727efcfb884c97ee894764f1dc7" | "LUA" |
| "mymodule.lua" | "4e4dfd2ac120e161f69d1dfbab14eec157d0eaaf" | "LUA" |
+-----------------+--------------------------------------------+-------+
2 rows in set (0.002 secs)
aql> insert into test.foo (PK, x) values ('1', 24)
OK, 1 record affected.
aql> execute example.helloworld() on test.foo where PK='1'
+----------------+
| helloworld |
+----------------+
| "Hello World!" |
+----------------+
1 row in set (0.001 secs)

Using C functions in UDF Modules

Aerospike UDFs written in Lua can call C functions from shared objects. For more information read about the C API for Lua.

Example: Compiling and Registering a Shared Object

In this example the file power.c contains sample C code:

#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
static int go(lua_State * L) {
int rtrn = lua_tonumber(L, -1); /* Get the single number arg */
lua_pushnumber(L,rtrn*rtrn); /* square it and push the return */
return 1;
}
static const struct luaL_reg golib [] = {
{"go", go},
{NULL, NULL}
};
int luaopen_power(lua_State * L) {
luaL_openlib(L, "go", golib, 0);
return 1;
}

The Lua UDF module use.lua requires and calls the power.so shared object

function thepower(rec, basenum)
local power = require("power")
local rtn = power.go(basenum);
--info(rtn)
return rtn
end

Get the Lua Source

Download the Lua 5.1.4 library to allow for the necessary Lua code to be linked.

Compile

gcc -fPIC -o power.so -shared power.c -I /usr/include/

Register and Execute

In aql:

Terminal window
aql> register module 'power.so'
OK, 1 module added.
aql> register module 'use.lua'
OK, 1 module added.
aql> show modules
+-----------------+--------------------------------------------+-------+
| filename | hash | type |
+-----------------+--------------------------------------------+-------+
| "example.lua" | "c42bf3f4a6f8f727efcfb884c97ee894764f1dc7" | "LUA" |
| "power.so" | "99703e01482f065c62f0d0c55ba6b1f3214e3601" | "LUA" |
| "use.lua" | "5093704498b333e57d7dd033b529c4b4e0d99edb" | "LUA" |
| "mymodule.lua" | "4e4dfd2ac120e161f69d1dfbab14eec157d0eaaf" | "LUA" |
+-----------------+--------------------------------------------+-------+
4 rows in set (0.002 secs)
aql> execute use.thepower(4) on test.foo where PK='1'
+----------+
| thepower |
+----------+
| 16 |
+----------+
1 row in set (0.001 secs)
Feedback

Was this page helpful?

What type of feedback are you giving?

What would you like us to know?

+Capture screenshot

Can we reach out to you?