{"id":13636452,"url":"https://github.com/perusio/lua-resty-tarantool","last_synced_at":"2026-02-23T00:55:33.629Z","repository":{"id":137677457,"uuid":"43334728","full_name":"perusio/lua-resty-tarantool","owner":"perusio","description":"Library for working with tarantool from nginx with the embedded Lua module or with Openresty","archived":false,"fork":false,"pushed_at":"2019-11-11T09:26:15.000Z","size":54,"stargazers_count":45,"open_issues_count":4,"forks_count":5,"subscribers_count":11,"default_branch":"origin","last_synced_at":"2024-02-14T19:31:43.985Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Lua","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/perusio.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2015-09-29T00:20:18.000Z","updated_at":"2024-08-02T00:04:17.576Z","dependencies_parsed_at":null,"dependency_job_id":"10f9ec61-3837-4723-be2c-c3558b6d00c1","html_url":"https://github.com/perusio/lua-resty-tarantool","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/perusio%2Flua-resty-tarantool","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/perusio%2Flua-resty-tarantool/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/perusio%2Flua-resty-tarantool/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/perusio%2Flua-resty-tarantool/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/perusio","download_url":"https://codeload.github.com/perusio/lua-resty-tarantool/tar.gz/refs/heads/origin","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249650184,"owners_count":21305976,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-02T00:01:01.401Z","updated_at":"2026-02-23T00:55:33.587Z","avatar_url":"https://github.com/perusio.png","language":"Lua","readme":"# Openresty library for querying the tarantool NoSQL database\n\n## Introduction\n\nThis is a library to connect to the [tarantool](http://tarantool.org)\nNoSQL database. This database has very interesting features that make\nit be sort of a bridge between a traditional SQL based database and\ndocument oriented storages like [CouchDB](http://couchdb.org).\n\nIt's a fork of another\n[project](https://github.com/ziontab/lua-nginx-tarantool) that I was\nunhappy with. It's abundantly documented and is update regarding the\ntarantool API. Notably wtih support for the\n[upsert](https://github.com/tarantool/tarantool/issues/905) command. \n\nAnother thing to bear in mind is that the library tries to be\nconsistent between the way the `update` and `upsert` commands are\nissued in the console using Lua and the way the API works. Notably the\nfield numbers. In the console a field number takes into account the\nexistence of a primary index as the first field. Hence any field that\ncome afterward will have an position that accounts for\nit. Specifically when specifying the operators to use for the `update`\nor `upsert` operations.\n\n## Installation\n\n### OpenResty\n\nIf you're using [OpenResty](http://openresty.org) the library should\nbe installed under: `/usr/local/openresty/lualib/resty`.\n\n### Debian package\n\nI package the library for debian\n[here](https://debian.perusio.net). Just follow the instructions there\nand install it.\n\n### adhoc installation\n\nPut the library in a place in your filesystem that you deem\nappropriate. Don't forget to adjust the Lua package path, either by\nsetting `package.path` in Lua code or using the\n[`lua_package_path`](https://www.nginx.com/resources/wiki/modules/lua/#lua-package-path)\ndirective.\n\n## Requirements\n\nSince tarantool uses [MessagePack](http://msgpack.org) for\nserialization the\n[lua-MessagePack](https://github.com/fperrad/lua-MessagePack) package\nis required. \n\nIt relies on the [BitOp](http://bitop.luajit.org/api.html) from\nLuaJIT. Therefore you need a nginx Lua module that is linked against **LuaJIT** and\nnot Lua 5.1. \n\n## Usage\n\n### Creating a connection\n\n```lua\nlocal tnt = require 'resty.tarantool'\n\nlocal tar, err = tnt:new({\n    host = '127.0.0.1',\n    port = 3301,\n    user = 'luser',\n    password = 'some_password',\n    socket_timeout = 2000,\n    call_semantics = 'new' -- can be 'new' or 'old'*\n})\n```\n\nThe above creates a connection object that connects to a tarantool\nserver instance running on the loopback in port 3301, for user `luser`\nwith password `some password`. See the\n[Tarantool manual in authentication](http://tarantool.org/doc/book/box/authentication.html)\nfor details on how to setup users and assigning privileges to them.\n\nThe socket timeout (receive and send) is 2 seconds (2000 ms).\n\n\\* The option `call_semantics` controls whether the code for the new call\nmethod (0x0a) or the old one (0x06) is used.\nThe old method wraps every result in a table as described [here][binary-protocol].\n**The current default is 'old', but this might change in the future**.\nIt is therefore suggested to set it manually to 'old' in projects that rely on\nthe old behavior.\n\n[binary-protocol]: https://www.tarantool.io/en/doc/2.2/dev_guide/internals/box_protocol/ 'Tarantool Binary Protocol'\n\n### set_timeout\n\n    settimeout(\u003cconnection object\u003e, \u003ctimeout in ms\u003e)\n\nSets both the send and receive timeouts in miliseconds for a given\nsocket.\n\n```lua\ntnt:set_timeout(5000) -- 5s timeout for send/receive operations\n```\n\nThe function returns true if the setting succeeds, `nil` if not. Note\nthat for the timeout to take effect this function needs to be invoked\n**before** the connection is established, i.e., before invoking the\n`connect` function. Alternatively the timeout can be specified when\ncreating the connection object (cosocket).\n\n### connect\n\n    connect(\u003cconnection object\u003e)\n\nConnects the socket created above to the port and address specified\nwhen creating the connection object.\n\n```lua\ntar:connect()\n```\nThe function returns true if the connection succeeds, `nil` if not.\n\n### set_keepalive\n\n    set_keepalive(\u003cconnection object\u003e)\n\nMakes the connection created get pushed to a connection pool so that\nthe connection is kept alive across multiple requests.\n\n```lua\ntar:set_keepalive()\n```\n\nThe function returns true if the socket is successfully pushed to\nconnection pool (set keepalive). `nil` if not.\n\n### disconnect\n\n    disconnect(\u003cconnection object\u003e)\n\nCloses a connection to a given tarantool server running on a given\naddress and port.\n\n```lua\ntar:disconnect()\n```\n\nThe function returns true if the connection is successfully closed. `nil` if not.\n\n\n### ping\n\nThe ping command is useful for monitoring the tarantool server to see\nif it's available. If it's available for queries it returns the string\n`PONG`.\n\n```lua\ntar:ping()\n-- returns PONG\n```\n\n### select\n\nThe select operation queries a given database (space) for retrieving\nrecords.\n\n    select(\u003cconnection object\u003e, \u003cspace name\u003e, \u003cindex\u003e, \u003ckey\u003e, \u003coptions\u003e)\n\nwhere `\u003coptions\u003e` is an optional argument that can consists of a table\nthat can have the following keys:\n\n * `offset`: number of records to skip when doing the query.\n * `limit`: the maximum number of records to return.\n * `iterator`: a number specifiyng the iterator to use. Specified by\n the table:\n\n```lua\nlocal iterator_keys = {\n  EQ = 0, -- equality\n  REQ = 1, -- reverse equality\n  ALL = 2, -- all tuples in an index\n  LT = 3, -- less than\n  LE = 4, -- less than or equal\n  GE = 5, -- greater than or equal\n  GT = 6, -- greater than\n  BITSET_ALL_SET = 7, -- bits in the bitmask all set\n  BITSET_ANY_SET = 8, -- any of the bist in the bitmask are set\n  BITSET_ALL_NOT_SET = 9, -- none on the bits on the bitmask are set\n}\n```\nMore details about iterators on the [tarantool manual](http://tarantool.org/doc/book/box/box_index.html).\n\n#### select examples\n\n##### Query the `_space` space (DB) to get the space id of the `_index` space.\n\n```lua\nlocal res, err = tar:select('_space', 'name', '_index')\n\nif err then return ngx.say(err) end\n\n-- response:\n[2881,\"_index\",\"memtx\",0,\"\",\n  [{\"name\":\"id\",\"type\":\"num\"},\n   {\"name\":\"iid\",\"type\":\"num\"},\n   {\"name\":\"name\",\"type\":\"str\"},\n   {\"name\":\"type\",\"type\":\"str\"},\n   {\"name\":\"opts\",\"type\":\"array\"},\n   {\"name\":\"parts\",\"type\":\"array\"}]]]\n```\nThe above request is equivalent to the console request:\n\n```lua\nbox.space._space.index.name:select{ '_index' }\n```\n\n#### Query the space 'activities' for the activities with a `price` less than 300 \n\n```lua\n-- N.B. price is an index of the activities space.\nlocal res, err = tar:select('activities', 'price', 300, { iterator = 'LT' })\n```\nThe above request is equivalent to the console request:\n\n```lua\nbox.space.activities.index.price:select({ 300 }, { iterator = 'LT' }) \n```\n### insert\n\n    insert(\u003cconnection object\u003e, \u003cspace name\u003e, \u003ctuple\u003e)\n\nwhere `\u003ctuple\u003e` is the tuple to insert into `\u003cspace\u003e` while setting\nthe primary index, which is unique, to the value specified in the\ntuple.\n\nThe function returns the **inserted** record if the operation succeeds.\n\n#### insert examples\n\n```lua\nlocal res, err = tar:insert('activities', { 16, 120, { activity = 'surf', price = 121 } })\n\n-- response: \n[[16,120,{\"activity\":\"surf\",\"price\":121}]]\n```\nThe above request is equivalent to the console request:\n\n```lua\nbox.space.activities:insert({16, 120, { activity = 'surf', price = 121 }})\n```\n16 is the value of the primary index here. This means that for an\ninteger type index this will be the record with primary index 16.\n\n### replace\n\n    replace(\u003cconnection object\u003e, \u003cspace name\u003e, \u003ctuple\u003e)\n\nThe replace command is similar in the invocation and signature to the\ninsert command. But now we're looking for **replacing** a record that\nexists already instead of inserting a new one. We need again the value\nof a primary unique index. But now the value must exist for the\noperation to succeed. If the operations succeeds the record with the\n**replaced** values is returned.\n\n#### replace examples\n\n```lua\nlocal res, err = tar:replace('activities', { 16, 120, { activity = 'surf', price = 120 } })\n-- response:\n[[16,120,{\"activity\":\"surf\",\"price\":120}]]\n```\nHere we replace the former 121 price by 120. The value of the primary\nindex, 16 matches the record we inserted above.\n\nThe above request is equivalent to the console request:\n\n```lua\nbox.space.activities:update({ 16, 120, { activity = 'surf', price = 120 }})\n```\n### update\n\n    update(\u003cconnection object\u003e, \u003cspace name\u003e, \u003cindex\u003e, \u003ckey\u003e, \u003coperator list\u003e) \n\nwhere `\u003coperator list\u003e` is the list of operators as specified n\n[tarantool manual](http://tarantool.org/doc/book/box/box_space.html?highlight=operator#lua-function.space_object.update).\nThe pair (\u003cindex\u003e, \u003ckey\u003e) uniquely identifies a record, i.e., the\n`\u003ckey\u003e` is a value of the primary (unique) `\u003cindex\u003e`.\n\n`\u003coperator list\u003e` is a table of the form:\n\n```lua\n{ \u003coperator\u003e, \u003cfield position\u003e, \u003cvalue\u003e }\n```\nthe operators are:\n\n * `+` for adding to a numeric field. \n * `-` for subtracting to a numeric field.\n * `\u0026` for bitwise AND operation between two unsigned integers.\n * `|` for bitwise OR operation between two unsigned integers.\n * `^` for bitwise XOR operation between two unsigned integers.\n * `:` for string splicing.\n * `!` for field insertion.\n * `#` for field deletion.\n * `=` for assigning a given value to a field.\n\nit returns the **updated** record if the operation is successful.\n\n#### update examples\n\n```lua\nlocal res, err = tar:update('activities', 'primary', 16, { { '=', 2, 341 }, { '=', 3,  { activity = 'kitesurfing', price = 341 }}} )\n-- response:\n[16,341,{\"activity\":\"kitesurfing\",\"price\":341}]]\n```\nThe record with `primary` index 16 that we inserted above was updated.\n\nThe above request is equivalent to the console request:\n\n```lua\nbox.space.activities.index.primary({ 16 }, { { '=', 2, 341 }, { '=', 3,  { activity = 'kitesurfing', price = 341 }}})\n```\n### upsert\n\n    upsert(\u003cconnection object\u003e, \u003cspace name\u003e, \u003ckey\u003e, \u003coperator list\u003e, \u003cnew tuple\u003e)\n\napart from the `\u003cnew tuple\u003e` argument the function signature is\nsimilar to update. In fact upsert is two commands in one. update if\nthe record specified by the pair (\u003cindex\u003e, \u003ckey\u003e) exists and insert if\nnot. The key is a value from a primary index, i.e., is unique. The\n`\u003cnew tuple\u003e` is the tuple to be inserted if the `\u003ckey\u003e` value doesn't\nexist in the `\u003cindex\u003e`. It returns an empty table `{}` if the\noperation is successful. If the operation is unsuccessful it returns `nil`.\n\n#### upsert examples\n\nAn **insert**.\n\n```lua\nlocal res, err = tar:upsert('activities', 17, { { '=', 2, 450 }, { '=', 3,  { activity = 'submarine tour 8', price = 450 }}}, { 17, 450, { activity = 'waterski', price = 365 }})\n-- response:\n{}\n```\nWe **inserted** a new record with key 17 for the primary index from\nthe tuple:\n\n```lua\n{ 18, 450, { activity = 'waterski', price = 365 }}\n```\nThe above request is equivalent to the console request:\n\n```lua\nbox.space.activities:upsert({ 17 }, { { '=', 2, 450 }, { '=', 3,  { activity = 'submarine tour 8', price = 450 }}}, { 17, 450, { activity = 'waterski', price = 365 }})\n```\nAn **update**.\n\n```lua\nlocal res, err = tar:upsert('activities', 17, { { '=', 2, 450 }, { '=', 3,  { activity = 'submarine tour 8', price = 450 }}}, { 18, 285, { activity = 'kitesurfing', price = 285 }})\n-- response:\n{}\n```\nNow we perform an update of the record identified by the key 17 in de\n`primary` index (unique).\n\n### delete\n\n    delete(\u003cconnection object\u003e, \u003cspace\u003e, \u003ckey\u003e)\n\ndeletes the record uniquely specified by `\u003ckey\u003e` from `\u003cspace\u003e`. Note\nthat `\u003ckey\u003e` must belong to a primary (unique) index. It returns the\n**deleted** record if the operation is successful.\n\n#### delete examples\n\n```lua\nlocal response, err = tar:delete('activities', 17)\n-- response:\n[17,450,{\"activity\":\"waterski\",\"price\":365}]]\n```\nWe deleted the record uniquely identified by the key 17 in the primary\nindex from the activites space.\n\nThe above request is equivalent to the console request:\n\n```lua\nbox.space.activities:delete({ 17 })\n\n```\n\n### call\n\n    call(\u003cconnection object\u003e, \u003cproc\u003e, \u003cargs\u003e)\n\nInvokes a\n[stored procedure](http://tarantool.org/doc/book/app_c_lua_tutorial.html)\n(Lua function) in the tarantool server we're connected to. It returns\nthe **results** of the invocation.\n\n#### call examples\n\nSince the tarantool console is a Lua REPL any function can be invoked\nas long as it is available in the environment.\n\n```lua\nlocal res, err = tar:call('table.concat', {{ 'hello', ' ', 'world' }})\n-- response:\n[[\"hello world\"]]\n```\nWe called the `table.concat` function from the table library to\nconcatenate the table:\n\n```lua\n{'hello', ' ', 'world' }\n```\nThe above request is equivalent to the console request:\n\n```lua\ntable.concat({ 'hello', ' ', 'world' })\n```\n\nFor many examples of tarantool stored procedures see the repository;\nhttps://github.com/mailru/tarlua\n\n### eval\n\n    eval(\u003cconnection object\u003e, \u003cexpression\u003e, \u003creturn object\u003e)\n\nInvokes the tarantool embedded Lua interpreter to evaluate the given\n`\u003cexpression\u003e` and returns the result in the `\u003creturn object\u003e`, which\nis usually just an empty table `{ }`.\n\n### eval examples\n\n```lua\nlocal res, err = tar:eval('return 23 * 20', { })\n-- response:\n[460]\n```\nwe invoked the interpreter to evaluate the Lua expression:\n\n```lua\nreturn 23 * 20\n```\n\nwhich is also the equivalent tarantool console request.\n\n### hide\\_version\\_header\n\n    hide_version_header(\u003cconnection object\u003e)\n\nBy default each response sends a custom HTTP header\n`X-Tarantool-Version` with the version of the tarantool server.\n\n    X-Tarantool-Version: 1.6.6-191-g82d1bc3\n\nInvoking `hide_version_header` removes the header.\n\n```lua\ntar:hide_version_header()\n```\n\nIt returns no values.\n\n## TODO\n\n * Test setup.\n","funding_links":[],"categories":["Libraries"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fperusio%2Flua-resty-tarantool","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fperusio%2Flua-resty-tarantool","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fperusio%2Flua-resty-tarantool/lists"}